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"
30 #include "../librpc/gen_ndr/cli_samr.h"
31 #include "../librpc/gen_ndr/srv_samr.h"
32 #include "../lib/util/binsearch.h"
39 #define NERR_Success 0
40 #define NERR_badpass 86
41 #define NERR_notsupported 50
43 #define NERR_BASE (2100)
44 #define NERR_BufTooSmall (NERR_BASE+23)
45 #define NERR_JobNotFound (NERR_BASE+51)
46 #define NERR_DestNotFound (NERR_BASE+52)
48 #define ACCESS_READ 0x01
49 #define ACCESS_WRITE 0x02
50 #define ACCESS_CREATE 0x04
52 #define SHPWLEN 8 /* share password length */
54 /* Limit size of ipc replies */
56 static char *smb_realloc_limit(void *ptr
, size_t size
)
60 size
= MAX((size
),4*1024);
61 val
= (char *)SMB_REALLOC(ptr
,size
);
63 memset(val
,'\0',size
);
68 static bool api_Unsupported(connection_struct
*conn
, uint16 vuid
,
69 char *param
, int tpscnt
,
70 char *data
, int tdscnt
,
71 int mdrcnt
, int mprcnt
,
72 char **rdata
, char **rparam
,
73 int *rdata_len
, int *rparam_len
);
75 static bool api_TooSmall(connection_struct
*conn
, uint16 vuid
, char *param
, char *data
,
76 int mdrcnt
, int mprcnt
,
77 char **rdata
, char **rparam
,
78 int *rdata_len
, int *rparam_len
);
81 static int CopyExpanded(connection_struct
*conn
,
82 int snum
, char **dst
, char *src
, int *p_space_remaining
)
84 TALLOC_CTX
*ctx
= talloc_tos();
88 if (!src
|| !dst
|| !p_space_remaining
|| !(*dst
) ||
89 *p_space_remaining
<= 0) {
93 buf
= talloc_strdup(ctx
, src
);
95 *p_space_remaining
= 0;
98 buf
= talloc_string_sub(ctx
, buf
,"%S",lp_servicename(snum
));
100 *p_space_remaining
= 0;
103 buf
= talloc_sub_advanced(ctx
,
104 lp_servicename(SNUM(conn
)),
105 conn
->server_info
->unix_name
,
107 conn
->server_info
->utok
.gid
,
108 conn
->server_info
->sanitized_username
,
109 pdb_get_domain(conn
->server_info
->sam_account
),
112 *p_space_remaining
= 0;
115 l
= push_ascii(*dst
,buf
,*p_space_remaining
, STR_TERMINATE
);
120 (*p_space_remaining
) -= l
;
124 static int CopyAndAdvance(char **dst
, char *src
, int *n
)
127 if (!src
|| !dst
|| !n
|| !(*dst
)) {
130 l
= push_ascii(*dst
,src
,*n
, STR_TERMINATE
);
139 static int StrlenExpanded(connection_struct
*conn
, int snum
, char *s
)
141 TALLOC_CTX
*ctx
= talloc_tos();
146 buf
= talloc_strdup(ctx
,s
);
150 buf
= talloc_string_sub(ctx
,buf
,"%S",lp_servicename(snum
));
154 buf
= talloc_sub_advanced(ctx
,
155 lp_servicename(SNUM(conn
)),
156 conn
->server_info
->unix_name
,
158 conn
->server_info
->utok
.gid
,
159 conn
->server_info
->sanitized_username
,
160 pdb_get_domain(conn
->server_info
->sam_account
),
165 return strlen(buf
) + 1;
168 static char *Expand(connection_struct
*conn
, int snum
, char *s
)
170 TALLOC_CTX
*ctx
= talloc_tos();
176 buf
= talloc_strdup(ctx
,s
);
180 buf
= talloc_string_sub(ctx
,buf
,"%S",lp_servicename(snum
));
184 return talloc_sub_advanced(ctx
,
185 lp_servicename(SNUM(conn
)),
186 conn
->server_info
->unix_name
,
188 conn
->server_info
->utok
.gid
,
189 conn
->server_info
->sanitized_username
,
190 pdb_get_domain(conn
->server_info
->sam_account
),
194 /*******************************************************************
195 Check a API string for validity when we only need to check the prefix.
196 ******************************************************************/
198 static bool prefix_ok(const char *str
, const char *prefix
)
200 return(strncmp(str
,prefix
,strlen(prefix
)) == 0);
204 const char *format
; /* formatstring for structure */
205 const char *subformat
; /* subformat for structure */
206 char *base
; /* baseaddress of buffer */
207 int buflen
; /* remaining size for fixed part; on init: length of base */
208 int subcount
; /* count of substructures */
209 char *structbuf
; /* pointer into buffer for remaining fixed part */
210 int stringlen
; /* remaining size for variable part */
211 char *stringbuf
; /* pointer into buffer for remaining variable part */
212 int neededlen
; /* total needed size */
213 int usedlen
; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
214 const char *curpos
; /* current position; pointer into format or subformat */
218 static int get_counter(const char **p
)
224 if (!isdigit((int)**p
)) {
230 n
= 10 * n
+ (i
- '0');
238 static int getlen(const char *p
)
247 case 'W': /* word (2 byte) */
250 case 'K': /* status word? (2 byte) */
253 case 'N': /* count of substructures (word) at end */
256 case 'D': /* double word (4 byte) */
257 case 'z': /* offset to zero terminated string (4 byte) */
258 case 'l': /* offset to user data (4 byte) */
261 case 'b': /* offset to data (with counter) (4 byte) */
265 case 'B': /* byte (with optional counter) */
266 n
+= get_counter(&p
);
273 static bool init_package(struct pack_desc
*p
, int count
, int subcount
)
278 if (!p
->format
|| !p
->base
) {
282 i
= count
* getlen(p
->format
);
284 i
+= subcount
* getlen(p
->subformat
);
286 p
->structbuf
= p
->base
;
290 p
->curpos
= p
->format
;
296 * This is the old error code we used. Aparently
297 * WinNT/2k systems return ERRbuftoosmall (2123) and
298 * OS/2 needs this. I'm leaving this here so we can revert
301 p
->errcode
= ERRmoredata
;
303 p
->errcode
= ERRbuftoosmall
;
306 p
->errcode
= NERR_Success
;
310 p
->stringbuf
= p
->base
+ i
;
312 return (p
->errcode
== NERR_Success
);
315 static int package(struct pack_desc
*p
, ...)
318 int needed
=0, stringneeded
;
319 const char *str
=NULL
;
320 int is_string
=0, stringused
;
327 p
->curpos
= p
->format
;
329 p
->curpos
= p
->subformat
;
334 str
= va_arg(args
,char*);
335 SMB_ASSERT(strncmp(str
,p
->curpos
,strlen(str
)) == 0);
344 switch( *p
->curpos
++ ) {
345 case 'W': /* word (2 byte) */
347 temp
= va_arg(args
,int);
348 if (p
->buflen
>= needed
) {
349 SSVAL(p
->structbuf
,0,temp
);
352 case 'K': /* status word? (2 byte) */
354 temp
= va_arg(args
,int);
355 if (p
->buflen
>= needed
) {
356 SSVAL(p
->structbuf
,0,temp
);
359 case 'N': /* count of substructures (word) at end */
361 p
->subcount
= va_arg(args
,int);
362 if (p
->buflen
>= needed
) {
363 SSVAL(p
->structbuf
,0,p
->subcount
);
366 case 'D': /* double word (4 byte) */
368 temp
= va_arg(args
,int);
369 if (p
->buflen
>= needed
) {
370 SIVAL(p
->structbuf
,0,temp
);
373 case 'B': /* byte (with optional counter) */
374 needed
= get_counter(&p
->curpos
);
376 char *s
= va_arg(args
,char*);
377 if (p
->buflen
>= needed
) {
378 StrnCpy(p
->structbuf
,s
?s
:"",needed
-1);
382 case 'z': /* offset to zero terminated string (4 byte) */
383 str
= va_arg(args
,char*);
384 stringneeded
= (str
? strlen(str
)+1 : 0);
387 case 'l': /* offset to user data (4 byte) */
388 str
= va_arg(args
,char*);
389 stringneeded
= va_arg(args
,int);
392 case 'b': /* offset to data (with counter) (4 byte) */
393 str
= va_arg(args
,char*);
394 stringneeded
= get_counter(&p
->curpos
);
400 if (stringneeded
>= 0) {
402 if (p
->buflen
>= needed
) {
403 stringused
= stringneeded
;
404 if (stringused
> p
->stringlen
) {
405 stringused
= (is_string
? p
->stringlen
: 0);
406 if (p
->errcode
== NERR_Success
) {
407 p
->errcode
= ERRmoredata
;
411 SIVAL(p
->structbuf
,0,0);
413 SIVAL(p
->structbuf
,0,PTR_DIFF(p
->stringbuf
,p
->base
));
414 memcpy(p
->stringbuf
,str
?str
:"",stringused
);
416 p
->stringbuf
[stringused
-1] = '\0';
418 p
->stringbuf
+= stringused
;
419 p
->stringlen
-= stringused
;
420 p
->usedlen
+= stringused
;
423 p
->neededlen
+= stringneeded
;
426 p
->neededlen
+= needed
;
427 if (p
->buflen
>= needed
) {
428 p
->structbuf
+= needed
;
430 p
->usedlen
+= needed
;
432 if (p
->errcode
== NERR_Success
) {
433 p
->errcode
= ERRmoredata
;
440 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
441 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
443 #define PACK(desc,t,v) package(desc,v)
444 #define PACKl(desc,t,v,l) package(desc,v,l)
447 static void PACKI(struct pack_desc
* desc
, const char *t
,int v
)
452 static void PACKS(struct pack_desc
* desc
,const char *t
,const char *v
)
457 /****************************************************************************
459 ****************************************************************************/
461 static void PackDriverData(struct pack_desc
* desc
)
463 char drivdata
[4+4+32];
464 SIVAL(drivdata
,0,sizeof drivdata
); /* cb */
465 SIVAL(drivdata
,4,1000); /* lVersion */
466 memset(drivdata
+8,0,32); /* szDeviceName */
467 push_ascii(drivdata
+8,"NULL",32, STR_TERMINATE
);
468 PACKl(desc
,"l",drivdata
,sizeof drivdata
); /* pDriverData */
471 static int check_printq_info(struct pack_desc
* desc
,
472 unsigned int uLevel
, char *id1
, char *id2
)
474 desc
->subformat
= NULL
;
477 desc
->format
= "B13";
480 desc
->format
= "B13BWWWzzzzzWW";
483 desc
->format
= "B13BWWWzzzzzWN";
484 desc
->subformat
= "WB21BB16B10zWWzDDz";
487 desc
->format
= "zWWWWzzzzWWzzl";
490 desc
->format
= "zWWWWzzzzWNzzl";
491 desc
->subformat
= "WWzWWDDzz";
500 desc
->format
= "WzzzzzzzzN";
501 desc
->subformat
= "z";
504 DEBUG(0,("check_printq_info: invalid level %d\n",
508 if (id1
== NULL
|| strcmp(desc
->format
,id1
) != 0) {
509 DEBUG(0,("check_printq_info: invalid format %s\n",
510 id1
? id1
: "<NULL>" ));
513 if (desc
->subformat
&& (id2
== NULL
|| strcmp(desc
->subformat
,id2
) != 0)) {
514 DEBUG(0,("check_printq_info: invalid subformat %s\n",
515 id2
? id2
: "<NULL>" ));
522 #define RAP_JOB_STATUS_QUEUED 0
523 #define RAP_JOB_STATUS_PAUSED 1
524 #define RAP_JOB_STATUS_SPOOLING 2
525 #define RAP_JOB_STATUS_PRINTING 3
526 #define RAP_JOB_STATUS_PRINTED 4
528 #define RAP_QUEUE_STATUS_PAUSED 1
529 #define RAP_QUEUE_STATUS_ERROR 2
531 /* turn a print job status into a on the wire status
533 static int printj_status(int v
)
537 return RAP_JOB_STATUS_QUEUED
;
539 return RAP_JOB_STATUS_PAUSED
;
541 return RAP_JOB_STATUS_SPOOLING
;
543 return RAP_JOB_STATUS_PRINTING
;
548 /* turn a print queue status into a on the wire status
550 static int printq_status(int v
)
556 return RAP_QUEUE_STATUS_PAUSED
;
558 return RAP_QUEUE_STATUS_ERROR
;
561 static void fill_printjob_info(connection_struct
*conn
, int snum
, int uLevel
,
562 struct pack_desc
*desc
,
563 print_queue_struct
*queue
, int n
)
565 time_t t
= queue
->time
;
567 /* the client expects localtime */
568 t
-= get_time_zone(t
);
570 PACKI(desc
,"W",pjobid_to_rap(lp_const_servicename(snum
),queue
->job
)); /* uJobId */
572 PACKS(desc
,"B21",queue
->fs_user
); /* szUserName */
573 PACKS(desc
,"B",""); /* pad */
574 PACKS(desc
,"B16",""); /* szNotifyName */
575 PACKS(desc
,"B10","PM_Q_RAW"); /* szDataType */
576 PACKS(desc
,"z",""); /* pszParms */
577 PACKI(desc
,"W",n
+1); /* uPosition */
578 PACKI(desc
,"W",printj_status(queue
->status
)); /* fsStatus */
579 PACKS(desc
,"z",""); /* pszStatus */
580 PACKI(desc
,"D",t
); /* ulSubmitted */
581 PACKI(desc
,"D",queue
->size
); /* ulSize */
582 PACKS(desc
,"z",queue
->fs_file
); /* pszComment */
584 if (uLevel
== 2 || uLevel
== 3 || uLevel
== 4) {
585 PACKI(desc
,"W",queue
->priority
); /* uPriority */
586 PACKS(desc
,"z",queue
->fs_user
); /* pszUserName */
587 PACKI(desc
,"W",n
+1); /* uPosition */
588 PACKI(desc
,"W",printj_status(queue
->status
)); /* fsStatus */
589 PACKI(desc
,"D",t
); /* ulSubmitted */
590 PACKI(desc
,"D",queue
->size
); /* ulSize */
591 PACKS(desc
,"z","Samba"); /* pszComment */
592 PACKS(desc
,"z",queue
->fs_file
); /* pszDocument */
594 PACKS(desc
,"z",""); /* pszNotifyName */
595 PACKS(desc
,"z","PM_Q_RAW"); /* pszDataType */
596 PACKS(desc
,"z",""); /* pszParms */
597 PACKS(desc
,"z",""); /* pszStatus */
598 PACKS(desc
,"z",SERVICE(snum
)); /* pszQueue */
599 PACKS(desc
,"z","lpd"); /* pszQProcName */
600 PACKS(desc
,"z",""); /* pszQProcParms */
601 PACKS(desc
,"z","NULL"); /* pszDriverName */
602 PackDriverData(desc
); /* pDriverData */
603 PACKS(desc
,"z",""); /* pszPrinterName */
604 } else if (uLevel
== 4) { /* OS2 */
605 PACKS(desc
,"z",""); /* pszSpoolFileName */
606 PACKS(desc
,"z",""); /* pszPortName */
607 PACKS(desc
,"z",""); /* pszStatus */
608 PACKI(desc
,"D",0); /* ulPagesSpooled */
609 PACKI(desc
,"D",0); /* ulPagesSent */
610 PACKI(desc
,"D",0); /* ulPagesPrinted */
611 PACKI(desc
,"D",0); /* ulTimePrinted */
612 PACKI(desc
,"D",0); /* ulExtendJobStatus */
613 PACKI(desc
,"D",0); /* ulStartPage */
614 PACKI(desc
,"D",0); /* ulEndPage */
619 /********************************************************************
620 Return a driver name given an snum.
621 Returns True if from tdb, False otherwise.
622 ********************************************************************/
624 static bool get_driver_name(int snum
, char **pp_drivername
)
626 NT_PRINTER_INFO_LEVEL
*info
= NULL
;
629 get_a_printer (NULL
, &info
, 2, lp_servicename(snum
));
631 *pp_drivername
= talloc_strdup(talloc_tos(),
632 info
->info_2
->drivername
);
634 free_a_printer(&info
, 2);
635 if (!*pp_drivername
) {
643 /********************************************************************
644 Respond to the DosPrintQInfo command with a level of 52
645 This is used to get printer driver information for Win9x clients
646 ********************************************************************/
647 static void fill_printq_info_52(connection_struct
*conn
, int snum
,
648 struct pack_desc
* desc
, int count
)
652 struct spoolss_DriverInfo8
*driver
= NULL
;
653 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
655 if ( !W_ERROR_IS_OK(get_a_printer( NULL
, &printer
, 2, lp_servicename(snum
))) ) {
656 DEBUG(3,("fill_printq_info_52: Failed to lookup printer [%s]\n",
657 lp_servicename(snum
)));
661 if (!W_ERROR_IS_OK(get_a_printer_driver(talloc_tos(), &driver
, printer
->info_2
->drivername
,
664 DEBUG(3,("fill_printq_info_52: Failed to lookup driver [%s]\n",
665 printer
->info_2
->drivername
));
669 trim_string((char *)driver
->driver_path
, "\\print$\\WIN40\\0\\", 0);
670 trim_string((char *)driver
->data_file
, "\\print$\\WIN40\\0\\", 0);
671 trim_string((char *)driver
->help_file
, "\\print$\\WIN40\\0\\", 0);
673 PACKI(desc
, "W", 0x0400); /* don't know */
674 PACKS(desc
, "z", driver
->driver_name
); /* long printer name */
675 PACKS(desc
, "z", driver
->driver_path
); /* Driverfile Name */
676 PACKS(desc
, "z", driver
->data_file
); /* Datafile name */
677 PACKS(desc
, "z", driver
->monitor_name
); /* language monitor */
679 fstrcpy(location
, "\\\\%L\\print$\\WIN40\\0");
680 standard_sub_basic( "", "", location
, sizeof(location
)-1 );
681 PACKS(desc
,"z", location
); /* share to retrieve files */
683 PACKS(desc
,"z", driver
->default_datatype
); /* default data type */
684 PACKS(desc
,"z", driver
->help_file
); /* helpfile name */
685 PACKS(desc
,"z", driver
->driver_path
); /* driver name */
687 DEBUG(3,("Printer Driver Name: %s:\n",driver
->driver_name
));
688 DEBUG(3,("Driver: %s:\n",driver
->driver_path
));
689 DEBUG(3,("Data File: %s:\n",driver
->data_file
));
690 DEBUG(3,("Language Monitor: %s:\n",driver
->monitor_name
));
691 DEBUG(3,("Driver Location: %s:\n",location
));
692 DEBUG(3,("Data Type: %s:\n",driver
->default_datatype
));
693 DEBUG(3,("Help File: %s:\n",driver
->help_file
));
694 PACKI(desc
,"N",count
); /* number of files to copy */
696 for ( i
=0; i
<count
&& driver
->dependent_files
&& *driver
->dependent_files
[i
]; i
++)
698 trim_string((char *)driver
->dependent_files
[i
], "\\print$\\WIN40\\0\\", 0);
699 PACKS(desc
,"z",driver
->dependent_files
[i
]); /* driver files to copy */
700 DEBUG(3,("Dependent File: %s:\n", driver
->dependent_files
[i
]));
705 DEBUG(3,("fill_printq_info_52: file count specified by client [%d] != number of dependent files [%i]\n",
708 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n", SERVICE(snum
),i
));
710 desc
->errcode
=NERR_Success
;
714 DEBUG(3,("fill_printq_info: Can't supply driver files\n"));
715 desc
->errcode
=NERR_notsupported
;
719 free_a_printer( &printer
, 2 );
721 free_a_printer_driver(driver
);
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 struct spoolss_DriverInfo8
*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(talloc_tos(), &driver
, 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
->dependent_files
&& *driver
->dependent_files
[result
])
834 free_a_printer( &printer
, 2 );
836 free_a_printer_driver(driver
);
841 static bool api_DosPrintQGetInfo(connection_struct
*conn
, uint16 vuid
,
842 char *param
, int tpscnt
,
843 char *data
, int tdscnt
,
844 int mdrcnt
,int mprcnt
,
845 char **rdata
,char **rparam
,
846 int *rdata_len
,int *rparam_len
)
848 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
849 char *str2
= skip_string(param
,tpscnt
,str1
);
850 char *p
= skip_string(param
,tpscnt
,str2
);
856 struct pack_desc desc
;
857 print_queue_struct
*queue
=NULL
;
858 print_status_struct status
;
861 if (!str1
|| !str2
|| !p
) {
864 memset((char *)&status
,'\0',sizeof(status
));
865 memset((char *)&desc
,'\0',sizeof(desc
));
867 p
= skip_string(param
,tpscnt
,p
);
871 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
872 str3
= get_safe_str_ptr(param
,tpscnt
,p
,4);
873 /* str3 may be null here and is checked in check_printq_info(). */
875 /* remove any trailing username */
876 if ((p
= strchr_m(QueueName
,'%')))
879 DEBUG(3,("api_DosPrintQGetInfo uLevel=%d name=%s\n",uLevel
,QueueName
));
881 /* check it's a supported varient */
882 if (!prefix_ok(str1
,"zWrLh"))
884 if (!check_printq_info(&desc
,uLevel
,str2
,str3
)) {
886 * Patch from Scott Moomaw <scott@bridgewater.edu>
887 * to return the 'invalid info level' error if an
888 * unknown level was requested.
892 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
896 SSVALS(*rparam
,0,ERRunknownlevel
);
902 snum
= find_service(QueueName
);
903 if ( !(lp_snum_ok(snum
) && lp_print_ok(snum
)) )
907 count
= get_printerdrivernumber(snum
);
908 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count
));
910 count
= print_queue_status(snum
, &queue
,&status
);
914 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
920 desc
.buflen
= mdrcnt
;
923 * Don't return data but need to get correct length
924 * init_package will return wrong size if buflen=0
926 desc
.buflen
= getlen(desc
.format
);
927 desc
.base
= tmpdata
= (char *) SMB_MALLOC (desc
.buflen
);
930 if (init_package(&desc
,1,count
)) {
931 desc
.subcount
= count
;
932 fill_printq_info(conn
,snum
,uLevel
,&desc
,count
,queue
,&status
);
935 *rdata_len
= desc
.usedlen
;
938 * We must set the return code to ERRbuftoosmall
939 * in order to support lanman style printing with Win NT/2k
942 if (!mdrcnt
&& lp_disable_spoolss())
943 desc
.errcode
= ERRbuftoosmall
;
945 *rdata_len
= desc
.usedlen
;
947 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
953 SSVALS(*rparam
,0,desc
.errcode
);
955 SSVAL(*rparam
,4,desc
.neededlen
);
957 DEBUG(4,("printqgetinfo: errorcode %d\n",desc
.errcode
));
965 /****************************************************************************
966 View list of all print jobs on all queues.
967 ****************************************************************************/
969 static bool api_DosPrintQEnum(connection_struct
*conn
, uint16 vuid
,
970 char *param
, int tpscnt
,
971 char *data
, int tdscnt
,
972 int mdrcnt
, int mprcnt
,
973 char **rdata
, char** rparam
,
974 int *rdata_len
, int *rparam_len
)
976 char *param_format
= get_safe_str_ptr(param
,tpscnt
,param
,2);
977 char *output_format1
= skip_string(param
,tpscnt
,param_format
);
978 char *p
= skip_string(param
,tpscnt
,output_format1
);
979 unsigned int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
980 char *output_format2
= get_safe_str_ptr(param
,tpscnt
,p
,4);
981 int services
= lp_numservices();
983 struct pack_desc desc
;
984 print_queue_struct
**queue
= NULL
;
985 print_status_struct
*status
= NULL
;
986 int *subcntarr
= NULL
;
987 int queuecnt
= 0, subcnt
= 0, succnt
= 0;
989 if (!param_format
|| !output_format1
|| !p
) {
993 memset((char *)&desc
,'\0',sizeof(desc
));
995 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel
));
997 if (!prefix_ok(param_format
,"WrLeh")) {
1000 if (!check_printq_info(&desc
,uLevel
,output_format1
,output_format2
)) {
1002 * Patch from Scott Moomaw <scott@bridgewater.edu>
1003 * to return the 'invalid info level' error if an
1004 * unknown level was requested.
1008 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1012 SSVALS(*rparam
,0,ERRunknownlevel
);
1018 for (i
= 0; i
< services
; i
++) {
1019 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
)) {
1024 if((queue
= SMB_MALLOC_ARRAY(print_queue_struct
*, queuecnt
)) == NULL
) {
1025 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
1028 memset(queue
,0,queuecnt
*sizeof(print_queue_struct
*));
1029 if((status
= SMB_MALLOC_ARRAY(print_status_struct
,queuecnt
)) == NULL
) {
1030 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
1033 memset(status
,0,queuecnt
*sizeof(print_status_struct
));
1034 if((subcntarr
= SMB_MALLOC_ARRAY(int,queuecnt
)) == NULL
) {
1035 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
1041 for (i
= 0; i
< services
; i
++) {
1042 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
)) {
1043 subcntarr
[n
] = print_queue_status(i
, &queue
[n
],&status
[n
]);
1044 subcnt
+= subcntarr
[n
];
1050 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
1056 desc
.buflen
= mdrcnt
;
1058 if (init_package(&desc
,queuecnt
,subcnt
)) {
1061 for (i
= 0; i
< services
; i
++) {
1062 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
)) {
1063 fill_printq_info(conn
,i
,uLevel
,&desc
,subcntarr
[n
],queue
[n
],&status
[n
]);
1065 if (desc
.errcode
== NERR_Success
) {
1072 SAFE_FREE(subcntarr
);
1074 *rdata_len
= desc
.usedlen
;
1076 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1080 SSVALS(*rparam
,0,desc
.errcode
);
1082 SSVAL(*rparam
,4,succnt
);
1083 SSVAL(*rparam
,6,queuecnt
);
1085 for (i
= 0; i
< queuecnt
; i
++) {
1087 SAFE_FREE(queue
[i
]);
1098 SAFE_FREE(subcntarr
);
1099 for (i
= 0; i
< queuecnt
; i
++) {
1101 SAFE_FREE(queue
[i
]);
1110 /****************************************************************************
1111 Get info level for a server list query.
1112 ****************************************************************************/
1114 static bool check_server_info(int uLevel
, char* id
)
1118 if (strcmp(id
,"B16") != 0) {
1123 if (strcmp(id
,"B16BBDz") != 0) {
1133 struct srv_info_struct
{
1141 /*******************************************************************
1142 Get server info lists from the files saved by nmbd. Return the
1144 ******************************************************************/
1146 static int get_server_info(uint32 servertype
,
1147 struct srv_info_struct
**servers
,
1153 bool local_list_only
;
1156 lines
= file_lines_load(cache_path(SERVER_LIST
), NULL
, 0, NULL
);
1158 DEBUG(4,("Can't open %s - %s\n",cache_path(SERVER_LIST
),strerror(errno
)));
1162 /* request for everything is code for request all servers */
1163 if (servertype
== SV_TYPE_ALL
) {
1164 servertype
&= ~(SV_TYPE_DOMAIN_ENUM
|SV_TYPE_LOCAL_LIST_ONLY
);
1167 local_list_only
= (servertype
& SV_TYPE_LOCAL_LIST_ONLY
);
1169 DEBUG(4,("Servertype search: %8x\n",servertype
));
1171 for (i
=0;lines
[i
];i
++) {
1173 struct srv_info_struct
*s
;
1174 const char *ptr
= lines
[i
];
1176 TALLOC_CTX
*frame
= NULL
;
1183 if (count
== alloced
) {
1185 *servers
= SMB_REALLOC_ARRAY(*servers
,struct srv_info_struct
, alloced
);
1187 DEBUG(0,("get_server_info: failed to enlarge servers info struct!\n"));
1191 memset((char *)((*servers
)+count
),'\0',sizeof(**servers
)*(alloced
-count
));
1193 s
= &(*servers
)[count
];
1195 frame
= talloc_stackframe();
1197 if (!next_token_talloc(frame
,&ptr
,&p
, NULL
)) {
1201 fstrcpy(s
->name
, p
);
1204 if (!next_token_talloc(frame
,&ptr
, &p
, NULL
)) {
1210 s
->comment
[0] = '\0';
1211 if (!next_token_talloc(frame
,&ptr
, &p
, NULL
)) {
1215 fstrcpy(s
->comment
, p
);
1216 string_truncate(s
->comment
, MAX_SERVER_STRING_LENGTH
);
1218 s
->domain
[0] = '\0';
1219 if (!next_token_talloc(frame
,&ptr
,&p
, NULL
)) {
1220 /* this allows us to cope with an old nmbd */
1221 fstrcpy(s
->domain
,lp_workgroup());
1223 fstrcpy(s
->domain
, p
);
1227 if (sscanf(stype
,"%X",&s
->type
) != 1) {
1228 DEBUG(4,("r:host file "));
1232 /* Filter the servers/domains we return based on what was asked for. */
1234 /* Check to see if we are being asked for a local list only. */
1235 if(local_list_only
&& ((s
->type
& SV_TYPE_LOCAL_LIST_ONLY
) == 0)) {
1236 DEBUG(4,("r: local list only"));
1240 /* doesn't match up: don't want it */
1241 if (!(servertype
& s
->type
)) {
1242 DEBUG(4,("r:serv type "));
1246 if ((servertype
& SV_TYPE_DOMAIN_ENUM
) !=
1247 (s
->type
& SV_TYPE_DOMAIN_ENUM
)) {
1248 DEBUG(4,("s: dom mismatch "));
1252 if (!strequal(domain
, s
->domain
) && !(servertype
& SV_TYPE_DOMAIN_ENUM
)) {
1256 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1257 s
->type
&= ~SV_TYPE_LOCAL_LIST_ONLY
;
1260 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1261 s
->name
, s
->type
, s
->comment
, s
->domain
));
1262 s
->server_added
= True
;
1265 DEBUG(4,("%20s %8x %25s %15s\n",
1266 s
->name
, s
->type
, s
->comment
, s
->domain
));
1274 /*******************************************************************
1275 Fill in a server info structure.
1276 ******************************************************************/
1278 static int fill_srv_info(struct srv_info_struct
*service
,
1279 int uLevel
, char **buf
, int *buflen
,
1280 char **stringbuf
, int *stringspace
, char *baseaddr
)
1303 len
= strlen(service
->comment
)+1;
1307 *buflen
= struct_len
;
1309 return struct_len
+ len
;
1314 if (*buflen
< struct_len
) {
1321 p2
= p
+ struct_len
;
1322 l2
= *buflen
- struct_len
;
1330 push_ascii(p
,service
->name
, MAX_NETBIOSNAME_LEN
, STR_TERMINATE
);
1334 push_ascii(p
,service
->name
,MAX_NETBIOSNAME_LEN
, STR_TERMINATE
);
1335 SIVAL(p
,18,service
->type
);
1336 SIVAL(p
,22,PTR_DIFF(p2
,baseaddr
));
1337 len
+= CopyAndAdvance(&p2
,service
->comment
,&l2
);
1342 *buf
= p
+ struct_len
;
1343 *buflen
-= struct_len
;
1354 static int srv_comp(struct srv_info_struct
*s1
,struct srv_info_struct
*s2
)
1356 return StrCaseCmp(s1
->name
,s2
->name
);
1359 /****************************************************************************
1360 View list of servers available (or possibly domains). The info is
1361 extracted from lists saved by nmbd on the local host.
1362 ****************************************************************************/
1364 static bool api_RNetServerEnum2(connection_struct
*conn
, uint16 vuid
,
1365 char *param
, int tpscnt
,
1366 char *data
, int tdscnt
,
1367 int mdrcnt
, int mprcnt
, char **rdata
,
1368 char **rparam
, int *rdata_len
, int *rparam_len
)
1370 char *str1
= get_safe_str_ptr(param
, tpscnt
, param
, 2);
1371 char *str2
= skip_string(param
,tpscnt
,str1
);
1372 char *p
= skip_string(param
,tpscnt
,str2
);
1373 int uLevel
= get_safe_SVAL(param
, tpscnt
, p
, 0, -1);
1374 int buf_len
= get_safe_SVAL(param
,tpscnt
, p
, 2, 0);
1375 uint32 servertype
= get_safe_IVAL(param
,tpscnt
,p
,4, 0);
1377 int data_len
, fixed_len
, string_len
;
1378 int f_len
= 0, s_len
= 0;
1379 struct srv_info_struct
*servers
=NULL
;
1380 int counted
=0,total
=0;
1383 bool domain_request
;
1386 if (!str1
|| !str2
|| !p
) {
1390 /* If someone sets all the bits they don't really mean to set
1391 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1394 if (servertype
== SV_TYPE_ALL
) {
1395 servertype
&= ~(SV_TYPE_DOMAIN_ENUM
|SV_TYPE_LOCAL_LIST_ONLY
);
1398 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1399 any other bit (they may just set this bit on its own) they
1400 want all the locally seen servers. However this bit can be
1401 set on its own so set the requested servers to be
1402 ALL - DOMAIN_ENUM. */
1404 if ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) && !(servertype
& SV_TYPE_DOMAIN_ENUM
)) {
1405 servertype
= SV_TYPE_ALL
& ~(SV_TYPE_DOMAIN_ENUM
);
1408 domain_request
= ((servertype
& SV_TYPE_DOMAIN_ENUM
) != 0);
1409 local_request
= ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) != 0);
1413 if (!prefix_ok(str1
,"WrLehD")) {
1416 if (!check_server_info(uLevel
,str2
)) {
1420 DEBUG(4, ("server request level: %s %8x ", str2
, servertype
));
1421 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request
)));
1422 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request
)));
1424 if (strcmp(str1
, "WrLehDz") == 0) {
1425 if (skip_string(param
,tpscnt
,p
) == NULL
) {
1428 pull_ascii_fstring(domain
, p
);
1430 fstrcpy(domain
, lp_workgroup());
1433 DEBUG(4, ("domain [%s]\n", domain
));
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[%d] %20s %8x %25s %15s\n",
1458 i
, 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[%d] %20s %8x %25s %15s\n",
1494 i
, 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,("NetServerEnum2 domain = %s uLevel=%d counted=%d total=%d\n",
1512 domain
,uLevel
,counted
,counted
+missed
));
1517 static int srv_name_match(const char *n1
, const char *n2
)
1520 * [MS-RAP] footnote <88> for Section 3.2.5.15 says:
1522 * In Windows, FirstNameToReturn need not be an exact match:
1523 * the server will return a list of servers that exist on
1524 * the network greater than or equal to the FirstNameToReturn.
1526 int ret
= StrCaseCmp(n1
, n2
);
1535 static bool api_RNetServerEnum3(connection_struct
*conn
, uint16 vuid
,
1536 char *param
, int tpscnt
,
1537 char *data
, int tdscnt
,
1538 int mdrcnt
, int mprcnt
, char **rdata
,
1539 char **rparam
, int *rdata_len
, int *rparam_len
)
1541 char *str1
= get_safe_str_ptr(param
, tpscnt
, param
, 2);
1542 char *str2
= skip_string(param
,tpscnt
,str1
);
1543 char *p
= skip_string(param
,tpscnt
,str2
);
1544 int uLevel
= get_safe_SVAL(param
, tpscnt
, p
, 0, -1);
1545 int buf_len
= get_safe_SVAL(param
,tpscnt
, p
, 2, 0);
1546 uint32 servertype
= get_safe_IVAL(param
,tpscnt
,p
,4, 0);
1548 int data_len
, fixed_len
, string_len
;
1549 int f_len
= 0, s_len
= 0;
1550 struct srv_info_struct
*servers
=NULL
;
1551 int counted
=0,first
=0,total
=0;
1555 bool domain_request
;
1558 if (!str1
|| !str2
|| !p
) {
1562 /* If someone sets all the bits they don't really mean to set
1563 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1566 if (servertype
== SV_TYPE_ALL
) {
1567 servertype
&= ~(SV_TYPE_DOMAIN_ENUM
|SV_TYPE_LOCAL_LIST_ONLY
);
1570 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1571 any other bit (they may just set this bit on its own) they
1572 want all the locally seen servers. However this bit can be
1573 set on its own so set the requested servers to be
1574 ALL - DOMAIN_ENUM. */
1576 if ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) && !(servertype
& SV_TYPE_DOMAIN_ENUM
)) {
1577 servertype
= SV_TYPE_ALL
& ~(SV_TYPE_DOMAIN_ENUM
);
1580 domain_request
= ((servertype
& SV_TYPE_DOMAIN_ENUM
) != 0);
1581 local_request
= ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) != 0);
1585 if (strcmp(str1
, "WrLehDzz") != 0) {
1588 if (!check_server_info(uLevel
,str2
)) {
1592 DEBUG(4, ("server request level: %s %8x ", str2
, servertype
));
1593 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request
)));
1594 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request
)));
1596 if (skip_string(param
,tpscnt
,p
) == NULL
) {
1599 pull_ascii_fstring(domain
, p
);
1600 if (domain
[0] == '\0') {
1601 fstrcpy(domain
, lp_workgroup());
1603 p
= skip_string(param
,tpscnt
,p
);
1604 if (skip_string(param
,tpscnt
,p
) == NULL
) {
1607 pull_ascii_fstring(first_name
, p
);
1609 DEBUG(4, ("domain: '%s' first_name: '%s'\n",
1610 domain
, first_name
));
1612 if (lp_browse_list()) {
1613 total
= get_server_info(servertype
,&servers
,domain
);
1616 data_len
= fixed_len
= string_len
= 0;
1620 qsort(servers
,total
,sizeof(servers
[0]),QSORT_CAST srv_comp
);
1623 if (first_name
[0] != '\0') {
1624 struct srv_info_struct
*first_server
= NULL
;
1626 BINARY_ARRAY_SEARCH(servers
, total
, name
, first_name
,
1627 srv_name_match
, first_server
);
1629 first
= PTR_DIFF(first_server
, servers
) / sizeof(*servers
);
1631 * The binary search may not find the exact match
1632 * so we need to search backward to find the first match
1634 * This implements the strange matching windows
1635 * implements. (see the comment in srv_name_match().
1639 ret
= StrCaseCmp(first_name
,
1640 servers
[first
-1].name
);
1647 /* we should return no entries */
1653 char *lastname
=NULL
;
1655 for (i
=first
;i
<total
;i
++) {
1656 struct srv_info_struct
*s
= &servers
[i
];
1658 if (lastname
&& strequal(lastname
,s
->name
)) {
1662 data_len
+= fill_srv_info(s
,uLevel
,0,&f_len
,0,&s_len
,0);
1663 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1664 i
, s
->name
, s
->type
, s
->comment
, s
->domain
));
1666 if (data_len
<= buf_len
) {
1669 string_len
+= s_len
;
1676 *rdata_len
= fixed_len
+ string_len
;
1677 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
1682 p2
= (*rdata
) + fixed_len
; /* auxilliary data (strings) will go here */
1688 char *lastname
=NULL
;
1689 int count2
= counted
;
1691 for (i
= first
; i
< total
&& count2
;i
++) {
1692 struct srv_info_struct
*s
= &servers
[i
];
1694 if (lastname
&& strequal(lastname
,s
->name
)) {
1698 fill_srv_info(s
,uLevel
,&p
,&f_len
,&p2
,&s_len
,*rdata
);
1699 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1700 i
, s
->name
, s
->type
, s
->comment
, s
->domain
));
1706 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1710 SSVAL(*rparam
,0,(missed
== 0 ? NERR_Success
: ERRmoredata
));
1712 SSVAL(*rparam
,4,counted
);
1713 SSVAL(*rparam
,6,counted
+missed
);
1715 DEBUG(3,("NetServerEnum3 domain = %s uLevel=%d first=%d[%s => %s] counted=%d total=%d\n",
1716 domain
,uLevel
,first
,first_name
,
1717 first
< total
? servers
[first
].name
: "",
1718 counted
,counted
+missed
));
1725 /****************************************************************************
1726 command 0x34 - suspected of being a "Lookup Names" stub api
1727 ****************************************************************************/
1729 static bool api_RNetGroupGetUsers(connection_struct
*conn
, uint16 vuid
,
1730 char *param
, int tpscnt
,
1731 char *data
, int tdscnt
,
1732 int mdrcnt
, int mprcnt
, char **rdata
,
1733 char **rparam
, int *rdata_len
, int *rparam_len
)
1735 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
1736 char *str2
= skip_string(param
,tpscnt
,str1
);
1737 char *p
= skip_string(param
,tpscnt
,str2
);
1738 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
1739 int buf_len
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
1743 if (!str1
|| !str2
|| !p
) {
1747 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1748 str1
, str2
, p
, uLevel
, buf_len
));
1750 if (!prefix_ok(str1
,"zWrLeh")) {
1757 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1762 SSVAL(*rparam
,0,0x08AC); /* informational warning message */
1764 SSVAL(*rparam
,4,counted
);
1765 SSVAL(*rparam
,6,counted
+missed
);
1770 /****************************************************************************
1771 get info about a share
1772 ****************************************************************************/
1774 static bool check_share_info(int uLevel
, char* id
)
1778 if (strcmp(id
,"B13") != 0) {
1783 /* Level-2 descriptor is allowed (and ignored) */
1784 if (strcmp(id
,"B13BWz") != 0 &&
1785 strcmp(id
,"B13BWzWWWzB9B") != 0) {
1790 if (strcmp(id
,"B13BWzWWWzB9B") != 0) {
1795 if (strcmp(id
,"B13BWzWWWzB9BB9BWzWWzWW") != 0) {
1805 static int fill_share_info(connection_struct
*conn
, int snum
, int uLevel
,
1806 char** buf
, int* buflen
,
1807 char** stringbuf
, int* stringspace
, char* baseaddr
)
1836 len
+= StrlenExpanded(conn
,snum
,lp_comment(snum
));
1839 len
+= strlen(lp_pathname(snum
)) + 1;
1842 *buflen
= struct_len
;
1847 return struct_len
+ len
;
1852 if ((*buflen
) < struct_len
) {
1860 p2
= p
+ struct_len
;
1861 l2
= (*buflen
) - struct_len
;
1868 push_ascii(p
,lp_servicename(snum
),13, STR_TERMINATE
);
1874 type
= STYPE_DISKTREE
;
1875 if (lp_print_ok(snum
)) {
1876 type
= STYPE_PRINTQ
;
1878 if (strequal("IPC",lp_fstype(snum
))) {
1881 SSVAL(p
,14,type
); /* device type */
1882 SIVAL(p
,16,PTR_DIFF(p2
,baseaddr
));
1883 len
+= CopyExpanded(conn
,snum
,&p2
,lp_comment(snum
),&l2
);
1887 SSVAL(p
,20,ACCESS_READ
|ACCESS_WRITE
|ACCESS_CREATE
); /* permissions */
1888 SSVALS(p
,22,-1); /* max uses */
1889 SSVAL(p
,24,1); /* current uses */
1890 SIVAL(p
,26,PTR_DIFF(p2
,baseaddr
)); /* local pathname */
1891 len
+= CopyAndAdvance(&p2
,lp_pathname(snum
),&l2
);
1892 memset(p
+30,0,SHPWLEN
+2); /* passwd (reserved), pad field */
1896 memset(p
+40,0,SHPWLEN
+2);
1907 (*buf
) = p
+ struct_len
;
1908 (*buflen
) -= struct_len
;
1910 (*stringspace
) = l2
;
1919 static bool api_RNetShareGetInfo(connection_struct
*conn
,uint16 vuid
,
1920 char *param
, int tpscnt
,
1921 char *data
, int tdscnt
,
1922 int mdrcnt
,int mprcnt
,
1923 char **rdata
,char **rparam
,
1924 int *rdata_len
,int *rparam_len
)
1926 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
1927 char *str2
= skip_string(param
,tpscnt
,str1
);
1928 char *netname
= skip_string(param
,tpscnt
,str2
);
1929 char *p
= skip_string(param
,tpscnt
,netname
);
1930 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
1933 if (!str1
|| !str2
|| !netname
|| !p
) {
1937 snum
= find_service(netname
);
1942 /* check it's a supported varient */
1943 if (!prefix_ok(str1
,"zWrLh")) {
1946 if (!check_share_info(uLevel
,str2
)) {
1950 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
1955 *rdata_len
= fill_share_info(conn
,snum
,uLevel
,&p
,&mdrcnt
,0,0,0);
1956 if (*rdata_len
< 0) {
1961 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1965 SSVAL(*rparam
,0,NERR_Success
);
1966 SSVAL(*rparam
,2,0); /* converter word */
1967 SSVAL(*rparam
,4,*rdata_len
);
1972 /****************************************************************************
1973 View the list of available shares.
1975 This function is the server side of the NetShareEnum() RAP call.
1976 It fills the return buffer with share names and share comments.
1977 Note that the return buffer normally (in all known cases) allows only
1978 twelve byte strings for share names (plus one for a nul terminator).
1979 Share names longer than 12 bytes must be skipped.
1980 ****************************************************************************/
1982 static bool api_RNetShareEnum( connection_struct
*conn
, uint16 vuid
,
1983 char *param
, int tpscnt
,
1984 char *data
, int tdscnt
,
1992 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
1993 char *str2
= skip_string(param
,tpscnt
,str1
);
1994 char *p
= skip_string(param
,tpscnt
,str2
);
1995 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
1996 int buf_len
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
1999 int total
=0,counted
=0;
2000 bool missed
= False
;
2002 int data_len
, fixed_len
, string_len
;
2003 int f_len
= 0, s_len
= 0;
2005 if (!str1
|| !str2
|| !p
) {
2009 if (!prefix_ok(str1
,"WrLeh")) {
2012 if (!check_share_info(uLevel
,str2
)) {
2016 /* Ensure all the usershares are loaded. */
2018 load_registry_shares();
2019 count
= load_usershare_shares();
2022 data_len
= fixed_len
= string_len
= 0;
2023 for (i
=0;i
<count
;i
++) {
2024 fstring servicename_dos
;
2025 if (!(lp_browseable(i
) && lp_snum_ok(i
))) {
2028 push_ascii_fstring(servicename_dos
, lp_servicename(i
));
2029 /* Maximum name length = 13. */
2030 if( lp_browseable( i
) && lp_snum_ok( i
) && (strlen(servicename_dos
) < 13)) {
2032 data_len
+= fill_share_info(conn
,i
,uLevel
,0,&f_len
,0,&s_len
,0);
2033 if (data_len
<= buf_len
) {
2036 string_len
+= s_len
;
2043 *rdata_len
= fixed_len
+ string_len
;
2044 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2049 p2
= (*rdata
) + fixed_len
; /* auxiliary data (strings) will go here */
2054 for( i
= 0; i
< count
; i
++ ) {
2055 fstring servicename_dos
;
2056 if (!(lp_browseable(i
) && lp_snum_ok(i
))) {
2060 push_ascii_fstring(servicename_dos
, lp_servicename(i
));
2061 if (lp_browseable(i
) && lp_snum_ok(i
) && (strlen(servicename_dos
) < 13)) {
2062 if (fill_share_info( conn
,i
,uLevel
,&p
,&f_len
,&p2
,&s_len
,*rdata
) < 0) {
2069 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2073 SSVAL(*rparam
,0,missed
? ERRmoredata
: NERR_Success
);
2075 SSVAL(*rparam
,4,counted
);
2076 SSVAL(*rparam
,6,total
);
2078 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
2079 counted
,total
,uLevel
,
2080 buf_len
,*rdata_len
,mdrcnt
));
2085 /****************************************************************************
2087 ****************************************************************************/
2089 static bool api_RNetShareAdd(connection_struct
*conn
,uint16 vuid
,
2090 char *param
, int tpscnt
,
2091 char *data
, int tdscnt
,
2092 int mdrcnt
,int mprcnt
,
2093 char **rdata
,char **rparam
,
2094 int *rdata_len
,int *rparam_len
)
2096 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2097 char *str2
= skip_string(param
,tpscnt
,str1
);
2098 char *p
= skip_string(param
,tpscnt
,str2
);
2099 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2102 char *pathname
= NULL
;
2103 char *command
, *cmdname
;
2104 unsigned int offset
;
2107 size_t converted_size
;
2109 if (!str1
|| !str2
|| !p
) {
2113 /* check it's a supported varient */
2114 if (!prefix_ok(str1
,RAP_WShareAdd_REQ
)) {
2117 if (!check_share_info(uLevel
,str2
)) {
2124 /* Do we have a string ? */
2125 if (skip_string(data
,mdrcnt
,data
) == NULL
) {
2128 pull_ascii_fstring(sharename
,data
);
2129 snum
= find_service(sharename
);
2130 if (snum
>= 0) { /* already exists */
2139 /* only support disk share adds */
2140 if (SVAL(data
,14)!=STYPE_DISKTREE
) {
2144 offset
= IVAL(data
, 16);
2145 if (offset
>= mdrcnt
) {
2146 res
= ERRinvalidparam
;
2150 /* Do we have a string ? */
2151 if (skip_string(data
,mdrcnt
,data
+offset
) == NULL
) {
2154 pull_ascii_fstring(comment
, offset
? (data
+offset
) : "");
2156 offset
= IVAL(data
, 26);
2158 if (offset
>= mdrcnt
) {
2159 res
= ERRinvalidparam
;
2163 /* Do we have a string ? */
2164 if (skip_string(data
,mdrcnt
,data
+offset
) == NULL
) {
2168 if (!pull_ascii_talloc(talloc_tos(), &pathname
,
2169 offset
? (data
+offset
) : "", &converted_size
))
2171 DEBUG(0,("api_RNetShareAdd: pull_ascii_talloc failed: %s",
2179 string_replace(sharename
, '"', ' ');
2180 string_replace(pathname
, '"', ' ');
2181 string_replace(comment
, '"', ' ');
2183 cmdname
= lp_add_share_cmd();
2185 if (!cmdname
|| *cmdname
== '\0') {
2189 if (asprintf(&command
, "%s \"%s\" \"%s\" \"%s\" \"%s\"",
2190 lp_add_share_cmd(), get_dyn_CONFIGFILE(), sharename
,
2191 pathname
, comment
) == -1) {
2195 DEBUG(10,("api_RNetShareAdd: Running [%s]\n", command
));
2197 if ((res
= smbrun(command
, NULL
)) != 0) {
2198 DEBUG(1,("api_RNetShareAdd: Running [%s] returned (%d)\n",
2205 message_send_all(smbd_messaging_context(),
2206 MSG_SMB_CONF_UPDATED
, NULL
, 0, NULL
);
2210 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2214 SSVAL(*rparam
,0,NERR_Success
);
2215 SSVAL(*rparam
,2,0); /* converter word */
2216 SSVAL(*rparam
,4,*rdata_len
);
2224 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2229 SSVAL(*rparam
,0,res
);
2234 /****************************************************************************
2235 view list of groups available
2236 ****************************************************************************/
2238 static bool api_RNetGroupEnum(connection_struct
*conn
,uint16 vuid
,
2239 char *param
, int tpscnt
,
2240 char *data
, int tdscnt
,
2241 int mdrcnt
,int mprcnt
,
2242 char **rdata
,char **rparam
,
2243 int *rdata_len
,int *rparam_len
)
2247 int resume_context
, cli_buf_size
;
2248 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2249 char *str2
= skip_string(param
,tpscnt
,str1
);
2250 char *p
= skip_string(param
,tpscnt
,str2
);
2252 uint32_t num_groups
;
2253 uint32_t resume_handle
;
2254 struct rpc_pipe_client
*samr_pipe
;
2255 struct policy_handle samr_handle
, domain_handle
;
2258 if (!str1
|| !str2
|| !p
) {
2262 if (strcmp(str1
,"WrLeh") != 0) {
2267 * W-> resume context (number of users to skip)
2268 * r -> return parameter pointer to receive buffer
2269 * L -> length of receive buffer
2270 * e -> return parameter number of entries
2271 * h -> return parameter total number of users
2274 if (strcmp("B21",str2
) != 0) {
2278 status
= rpc_pipe_open_internal(
2279 talloc_tos(), &ndr_table_samr
.syntax_id
, rpc_samr_dispatch
,
2280 conn
->server_info
, &samr_pipe
);
2281 if (!NT_STATUS_IS_OK(status
)) {
2282 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2283 nt_errstr(status
)));
2287 status
= rpccli_samr_Connect2(samr_pipe
, talloc_tos(), global_myname(),
2288 SAMR_ACCESS_LOOKUP_DOMAIN
, &samr_handle
);
2289 if (!NT_STATUS_IS_OK(status
)) {
2290 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2291 nt_errstr(status
)));
2295 status
= rpccli_samr_OpenDomain(samr_pipe
, talloc_tos(), &samr_handle
,
2296 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS
,
2297 get_global_sam_sid(), &domain_handle
);
2298 if (!NT_STATUS_IS_OK(status
)) {
2299 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2300 nt_errstr(status
)));
2301 rpccli_samr_Close(samr_pipe
, talloc_tos(), &samr_handle
);
2305 resume_context
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2306 cli_buf_size
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
2307 DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: "
2308 "%d\n", resume_context
, cli_buf_size
));
2310 *rdata_len
= cli_buf_size
;
2311 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2318 errflags
= NERR_Success
;
2323 struct samr_SamArray
*sam_entries
;
2324 uint32_t num_entries
;
2326 status
= rpccli_samr_EnumDomainGroups(samr_pipe
, talloc_tos(),
2331 if (!NT_STATUS_IS_OK(status
)) {
2332 DEBUG(10, ("rpccli_samr_EnumDomainGroups returned "
2333 "%s\n", nt_errstr(status
)));
2337 if (num_entries
== 0) {
2338 DEBUG(10, ("rpccli_samr_EnumDomainGroups returned "
2339 "no entries -- done\n"));
2343 for(i
=0; i
<num_entries
; i
++) {
2346 name
= sam_entries
->entries
[i
].name
.string
;
2348 if( ((PTR_DIFF(p
,*rdata
)+21) > *rdata_len
) ) {
2349 /* set overflow error */
2350 DEBUG(3,("overflow on entry %d group %s\n", i
,
2356 /* truncate the name at 21 chars. */
2358 strlcpy(p
, name
, 21);
2359 DEBUG(10,("adding entry %d group %s\n", i
, p
));
2361 p
+= 5; /* Both NT4 and W2k3SP1 do padding here. No
2366 if (errflags
!= NERR_Success
) {
2370 TALLOC_FREE(sam_entries
);
2373 rpccli_samr_Close(samr_pipe
, talloc_tos(), &domain_handle
);
2374 rpccli_samr_Close(samr_pipe
, talloc_tos(), &samr_handle
);
2376 *rdata_len
= PTR_DIFF(p
,*rdata
);
2379 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2383 SSVAL(*rparam
, 0, errflags
);
2384 SSVAL(*rparam
, 2, 0); /* converter word */
2385 SSVAL(*rparam
, 4, num_groups
); /* is this right?? */
2386 SSVAL(*rparam
, 6, resume_context
+num_groups
); /* is this right?? */
2391 /*******************************************************************
2392 Get groups that a user is a member of.
2393 ******************************************************************/
2395 static bool api_NetUserGetGroups(connection_struct
*conn
,uint16 vuid
,
2396 char *param
, int tpscnt
,
2397 char *data
, int tdscnt
,
2398 int mdrcnt
,int mprcnt
,
2399 char **rdata
,char **rparam
,
2400 int *rdata_len
,int *rparam_len
)
2402 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2403 char *str2
= skip_string(param
,tpscnt
,str1
);
2404 char *UserName
= skip_string(param
,tpscnt
,str2
);
2405 char *p
= skip_string(param
,tpscnt
,UserName
);
2406 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2407 const char *level_string
;
2413 struct rpc_pipe_client
*samr_pipe
;
2414 struct policy_handle samr_handle
, domain_handle
, user_handle
;
2415 struct lsa_String name
;
2416 struct lsa_Strings names
;
2417 struct samr_Ids type
, rid
;
2418 struct samr_RidWithAttributeArray
*rids
;
2421 if (!str1
|| !str2
|| !UserName
|| !p
) {
2426 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2431 /* check it's a supported varient */
2433 if ( strcmp(str1
,"zWrLeh") != 0 )
2438 level_string
= "B21";
2444 if (strcmp(level_string
,str2
) != 0)
2447 *rdata_len
= mdrcnt
+ 1024;
2448 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2453 SSVAL(*rparam
,0,NERR_Success
);
2454 SSVAL(*rparam
,2,0); /* converter word */
2457 endp
= *rdata
+ *rdata_len
;
2459 status
= rpc_pipe_open_internal(
2460 talloc_tos(), &ndr_table_samr
.syntax_id
, rpc_samr_dispatch
,
2461 conn
->server_info
, &samr_pipe
);
2462 if (!NT_STATUS_IS_OK(status
)) {
2463 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2464 nt_errstr(status
)));
2468 status
= rpccli_samr_Connect2(samr_pipe
, talloc_tos(), global_myname(),
2469 SAMR_ACCESS_LOOKUP_DOMAIN
, &samr_handle
);
2470 if (!NT_STATUS_IS_OK(status
)) {
2471 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2472 nt_errstr(status
)));
2476 status
= rpccli_samr_OpenDomain(samr_pipe
, talloc_tos(), &samr_handle
,
2477 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT
,
2478 get_global_sam_sid(), &domain_handle
);
2479 if (!NT_STATUS_IS_OK(status
)) {
2480 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2481 nt_errstr(status
)));
2485 name
.string
= UserName
;
2487 status
= rpccli_samr_LookupNames(samr_pipe
, talloc_tos(),
2488 &domain_handle
, 1, &name
,
2490 if (!NT_STATUS_IS_OK(status
)) {
2491 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2492 nt_errstr(status
)));
2496 if (type
.ids
[0] != SID_NAME_USER
) {
2497 DEBUG(10, ("%s is a %s, not a user\n", UserName
,
2498 sid_type_lookup(type
.ids
[0])));
2502 status
= rpccli_samr_OpenUser(samr_pipe
, talloc_tos(),
2504 SAMR_USER_ACCESS_GET_GROUPS
,
2505 rid
.ids
[0], &user_handle
);
2506 if (!NT_STATUS_IS_OK(status
)) {
2507 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2508 nt_errstr(status
)));
2512 status
= rpccli_samr_GetGroupsForUser(samr_pipe
, talloc_tos(),
2513 &user_handle
, &rids
);
2514 if (!NT_STATUS_IS_OK(status
)) {
2515 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2516 nt_errstr(status
)));
2520 for (i
=0; i
<rids
->count
; i
++) {
2522 status
= rpccli_samr_LookupRids(samr_pipe
, talloc_tos(),
2524 1, &rids
->rids
[i
].rid
,
2526 if (NT_STATUS_IS_OK(status
) && (names
.count
== 1)) {
2527 strlcpy(p
, names
.names
[0].string
, PTR_DIFF(endp
,p
));
2533 *rdata_len
= PTR_DIFF(p
,*rdata
);
2535 SSVAL(*rparam
,4,count
); /* is this right?? */
2536 SSVAL(*rparam
,6,count
); /* is this right?? */
2541 rpccli_samr_Close(samr_pipe
, talloc_tos(), &user_handle
);
2543 rpccli_samr_Close(samr_pipe
, talloc_tos(), &domain_handle
);
2545 rpccli_samr_Close(samr_pipe
, talloc_tos(), &samr_handle
);
2550 /*******************************************************************
2552 ******************************************************************/
2554 static bool api_RNetUserEnum(connection_struct
*conn
, uint16 vuid
,
2555 char *param
, int tpscnt
,
2556 char *data
, int tdscnt
,
2557 int mdrcnt
,int mprcnt
,
2558 char **rdata
,char **rparam
,
2559 int *rdata_len
,int *rparam_len
)
2564 int i
, resume_context
, cli_buf_size
;
2565 uint32_t resume_handle
;
2567 struct rpc_pipe_client
*samr_pipe
;
2568 struct policy_handle samr_handle
, domain_handle
;
2571 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2572 char *str2
= skip_string(param
,tpscnt
,str1
);
2573 char *p
= skip_string(param
,tpscnt
,str2
);
2576 if (!str1
|| !str2
|| !p
) {
2580 if (strcmp(str1
,"WrLeh") != 0)
2583 * W-> resume context (number of users to skip)
2584 * r -> return parameter pointer to receive buffer
2585 * L -> length of receive buffer
2586 * e -> return parameter number of entries
2587 * h -> return parameter total number of users
2590 resume_context
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2591 cli_buf_size
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
2592 DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n",
2593 resume_context
, cli_buf_size
));
2596 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2601 /* check it's a supported varient */
2602 if (strcmp("B21",str2
) != 0)
2605 *rdata_len
= cli_buf_size
;
2606 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2612 endp
= *rdata
+ *rdata_len
;
2614 status
= rpc_pipe_open_internal(
2615 talloc_tos(), &ndr_table_samr
.syntax_id
, rpc_samr_dispatch
,
2616 conn
->server_info
, &samr_pipe
);
2617 if (!NT_STATUS_IS_OK(status
)) {
2618 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2619 nt_errstr(status
)));
2623 status
= rpccli_samr_Connect2(samr_pipe
, talloc_tos(), global_myname(),
2624 SAMR_ACCESS_LOOKUP_DOMAIN
, &samr_handle
);
2625 if (!NT_STATUS_IS_OK(status
)) {
2626 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2627 nt_errstr(status
)));
2631 status
= rpccli_samr_OpenDomain(samr_pipe
, talloc_tos(), &samr_handle
,
2632 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS
,
2633 get_global_sam_sid(), &domain_handle
);
2634 if (!NT_STATUS_IS_OK(status
)) {
2635 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2636 nt_errstr(status
)));
2637 rpccli_samr_Close(samr_pipe
, talloc_tos(), &samr_handle
);
2641 errflags
=NERR_Success
;
2646 struct samr_SamArray
*sam_entries
;
2647 uint32_t num_entries
;
2649 status
= rpccli_samr_EnumDomainUsers(samr_pipe
, talloc_tos(),
2655 if (!NT_STATUS_IS_OK(status
)) {
2656 DEBUG(10, ("rpccli_samr_EnumDomainUsers returned "
2657 "%s\n", nt_errstr(status
)));
2661 if (num_entries
== 0) {
2662 DEBUG(10, ("rpccli_samr_EnumDomainUsers returned "
2663 "no entries -- done\n"));
2667 for (i
=0; i
<num_entries
; i
++) {
2670 name
= sam_entries
->entries
[i
].name
.string
;
2672 if(((PTR_DIFF(p
,*rdata
)+21)<=*rdata_len
)
2673 &&(strlen(name
)<=21)) {
2674 strlcpy(p
,name
,PTR_DIFF(endp
,p
));
2675 DEBUG(10,("api_RNetUserEnum:adding entry %d "
2676 "username %s\n",count_sent
,p
));
2680 /* set overflow error */
2681 DEBUG(10,("api_RNetUserEnum:overflow on entry %d "
2682 "username %s\n",count_sent
,name
));
2688 if (errflags
!= NERR_Success
) {
2692 TALLOC_FREE(sam_entries
);
2695 rpccli_samr_Close(samr_pipe
, talloc_tos(), &domain_handle
);
2696 rpccli_samr_Close(samr_pipe
, talloc_tos(), &samr_handle
);
2698 *rdata_len
= PTR_DIFF(p
,*rdata
);
2700 SSVAL(*rparam
,0,errflags
);
2701 SSVAL(*rparam
,2,0); /* converter word */
2702 SSVAL(*rparam
,4,count_sent
); /* is this right?? */
2703 SSVAL(*rparam
,6,num_users
); /* is this right?? */
2708 /****************************************************************************
2709 Get the time of day info.
2710 ****************************************************************************/
2712 static bool api_NetRemoteTOD(connection_struct
*conn
,uint16 vuid
,
2713 char *param
, int tpscnt
,
2714 char *data
, int tdscnt
,
2715 int mdrcnt
,int mprcnt
,
2716 char **rdata
,char **rparam
,
2717 int *rdata_len
,int *rparam_len
)
2720 time_t unixdate
= time(NULL
);
2724 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2730 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2735 SSVAL(*rparam
,0,NERR_Success
);
2736 SSVAL(*rparam
,2,0); /* converter word */
2740 srv_put_dos_date3(p
,0,unixdate
); /* this is the time that is looked at
2741 by NT in a "net time" operation,
2742 it seems to ignore the one below */
2744 /* the client expects to get localtime, not GMT, in this bit
2745 (I think, this needs testing) */
2746 t
= localtime(&unixdate
);
2751 SIVAL(p
,4,0); /* msecs ? */
2752 SCVAL(p
,8,t
->tm_hour
);
2753 SCVAL(p
,9,t
->tm_min
);
2754 SCVAL(p
,10,t
->tm_sec
);
2755 SCVAL(p
,11,0); /* hundredths of seconds */
2756 SSVALS(p
,12,get_time_zone(unixdate
)/60); /* timezone in minutes from GMT */
2757 SSVAL(p
,14,10000); /* timer interval in 0.0001 of sec */
2758 SCVAL(p
,16,t
->tm_mday
);
2759 SCVAL(p
,17,t
->tm_mon
+ 1);
2760 SSVAL(p
,18,1900+t
->tm_year
);
2761 SCVAL(p
,20,t
->tm_wday
);
2766 /****************************************************************************
2767 Set the user password.
2768 *****************************************************************************/
2770 static bool api_SetUserPassword(connection_struct
*conn
,uint16 vuid
,
2771 char *param
, int tpscnt
,
2772 char *data
, int tdscnt
,
2773 int mdrcnt
,int mprcnt
,
2774 char **rdata
,char **rparam
,
2775 int *rdata_len
,int *rparam_len
)
2777 char *np
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2780 fstring pass1
,pass2
;
2782 /* Skip 2 strings. */
2783 p
= skip_string(param
,tpscnt
,np
);
2784 p
= skip_string(param
,tpscnt
,p
);
2790 /* Do we have a string ? */
2791 if (skip_string(param
,tpscnt
,p
) == NULL
) {
2794 pull_ascii_fstring(user
,p
);
2796 p
= skip_string(param
,tpscnt
,p
);
2801 memset(pass1
,'\0',sizeof(pass1
));
2802 memset(pass2
,'\0',sizeof(pass2
));
2804 * We use 31 here not 32 as we're checking
2805 * the last byte we want to access is safe.
2807 if (!is_offset_safe(param
,tpscnt
,p
,31)) {
2811 memcpy(pass2
,p
+16,16);
2814 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2821 SSVAL(*rparam
,0,NERR_badpass
);
2822 SSVAL(*rparam
,2,0); /* converter word */
2824 DEBUG(3,("Set password for <%s>\n",user
));
2827 * Attempt to verify the old password against smbpasswd entries
2828 * Win98 clients send old and new password in plaintext for this call.
2832 auth_serversupplied_info
*server_info
= NULL
;
2833 DATA_BLOB password
= data_blob(pass1
, strlen(pass1
)+1);
2835 if (NT_STATUS_IS_OK(check_plaintext_password(user
,password
,&server_info
))) {
2838 if (NT_STATUS_IS_OK(change_oem_password(server_info
->sam_account
, pass1
, pass2
, False
, NULL
))) {
2839 SSVAL(*rparam
,0,NERR_Success
);
2843 TALLOC_FREE(server_info
);
2845 data_blob_clear_free(&password
);
2849 * If the plaintext change failed, attempt
2850 * the old encrypted method. NT will generate this
2851 * after trying the samr method. Note that this
2852 * method is done as a last resort as this
2853 * password change method loses the NT password hash
2854 * and cannot change the UNIX password as no plaintext
2858 if(SVAL(*rparam
,0) != NERR_Success
) {
2859 struct samu
*hnd
= NULL
;
2861 if (check_lanman_password(user
,(unsigned char *)pass1
,(unsigned char *)pass2
, &hnd
)) {
2863 if (change_lanman_password(hnd
,(uchar
*)pass2
)) {
2864 SSVAL(*rparam
,0,NERR_Success
);
2871 memset((char *)pass1
,'\0',sizeof(fstring
));
2872 memset((char *)pass2
,'\0',sizeof(fstring
));
2877 /****************************************************************************
2878 Set the user password (SamOEM version - gets plaintext).
2879 ****************************************************************************/
2881 static bool api_SamOEMChangePassword(connection_struct
*conn
,uint16 vuid
,
2882 char *param
, int tpscnt
,
2883 char *data
, int tdscnt
,
2884 int mdrcnt
,int mprcnt
,
2885 char **rdata
,char **rparam
,
2886 int *rdata_len
,int *rparam_len
)
2888 struct smbd_server_connection
*sconn
= smbd_server_conn
;
2890 char *p
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2892 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2902 SSVAL(*rparam
,0,NERR_badpass
);
2905 * Check the parameter definition is correct.
2908 /* Do we have a string ? */
2909 if (skip_string(param
,tpscnt
,p
) == 0) {
2912 if(!strequal(p
, "zsT")) {
2913 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", p
));
2916 p
= skip_string(param
, tpscnt
, p
);
2921 /* Do we have a string ? */
2922 if (skip_string(param
,tpscnt
,p
) == 0) {
2925 if(!strequal(p
, "B516B16")) {
2926 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p
));
2929 p
= skip_string(param
,tpscnt
,p
);
2933 /* Do we have a string ? */
2934 if (skip_string(param
,tpscnt
,p
) == 0) {
2937 p
+= pull_ascii_fstring(user
,p
);
2939 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user
));
2942 * Pass the user through the NT -> unix user mapping
2946 (void)map_username(sconn
, user
);
2948 if (NT_STATUS_IS_OK(pass_oem_change(user
, (uchar
*) data
, (uchar
*)&data
[516], NULL
, NULL
, NULL
))) {
2949 SSVAL(*rparam
,0,NERR_Success
);
2955 /****************************************************************************
2958 ****************************************************************************/
2960 static bool api_RDosPrintJobDel(connection_struct
*conn
,uint16 vuid
,
2961 char *param
, int tpscnt
,
2962 char *data
, int tdscnt
,
2963 int mdrcnt
,int mprcnt
,
2964 char **rdata
,char **rparam
,
2965 int *rdata_len
,int *rparam_len
)
2967 int function
= get_safe_SVAL(param
,tpscnt
,param
,0,0);
2968 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2969 char *str2
= skip_string(param
,tpscnt
,str1
);
2970 char *p
= skip_string(param
,tpscnt
,str2
);
2975 WERROR werr
= WERR_OK
;
2977 if (!str1
|| !str2
|| !p
) {
2981 * We use 1 here not 2 as we're checking
2982 * the last byte we want to access is safe.
2984 if (!is_offset_safe(param
,tpscnt
,p
,1)) {
2987 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
))
2990 /* check it's a supported varient */
2991 if (!(strcsequal(str1
,"W") && strcsequal(str2
,"")))
2995 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3001 if (!print_job_exists(sharename
, jobid
)) {
3002 errcode
= NERR_JobNotFound
;
3006 snum
= lp_servicenumber( sharename
);
3008 errcode
= NERR_DestNotFound
;
3012 errcode
= NERR_notsupported
;
3015 case 81: /* delete */
3016 if (print_job_delete(conn
->server_info
, snum
, jobid
, &werr
))
3017 errcode
= NERR_Success
;
3019 case 82: /* pause */
3020 if (print_job_pause(conn
->server_info
, snum
, jobid
, &werr
))
3021 errcode
= NERR_Success
;
3023 case 83: /* resume */
3024 if (print_job_resume(conn
->server_info
, snum
, jobid
, &werr
))
3025 errcode
= NERR_Success
;
3029 if (!W_ERROR_IS_OK(werr
))
3030 errcode
= W_ERROR_V(werr
);
3033 SSVAL(*rparam
,0,errcode
);
3034 SSVAL(*rparam
,2,0); /* converter word */
3039 /****************************************************************************
3040 Purge a print queue - or pause or resume it.
3041 ****************************************************************************/
3043 static bool api_WPrintQueueCtrl(connection_struct
*conn
,uint16 vuid
,
3044 char *param
, int tpscnt
,
3045 char *data
, int tdscnt
,
3046 int mdrcnt
,int mprcnt
,
3047 char **rdata
,char **rparam
,
3048 int *rdata_len
,int *rparam_len
)
3050 int function
= get_safe_SVAL(param
,tpscnt
,param
,0,0);
3051 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3052 char *str2
= skip_string(param
,tpscnt
,str1
);
3053 char *QueueName
= skip_string(param
,tpscnt
,str2
);
3054 int errcode
= NERR_notsupported
;
3056 WERROR werr
= WERR_OK
;
3058 if (!str1
|| !str2
|| !QueueName
) {
3062 /* check it's a supported varient */
3063 if (!(strcsequal(str1
,"z") && strcsequal(str2
,"")))
3067 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3073 if (skip_string(param
,tpscnt
,QueueName
) == NULL
) {
3076 snum
= print_queue_snum(QueueName
);
3079 errcode
= NERR_JobNotFound
;
3084 case 74: /* Pause queue */
3085 werr
= print_queue_pause(conn
->server_info
, snum
);
3087 case 75: /* Resume queue */
3088 werr
= print_queue_resume(conn
->server_info
, snum
);
3090 case 103: /* Purge */
3091 werr
= print_queue_purge(conn
->server_info
, snum
);
3094 werr
= WERR_NOT_SUPPORTED
;
3098 errcode
= W_ERROR_V(werr
);
3101 SSVAL(*rparam
,0,errcode
);
3102 SSVAL(*rparam
,2,0); /* converter word */
3107 /****************************************************************************
3108 set the property of a print job (undocumented?)
3109 ? function = 0xb -> set name of print job
3110 ? function = 0x6 -> move print job up/down
3111 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
3112 or <WWsTP> <WB21BB16B10zWWzDDz>
3113 ****************************************************************************/
3115 static int check_printjob_info(struct pack_desc
* desc
,
3116 int uLevel
, char* id
)
3118 desc
->subformat
= NULL
;
3120 case 0: desc
->format
= "W"; break;
3121 case 1: desc
->format
= "WB21BB16B10zWWzDDz"; break;
3122 case 2: desc
->format
= "WWzWWDDzz"; break;
3123 case 3: desc
->format
= "WWzWWDDzzzzzzzzzzlz"; break;
3124 case 4: desc
->format
= "WWzWWDDzzzzzDDDDDDD"; break;
3126 DEBUG(0,("check_printjob_info: invalid level %d\n",
3130 if (id
== NULL
|| strcmp(desc
->format
,id
) != 0) {
3131 DEBUG(0,("check_printjob_info: invalid format %s\n",
3132 id
? id
: "<NULL>" ));
3138 static bool api_PrintJobInfo(connection_struct
*conn
, uint16 vuid
,
3139 char *param
, int tpscnt
,
3140 char *data
, int tdscnt
,
3141 int mdrcnt
,int mprcnt
,
3142 char **rdata
,char **rparam
,
3143 int *rdata_len
,int *rparam_len
)
3145 struct pack_desc desc
;
3146 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3147 char *str2
= skip_string(param
,tpscnt
,str1
);
3148 char *p
= skip_string(param
,tpscnt
,str2
);
3151 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,2,-1);
3152 int function
= get_safe_SVAL(param
,tpscnt
,p
,4,-1);
3155 if (!str1
|| !str2
|| !p
) {
3159 * We use 1 here not 2 as we're checking
3160 * the last byte we want to access is safe.
3162 if (!is_offset_safe(param
,tpscnt
,p
,1)) {
3165 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
))
3168 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3173 if (!share_defined(sharename
)) {
3174 DEBUG(0,("api_PrintJobInfo: sharen [%s] not defined\n",
3181 /* check it's a supported varient */
3182 if ((strcmp(str1
,"WWsTP")) ||
3183 (!check_printjob_info(&desc
,uLevel
,str2
)))
3186 if (!print_job_exists(sharename
, jobid
)) {
3187 errcode
=NERR_JobNotFound
;
3191 errcode
= NERR_notsupported
;
3195 /* change job place in the queue,
3196 data gives the new place */
3197 place
= SVAL(data
,0);
3198 if (print_job_set_place(sharename
, jobid
, place
)) {
3199 errcode
=NERR_Success
;
3204 /* change print job name, data gives the name */
3205 if (print_job_set_name(sharename
, jobid
, data
)) {
3206 errcode
=NERR_Success
;
3215 SSVALS(*rparam
,0,errcode
);
3216 SSVAL(*rparam
,2,0); /* converter word */
3222 /****************************************************************************
3223 Get info about the server.
3224 ****************************************************************************/
3226 static bool api_RNetServerGetInfo(connection_struct
*conn
,uint16 vuid
,
3227 char *param
, int tpscnt
,
3228 char *data
, int tdscnt
,
3229 int mdrcnt
,int mprcnt
,
3230 char **rdata
,char **rparam
,
3231 int *rdata_len
,int *rparam_len
)
3233 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3234 char *str2
= skip_string(param
,tpscnt
,str1
);
3235 char *p
= skip_string(param
,tpscnt
,str2
);
3236 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3240 if (!str1
|| !str2
|| !p
) {
3244 DEBUG(4,("NetServerGetInfo level %d\n",uLevel
));
3246 /* check it's a supported varient */
3247 if (!prefix_ok(str1
,"WrLh")) {
3253 if (strcmp(str2
,"B16") != 0) {
3259 if (strcmp(str2
,"B16BBDz") != 0) {
3265 if (strcmp(str2
,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")!= 0) {
3271 if (strcmp(str2
,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz") != 0) {
3277 if (strcmp(str2
,"DN") != 0) {
3283 if (strcmp(str2
,"B16BBDzWWzzz") != 0) {
3292 *rdata_len
= mdrcnt
;
3293 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
3299 p2
= p
+ struct_len
;
3301 srvstr_push(NULL
, 0, p
,global_myname(),16,
3302 STR_ASCII
|STR_UPPER
|STR_TERMINATE
);
3306 struct srv_info_struct
*servers
=NULL
;
3308 char *comment
= NULL
;
3309 TALLOC_CTX
*ctx
= talloc_tos();
3310 uint32 servertype
= lp_default_server_announce();
3312 comment
= talloc_strdup(ctx
,lp_serverstring());
3317 if ((count
=get_server_info(SV_TYPE_ALL
,&servers
,lp_workgroup()))>0) {
3318 for (i
=0;i
<count
;i
++) {
3319 if (strequal(servers
[i
].name
,global_myname())) {
3320 servertype
= servers
[i
].type
;
3321 TALLOC_FREE(comment
);
3322 comment
= talloc_strdup(ctx
,
3323 servers
[i
].comment
);
3333 SCVAL(p
,0,lp_major_announce_version());
3334 SCVAL(p
,1,lp_minor_announce_version());
3335 SIVAL(p
,2,servertype
);
3337 if (mdrcnt
== struct_len
) {
3340 SIVAL(p
,6,PTR_DIFF(p2
,*rdata
));
3341 comment
= talloc_sub_advanced(
3343 lp_servicename(SNUM(conn
)),
3344 conn
->server_info
->unix_name
,
3346 conn
->server_info
->utok
.gid
,
3347 conn
->server_info
->sanitized_username
,
3348 pdb_get_domain(conn
->server_info
->sam_account
),
3353 if (mdrcnt
- struct_len
<= 0) {
3358 MIN(mdrcnt
- struct_len
,
3359 MAX_SERVER_STRING_LENGTH
),
3361 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3369 return False
; /* not yet implemented */
3372 *rdata_len
= PTR_DIFF(p2
,*rdata
);
3375 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3379 SSVAL(*rparam
,0,NERR_Success
);
3380 SSVAL(*rparam
,2,0); /* converter word */
3381 SSVAL(*rparam
,4,*rdata_len
);
3386 /****************************************************************************
3387 Get info about the server.
3388 ****************************************************************************/
3390 static bool api_NetWkstaGetInfo(connection_struct
*conn
,uint16 vuid
,
3391 char *param
, int tpscnt
,
3392 char *data
, int tdscnt
,
3393 int mdrcnt
,int mprcnt
,
3394 char **rdata
,char **rparam
,
3395 int *rdata_len
,int *rparam_len
)
3397 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3398 char *str2
= skip_string(param
,tpscnt
,str1
);
3399 char *p
= skip_string(param
,tpscnt
,str2
);
3402 int level
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3404 if (!str1
|| !str2
|| !p
) {
3408 DEBUG(4,("NetWkstaGetInfo level %d\n",level
));
3411 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3416 /* check it's a supported varient */
3417 if (!(level
==10 && strcsequal(str1
,"WrLh") && strcsequal(str2
,"zzzBBzz"))) {
3421 *rdata_len
= mdrcnt
+ 1024;
3422 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
3427 SSVAL(*rparam
,0,NERR_Success
);
3428 SSVAL(*rparam
,2,0); /* converter word */
3431 endp
= *rdata
+ *rdata_len
;
3433 p2
= get_safe_ptr(*rdata
,*rdata_len
,p
,22);
3438 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* host name */
3439 strlcpy(p2
,get_local_machine_name(),PTR_DIFF(endp
,p2
));
3441 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3447 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
));
3448 strlcpy(p2
,conn
->server_info
->sanitized_username
,PTR_DIFF(endp
,p2
));
3449 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3455 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* login domain */
3456 strlcpy(p2
,lp_workgroup(),PTR_DIFF(endp
,p2
));
3458 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3464 SCVAL(p
,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
3465 SCVAL(p
,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
3468 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
));
3469 strlcpy(p2
,lp_workgroup(),PTR_DIFF(endp
,p2
)); /* don't know. login domain?? */
3470 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3476 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* don't know */
3477 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
3478 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3484 *rdata_len
= PTR_DIFF(p2
,*rdata
);
3486 SSVAL(*rparam
,4,*rdata_len
);
3491 /****************************************************************************
3492 get info about a user
3494 struct user_info_11 {
3495 char usri11_name[21]; 0-20
3497 char *usri11_comment; 22-25
3498 char *usri11_usr_comment; 26-29
3499 unsigned short usri11_priv; 30-31
3500 unsigned long usri11_auth_flags; 32-35
3501 long usri11_password_age; 36-39
3502 char *usri11_homedir; 40-43
3503 char *usri11_parms; 44-47
3504 long usri11_last_logon; 48-51
3505 long usri11_last_logoff; 52-55
3506 unsigned short usri11_bad_pw_count; 56-57
3507 unsigned short usri11_num_logons; 58-59
3508 char *usri11_logon_server; 60-63
3509 unsigned short usri11_country_code; 64-65
3510 char *usri11_workstations; 66-69
3511 unsigned long usri11_max_storage; 70-73
3512 unsigned short usri11_units_per_week; 74-75
3513 unsigned char *usri11_logon_hours; 76-79
3514 unsigned short usri11_code_page; 80-81
3519 usri11_name specifies the user name for which information is retrieved
3521 usri11_pad aligns the next data structure element to a word boundary
3523 usri11_comment is a null terminated ASCII comment
3525 usri11_user_comment is a null terminated ASCII comment about the user
3527 usri11_priv specifies the level of the privilege assigned to the user.
3528 The possible values are:
3530 Name Value Description
3531 USER_PRIV_GUEST 0 Guest privilege
3532 USER_PRIV_USER 1 User privilege
3533 USER_PRV_ADMIN 2 Administrator privilege
3535 usri11_auth_flags specifies the account operator privileges. The
3536 possible values are:
3538 Name Value Description
3539 AF_OP_PRINT 0 Print operator
3542 Leach, Naik [Page 28]
3546 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
3549 AF_OP_COMM 1 Communications operator
3550 AF_OP_SERVER 2 Server operator
3551 AF_OP_ACCOUNTS 3 Accounts operator
3554 usri11_password_age specifies how many seconds have elapsed since the
3555 password was last changed.
3557 usri11_home_dir points to a null terminated ASCII string that contains
3558 the path name of the user's home directory.
3560 usri11_parms points to a null terminated ASCII string that is set
3561 aside for use by applications.
3563 usri11_last_logon specifies the time when the user last logged on.
3564 This value is stored as the number of seconds elapsed since
3565 00:00:00, January 1, 1970.
3567 usri11_last_logoff specifies the time when the user last logged off.
3568 This value is stored as the number of seconds elapsed since
3569 00:00:00, January 1, 1970. A value of 0 means the last logoff
3572 usri11_bad_pw_count specifies the number of incorrect passwords
3573 entered since the last successful logon.
3575 usri11_log1_num_logons specifies the number of times this user has
3576 logged on. A value of -1 means the number of logons is unknown.
3578 usri11_logon_server points to a null terminated ASCII string that
3579 contains the name of the server to which logon requests are sent.
3580 A null string indicates logon requests should be sent to the
3583 usri11_country_code specifies the country code for the user's language
3586 usri11_workstations points to a null terminated ASCII string that
3587 contains the names of workstations the user may log on from.
3588 There may be up to 8 workstations, with the names separated by
3589 commas. A null strings indicates there are no restrictions.
3591 usri11_max_storage specifies the maximum amount of disk space the user
3592 can occupy. A value of 0xffffffff indicates there are no
3595 usri11_units_per_week specifies the equal number of time units into
3596 which a week is divided. This value must be equal to 168.
3598 usri11_logon_hours points to a 21 byte (168 bits) string that
3599 specifies the time during which the user can log on. Each bit
3600 represents one unique hour in a week. The first bit (bit 0, word
3601 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
3605 Leach, Naik [Page 29]
3609 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
3612 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
3613 are no restrictions.
3615 usri11_code_page specifies the code page for the user's language of
3618 All of the pointers in this data structure need to be treated
3619 specially. The pointer is a 32 bit pointer. The higher 16 bits need
3620 to be ignored. The converter word returned in the parameters section
3621 needs to be subtracted from the lower 16 bits to calculate an offset
3622 into the return buffer where this ASCII string resides.
3624 There is no auxiliary data in the response.
3626 ****************************************************************************/
3628 #define usri11_name 0
3629 #define usri11_pad 21
3630 #define usri11_comment 22
3631 #define usri11_usr_comment 26
3632 #define usri11_full_name 30
3633 #define usri11_priv 34
3634 #define usri11_auth_flags 36
3635 #define usri11_password_age 40
3636 #define usri11_homedir 44
3637 #define usri11_parms 48
3638 #define usri11_last_logon 52
3639 #define usri11_last_logoff 56
3640 #define usri11_bad_pw_count 60
3641 #define usri11_num_logons 62
3642 #define usri11_logon_server 64
3643 #define usri11_country_code 68
3644 #define usri11_workstations 70
3645 #define usri11_max_storage 74
3646 #define usri11_units_per_week 78
3647 #define usri11_logon_hours 80
3648 #define usri11_code_page 84
3649 #define usri11_end 86
3651 #define USER_PRIV_GUEST 0
3652 #define USER_PRIV_USER 1
3653 #define USER_PRIV_ADMIN 2
3655 #define AF_OP_PRINT 0
3656 #define AF_OP_COMM 1
3657 #define AF_OP_SERVER 2
3658 #define AF_OP_ACCOUNTS 3
3661 static bool api_RNetUserGetInfo(connection_struct
*conn
, uint16 vuid
,
3662 char *param
, int tpscnt
,
3663 char *data
, int tdscnt
,
3664 int mdrcnt
,int mprcnt
,
3665 char **rdata
,char **rparam
,
3666 int *rdata_len
,int *rparam_len
)
3668 struct smbd_server_connection
*sconn
= smbd_server_conn
;
3669 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3670 char *str2
= skip_string(param
,tpscnt
,str1
);
3671 char *UserName
= skip_string(param
,tpscnt
,str2
);
3672 char *p
= skip_string(param
,tpscnt
,UserName
);
3673 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3676 const char *level_string
;
3678 /* get NIS home of a previously validated user - simeon */
3679 /* With share level security vuid will always be zero.
3680 Don't depend on vuser being non-null !!. JRA */
3681 user_struct
*vuser
= get_valid_user_struct(sconn
, vuid
);
3683 DEBUG(3,(" Username of UID %d is %s\n",
3684 (int)vuser
->server_info
->utok
.uid
,
3685 vuser
->server_info
->unix_name
));
3688 if (!str1
|| !str2
|| !UserName
|| !p
) {
3693 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3698 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel
));
3700 /* check it's a supported variant */
3701 if (strcmp(str1
,"zWrLh") != 0) {
3705 case 0: level_string
= "B21"; break;
3706 case 1: level_string
= "B21BB16DWzzWz"; break;
3707 case 2: level_string
= "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
3708 case 10: level_string
= "B21Bzzz"; break;
3709 case 11: level_string
= "B21BzzzWDDzzDDWWzWzDWb21W"; break;
3710 default: return False
;
3713 if (strcmp(level_string
,str2
) != 0) {
3717 *rdata_len
= mdrcnt
+ 1024;
3718 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
3723 SSVAL(*rparam
,0,NERR_Success
);
3724 SSVAL(*rparam
,2,0); /* converter word */
3727 endp
= *rdata
+ *rdata_len
;
3728 p2
= get_safe_ptr(*rdata
,*rdata_len
,p
,usri11_end
);
3734 fstrcpy(p
+usri11_name
,UserName
); /* 21 bytes - user name */
3737 SCVAL(p
,usri11_pad
,0); /* padding - 1 byte */
3742 SIVAL(p
,usri11_comment
,PTR_DIFF(p2
,p
)); /* comment */
3743 strlcpy(p2
,"Comment",PTR_DIFF(endp
,p2
));
3744 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3749 SIVAL(p
,usri11_usr_comment
,PTR_DIFF(p2
,p
)); /* user_comment */
3750 strlcpy(p2
,"UserComment",PTR_DIFF(endp
,p2
));
3751 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3756 /* EEK! the cifsrap.txt doesn't have this in!!!! */
3757 SIVAL(p
,usri11_full_name
,PTR_DIFF(p2
,p
)); /* full name */
3758 strlcpy(p2
,((vuser
!= NULL
)
3759 ? pdb_get_fullname(vuser
->server_info
->sam_account
)
3760 : UserName
),PTR_DIFF(endp
,p2
));
3761 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3768 const char *homedir
= "";
3769 if (vuser
!= NULL
) {
3770 homedir
= pdb_get_homedir(
3771 vuser
->server_info
->sam_account
);
3773 /* modelled after NTAS 3.51 reply */
3774 SSVAL(p
,usri11_priv
,conn
->admin_user
?USER_PRIV_ADMIN
:USER_PRIV_USER
);
3775 SIVAL(p
,usri11_auth_flags
,AF_OP_PRINT
); /* auth flags */
3776 SIVALS(p
,usri11_password_age
,-1); /* password age */
3777 SIVAL(p
,usri11_homedir
,PTR_DIFF(p2
,p
)); /* home dir */
3778 strlcpy(p2
, homedir
, PTR_DIFF(endp
,p2
));
3779 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3783 SIVAL(p
,usri11_parms
,PTR_DIFF(p2
,p
)); /* parms */
3784 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
3785 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3789 SIVAL(p
,usri11_last_logon
,0); /* last logon */
3790 SIVAL(p
,usri11_last_logoff
,0); /* last logoff */
3791 SSVALS(p
,usri11_bad_pw_count
,-1); /* bad pw counts */
3792 SSVALS(p
,usri11_num_logons
,-1); /* num logons */
3793 SIVAL(p
,usri11_logon_server
,PTR_DIFF(p2
,p
)); /* logon server */
3794 strlcpy(p2
,"\\\\*",PTR_DIFF(endp
,p2
));
3795 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3799 SSVAL(p
,usri11_country_code
,0); /* country code */
3801 SIVAL(p
,usri11_workstations
,PTR_DIFF(p2
,p
)); /* workstations */
3802 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
3803 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3808 SIVALS(p
,usri11_max_storage
,-1); /* max storage */
3809 SSVAL(p
,usri11_units_per_week
,168); /* units per week */
3810 SIVAL(p
,usri11_logon_hours
,PTR_DIFF(p2
,p
)); /* logon hours */
3812 /* a simple way to get logon hours at all times. */
3814 SCVAL(p2
,21,0); /* fix zero termination */
3815 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3820 SSVAL(p
,usri11_code_page
,0); /* code page */
3823 if (uLevel
== 1 || uLevel
== 2) {
3824 memset(p
+22,' ',16); /* password */
3825 SIVALS(p
,38,-1); /* password age */
3827 conn
->admin_user
?USER_PRIV_ADMIN
:USER_PRIV_USER
);
3828 SIVAL(p
,44,PTR_DIFF(p2
,*rdata
)); /* home dir */
3829 strlcpy(p2
, vuser
? pdb_get_homedir(
3830 vuser
->server_info
->sam_account
) : "",
3832 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3836 SIVAL(p
,48,PTR_DIFF(p2
,*rdata
)); /* comment */
3838 SSVAL(p
,52,0); /* flags */
3839 SIVAL(p
,54,PTR_DIFF(p2
,*rdata
)); /* script_path */
3840 strlcpy(p2
, vuser
? pdb_get_logon_script(
3841 vuser
->server_info
->sam_account
) : "",
3843 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3848 SIVAL(p
,60,0); /* auth_flags */
3849 SIVAL(p
,64,PTR_DIFF(p2
,*rdata
)); /* full_name */
3850 strlcpy(p2
,((vuser
!= NULL
)
3851 ? pdb_get_fullname(vuser
->server_info
->sam_account
)
3852 : UserName
),PTR_DIFF(endp
,p2
));
3853 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3857 SIVAL(p
,68,0); /* urs_comment */
3858 SIVAL(p
,72,PTR_DIFF(p2
,*rdata
)); /* parms */
3859 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
3860 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3864 SIVAL(p
,76,0); /* workstations */
3865 SIVAL(p
,80,0); /* last_logon */
3866 SIVAL(p
,84,0); /* last_logoff */
3867 SIVALS(p
,88,-1); /* acct_expires */
3868 SIVALS(p
,92,-1); /* max_storage */
3869 SSVAL(p
,96,168); /* units_per_week */
3870 SIVAL(p
,98,PTR_DIFF(p2
,*rdata
)); /* logon_hours */
3873 SSVALS(p
,102,-1); /* bad_pw_count */
3874 SSVALS(p
,104,-1); /* num_logons */
3875 SIVAL(p
,106,PTR_DIFF(p2
,*rdata
)); /* logon_server */
3877 TALLOC_CTX
*ctx
= talloc_tos();
3878 int space_rem
= *rdata_len
- (p2
- *rdata
);
3881 if (space_rem
<= 0) {
3884 tmp
= talloc_strdup(ctx
, "\\\\%L");
3888 tmp
= talloc_sub_basic(ctx
,
3901 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3905 SSVAL(p
,110,49); /* country_code */
3906 SSVAL(p
,112,860); /* code page */
3910 *rdata_len
= PTR_DIFF(p2
,*rdata
);
3912 SSVAL(*rparam
,4,*rdata_len
); /* is this right?? */
3917 static bool api_WWkstaUserLogon(connection_struct
*conn
,uint16 vuid
,
3918 char *param
, int tpscnt
,
3919 char *data
, int tdscnt
,
3920 int mdrcnt
,int mprcnt
,
3921 char **rdata
,char **rparam
,
3922 int *rdata_len
,int *rparam_len
)
3924 struct smbd_server_connection
*sconn
= smbd_server_conn
;
3925 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3926 char *str2
= skip_string(param
,tpscnt
,str1
);
3927 char *p
= skip_string(param
,tpscnt
,str2
);
3929 struct pack_desc desc
;
3931 /* With share level security vuid will always be zero.
3932 Don't depend on vuser being non-null !!. JRA */
3933 user_struct
*vuser
= get_valid_user_struct(sconn
, vuid
);
3935 if (!str1
|| !str2
|| !p
) {
3940 DEBUG(3,(" Username of UID %d is %s\n",
3941 (int)vuser
->server_info
->utok
.uid
,
3942 vuser
->server_info
->unix_name
));
3945 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3946 name
= get_safe_str_ptr(param
,tpscnt
,p
,2);
3951 memset((char *)&desc
,'\0',sizeof(desc
));
3953 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel
,name
));
3955 /* check it's a supported varient */
3956 if (strcmp(str1
,"OOWb54WrLh") != 0) {
3959 if (uLevel
!= 1 || strcmp(str2
,"WB21BWDWWDDDDDDDzzzD") != 0) {
3963 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
3970 desc
.buflen
= mdrcnt
;
3971 desc
.subformat
= NULL
;
3974 if (init_package(&desc
,1,0)) {
3975 PACKI(&desc
,"W",0); /* code */
3976 PACKS(&desc
,"B21",name
); /* eff. name */
3977 PACKS(&desc
,"B",""); /* pad */
3978 PACKI(&desc
,"W", conn
->admin_user
?USER_PRIV_ADMIN
:USER_PRIV_USER
);
3979 PACKI(&desc
,"D",0); /* auth flags XXX */
3980 PACKI(&desc
,"W",0); /* num logons */
3981 PACKI(&desc
,"W",0); /* bad pw count */
3982 PACKI(&desc
,"D",0); /* last logon */
3983 PACKI(&desc
,"D",-1); /* last logoff */
3984 PACKI(&desc
,"D",-1); /* logoff time */
3985 PACKI(&desc
,"D",-1); /* kickoff time */
3986 PACKI(&desc
,"D",0); /* password age */
3987 PACKI(&desc
,"D",0); /* password can change */
3988 PACKI(&desc
,"D",-1); /* password must change */
3992 fstrcpy(mypath
,"\\\\");
3993 fstrcat(mypath
,get_local_machine_name());
3995 PACKS(&desc
,"z",mypath
); /* computer */
3998 PACKS(&desc
,"z",lp_workgroup());/* domain */
3999 PACKS(&desc
,"z", vuser
? pdb_get_logon_script(
4000 vuser
->server_info
->sam_account
) : ""); /* script path */
4001 PACKI(&desc
,"D",0x00000000); /* reserved */
4004 *rdata_len
= desc
.usedlen
;
4006 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4010 SSVALS(*rparam
,0,desc
.errcode
);
4012 SSVAL(*rparam
,4,desc
.neededlen
);
4014 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc
.errcode
));
4019 /****************************************************************************
4020 api_WAccessGetUserPerms
4021 ****************************************************************************/
4023 static bool api_WAccessGetUserPerms(connection_struct
*conn
,uint16 vuid
,
4024 char *param
, int tpscnt
,
4025 char *data
, int tdscnt
,
4026 int mdrcnt
,int mprcnt
,
4027 char **rdata
,char **rparam
,
4028 int *rdata_len
,int *rparam_len
)
4030 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4031 char *str2
= skip_string(param
,tpscnt
,str1
);
4032 char *user
= skip_string(param
,tpscnt
,str2
);
4033 char *resource
= skip_string(param
,tpscnt
,user
);
4035 if (!str1
|| !str2
|| !user
|| !resource
) {
4039 if (skip_string(param
,tpscnt
,resource
) == NULL
) {
4042 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user
,resource
));
4044 /* check it's a supported varient */
4045 if (strcmp(str1
,"zzh") != 0) {
4048 if (strcmp(str2
,"") != 0) {
4053 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4057 SSVALS(*rparam
,0,0); /* errorcode */
4058 SSVAL(*rparam
,2,0); /* converter word */
4059 SSVAL(*rparam
,4,0x7f); /* permission flags */
4064 /****************************************************************************
4065 api_WPrintJobEnumerate
4066 ****************************************************************************/
4068 static bool api_WPrintJobGetInfo(connection_struct
*conn
, uint16 vuid
,
4069 char *param
, int tpscnt
,
4070 char *data
, int tdscnt
,
4071 int mdrcnt
,int mprcnt
,
4072 char **rdata
,char **rparam
,
4073 int *rdata_len
,int *rparam_len
)
4075 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4076 char *str2
= skip_string(param
,tpscnt
,str1
);
4077 char *p
= skip_string(param
,tpscnt
,str2
);
4084 struct pack_desc desc
;
4085 print_queue_struct
*queue
=NULL
;
4086 print_status_struct status
;
4089 if (!str1
|| !str2
|| !p
) {
4093 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,2,-1);
4095 memset((char *)&desc
,'\0',sizeof(desc
));
4096 memset((char *)&status
,'\0',sizeof(status
));
4098 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel
,SVAL(p
,0)));
4100 /* check it's a supported varient */
4101 if (strcmp(str1
,"WWrLh") != 0) {
4104 if (!check_printjob_info(&desc
,uLevel
,str2
)) {
4108 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
)) {
4112 snum
= lp_servicenumber( sharename
);
4113 if (snum
< 0 || !VALID_SNUM(snum
)) {
4117 count
= print_queue_status(snum
,&queue
,&status
);
4118 for (i
= 0; i
< count
; i
++) {
4119 if (queue
[i
].job
== jobid
) {
4125 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4130 desc
.buflen
= mdrcnt
;
4133 * Don't return data but need to get correct length
4134 * init_package will return wrong size if buflen=0
4136 desc
.buflen
= getlen(desc
.format
);
4137 desc
.base
= tmpdata
= (char *)SMB_MALLOC( desc
.buflen
);
4140 if (init_package(&desc
,1,0)) {
4142 fill_printjob_info(conn
,snum
,uLevel
,&desc
,&queue
[i
],i
);
4143 *rdata_len
= desc
.usedlen
;
4145 desc
.errcode
= NERR_JobNotFound
;
4151 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4155 SSVALS(*rparam
,0,desc
.errcode
);
4157 SSVAL(*rparam
,4,desc
.neededlen
);
4162 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc
.errcode
));
4167 static bool api_WPrintJobEnumerate(connection_struct
*conn
, uint16 vuid
,
4168 char *param
, int tpscnt
,
4169 char *data
, int tdscnt
,
4170 int mdrcnt
,int mprcnt
,
4171 char **rdata
,char **rparam
,
4172 int *rdata_len
,int *rparam_len
)
4174 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4175 char *str2
= skip_string(param
,tpscnt
,str1
);
4176 char *p
= skip_string(param
,tpscnt
,str2
);
4182 struct pack_desc desc
;
4183 print_queue_struct
*queue
=NULL
;
4184 print_status_struct status
;
4186 if (!str1
|| !str2
|| !p
) {
4190 memset((char *)&desc
,'\0',sizeof(desc
));
4191 memset((char *)&status
,'\0',sizeof(status
));
4193 p
= skip_string(param
,tpscnt
,p
);
4197 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4199 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel
,name
));
4201 /* check it's a supported variant */
4202 if (strcmp(str1
,"zWrLeh") != 0) {
4207 return False
; /* defined only for uLevel 0,1,2 */
4210 if (!check_printjob_info(&desc
,uLevel
,str2
)) {
4214 snum
= find_service(name
);
4215 if ( !(lp_snum_ok(snum
) && lp_print_ok(snum
)) ) {
4219 count
= print_queue_status(snum
,&queue
,&status
);
4221 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4227 desc
.buflen
= mdrcnt
;
4229 if (init_package(&desc
,count
,0)) {
4231 for (i
= 0; i
< count
; i
++) {
4232 fill_printjob_info(conn
,snum
,uLevel
,&desc
,&queue
[i
],i
);
4233 if (desc
.errcode
== NERR_Success
) {
4239 *rdata_len
= desc
.usedlen
;
4242 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4246 SSVALS(*rparam
,0,desc
.errcode
);
4248 SSVAL(*rparam
,4,succnt
);
4249 SSVAL(*rparam
,6,count
);
4253 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc
.errcode
));
4258 static int check_printdest_info(struct pack_desc
* desc
,
4259 int uLevel
, char* id
)
4261 desc
->subformat
= NULL
;
4264 desc
->format
= "B9";
4267 desc
->format
= "B9B21WWzW";
4273 desc
->format
= "zzzWWzzzWW";
4276 DEBUG(0,("check_printdest_info: invalid level %d\n",
4280 if (id
== NULL
|| strcmp(desc
->format
,id
) != 0) {
4281 DEBUG(0,("check_printdest_info: invalid string %s\n",
4282 id
? id
: "<NULL>" ));
4288 static void fill_printdest_info(connection_struct
*conn
, int snum
, int uLevel
,
4289 struct pack_desc
* desc
)
4293 strncpy(buf
,SERVICE(snum
),sizeof(buf
)-1);
4294 buf
[sizeof(buf
)-1] = 0;
4298 PACKS(desc
,"B9",buf
); /* szName */
4300 PACKS(desc
,"B21",""); /* szUserName */
4301 PACKI(desc
,"W",0); /* uJobId */
4302 PACKI(desc
,"W",0); /* fsStatus */
4303 PACKS(desc
,"z",""); /* pszStatus */
4304 PACKI(desc
,"W",0); /* time */
4308 if (uLevel
== 2 || uLevel
== 3) {
4309 PACKS(desc
,"z",buf
); /* pszPrinterName */
4311 PACKS(desc
,"z",""); /* pszUserName */
4312 PACKS(desc
,"z",""); /* pszLogAddr */
4313 PACKI(desc
,"W",0); /* uJobId */
4314 PACKI(desc
,"W",0); /* fsStatus */
4315 PACKS(desc
,"z",""); /* pszStatus */
4316 PACKS(desc
,"z",""); /* pszComment */
4317 PACKS(desc
,"z","NULL"); /* pszDrivers */
4318 PACKI(desc
,"W",0); /* time */
4319 PACKI(desc
,"W",0); /* pad1 */
4324 static bool api_WPrintDestGetInfo(connection_struct
*conn
, uint16 vuid
,
4325 char *param
, int tpscnt
,
4326 char *data
, int tdscnt
,
4327 int mdrcnt
,int mprcnt
,
4328 char **rdata
,char **rparam
,
4329 int *rdata_len
,int *rparam_len
)
4331 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4332 char *str2
= skip_string(param
,tpscnt
,str1
);
4333 char *p
= skip_string(param
,tpscnt
,str2
);
4334 char* PrinterName
= p
;
4336 struct pack_desc desc
;
4340 if (!str1
|| !str2
|| !p
) {
4344 memset((char *)&desc
,'\0',sizeof(desc
));
4346 p
= skip_string(param
,tpscnt
,p
);
4350 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4352 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel
,PrinterName
));
4354 /* check it's a supported varient */
4355 if (strcmp(str1
,"zWrLh") != 0) {
4358 if (!check_printdest_info(&desc
,uLevel
,str2
)) {
4362 snum
= find_service(PrinterName
);
4363 if ( !(lp_snum_ok(snum
) && lp_print_ok(snum
)) ) {
4365 desc
.errcode
= NERR_DestNotFound
;
4369 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4374 desc
.buflen
= mdrcnt
;
4377 * Don't return data but need to get correct length
4378 * init_package will return wrong size if buflen=0
4380 desc
.buflen
= getlen(desc
.format
);
4381 desc
.base
= tmpdata
= (char *)SMB_MALLOC( desc
.buflen
);
4383 if (init_package(&desc
,1,0)) {
4384 fill_printdest_info(conn
,snum
,uLevel
,&desc
);
4386 *rdata_len
= desc
.usedlen
;
4390 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4394 SSVALS(*rparam
,0,desc
.errcode
);
4396 SSVAL(*rparam
,4,desc
.neededlen
);
4398 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc
.errcode
));
4404 static bool api_WPrintDestEnum(connection_struct
*conn
, uint16 vuid
,
4405 char *param
, int tpscnt
,
4406 char *data
, int tdscnt
,
4407 int mdrcnt
,int mprcnt
,
4408 char **rdata
,char **rparam
,
4409 int *rdata_len
,int *rparam_len
)
4411 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4412 char *str2
= skip_string(param
,tpscnt
,str1
);
4413 char *p
= skip_string(param
,tpscnt
,str2
);
4417 struct pack_desc desc
;
4418 int services
= lp_numservices();
4420 if (!str1
|| !str2
|| !p
) {
4424 memset((char *)&desc
,'\0',sizeof(desc
));
4426 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4428 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel
));
4430 /* check it's a supported varient */
4431 if (strcmp(str1
,"WrLeh") != 0) {
4434 if (!check_printdest_info(&desc
,uLevel
,str2
)) {
4439 for (i
= 0; i
< services
; i
++) {
4440 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
)) {
4446 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4453 desc
.buflen
= mdrcnt
;
4454 if (init_package(&desc
,queuecnt
,0)) {
4457 for (i
= 0; i
< services
; i
++) {
4458 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
)) {
4459 fill_printdest_info(conn
,i
,uLevel
,&desc
);
4461 if (desc
.errcode
== NERR_Success
) {
4468 *rdata_len
= desc
.usedlen
;
4471 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4475 SSVALS(*rparam
,0,desc
.errcode
);
4477 SSVAL(*rparam
,4,succnt
);
4478 SSVAL(*rparam
,6,queuecnt
);
4480 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc
.errcode
));
4485 static bool api_WPrintDriverEnum(connection_struct
*conn
, uint16 vuid
,
4486 char *param
, int tpscnt
,
4487 char *data
, int tdscnt
,
4488 int mdrcnt
,int mprcnt
,
4489 char **rdata
,char **rparam
,
4490 int *rdata_len
,int *rparam_len
)
4492 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4493 char *str2
= skip_string(param
,tpscnt
,str1
);
4494 char *p
= skip_string(param
,tpscnt
,str2
);
4497 struct pack_desc desc
;
4499 if (!str1
|| !str2
|| !p
) {
4503 memset((char *)&desc
,'\0',sizeof(desc
));
4505 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4507 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel
));
4509 /* check it's a supported varient */
4510 if (strcmp(str1
,"WrLeh") != 0) {
4513 if (uLevel
!= 0 || strcmp(str2
,"B41") != 0) {
4518 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4524 desc
.buflen
= mdrcnt
;
4525 if (init_package(&desc
,1,0)) {
4526 PACKS(&desc
,"B41","NULL");
4529 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
4531 *rdata_len
= desc
.usedlen
;
4534 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4538 SSVALS(*rparam
,0,desc
.errcode
);
4540 SSVAL(*rparam
,4,succnt
);
4543 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc
.errcode
));
4548 static bool api_WPrintQProcEnum(connection_struct
*conn
, uint16 vuid
,
4549 char *param
, int tpscnt
,
4550 char *data
, int tdscnt
,
4551 int mdrcnt
,int mprcnt
,
4552 char **rdata
,char **rparam
,
4553 int *rdata_len
,int *rparam_len
)
4555 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4556 char *str2
= skip_string(param
,tpscnt
,str1
);
4557 char *p
= skip_string(param
,tpscnt
,str2
);
4560 struct pack_desc desc
;
4562 if (!str1
|| !str2
|| !p
) {
4565 memset((char *)&desc
,'\0',sizeof(desc
));
4567 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4569 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel
));
4571 /* check it's a supported varient */
4572 if (strcmp(str1
,"WrLeh") != 0) {
4575 if (uLevel
!= 0 || strcmp(str2
,"B13") != 0) {
4580 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4586 desc
.buflen
= mdrcnt
;
4588 if (init_package(&desc
,1,0)) {
4589 PACKS(&desc
,"B13","lpd");
4592 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
4594 *rdata_len
= desc
.usedlen
;
4597 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4601 SSVALS(*rparam
,0,desc
.errcode
);
4603 SSVAL(*rparam
,4,succnt
);
4606 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc
.errcode
));
4611 static bool api_WPrintPortEnum(connection_struct
*conn
, uint16 vuid
,
4612 char *param
, int tpscnt
,
4613 char *data
, int tdscnt
,
4614 int mdrcnt
,int mprcnt
,
4615 char **rdata
,char **rparam
,
4616 int *rdata_len
,int *rparam_len
)
4618 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4619 char *str2
= skip_string(param
,tpscnt
,str1
);
4620 char *p
= skip_string(param
,tpscnt
,str2
);
4623 struct pack_desc desc
;
4625 if (!str1
|| !str2
|| !p
) {
4629 memset((char *)&desc
,'\0',sizeof(desc
));
4631 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4633 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel
));
4635 /* check it's a supported varient */
4636 if (strcmp(str1
,"WrLeh") != 0) {
4639 if (uLevel
!= 0 || strcmp(str2
,"B9") != 0) {
4644 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4649 memset((char *)&desc
,'\0',sizeof(desc
));
4651 desc
.buflen
= mdrcnt
;
4653 if (init_package(&desc
,1,0)) {
4654 PACKS(&desc
,"B13","lp0");
4657 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
4659 *rdata_len
= desc
.usedlen
;
4662 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4666 SSVALS(*rparam
,0,desc
.errcode
);
4668 SSVAL(*rparam
,4,succnt
);
4671 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc
.errcode
));
4676 /****************************************************************************
4678 ****************************************************************************/
4680 static bool api_RNetSessionEnum(connection_struct
*conn
, uint16 vuid
,
4681 char *param
, int tpscnt
,
4682 char *data
, int tdscnt
,
4683 int mdrcnt
,int mprcnt
,
4684 char **rdata
,char **rparam
,
4685 int *rdata_len
,int *rparam_len
)
4688 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4689 char *str2
= skip_string(param
,tpscnt
,str1
);
4690 char *p
= skip_string(param
,tpscnt
,str2
);
4692 struct pack_desc desc
;
4693 struct sessionid
*session_list
;
4694 int i
, num_sessions
;
4696 if (!str1
|| !str2
|| !p
) {
4700 memset((char *)&desc
,'\0',sizeof(desc
));
4702 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4704 DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel
));
4705 DEBUG(7,("RNetSessionEnum req string=%s\n",str1
));
4706 DEBUG(7,("RNetSessionEnum ret string=%s\n",str2
));
4708 /* check it's a supported varient */
4709 if (strcmp(str1
,RAP_NetSessionEnum_REQ
) != 0) {
4712 if (uLevel
!= 2 || strcmp(str2
,RAP_SESSION_INFO_L2
) != 0) {
4716 num_sessions
= list_sessions(talloc_tos(), &session_list
);
4719 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4724 memset((char *)&desc
,'\0',sizeof(desc
));
4726 desc
.buflen
= mdrcnt
;
4728 if (!init_package(&desc
,num_sessions
,0)) {
4732 for(i
=0; i
<num_sessions
; i
++) {
4733 PACKS(&desc
, "z", session_list
[i
].remote_machine
);
4734 PACKS(&desc
, "z", session_list
[i
].username
);
4735 PACKI(&desc
, "W", 1); /* num conns */
4736 PACKI(&desc
, "W", 0); /* num opens */
4737 PACKI(&desc
, "W", 1); /* num users */
4738 PACKI(&desc
, "D", 0); /* session time */
4739 PACKI(&desc
, "D", 0); /* idle time */
4740 PACKI(&desc
, "D", 0); /* flags */
4741 PACKS(&desc
, "z", "Unknown Client"); /* client type string */
4744 *rdata_len
= desc
.usedlen
;
4747 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4751 SSVALS(*rparam
,0,desc
.errcode
);
4752 SSVAL(*rparam
,2,0); /* converter */
4753 SSVAL(*rparam
,4,num_sessions
); /* count */
4755 DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc
.errcode
));
4761 /****************************************************************************
4762 The buffer was too small.
4763 ****************************************************************************/
4765 static bool api_TooSmall(connection_struct
*conn
,uint16 vuid
, char *param
, char *data
,
4766 int mdrcnt
, int mprcnt
,
4767 char **rdata
, char **rparam
,
4768 int *rdata_len
, int *rparam_len
)
4770 *rparam_len
= MIN(*rparam_len
,mprcnt
);
4771 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4778 SSVAL(*rparam
,0,NERR_BufTooSmall
);
4780 DEBUG(3,("Supplied buffer too small in API command\n"));
4785 /****************************************************************************
4786 The request is not supported.
4787 ****************************************************************************/
4789 static bool api_Unsupported(connection_struct
*conn
, uint16 vuid
,
4790 char *param
, int tpscnt
,
4791 char *data
, int tdscnt
,
4792 int mdrcnt
, int mprcnt
,
4793 char **rdata
, char **rparam
,
4794 int *rdata_len
, int *rparam_len
)
4797 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4804 SSVAL(*rparam
,0,NERR_notsupported
);
4805 SSVAL(*rparam
,2,0); /* converter word */
4807 DEBUG(3,("Unsupported API command\n"));
4812 static const struct {
4815 bool (*fn
)(connection_struct
*, uint16
,
4818 int,int,char **,char **,int *,int *);
4819 bool auth_user
; /* Deny anonymous access? */
4820 } api_commands
[] = {
4821 {"RNetShareEnum", RAP_WshareEnum
, api_RNetShareEnum
, True
},
4822 {"RNetShareGetInfo", RAP_WshareGetInfo
, api_RNetShareGetInfo
},
4823 {"RNetShareAdd", RAP_WshareAdd
, api_RNetShareAdd
},
4824 {"RNetSessionEnum", RAP_WsessionEnum
, api_RNetSessionEnum
, True
},
4825 {"RNetServerGetInfo", RAP_WserverGetInfo
, api_RNetServerGetInfo
},
4826 {"RNetGroupEnum", RAP_WGroupEnum
, api_RNetGroupEnum
, True
},
4827 {"RNetGroupGetUsers", RAP_WGroupGetUsers
, api_RNetGroupGetUsers
, True
},
4828 {"RNetUserEnum", RAP_WUserEnum
, api_RNetUserEnum
, True
},
4829 {"RNetUserGetInfo", RAP_WUserGetInfo
, api_RNetUserGetInfo
},
4830 {"NetUserGetGroups", RAP_WUserGetGroups
, api_NetUserGetGroups
},
4831 {"NetWkstaGetInfo", RAP_WWkstaGetInfo
, api_NetWkstaGetInfo
},
4832 {"DosPrintQEnum", RAP_WPrintQEnum
, api_DosPrintQEnum
, True
},
4833 {"DosPrintQGetInfo", RAP_WPrintQGetInfo
, api_DosPrintQGetInfo
},
4834 {"WPrintQueuePause", RAP_WPrintQPause
, api_WPrintQueueCtrl
},
4835 {"WPrintQueueResume", RAP_WPrintQContinue
, api_WPrintQueueCtrl
},
4836 {"WPrintJobEnumerate",RAP_WPrintJobEnum
, api_WPrintJobEnumerate
},
4837 {"WPrintJobGetInfo", RAP_WPrintJobGetInfo
, api_WPrintJobGetInfo
},
4838 {"RDosPrintJobDel", RAP_WPrintJobDel
, api_RDosPrintJobDel
},
4839 {"RDosPrintJobPause", RAP_WPrintJobPause
, api_RDosPrintJobDel
},
4840 {"RDosPrintJobResume",RAP_WPrintJobContinue
, api_RDosPrintJobDel
},
4841 {"WPrintDestEnum", RAP_WPrintDestEnum
, api_WPrintDestEnum
},
4842 {"WPrintDestGetInfo", RAP_WPrintDestGetInfo
, api_WPrintDestGetInfo
},
4843 {"NetRemoteTOD", RAP_NetRemoteTOD
, api_NetRemoteTOD
},
4844 {"WPrintQueuePurge", RAP_WPrintQPurge
, api_WPrintQueueCtrl
},
4845 {"NetServerEnum2", RAP_NetServerEnum2
, api_RNetServerEnum2
}, /* anon OK */
4846 {"NetServerEnum3", RAP_NetServerEnum3
, api_RNetServerEnum3
}, /* anon OK */
4847 {"WAccessGetUserPerms",RAP_WAccessGetUserPerms
,api_WAccessGetUserPerms
},
4848 {"SetUserPassword", RAP_WUserPasswordSet2
, api_SetUserPassword
},
4849 {"WWkstaUserLogon", RAP_WWkstaUserLogon
, api_WWkstaUserLogon
},
4850 {"PrintJobInfo", RAP_WPrintJobSetInfo
, api_PrintJobInfo
},
4851 {"WPrintDriverEnum", RAP_WPrintDriverEnum
, api_WPrintDriverEnum
},
4852 {"WPrintQProcEnum", RAP_WPrintQProcessorEnum
,api_WPrintQProcEnum
},
4853 {"WPrintPortEnum", RAP_WPrintPortEnum
, api_WPrintPortEnum
},
4854 {"SamOEMChangePassword",RAP_SamOEMChgPasswordUser2_P
,api_SamOEMChangePassword
}, /* anon OK */
4855 {NULL
, -1, api_Unsupported
}
4856 /* The following RAP calls are not implemented by Samba:
4858 RAP_WFileEnum2 - anon not OK
4863 /****************************************************************************
4864 Handle remote api calls.
4865 ****************************************************************************/
4867 void api_reply(connection_struct
*conn
, uint16 vuid
,
4868 struct smb_request
*req
,
4869 char *data
, char *params
,
4870 int tdscnt
, int tpscnt
,
4871 int mdrcnt
, int mprcnt
)
4873 struct smbd_server_connection
*sconn
= smbd_server_conn
;
4876 char *rparam
= NULL
;
4877 const char *name1
= NULL
;
4878 const char *name2
= NULL
;
4885 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
4886 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4891 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4894 api_command
= SVAL(params
,0);
4895 /* Is there a string at position params+2 ? */
4896 if (skip_string(params
,tpscnt
,params
+2)) {
4901 name2
= skip_string(params
,tpscnt
,params
+2);
4906 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
4910 tdscnt
,tpscnt
,mdrcnt
,mprcnt
));
4912 for (i
=0;api_commands
[i
].name
;i
++) {
4913 if (api_commands
[i
].id
== api_command
&& api_commands
[i
].fn
) {
4914 DEBUG(3,("Doing %s\n",api_commands
[i
].name
));
4919 /* Check whether this api call can be done anonymously */
4921 if (api_commands
[i
].auth_user
&& lp_restrict_anonymous()) {
4922 user_struct
*user
= get_valid_user_struct(sconn
, vuid
);
4924 if (!user
|| user
->server_info
->guest
) {
4925 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4930 rdata
= (char *)SMB_MALLOC(1024);
4932 memset(rdata
,'\0',1024);
4935 rparam
= (char *)SMB_MALLOC(1024);
4937 memset(rparam
,'\0',1024);
4940 if(!rdata
|| !rparam
) {
4941 DEBUG(0,("api_reply: malloc fail !\n"));
4944 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4948 reply
= api_commands
[i
].fn(conn
,
4950 params
,tpscnt
, /* params + length */
4951 data
,tdscnt
, /* data + length */
4953 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
4956 if (rdata_len
> mdrcnt
|| rparam_len
> mprcnt
) {
4957 reply
= api_TooSmall(conn
,vuid
,params
,data
,mdrcnt
,mprcnt
,
4958 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
4961 /* if we get False back then it's actually unsupported */
4963 reply
= api_Unsupported(conn
,vuid
,params
,tpscnt
,data
,tdscnt
,mdrcnt
,mprcnt
,
4964 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
4967 /* If api_Unsupported returns false we can't return anything. */
4969 send_trans_reply(conn
, req
, rparam
, rparam_len
,
4970 rdata
, rdata_len
, False
);