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
)
1357 return strcasecmp(s1
->name
,s2
->name
);
1360 /****************************************************************************
1361 View list of servers available (or possibly domains). The info is
1362 extracted from lists saved by nmbd on the local host.
1363 ****************************************************************************/
1365 static bool api_RNetServerEnum2(connection_struct
*conn
, uint16 vuid
,
1366 char *param
, int tpscnt
,
1367 char *data
, int tdscnt
,
1368 int mdrcnt
, int mprcnt
, char **rdata
,
1369 char **rparam
, int *rdata_len
, int *rparam_len
)
1371 char *str1
= get_safe_str_ptr(param
, tpscnt
, param
, 2);
1372 char *str2
= skip_string(param
,tpscnt
,str1
);
1373 char *p
= skip_string(param
,tpscnt
,str2
);
1374 int uLevel
= get_safe_SVAL(param
, tpscnt
, p
, 0, -1);
1375 int buf_len
= get_safe_SVAL(param
,tpscnt
, p
, 2, 0);
1376 uint32 servertype
= get_safe_IVAL(param
,tpscnt
,p
,4, 0);
1378 int data_len
, fixed_len
, string_len
;
1379 int f_len
= 0, s_len
= 0;
1380 struct srv_info_struct
*servers
=NULL
;
1381 int counted
=0,total
=0;
1384 bool domain_request
;
1387 if (!str1
|| !str2
|| !p
) {
1391 /* If someone sets all the bits they don't really mean to set
1392 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1395 if (servertype
== SV_TYPE_ALL
) {
1396 servertype
&= ~(SV_TYPE_DOMAIN_ENUM
|SV_TYPE_LOCAL_LIST_ONLY
);
1399 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1400 any other bit (they may just set this bit on its own) they
1401 want all the locally seen servers. However this bit can be
1402 set on its own so set the requested servers to be
1403 ALL - DOMAIN_ENUM. */
1405 if ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) && !(servertype
& SV_TYPE_DOMAIN_ENUM
)) {
1406 servertype
= SV_TYPE_ALL
& ~(SV_TYPE_DOMAIN_ENUM
);
1409 domain_request
= ((servertype
& SV_TYPE_DOMAIN_ENUM
) != 0);
1410 local_request
= ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) != 0);
1414 if (!prefix_ok(str1
,"WrLehD")) {
1417 if (!check_server_info(uLevel
,str2
)) {
1421 DEBUG(4, ("server request level: %s %8x ", str2
, servertype
));
1422 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request
)));
1423 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request
)));
1425 if (strcmp(str1
, "WrLehDz") == 0) {
1426 if (skip_string(param
,tpscnt
,p
) == NULL
) {
1429 pull_ascii_fstring(domain
, p
);
1431 fstrcpy(domain
, lp_workgroup());
1434 DEBUG(4, ("domain [%s]\n", domain
));
1436 if (lp_browse_list()) {
1437 total
= get_server_info(servertype
,&servers
,domain
);
1440 data_len
= fixed_len
= string_len
= 0;
1444 qsort(servers
,total
,sizeof(servers
[0]),QSORT_CAST srv_comp
);
1448 char *lastname
=NULL
;
1450 for (i
=0;i
<total
;i
++) {
1451 struct srv_info_struct
*s
= &servers
[i
];
1453 if (lastname
&& strequal(lastname
,s
->name
)) {
1457 data_len
+= fill_srv_info(s
,uLevel
,0,&f_len
,0,&s_len
,0);
1458 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1459 i
, s
->name
, s
->type
, s
->comment
, s
->domain
));
1461 if (data_len
<= buf_len
) {
1464 string_len
+= s_len
;
1471 *rdata_len
= fixed_len
+ string_len
;
1472 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
1477 p2
= (*rdata
) + fixed_len
; /* auxilliary data (strings) will go here */
1483 char *lastname
=NULL
;
1484 int count2
= counted
;
1486 for (i
= 0; i
< total
&& count2
;i
++) {
1487 struct srv_info_struct
*s
= &servers
[i
];
1489 if (lastname
&& strequal(lastname
,s
->name
)) {
1493 fill_srv_info(s
,uLevel
,&p
,&f_len
,&p2
,&s_len
,*rdata
);
1494 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1495 i
, s
->name
, s
->type
, s
->comment
, s
->domain
));
1501 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1505 SSVAL(*rparam
,0,(missed
== 0 ? NERR_Success
: ERRmoredata
));
1507 SSVAL(*rparam
,4,counted
);
1508 SSVAL(*rparam
,6,counted
+missed
);
1512 DEBUG(3,("NetServerEnum2 domain = %s uLevel=%d counted=%d total=%d\n",
1513 domain
,uLevel
,counted
,counted
+missed
));
1518 static int srv_name_match(const char *n1
, const char *n2
)
1521 * [MS-RAP] footnote <88> for Section 3.2.5.15 says:
1523 * In Windows, FirstNameToReturn need not be an exact match:
1524 * the server will return a list of servers that exist on
1525 * the network greater than or equal to the FirstNameToReturn.
1527 int ret
= strcasecmp(n1
, n2
);
1536 static bool api_RNetServerEnum3(connection_struct
*conn
, uint16 vuid
,
1537 char *param
, int tpscnt
,
1538 char *data
, int tdscnt
,
1539 int mdrcnt
, int mprcnt
, char **rdata
,
1540 char **rparam
, int *rdata_len
, int *rparam_len
)
1542 char *str1
= get_safe_str_ptr(param
, tpscnt
, param
, 2);
1543 char *str2
= skip_string(param
,tpscnt
,str1
);
1544 char *p
= skip_string(param
,tpscnt
,str2
);
1545 int uLevel
= get_safe_SVAL(param
, tpscnt
, p
, 0, -1);
1546 int buf_len
= get_safe_SVAL(param
,tpscnt
, p
, 2, 0);
1547 uint32 servertype
= get_safe_IVAL(param
,tpscnt
,p
,4, 0);
1549 int data_len
, fixed_len
, string_len
;
1550 int f_len
= 0, s_len
= 0;
1551 struct srv_info_struct
*servers
=NULL
;
1552 int counted
=0,first
=0,total
=0;
1556 bool domain_request
;
1559 if (!str1
|| !str2
|| !p
) {
1563 /* If someone sets all the bits they don't really mean to set
1564 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1567 if (servertype
== SV_TYPE_ALL
) {
1568 servertype
&= ~(SV_TYPE_DOMAIN_ENUM
|SV_TYPE_LOCAL_LIST_ONLY
);
1571 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1572 any other bit (they may just set this bit on its own) they
1573 want all the locally seen servers. However this bit can be
1574 set on its own so set the requested servers to be
1575 ALL - DOMAIN_ENUM. */
1577 if ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) && !(servertype
& SV_TYPE_DOMAIN_ENUM
)) {
1578 servertype
= SV_TYPE_ALL
& ~(SV_TYPE_DOMAIN_ENUM
);
1581 domain_request
= ((servertype
& SV_TYPE_DOMAIN_ENUM
) != 0);
1582 local_request
= ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) != 0);
1586 if (strcmp(str1
, "WrLehDzz") != 0) {
1589 if (!check_server_info(uLevel
,str2
)) {
1593 DEBUG(4, ("server request level: %s %8x ", str2
, servertype
));
1594 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request
)));
1595 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request
)));
1597 if (skip_string(param
,tpscnt
,p
) == NULL
) {
1600 pull_ascii_fstring(domain
, p
);
1601 if (domain
[0] == '\0') {
1602 fstrcpy(domain
, lp_workgroup());
1604 p
= skip_string(param
,tpscnt
,p
);
1605 if (skip_string(param
,tpscnt
,p
) == NULL
) {
1608 pull_ascii_fstring(first_name
, p
);
1610 DEBUG(4, ("domain: '%s' first_name: '%s'\n",
1611 domain
, first_name
));
1613 if (lp_browse_list()) {
1614 total
= get_server_info(servertype
,&servers
,domain
);
1617 data_len
= fixed_len
= string_len
= 0;
1621 qsort(servers
,total
,sizeof(servers
[0]),QSORT_CAST srv_comp
);
1624 if (first_name
[0] != '\0') {
1625 struct srv_info_struct
*first_server
= NULL
;
1627 BINARY_ARRAY_SEARCH(servers
, total
, name
, first_name
,
1628 srv_name_match
, first_server
);
1630 first
= PTR_DIFF(first_server
, servers
) / sizeof(*servers
);
1632 * The binary search may not find the exact match
1633 * so we need to search backward to find the first match
1635 * This implements the strange matching windows
1636 * implements. (see the comment in srv_name_match().
1640 ret
= strcasecmp(first_name
,
1641 servers
[first
-1].name
);
1648 /* we should return no entries */
1654 char *lastname
=NULL
;
1656 for (i
=first
;i
<total
;i
++) {
1657 struct srv_info_struct
*s
= &servers
[i
];
1659 if (lastname
&& strequal(lastname
,s
->name
)) {
1663 data_len
+= fill_srv_info(s
,uLevel
,0,&f_len
,0,&s_len
,0);
1664 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1665 i
, s
->name
, s
->type
, s
->comment
, s
->domain
));
1667 if (data_len
<= buf_len
) {
1670 string_len
+= s_len
;
1677 *rdata_len
= fixed_len
+ string_len
;
1678 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
1683 p2
= (*rdata
) + fixed_len
; /* auxilliary data (strings) will go here */
1689 char *lastname
=NULL
;
1690 int count2
= counted
;
1692 for (i
= first
; i
< total
&& count2
;i
++) {
1693 struct srv_info_struct
*s
= &servers
[i
];
1695 if (lastname
&& strequal(lastname
,s
->name
)) {
1699 fill_srv_info(s
,uLevel
,&p
,&f_len
,&p2
,&s_len
,*rdata
);
1700 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1701 i
, s
->name
, s
->type
, s
->comment
, s
->domain
));
1707 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1711 SSVAL(*rparam
,0,(missed
== 0 ? NERR_Success
: ERRmoredata
));
1713 SSVAL(*rparam
,4,counted
);
1714 SSVAL(*rparam
,6,counted
+missed
);
1716 DEBUG(3,("NetServerEnum3 domain = %s uLevel=%d first=%d[%s => %s] counted=%d total=%d\n",
1717 domain
,uLevel
,first
,first_name
,
1718 first
< total
? servers
[first
].name
: "",
1719 counted
,counted
+missed
));
1726 /****************************************************************************
1727 command 0x34 - suspected of being a "Lookup Names" stub api
1728 ****************************************************************************/
1730 static bool api_RNetGroupGetUsers(connection_struct
*conn
, uint16 vuid
,
1731 char *param
, int tpscnt
,
1732 char *data
, int tdscnt
,
1733 int mdrcnt
, int mprcnt
, char **rdata
,
1734 char **rparam
, int *rdata_len
, int *rparam_len
)
1736 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
1737 char *str2
= skip_string(param
,tpscnt
,str1
);
1738 char *p
= skip_string(param
,tpscnt
,str2
);
1739 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
1740 int buf_len
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
1744 if (!str1
|| !str2
|| !p
) {
1748 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1749 str1
, str2
, p
, uLevel
, buf_len
));
1751 if (!prefix_ok(str1
,"zWrLeh")) {
1758 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1763 SSVAL(*rparam
,0,0x08AC); /* informational warning message */
1765 SSVAL(*rparam
,4,counted
);
1766 SSVAL(*rparam
,6,counted
+missed
);
1771 /****************************************************************************
1772 get info about a share
1773 ****************************************************************************/
1775 static bool check_share_info(int uLevel
, char* id
)
1779 if (strcmp(id
,"B13") != 0) {
1784 /* Level-2 descriptor is allowed (and ignored) */
1785 if (strcmp(id
,"B13BWz") != 0 &&
1786 strcmp(id
,"B13BWzWWWzB9B") != 0) {
1791 if (strcmp(id
,"B13BWzWWWzB9B") != 0) {
1796 if (strcmp(id
,"B13BWzWWWzB9BB9BWzWWzWW") != 0) {
1806 static int fill_share_info(connection_struct
*conn
, int snum
, int uLevel
,
1807 char** buf
, int* buflen
,
1808 char** stringbuf
, int* stringspace
, char* baseaddr
)
1837 len
+= StrlenExpanded(conn
,snum
,lp_comment(snum
));
1840 len
+= strlen(lp_pathname(snum
)) + 1;
1843 *buflen
= struct_len
;
1848 return struct_len
+ len
;
1853 if ((*buflen
) < struct_len
) {
1861 p2
= p
+ struct_len
;
1862 l2
= (*buflen
) - struct_len
;
1869 push_ascii(p
,lp_servicename(snum
),13, STR_TERMINATE
);
1875 type
= STYPE_DISKTREE
;
1876 if (lp_print_ok(snum
)) {
1877 type
= STYPE_PRINTQ
;
1879 if (strequal("IPC",lp_fstype(snum
))) {
1882 SSVAL(p
,14,type
); /* device type */
1883 SIVAL(p
,16,PTR_DIFF(p2
,baseaddr
));
1884 len
+= CopyExpanded(conn
,snum
,&p2
,lp_comment(snum
),&l2
);
1888 SSVAL(p
,20,ACCESS_READ
|ACCESS_WRITE
|ACCESS_CREATE
); /* permissions */
1889 SSVALS(p
,22,-1); /* max uses */
1890 SSVAL(p
,24,1); /* current uses */
1891 SIVAL(p
,26,PTR_DIFF(p2
,baseaddr
)); /* local pathname */
1892 len
+= CopyAndAdvance(&p2
,lp_pathname(snum
),&l2
);
1893 memset(p
+30,0,SHPWLEN
+2); /* passwd (reserved), pad field */
1897 memset(p
+40,0,SHPWLEN
+2);
1908 (*buf
) = p
+ struct_len
;
1909 (*buflen
) -= struct_len
;
1911 (*stringspace
) = l2
;
1920 static bool api_RNetShareGetInfo(connection_struct
*conn
,uint16 vuid
,
1921 char *param
, int tpscnt
,
1922 char *data
, int tdscnt
,
1923 int mdrcnt
,int mprcnt
,
1924 char **rdata
,char **rparam
,
1925 int *rdata_len
,int *rparam_len
)
1927 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
1928 char *str2
= skip_string(param
,tpscnt
,str1
);
1929 char *netname
= skip_string(param
,tpscnt
,str2
);
1930 char *p
= skip_string(param
,tpscnt
,netname
);
1931 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
1934 if (!str1
|| !str2
|| !netname
|| !p
) {
1938 snum
= find_service(netname
);
1943 /* check it's a supported varient */
1944 if (!prefix_ok(str1
,"zWrLh")) {
1947 if (!check_share_info(uLevel
,str2
)) {
1951 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
1956 *rdata_len
= fill_share_info(conn
,snum
,uLevel
,&p
,&mdrcnt
,0,0,0);
1957 if (*rdata_len
< 0) {
1962 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1966 SSVAL(*rparam
,0,NERR_Success
);
1967 SSVAL(*rparam
,2,0); /* converter word */
1968 SSVAL(*rparam
,4,*rdata_len
);
1973 /****************************************************************************
1974 View the list of available shares.
1976 This function is the server side of the NetShareEnum() RAP call.
1977 It fills the return buffer with share names and share comments.
1978 Note that the return buffer normally (in all known cases) allows only
1979 twelve byte strings for share names (plus one for a nul terminator).
1980 Share names longer than 12 bytes must be skipped.
1981 ****************************************************************************/
1983 static bool api_RNetShareEnum( connection_struct
*conn
, uint16 vuid
,
1984 char *param
, int tpscnt
,
1985 char *data
, int tdscnt
,
1993 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
1994 char *str2
= skip_string(param
,tpscnt
,str1
);
1995 char *p
= skip_string(param
,tpscnt
,str2
);
1996 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
1997 int buf_len
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
2000 int total
=0,counted
=0;
2001 bool missed
= False
;
2003 int data_len
, fixed_len
, string_len
;
2004 int f_len
= 0, s_len
= 0;
2006 if (!str1
|| !str2
|| !p
) {
2010 if (!prefix_ok(str1
,"WrLeh")) {
2013 if (!check_share_info(uLevel
,str2
)) {
2017 /* Ensure all the usershares are loaded. */
2019 load_registry_shares();
2020 count
= load_usershare_shares();
2023 data_len
= fixed_len
= string_len
= 0;
2024 for (i
=0;i
<count
;i
++) {
2025 fstring servicename_dos
;
2026 if (!(lp_browseable(i
) && lp_snum_ok(i
))) {
2029 push_ascii_fstring(servicename_dos
, lp_servicename(i
));
2030 /* Maximum name length = 13. */
2031 if( lp_browseable( i
) && lp_snum_ok( i
) && (strlen(servicename_dos
) < 13)) {
2033 data_len
+= fill_share_info(conn
,i
,uLevel
,0,&f_len
,0,&s_len
,0);
2034 if (data_len
<= buf_len
) {
2037 string_len
+= s_len
;
2044 *rdata_len
= fixed_len
+ string_len
;
2045 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2050 p2
= (*rdata
) + fixed_len
; /* auxiliary data (strings) will go here */
2055 for( i
= 0; i
< count
; i
++ ) {
2056 fstring servicename_dos
;
2057 if (!(lp_browseable(i
) && lp_snum_ok(i
))) {
2061 push_ascii_fstring(servicename_dos
, lp_servicename(i
));
2062 if (lp_browseable(i
) && lp_snum_ok(i
) && (strlen(servicename_dos
) < 13)) {
2063 if (fill_share_info( conn
,i
,uLevel
,&p
,&f_len
,&p2
,&s_len
,*rdata
) < 0) {
2070 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2074 SSVAL(*rparam
,0,missed
? ERRmoredata
: NERR_Success
);
2076 SSVAL(*rparam
,4,counted
);
2077 SSVAL(*rparam
,6,total
);
2079 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
2080 counted
,total
,uLevel
,
2081 buf_len
,*rdata_len
,mdrcnt
));
2086 /****************************************************************************
2088 ****************************************************************************/
2090 static bool api_RNetShareAdd(connection_struct
*conn
,uint16 vuid
,
2091 char *param
, int tpscnt
,
2092 char *data
, int tdscnt
,
2093 int mdrcnt
,int mprcnt
,
2094 char **rdata
,char **rparam
,
2095 int *rdata_len
,int *rparam_len
)
2097 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2098 char *str2
= skip_string(param
,tpscnt
,str1
);
2099 char *p
= skip_string(param
,tpscnt
,str2
);
2100 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2103 char *pathname
= NULL
;
2104 char *command
, *cmdname
;
2105 unsigned int offset
;
2108 size_t converted_size
;
2110 if (!str1
|| !str2
|| !p
) {
2114 /* check it's a supported varient */
2115 if (!prefix_ok(str1
,RAP_WShareAdd_REQ
)) {
2118 if (!check_share_info(uLevel
,str2
)) {
2125 /* Do we have a string ? */
2126 if (skip_string(data
,mdrcnt
,data
) == NULL
) {
2129 pull_ascii_fstring(sharename
,data
);
2130 snum
= find_service(sharename
);
2131 if (snum
>= 0) { /* already exists */
2140 /* only support disk share adds */
2141 if (SVAL(data
,14)!=STYPE_DISKTREE
) {
2145 offset
= IVAL(data
, 16);
2146 if (offset
>= mdrcnt
) {
2147 res
= ERRinvalidparam
;
2151 /* Do we have a string ? */
2152 if (skip_string(data
,mdrcnt
,data
+offset
) == NULL
) {
2155 pull_ascii_fstring(comment
, offset
? (data
+offset
) : "");
2157 offset
= IVAL(data
, 26);
2159 if (offset
>= mdrcnt
) {
2160 res
= ERRinvalidparam
;
2164 /* Do we have a string ? */
2165 if (skip_string(data
,mdrcnt
,data
+offset
) == NULL
) {
2169 if (!pull_ascii_talloc(talloc_tos(), &pathname
,
2170 offset
? (data
+offset
) : "", &converted_size
))
2172 DEBUG(0,("api_RNetShareAdd: pull_ascii_talloc failed: %s",
2180 string_replace(sharename
, '"', ' ');
2181 string_replace(pathname
, '"', ' ');
2182 string_replace(comment
, '"', ' ');
2184 cmdname
= lp_add_share_cmd();
2186 if (!cmdname
|| *cmdname
== '\0') {
2190 if (asprintf(&command
, "%s \"%s\" \"%s\" \"%s\" \"%s\"",
2191 lp_add_share_cmd(), get_dyn_CONFIGFILE(), sharename
,
2192 pathname
, comment
) == -1) {
2196 DEBUG(10,("api_RNetShareAdd: Running [%s]\n", command
));
2198 if ((res
= smbrun(command
, NULL
)) != 0) {
2199 DEBUG(1,("api_RNetShareAdd: Running [%s] returned (%d)\n",
2206 message_send_all(smbd_messaging_context(),
2207 MSG_SMB_CONF_UPDATED
, NULL
, 0, NULL
);
2211 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2215 SSVAL(*rparam
,0,NERR_Success
);
2216 SSVAL(*rparam
,2,0); /* converter word */
2217 SSVAL(*rparam
,4,*rdata_len
);
2225 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2230 SSVAL(*rparam
,0,res
);
2235 /****************************************************************************
2236 view list of groups available
2237 ****************************************************************************/
2239 static bool api_RNetGroupEnum(connection_struct
*conn
,uint16 vuid
,
2240 char *param
, int tpscnt
,
2241 char *data
, int tdscnt
,
2242 int mdrcnt
,int mprcnt
,
2243 char **rdata
,char **rparam
,
2244 int *rdata_len
,int *rparam_len
)
2248 int resume_context
, cli_buf_size
;
2249 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2250 char *str2
= skip_string(param
,tpscnt
,str1
);
2251 char *p
= skip_string(param
,tpscnt
,str2
);
2253 uint32_t num_groups
;
2254 uint32_t resume_handle
;
2255 struct rpc_pipe_client
*samr_pipe
;
2256 struct policy_handle samr_handle
, domain_handle
;
2259 if (!str1
|| !str2
|| !p
) {
2263 if (strcmp(str1
,"WrLeh") != 0) {
2268 * W-> resume context (number of users to skip)
2269 * r -> return parameter pointer to receive buffer
2270 * L -> length of receive buffer
2271 * e -> return parameter number of entries
2272 * h -> return parameter total number of users
2275 if (strcmp("B21",str2
) != 0) {
2279 status
= rpc_pipe_open_internal(
2280 talloc_tos(), &ndr_table_samr
.syntax_id
, rpc_samr_dispatch
,
2281 conn
->server_info
, &samr_pipe
);
2282 if (!NT_STATUS_IS_OK(status
)) {
2283 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2284 nt_errstr(status
)));
2288 status
= rpccli_samr_Connect2(samr_pipe
, talloc_tos(), global_myname(),
2289 SAMR_ACCESS_LOOKUP_DOMAIN
, &samr_handle
);
2290 if (!NT_STATUS_IS_OK(status
)) {
2291 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2292 nt_errstr(status
)));
2296 status
= rpccli_samr_OpenDomain(samr_pipe
, talloc_tos(), &samr_handle
,
2297 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS
,
2298 get_global_sam_sid(), &domain_handle
);
2299 if (!NT_STATUS_IS_OK(status
)) {
2300 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2301 nt_errstr(status
)));
2302 rpccli_samr_Close(samr_pipe
, talloc_tos(), &samr_handle
);
2306 resume_context
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2307 cli_buf_size
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
2308 DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: "
2309 "%d\n", resume_context
, cli_buf_size
));
2311 *rdata_len
= cli_buf_size
;
2312 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2319 errflags
= NERR_Success
;
2324 struct samr_SamArray
*sam_entries
;
2325 uint32_t num_entries
;
2327 status
= rpccli_samr_EnumDomainGroups(samr_pipe
, talloc_tos(),
2332 if (!NT_STATUS_IS_OK(status
)) {
2333 DEBUG(10, ("rpccli_samr_EnumDomainGroups returned "
2334 "%s\n", nt_errstr(status
)));
2338 if (num_entries
== 0) {
2339 DEBUG(10, ("rpccli_samr_EnumDomainGroups returned "
2340 "no entries -- done\n"));
2344 for(i
=0; i
<num_entries
; i
++) {
2347 name
= sam_entries
->entries
[i
].name
.string
;
2349 if( ((PTR_DIFF(p
,*rdata
)+21) > *rdata_len
) ) {
2350 /* set overflow error */
2351 DEBUG(3,("overflow on entry %d group %s\n", i
,
2357 /* truncate the name at 21 chars. */
2359 strlcpy(p
, name
, 21);
2360 DEBUG(10,("adding entry %d group %s\n", i
, p
));
2362 p
+= 5; /* Both NT4 and W2k3SP1 do padding here. No
2367 if (errflags
!= NERR_Success
) {
2371 TALLOC_FREE(sam_entries
);
2374 rpccli_samr_Close(samr_pipe
, talloc_tos(), &domain_handle
);
2375 rpccli_samr_Close(samr_pipe
, talloc_tos(), &samr_handle
);
2377 *rdata_len
= PTR_DIFF(p
,*rdata
);
2380 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2384 SSVAL(*rparam
, 0, errflags
);
2385 SSVAL(*rparam
, 2, 0); /* converter word */
2386 SSVAL(*rparam
, 4, num_groups
); /* is this right?? */
2387 SSVAL(*rparam
, 6, resume_context
+num_groups
); /* is this right?? */
2392 /*******************************************************************
2393 Get groups that a user is a member of.
2394 ******************************************************************/
2396 static bool api_NetUserGetGroups(connection_struct
*conn
,uint16 vuid
,
2397 char *param
, int tpscnt
,
2398 char *data
, int tdscnt
,
2399 int mdrcnt
,int mprcnt
,
2400 char **rdata
,char **rparam
,
2401 int *rdata_len
,int *rparam_len
)
2403 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2404 char *str2
= skip_string(param
,tpscnt
,str1
);
2405 char *UserName
= skip_string(param
,tpscnt
,str2
);
2406 char *p
= skip_string(param
,tpscnt
,UserName
);
2407 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2408 const char *level_string
;
2414 struct rpc_pipe_client
*samr_pipe
;
2415 struct policy_handle samr_handle
, domain_handle
, user_handle
;
2416 struct lsa_String name
;
2417 struct lsa_Strings names
;
2418 struct samr_Ids type
, rid
;
2419 struct samr_RidWithAttributeArray
*rids
;
2422 if (!str1
|| !str2
|| !UserName
|| !p
) {
2427 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2432 /* check it's a supported varient */
2434 if ( strcmp(str1
,"zWrLeh") != 0 )
2439 level_string
= "B21";
2445 if (strcmp(level_string
,str2
) != 0)
2448 *rdata_len
= mdrcnt
+ 1024;
2449 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2454 SSVAL(*rparam
,0,NERR_Success
);
2455 SSVAL(*rparam
,2,0); /* converter word */
2458 endp
= *rdata
+ *rdata_len
;
2460 status
= rpc_pipe_open_internal(
2461 talloc_tos(), &ndr_table_samr
.syntax_id
, rpc_samr_dispatch
,
2462 conn
->server_info
, &samr_pipe
);
2463 if (!NT_STATUS_IS_OK(status
)) {
2464 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2465 nt_errstr(status
)));
2469 status
= rpccli_samr_Connect2(samr_pipe
, talloc_tos(), global_myname(),
2470 SAMR_ACCESS_LOOKUP_DOMAIN
, &samr_handle
);
2471 if (!NT_STATUS_IS_OK(status
)) {
2472 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2473 nt_errstr(status
)));
2477 status
= rpccli_samr_OpenDomain(samr_pipe
, talloc_tos(), &samr_handle
,
2478 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT
,
2479 get_global_sam_sid(), &domain_handle
);
2480 if (!NT_STATUS_IS_OK(status
)) {
2481 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2482 nt_errstr(status
)));
2486 name
.string
= UserName
;
2488 status
= rpccli_samr_LookupNames(samr_pipe
, talloc_tos(),
2489 &domain_handle
, 1, &name
,
2491 if (!NT_STATUS_IS_OK(status
)) {
2492 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2493 nt_errstr(status
)));
2497 if (type
.ids
[0] != SID_NAME_USER
) {
2498 DEBUG(10, ("%s is a %s, not a user\n", UserName
,
2499 sid_type_lookup(type
.ids
[0])));
2503 status
= rpccli_samr_OpenUser(samr_pipe
, talloc_tos(),
2505 SAMR_USER_ACCESS_GET_GROUPS
,
2506 rid
.ids
[0], &user_handle
);
2507 if (!NT_STATUS_IS_OK(status
)) {
2508 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2509 nt_errstr(status
)));
2513 status
= rpccli_samr_GetGroupsForUser(samr_pipe
, talloc_tos(),
2514 &user_handle
, &rids
);
2515 if (!NT_STATUS_IS_OK(status
)) {
2516 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2517 nt_errstr(status
)));
2521 for (i
=0; i
<rids
->count
; i
++) {
2523 status
= rpccli_samr_LookupRids(samr_pipe
, talloc_tos(),
2525 1, &rids
->rids
[i
].rid
,
2527 if (NT_STATUS_IS_OK(status
) && (names
.count
== 1)) {
2528 strlcpy(p
, names
.names
[0].string
, PTR_DIFF(endp
,p
));
2534 *rdata_len
= PTR_DIFF(p
,*rdata
);
2536 SSVAL(*rparam
,4,count
); /* is this right?? */
2537 SSVAL(*rparam
,6,count
); /* is this right?? */
2542 rpccli_samr_Close(samr_pipe
, talloc_tos(), &user_handle
);
2544 rpccli_samr_Close(samr_pipe
, talloc_tos(), &domain_handle
);
2546 rpccli_samr_Close(samr_pipe
, talloc_tos(), &samr_handle
);
2551 /*******************************************************************
2553 ******************************************************************/
2555 static bool api_RNetUserEnum(connection_struct
*conn
, uint16 vuid
,
2556 char *param
, int tpscnt
,
2557 char *data
, int tdscnt
,
2558 int mdrcnt
,int mprcnt
,
2559 char **rdata
,char **rparam
,
2560 int *rdata_len
,int *rparam_len
)
2565 int i
, resume_context
, cli_buf_size
;
2566 uint32_t resume_handle
;
2568 struct rpc_pipe_client
*samr_pipe
;
2569 struct policy_handle samr_handle
, domain_handle
;
2572 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2573 char *str2
= skip_string(param
,tpscnt
,str1
);
2574 char *p
= skip_string(param
,tpscnt
,str2
);
2577 if (!str1
|| !str2
|| !p
) {
2581 if (strcmp(str1
,"WrLeh") != 0)
2584 * W-> resume context (number of users to skip)
2585 * r -> return parameter pointer to receive buffer
2586 * L -> length of receive buffer
2587 * e -> return parameter number of entries
2588 * h -> return parameter total number of users
2591 resume_context
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2592 cli_buf_size
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
2593 DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n",
2594 resume_context
, cli_buf_size
));
2597 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2602 /* check it's a supported varient */
2603 if (strcmp("B21",str2
) != 0)
2606 *rdata_len
= cli_buf_size
;
2607 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2613 endp
= *rdata
+ *rdata_len
;
2615 status
= rpc_pipe_open_internal(
2616 talloc_tos(), &ndr_table_samr
.syntax_id
, rpc_samr_dispatch
,
2617 conn
->server_info
, &samr_pipe
);
2618 if (!NT_STATUS_IS_OK(status
)) {
2619 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2620 nt_errstr(status
)));
2624 status
= rpccli_samr_Connect2(samr_pipe
, talloc_tos(), global_myname(),
2625 SAMR_ACCESS_LOOKUP_DOMAIN
, &samr_handle
);
2626 if (!NT_STATUS_IS_OK(status
)) {
2627 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2628 nt_errstr(status
)));
2632 status
= rpccli_samr_OpenDomain(samr_pipe
, talloc_tos(), &samr_handle
,
2633 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS
,
2634 get_global_sam_sid(), &domain_handle
);
2635 if (!NT_STATUS_IS_OK(status
)) {
2636 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2637 nt_errstr(status
)));
2638 rpccli_samr_Close(samr_pipe
, talloc_tos(), &samr_handle
);
2642 errflags
=NERR_Success
;
2647 struct samr_SamArray
*sam_entries
;
2648 uint32_t num_entries
;
2650 status
= rpccli_samr_EnumDomainUsers(samr_pipe
, talloc_tos(),
2656 if (!NT_STATUS_IS_OK(status
)) {
2657 DEBUG(10, ("rpccli_samr_EnumDomainUsers returned "
2658 "%s\n", nt_errstr(status
)));
2662 if (num_entries
== 0) {
2663 DEBUG(10, ("rpccli_samr_EnumDomainUsers returned "
2664 "no entries -- done\n"));
2668 for (i
=0; i
<num_entries
; i
++) {
2671 name
= sam_entries
->entries
[i
].name
.string
;
2673 if(((PTR_DIFF(p
,*rdata
)+21)<=*rdata_len
)
2674 &&(strlen(name
)<=21)) {
2675 strlcpy(p
,name
,PTR_DIFF(endp
,p
));
2676 DEBUG(10,("api_RNetUserEnum:adding entry %d "
2677 "username %s\n",count_sent
,p
));
2681 /* set overflow error */
2682 DEBUG(10,("api_RNetUserEnum:overflow on entry %d "
2683 "username %s\n",count_sent
,name
));
2689 if (errflags
!= NERR_Success
) {
2693 TALLOC_FREE(sam_entries
);
2696 rpccli_samr_Close(samr_pipe
, talloc_tos(), &domain_handle
);
2697 rpccli_samr_Close(samr_pipe
, talloc_tos(), &samr_handle
);
2699 *rdata_len
= PTR_DIFF(p
,*rdata
);
2701 SSVAL(*rparam
,0,errflags
);
2702 SSVAL(*rparam
,2,0); /* converter word */
2703 SSVAL(*rparam
,4,count_sent
); /* is this right?? */
2704 SSVAL(*rparam
,6,num_users
); /* is this right?? */
2709 /****************************************************************************
2710 Get the time of day info.
2711 ****************************************************************************/
2713 static bool api_NetRemoteTOD(connection_struct
*conn
,uint16 vuid
,
2714 char *param
, int tpscnt
,
2715 char *data
, int tdscnt
,
2716 int mdrcnt
,int mprcnt
,
2717 char **rdata
,char **rparam
,
2718 int *rdata_len
,int *rparam_len
)
2721 time_t unixdate
= time(NULL
);
2725 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2731 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2736 SSVAL(*rparam
,0,NERR_Success
);
2737 SSVAL(*rparam
,2,0); /* converter word */
2741 srv_put_dos_date3(p
,0,unixdate
); /* this is the time that is looked at
2742 by NT in a "net time" operation,
2743 it seems to ignore the one below */
2745 /* the client expects to get localtime, not GMT, in this bit
2746 (I think, this needs testing) */
2747 t
= localtime(&unixdate
);
2752 SIVAL(p
,4,0); /* msecs ? */
2753 SCVAL(p
,8,t
->tm_hour
);
2754 SCVAL(p
,9,t
->tm_min
);
2755 SCVAL(p
,10,t
->tm_sec
);
2756 SCVAL(p
,11,0); /* hundredths of seconds */
2757 SSVALS(p
,12,get_time_zone(unixdate
)/60); /* timezone in minutes from GMT */
2758 SSVAL(p
,14,10000); /* timer interval in 0.0001 of sec */
2759 SCVAL(p
,16,t
->tm_mday
);
2760 SCVAL(p
,17,t
->tm_mon
+ 1);
2761 SSVAL(p
,18,1900+t
->tm_year
);
2762 SCVAL(p
,20,t
->tm_wday
);
2767 /****************************************************************************
2768 Set the user password.
2769 *****************************************************************************/
2771 static bool api_SetUserPassword(connection_struct
*conn
,uint16 vuid
,
2772 char *param
, int tpscnt
,
2773 char *data
, int tdscnt
,
2774 int mdrcnt
,int mprcnt
,
2775 char **rdata
,char **rparam
,
2776 int *rdata_len
,int *rparam_len
)
2778 char *np
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2781 fstring pass1
,pass2
;
2783 /* Skip 2 strings. */
2784 p
= skip_string(param
,tpscnt
,np
);
2785 p
= skip_string(param
,tpscnt
,p
);
2791 /* Do we have a string ? */
2792 if (skip_string(param
,tpscnt
,p
) == NULL
) {
2795 pull_ascii_fstring(user
,p
);
2797 p
= skip_string(param
,tpscnt
,p
);
2802 memset(pass1
,'\0',sizeof(pass1
));
2803 memset(pass2
,'\0',sizeof(pass2
));
2805 * We use 31 here not 32 as we're checking
2806 * the last byte we want to access is safe.
2808 if (!is_offset_safe(param
,tpscnt
,p
,31)) {
2812 memcpy(pass2
,p
+16,16);
2815 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2822 SSVAL(*rparam
,0,NERR_badpass
);
2823 SSVAL(*rparam
,2,0); /* converter word */
2825 DEBUG(3,("Set password for <%s>\n",user
));
2828 * Attempt to verify the old password against smbpasswd entries
2829 * Win98 clients send old and new password in plaintext for this call.
2833 auth_serversupplied_info
*server_info
= NULL
;
2834 DATA_BLOB password
= data_blob(pass1
, strlen(pass1
)+1);
2836 if (NT_STATUS_IS_OK(check_plaintext_password(user
,password
,&server_info
))) {
2839 if (NT_STATUS_IS_OK(change_oem_password(server_info
->sam_account
, pass1
, pass2
, False
, NULL
))) {
2840 SSVAL(*rparam
,0,NERR_Success
);
2844 TALLOC_FREE(server_info
);
2846 data_blob_clear_free(&password
);
2850 * If the plaintext change failed, attempt
2851 * the old encrypted method. NT will generate this
2852 * after trying the samr method. Note that this
2853 * method is done as a last resort as this
2854 * password change method loses the NT password hash
2855 * and cannot change the UNIX password as no plaintext
2859 if(SVAL(*rparam
,0) != NERR_Success
) {
2860 struct samu
*hnd
= NULL
;
2862 if (check_lanman_password(user
,(unsigned char *)pass1
,(unsigned char *)pass2
, &hnd
)) {
2864 if (change_lanman_password(hnd
,(uchar
*)pass2
)) {
2865 SSVAL(*rparam
,0,NERR_Success
);
2872 memset((char *)pass1
,'\0',sizeof(fstring
));
2873 memset((char *)pass2
,'\0',sizeof(fstring
));
2878 /****************************************************************************
2879 Set the user password (SamOEM version - gets plaintext).
2880 ****************************************************************************/
2882 static bool api_SamOEMChangePassword(connection_struct
*conn
,uint16 vuid
,
2883 char *param
, int tpscnt
,
2884 char *data
, int tdscnt
,
2885 int mdrcnt
,int mprcnt
,
2886 char **rdata
,char **rparam
,
2887 int *rdata_len
,int *rparam_len
)
2889 struct smbd_server_connection
*sconn
= smbd_server_conn
;
2891 char *p
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2893 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2903 SSVAL(*rparam
,0,NERR_badpass
);
2906 * Check the parameter definition is correct.
2909 /* Do we have a string ? */
2910 if (skip_string(param
,tpscnt
,p
) == 0) {
2913 if(!strequal(p
, "zsT")) {
2914 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", p
));
2917 p
= skip_string(param
, tpscnt
, p
);
2922 /* Do we have a string ? */
2923 if (skip_string(param
,tpscnt
,p
) == 0) {
2926 if(!strequal(p
, "B516B16")) {
2927 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p
));
2930 p
= skip_string(param
,tpscnt
,p
);
2934 /* Do we have a string ? */
2935 if (skip_string(param
,tpscnt
,p
) == 0) {
2938 p
+= pull_ascii_fstring(user
,p
);
2940 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user
));
2943 * Pass the user through the NT -> unix user mapping
2947 (void)map_username(sconn
, user
);
2949 if (NT_STATUS_IS_OK(pass_oem_change(user
, (uchar
*) data
, (uchar
*)&data
[516], NULL
, NULL
, NULL
))) {
2950 SSVAL(*rparam
,0,NERR_Success
);
2956 /****************************************************************************
2959 ****************************************************************************/
2961 static bool api_RDosPrintJobDel(connection_struct
*conn
,uint16 vuid
,
2962 char *param
, int tpscnt
,
2963 char *data
, int tdscnt
,
2964 int mdrcnt
,int mprcnt
,
2965 char **rdata
,char **rparam
,
2966 int *rdata_len
,int *rparam_len
)
2968 int function
= get_safe_SVAL(param
,tpscnt
,param
,0,0);
2969 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2970 char *str2
= skip_string(param
,tpscnt
,str1
);
2971 char *p
= skip_string(param
,tpscnt
,str2
);
2976 WERROR werr
= WERR_OK
;
2978 if (!str1
|| !str2
|| !p
) {
2982 * We use 1 here not 2 as we're checking
2983 * the last byte we want to access is safe.
2985 if (!is_offset_safe(param
,tpscnt
,p
,1)) {
2988 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
))
2991 /* check it's a supported varient */
2992 if (!(strcsequal(str1
,"W") && strcsequal(str2
,"")))
2996 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3002 if (!print_job_exists(sharename
, jobid
)) {
3003 errcode
= NERR_JobNotFound
;
3007 snum
= lp_servicenumber( sharename
);
3009 errcode
= NERR_DestNotFound
;
3013 errcode
= NERR_notsupported
;
3016 case 81: /* delete */
3017 if (print_job_delete(conn
->server_info
, snum
, jobid
, &werr
))
3018 errcode
= NERR_Success
;
3020 case 82: /* pause */
3021 if (print_job_pause(conn
->server_info
, snum
, jobid
, &werr
))
3022 errcode
= NERR_Success
;
3024 case 83: /* resume */
3025 if (print_job_resume(conn
->server_info
, snum
, jobid
, &werr
))
3026 errcode
= NERR_Success
;
3030 if (!W_ERROR_IS_OK(werr
))
3031 errcode
= W_ERROR_V(werr
);
3034 SSVAL(*rparam
,0,errcode
);
3035 SSVAL(*rparam
,2,0); /* converter word */
3040 /****************************************************************************
3041 Purge a print queue - or pause or resume it.
3042 ****************************************************************************/
3044 static bool api_WPrintQueueCtrl(connection_struct
*conn
,uint16 vuid
,
3045 char *param
, int tpscnt
,
3046 char *data
, int tdscnt
,
3047 int mdrcnt
,int mprcnt
,
3048 char **rdata
,char **rparam
,
3049 int *rdata_len
,int *rparam_len
)
3051 int function
= get_safe_SVAL(param
,tpscnt
,param
,0,0);
3052 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3053 char *str2
= skip_string(param
,tpscnt
,str1
);
3054 char *QueueName
= skip_string(param
,tpscnt
,str2
);
3055 int errcode
= NERR_notsupported
;
3057 WERROR werr
= WERR_OK
;
3059 if (!str1
|| !str2
|| !QueueName
) {
3063 /* check it's a supported varient */
3064 if (!(strcsequal(str1
,"z") && strcsequal(str2
,"")))
3068 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3074 if (skip_string(param
,tpscnt
,QueueName
) == NULL
) {
3077 snum
= print_queue_snum(QueueName
);
3080 errcode
= NERR_JobNotFound
;
3085 case 74: /* Pause queue */
3086 werr
= print_queue_pause(conn
->server_info
, snum
);
3088 case 75: /* Resume queue */
3089 werr
= print_queue_resume(conn
->server_info
, snum
);
3091 case 103: /* Purge */
3092 werr
= print_queue_purge(conn
->server_info
, snum
);
3095 werr
= WERR_NOT_SUPPORTED
;
3099 errcode
= W_ERROR_V(werr
);
3102 SSVAL(*rparam
,0,errcode
);
3103 SSVAL(*rparam
,2,0); /* converter word */
3108 /****************************************************************************
3109 set the property of a print job (undocumented?)
3110 ? function = 0xb -> set name of print job
3111 ? function = 0x6 -> move print job up/down
3112 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
3113 or <WWsTP> <WB21BB16B10zWWzDDz>
3114 ****************************************************************************/
3116 static int check_printjob_info(struct pack_desc
* desc
,
3117 int uLevel
, char* id
)
3119 desc
->subformat
= NULL
;
3121 case 0: desc
->format
= "W"; break;
3122 case 1: desc
->format
= "WB21BB16B10zWWzDDz"; break;
3123 case 2: desc
->format
= "WWzWWDDzz"; break;
3124 case 3: desc
->format
= "WWzWWDDzzzzzzzzzzlz"; break;
3125 case 4: desc
->format
= "WWzWWDDzzzzzDDDDDDD"; break;
3127 DEBUG(0,("check_printjob_info: invalid level %d\n",
3131 if (id
== NULL
|| strcmp(desc
->format
,id
) != 0) {
3132 DEBUG(0,("check_printjob_info: invalid format %s\n",
3133 id
? id
: "<NULL>" ));
3139 static bool api_PrintJobInfo(connection_struct
*conn
, uint16 vuid
,
3140 char *param
, int tpscnt
,
3141 char *data
, int tdscnt
,
3142 int mdrcnt
,int mprcnt
,
3143 char **rdata
,char **rparam
,
3144 int *rdata_len
,int *rparam_len
)
3146 struct pack_desc desc
;
3147 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3148 char *str2
= skip_string(param
,tpscnt
,str1
);
3149 char *p
= skip_string(param
,tpscnt
,str2
);
3152 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,2,-1);
3153 int function
= get_safe_SVAL(param
,tpscnt
,p
,4,-1);
3156 if (!str1
|| !str2
|| !p
) {
3160 * We use 1 here not 2 as we're checking
3161 * the last byte we want to access is safe.
3163 if (!is_offset_safe(param
,tpscnt
,p
,1)) {
3166 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
))
3169 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3174 if (!share_defined(sharename
)) {
3175 DEBUG(0,("api_PrintJobInfo: sharen [%s] not defined\n",
3182 /* check it's a supported varient */
3183 if ((strcmp(str1
,"WWsTP")) ||
3184 (!check_printjob_info(&desc
,uLevel
,str2
)))
3187 if (!print_job_exists(sharename
, jobid
)) {
3188 errcode
=NERR_JobNotFound
;
3192 errcode
= NERR_notsupported
;
3196 /* change job place in the queue,
3197 data gives the new place */
3198 place
= SVAL(data
,0);
3199 if (print_job_set_place(sharename
, jobid
, place
)) {
3200 errcode
=NERR_Success
;
3205 /* change print job name, data gives the name */
3206 if (print_job_set_name(sharename
, jobid
, data
)) {
3207 errcode
=NERR_Success
;
3216 SSVALS(*rparam
,0,errcode
);
3217 SSVAL(*rparam
,2,0); /* converter word */
3223 /****************************************************************************
3224 Get info about the server.
3225 ****************************************************************************/
3227 static bool api_RNetServerGetInfo(connection_struct
*conn
,uint16 vuid
,
3228 char *param
, int tpscnt
,
3229 char *data
, int tdscnt
,
3230 int mdrcnt
,int mprcnt
,
3231 char **rdata
,char **rparam
,
3232 int *rdata_len
,int *rparam_len
)
3234 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3235 char *str2
= skip_string(param
,tpscnt
,str1
);
3236 char *p
= skip_string(param
,tpscnt
,str2
);
3237 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3241 if (!str1
|| !str2
|| !p
) {
3245 DEBUG(4,("NetServerGetInfo level %d\n",uLevel
));
3247 /* check it's a supported varient */
3248 if (!prefix_ok(str1
,"WrLh")) {
3254 if (strcmp(str2
,"B16") != 0) {
3260 if (strcmp(str2
,"B16BBDz") != 0) {
3266 if (strcmp(str2
,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")!= 0) {
3272 if (strcmp(str2
,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz") != 0) {
3278 if (strcmp(str2
,"DN") != 0) {
3284 if (strcmp(str2
,"B16BBDzWWzzz") != 0) {
3293 *rdata_len
= mdrcnt
;
3294 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
3300 p2
= p
+ struct_len
;
3302 srvstr_push(NULL
, 0, p
,global_myname(),16,
3303 STR_ASCII
|STR_UPPER
|STR_TERMINATE
);
3307 struct srv_info_struct
*servers
=NULL
;
3309 char *comment
= NULL
;
3310 TALLOC_CTX
*ctx
= talloc_tos();
3311 uint32 servertype
= lp_default_server_announce();
3313 comment
= talloc_strdup(ctx
,lp_serverstring());
3318 if ((count
=get_server_info(SV_TYPE_ALL
,&servers
,lp_workgroup()))>0) {
3319 for (i
=0;i
<count
;i
++) {
3320 if (strequal(servers
[i
].name
,global_myname())) {
3321 servertype
= servers
[i
].type
;
3322 TALLOC_FREE(comment
);
3323 comment
= talloc_strdup(ctx
,
3324 servers
[i
].comment
);
3334 SCVAL(p
,0,lp_major_announce_version());
3335 SCVAL(p
,1,lp_minor_announce_version());
3336 SIVAL(p
,2,servertype
);
3338 if (mdrcnt
== struct_len
) {
3341 SIVAL(p
,6,PTR_DIFF(p2
,*rdata
));
3342 comment
= talloc_sub_advanced(
3344 lp_servicename(SNUM(conn
)),
3345 conn
->server_info
->unix_name
,
3347 conn
->server_info
->utok
.gid
,
3348 conn
->server_info
->sanitized_username
,
3349 pdb_get_domain(conn
->server_info
->sam_account
),
3354 if (mdrcnt
- struct_len
<= 0) {
3359 MIN(mdrcnt
- struct_len
,
3360 MAX_SERVER_STRING_LENGTH
),
3362 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3370 return False
; /* not yet implemented */
3373 *rdata_len
= PTR_DIFF(p2
,*rdata
);
3376 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3380 SSVAL(*rparam
,0,NERR_Success
);
3381 SSVAL(*rparam
,2,0); /* converter word */
3382 SSVAL(*rparam
,4,*rdata_len
);
3387 /****************************************************************************
3388 Get info about the server.
3389 ****************************************************************************/
3391 static bool api_NetWkstaGetInfo(connection_struct
*conn
,uint16 vuid
,
3392 char *param
, int tpscnt
,
3393 char *data
, int tdscnt
,
3394 int mdrcnt
,int mprcnt
,
3395 char **rdata
,char **rparam
,
3396 int *rdata_len
,int *rparam_len
)
3398 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3399 char *str2
= skip_string(param
,tpscnt
,str1
);
3400 char *p
= skip_string(param
,tpscnt
,str2
);
3403 int level
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3405 if (!str1
|| !str2
|| !p
) {
3409 DEBUG(4,("NetWkstaGetInfo level %d\n",level
));
3412 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3417 /* check it's a supported varient */
3418 if (!(level
==10 && strcsequal(str1
,"WrLh") && strcsequal(str2
,"zzzBBzz"))) {
3422 *rdata_len
= mdrcnt
+ 1024;
3423 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
3428 SSVAL(*rparam
,0,NERR_Success
);
3429 SSVAL(*rparam
,2,0); /* converter word */
3432 endp
= *rdata
+ *rdata_len
;
3434 p2
= get_safe_ptr(*rdata
,*rdata_len
,p
,22);
3439 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* host name */
3440 strlcpy(p2
,get_local_machine_name(),PTR_DIFF(endp
,p2
));
3442 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3448 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
));
3449 strlcpy(p2
,conn
->server_info
->sanitized_username
,PTR_DIFF(endp
,p2
));
3450 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3456 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* login domain */
3457 strlcpy(p2
,lp_workgroup(),PTR_DIFF(endp
,p2
));
3459 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3465 SCVAL(p
,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
3466 SCVAL(p
,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
3469 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
));
3470 strlcpy(p2
,lp_workgroup(),PTR_DIFF(endp
,p2
)); /* don't know. login domain?? */
3471 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3477 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* don't know */
3478 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
3479 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3485 *rdata_len
= PTR_DIFF(p2
,*rdata
);
3487 SSVAL(*rparam
,4,*rdata_len
);
3492 /****************************************************************************
3493 get info about a user
3495 struct user_info_11 {
3496 char usri11_name[21]; 0-20
3498 char *usri11_comment; 22-25
3499 char *usri11_usr_comment; 26-29
3500 unsigned short usri11_priv; 30-31
3501 unsigned long usri11_auth_flags; 32-35
3502 long usri11_password_age; 36-39
3503 char *usri11_homedir; 40-43
3504 char *usri11_parms; 44-47
3505 long usri11_last_logon; 48-51
3506 long usri11_last_logoff; 52-55
3507 unsigned short usri11_bad_pw_count; 56-57
3508 unsigned short usri11_num_logons; 58-59
3509 char *usri11_logon_server; 60-63
3510 unsigned short usri11_country_code; 64-65
3511 char *usri11_workstations; 66-69
3512 unsigned long usri11_max_storage; 70-73
3513 unsigned short usri11_units_per_week; 74-75
3514 unsigned char *usri11_logon_hours; 76-79
3515 unsigned short usri11_code_page; 80-81
3520 usri11_name specifies the user name for which information is retrieved
3522 usri11_pad aligns the next data structure element to a word boundary
3524 usri11_comment is a null terminated ASCII comment
3526 usri11_user_comment is a null terminated ASCII comment about the user
3528 usri11_priv specifies the level of the privilege assigned to the user.
3529 The possible values are:
3531 Name Value Description
3532 USER_PRIV_GUEST 0 Guest privilege
3533 USER_PRIV_USER 1 User privilege
3534 USER_PRV_ADMIN 2 Administrator privilege
3536 usri11_auth_flags specifies the account operator privileges. The
3537 possible values are:
3539 Name Value Description
3540 AF_OP_PRINT 0 Print operator
3543 Leach, Naik [Page 28]
3547 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
3550 AF_OP_COMM 1 Communications operator
3551 AF_OP_SERVER 2 Server operator
3552 AF_OP_ACCOUNTS 3 Accounts operator
3555 usri11_password_age specifies how many seconds have elapsed since the
3556 password was last changed.
3558 usri11_home_dir points to a null terminated ASCII string that contains
3559 the path name of the user's home directory.
3561 usri11_parms points to a null terminated ASCII string that is set
3562 aside for use by applications.
3564 usri11_last_logon specifies the time when the user last logged on.
3565 This value is stored as the number of seconds elapsed since
3566 00:00:00, January 1, 1970.
3568 usri11_last_logoff specifies the time when the user last logged off.
3569 This value is stored as the number of seconds elapsed since
3570 00:00:00, January 1, 1970. A value of 0 means the last logoff
3573 usri11_bad_pw_count specifies the number of incorrect passwords
3574 entered since the last successful logon.
3576 usri11_log1_num_logons specifies the number of times this user has
3577 logged on. A value of -1 means the number of logons is unknown.
3579 usri11_logon_server points to a null terminated ASCII string that
3580 contains the name of the server to which logon requests are sent.
3581 A null string indicates logon requests should be sent to the
3584 usri11_country_code specifies the country code for the user's language
3587 usri11_workstations points to a null terminated ASCII string that
3588 contains the names of workstations the user may log on from.
3589 There may be up to 8 workstations, with the names separated by
3590 commas. A null strings indicates there are no restrictions.
3592 usri11_max_storage specifies the maximum amount of disk space the user
3593 can occupy. A value of 0xffffffff indicates there are no
3596 usri11_units_per_week specifies the equal number of time units into
3597 which a week is divided. This value must be equal to 168.
3599 usri11_logon_hours points to a 21 byte (168 bits) string that
3600 specifies the time during which the user can log on. Each bit
3601 represents one unique hour in a week. The first bit (bit 0, word
3602 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
3606 Leach, Naik [Page 29]
3610 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
3613 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
3614 are no restrictions.
3616 usri11_code_page specifies the code page for the user's language of
3619 All of the pointers in this data structure need to be treated
3620 specially. The pointer is a 32 bit pointer. The higher 16 bits need
3621 to be ignored. The converter word returned in the parameters section
3622 needs to be subtracted from the lower 16 bits to calculate an offset
3623 into the return buffer where this ASCII string resides.
3625 There is no auxiliary data in the response.
3627 ****************************************************************************/
3629 #define usri11_name 0
3630 #define usri11_pad 21
3631 #define usri11_comment 22
3632 #define usri11_usr_comment 26
3633 #define usri11_full_name 30
3634 #define usri11_priv 34
3635 #define usri11_auth_flags 36
3636 #define usri11_password_age 40
3637 #define usri11_homedir 44
3638 #define usri11_parms 48
3639 #define usri11_last_logon 52
3640 #define usri11_last_logoff 56
3641 #define usri11_bad_pw_count 60
3642 #define usri11_num_logons 62
3643 #define usri11_logon_server 64
3644 #define usri11_country_code 68
3645 #define usri11_workstations 70
3646 #define usri11_max_storage 74
3647 #define usri11_units_per_week 78
3648 #define usri11_logon_hours 80
3649 #define usri11_code_page 84
3650 #define usri11_end 86
3652 #define USER_PRIV_GUEST 0
3653 #define USER_PRIV_USER 1
3654 #define USER_PRIV_ADMIN 2
3656 #define AF_OP_PRINT 0
3657 #define AF_OP_COMM 1
3658 #define AF_OP_SERVER 2
3659 #define AF_OP_ACCOUNTS 3
3662 static bool api_RNetUserGetInfo(connection_struct
*conn
, uint16 vuid
,
3663 char *param
, int tpscnt
,
3664 char *data
, int tdscnt
,
3665 int mdrcnt
,int mprcnt
,
3666 char **rdata
,char **rparam
,
3667 int *rdata_len
,int *rparam_len
)
3669 struct smbd_server_connection
*sconn
= smbd_server_conn
;
3670 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3671 char *str2
= skip_string(param
,tpscnt
,str1
);
3672 char *UserName
= skip_string(param
,tpscnt
,str2
);
3673 char *p
= skip_string(param
,tpscnt
,UserName
);
3674 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3677 const char *level_string
;
3679 /* get NIS home of a previously validated user - simeon */
3680 /* With share level security vuid will always be zero.
3681 Don't depend on vuser being non-null !!. JRA */
3682 user_struct
*vuser
= get_valid_user_struct(sconn
, vuid
);
3684 DEBUG(3,(" Username of UID %d is %s\n",
3685 (int)vuser
->server_info
->utok
.uid
,
3686 vuser
->server_info
->unix_name
));
3689 if (!str1
|| !str2
|| !UserName
|| !p
) {
3694 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3699 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel
));
3701 /* check it's a supported variant */
3702 if (strcmp(str1
,"zWrLh") != 0) {
3706 case 0: level_string
= "B21"; break;
3707 case 1: level_string
= "B21BB16DWzzWz"; break;
3708 case 2: level_string
= "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
3709 case 10: level_string
= "B21Bzzz"; break;
3710 case 11: level_string
= "B21BzzzWDDzzDDWWzWzDWb21W"; break;
3711 default: return False
;
3714 if (strcmp(level_string
,str2
) != 0) {
3718 *rdata_len
= mdrcnt
+ 1024;
3719 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
3724 SSVAL(*rparam
,0,NERR_Success
);
3725 SSVAL(*rparam
,2,0); /* converter word */
3728 endp
= *rdata
+ *rdata_len
;
3729 p2
= get_safe_ptr(*rdata
,*rdata_len
,p
,usri11_end
);
3735 fstrcpy(p
+usri11_name
,UserName
); /* 21 bytes - user name */
3738 SCVAL(p
,usri11_pad
,0); /* padding - 1 byte */
3743 SIVAL(p
,usri11_comment
,PTR_DIFF(p2
,p
)); /* comment */
3744 strlcpy(p2
,"Comment",PTR_DIFF(endp
,p2
));
3745 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3750 SIVAL(p
,usri11_usr_comment
,PTR_DIFF(p2
,p
)); /* user_comment */
3751 strlcpy(p2
,"UserComment",PTR_DIFF(endp
,p2
));
3752 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3757 /* EEK! the cifsrap.txt doesn't have this in!!!! */
3758 SIVAL(p
,usri11_full_name
,PTR_DIFF(p2
,p
)); /* full name */
3759 strlcpy(p2
,((vuser
!= NULL
)
3760 ? pdb_get_fullname(vuser
->server_info
->sam_account
)
3761 : UserName
),PTR_DIFF(endp
,p2
));
3762 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3769 const char *homedir
= "";
3770 if (vuser
!= NULL
) {
3771 homedir
= pdb_get_homedir(
3772 vuser
->server_info
->sam_account
);
3774 /* modelled after NTAS 3.51 reply */
3775 SSVAL(p
,usri11_priv
,conn
->admin_user
?USER_PRIV_ADMIN
:USER_PRIV_USER
);
3776 SIVAL(p
,usri11_auth_flags
,AF_OP_PRINT
); /* auth flags */
3777 SIVALS(p
,usri11_password_age
,-1); /* password age */
3778 SIVAL(p
,usri11_homedir
,PTR_DIFF(p2
,p
)); /* home dir */
3779 strlcpy(p2
, homedir
, PTR_DIFF(endp
,p2
));
3780 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3784 SIVAL(p
,usri11_parms
,PTR_DIFF(p2
,p
)); /* parms */
3785 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
3786 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3790 SIVAL(p
,usri11_last_logon
,0); /* last logon */
3791 SIVAL(p
,usri11_last_logoff
,0); /* last logoff */
3792 SSVALS(p
,usri11_bad_pw_count
,-1); /* bad pw counts */
3793 SSVALS(p
,usri11_num_logons
,-1); /* num logons */
3794 SIVAL(p
,usri11_logon_server
,PTR_DIFF(p2
,p
)); /* logon server */
3795 strlcpy(p2
,"\\\\*",PTR_DIFF(endp
,p2
));
3796 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3800 SSVAL(p
,usri11_country_code
,0); /* country code */
3802 SIVAL(p
,usri11_workstations
,PTR_DIFF(p2
,p
)); /* workstations */
3803 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
3804 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3809 SIVALS(p
,usri11_max_storage
,-1); /* max storage */
3810 SSVAL(p
,usri11_units_per_week
,168); /* units per week */
3811 SIVAL(p
,usri11_logon_hours
,PTR_DIFF(p2
,p
)); /* logon hours */
3813 /* a simple way to get logon hours at all times. */
3815 SCVAL(p2
,21,0); /* fix zero termination */
3816 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3821 SSVAL(p
,usri11_code_page
,0); /* code page */
3824 if (uLevel
== 1 || uLevel
== 2) {
3825 memset(p
+22,' ',16); /* password */
3826 SIVALS(p
,38,-1); /* password age */
3828 conn
->admin_user
?USER_PRIV_ADMIN
:USER_PRIV_USER
);
3829 SIVAL(p
,44,PTR_DIFF(p2
,*rdata
)); /* home dir */
3830 strlcpy(p2
, vuser
? pdb_get_homedir(
3831 vuser
->server_info
->sam_account
) : "",
3833 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3837 SIVAL(p
,48,PTR_DIFF(p2
,*rdata
)); /* comment */
3839 SSVAL(p
,52,0); /* flags */
3840 SIVAL(p
,54,PTR_DIFF(p2
,*rdata
)); /* script_path */
3841 strlcpy(p2
, vuser
? pdb_get_logon_script(
3842 vuser
->server_info
->sam_account
) : "",
3844 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3849 SIVAL(p
,60,0); /* auth_flags */
3850 SIVAL(p
,64,PTR_DIFF(p2
,*rdata
)); /* full_name */
3851 strlcpy(p2
,((vuser
!= NULL
)
3852 ? pdb_get_fullname(vuser
->server_info
->sam_account
)
3853 : UserName
),PTR_DIFF(endp
,p2
));
3854 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3858 SIVAL(p
,68,0); /* urs_comment */
3859 SIVAL(p
,72,PTR_DIFF(p2
,*rdata
)); /* parms */
3860 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
3861 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3865 SIVAL(p
,76,0); /* workstations */
3866 SIVAL(p
,80,0); /* last_logon */
3867 SIVAL(p
,84,0); /* last_logoff */
3868 SIVALS(p
,88,-1); /* acct_expires */
3869 SIVALS(p
,92,-1); /* max_storage */
3870 SSVAL(p
,96,168); /* units_per_week */
3871 SIVAL(p
,98,PTR_DIFF(p2
,*rdata
)); /* logon_hours */
3874 SSVALS(p
,102,-1); /* bad_pw_count */
3875 SSVALS(p
,104,-1); /* num_logons */
3876 SIVAL(p
,106,PTR_DIFF(p2
,*rdata
)); /* logon_server */
3878 TALLOC_CTX
*ctx
= talloc_tos();
3879 int space_rem
= *rdata_len
- (p2
- *rdata
);
3882 if (space_rem
<= 0) {
3885 tmp
= talloc_strdup(ctx
, "\\\\%L");
3889 tmp
= talloc_sub_basic(ctx
,
3902 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3906 SSVAL(p
,110,49); /* country_code */
3907 SSVAL(p
,112,860); /* code page */
3911 *rdata_len
= PTR_DIFF(p2
,*rdata
);
3913 SSVAL(*rparam
,4,*rdata_len
); /* is this right?? */
3918 static bool api_WWkstaUserLogon(connection_struct
*conn
,uint16 vuid
,
3919 char *param
, int tpscnt
,
3920 char *data
, int tdscnt
,
3921 int mdrcnt
,int mprcnt
,
3922 char **rdata
,char **rparam
,
3923 int *rdata_len
,int *rparam_len
)
3925 struct smbd_server_connection
*sconn
= smbd_server_conn
;
3926 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3927 char *str2
= skip_string(param
,tpscnt
,str1
);
3928 char *p
= skip_string(param
,tpscnt
,str2
);
3930 struct pack_desc desc
;
3932 /* With share level security vuid will always be zero.
3933 Don't depend on vuser being non-null !!. JRA */
3934 user_struct
*vuser
= get_valid_user_struct(sconn
, vuid
);
3936 if (!str1
|| !str2
|| !p
) {
3941 DEBUG(3,(" Username of UID %d is %s\n",
3942 (int)vuser
->server_info
->utok
.uid
,
3943 vuser
->server_info
->unix_name
));
3946 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3947 name
= get_safe_str_ptr(param
,tpscnt
,p
,2);
3952 memset((char *)&desc
,'\0',sizeof(desc
));
3954 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel
,name
));
3956 /* check it's a supported varient */
3957 if (strcmp(str1
,"OOWb54WrLh") != 0) {
3960 if (uLevel
!= 1 || strcmp(str2
,"WB21BWDWWDDDDDDDzzzD") != 0) {
3964 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
3971 desc
.buflen
= mdrcnt
;
3972 desc
.subformat
= NULL
;
3975 if (init_package(&desc
,1,0)) {
3976 PACKI(&desc
,"W",0); /* code */
3977 PACKS(&desc
,"B21",name
); /* eff. name */
3978 PACKS(&desc
,"B",""); /* pad */
3979 PACKI(&desc
,"W", conn
->admin_user
?USER_PRIV_ADMIN
:USER_PRIV_USER
);
3980 PACKI(&desc
,"D",0); /* auth flags XXX */
3981 PACKI(&desc
,"W",0); /* num logons */
3982 PACKI(&desc
,"W",0); /* bad pw count */
3983 PACKI(&desc
,"D",0); /* last logon */
3984 PACKI(&desc
,"D",-1); /* last logoff */
3985 PACKI(&desc
,"D",-1); /* logoff time */
3986 PACKI(&desc
,"D",-1); /* kickoff time */
3987 PACKI(&desc
,"D",0); /* password age */
3988 PACKI(&desc
,"D",0); /* password can change */
3989 PACKI(&desc
,"D",-1); /* password must change */
3993 fstrcpy(mypath
,"\\\\");
3994 fstrcat(mypath
,get_local_machine_name());
3996 PACKS(&desc
,"z",mypath
); /* computer */
3999 PACKS(&desc
,"z",lp_workgroup());/* domain */
4000 PACKS(&desc
,"z", vuser
? pdb_get_logon_script(
4001 vuser
->server_info
->sam_account
) : ""); /* script path */
4002 PACKI(&desc
,"D",0x00000000); /* reserved */
4005 *rdata_len
= desc
.usedlen
;
4007 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4011 SSVALS(*rparam
,0,desc
.errcode
);
4013 SSVAL(*rparam
,4,desc
.neededlen
);
4015 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc
.errcode
));
4020 /****************************************************************************
4021 api_WAccessGetUserPerms
4022 ****************************************************************************/
4024 static bool api_WAccessGetUserPerms(connection_struct
*conn
,uint16 vuid
,
4025 char *param
, int tpscnt
,
4026 char *data
, int tdscnt
,
4027 int mdrcnt
,int mprcnt
,
4028 char **rdata
,char **rparam
,
4029 int *rdata_len
,int *rparam_len
)
4031 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4032 char *str2
= skip_string(param
,tpscnt
,str1
);
4033 char *user
= skip_string(param
,tpscnt
,str2
);
4034 char *resource
= skip_string(param
,tpscnt
,user
);
4036 if (!str1
|| !str2
|| !user
|| !resource
) {
4040 if (skip_string(param
,tpscnt
,resource
) == NULL
) {
4043 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user
,resource
));
4045 /* check it's a supported varient */
4046 if (strcmp(str1
,"zzh") != 0) {
4049 if (strcmp(str2
,"") != 0) {
4054 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4058 SSVALS(*rparam
,0,0); /* errorcode */
4059 SSVAL(*rparam
,2,0); /* converter word */
4060 SSVAL(*rparam
,4,0x7f); /* permission flags */
4065 /****************************************************************************
4066 api_WPrintJobEnumerate
4067 ****************************************************************************/
4069 static bool api_WPrintJobGetInfo(connection_struct
*conn
, uint16 vuid
,
4070 char *param
, int tpscnt
,
4071 char *data
, int tdscnt
,
4072 int mdrcnt
,int mprcnt
,
4073 char **rdata
,char **rparam
,
4074 int *rdata_len
,int *rparam_len
)
4076 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4077 char *str2
= skip_string(param
,tpscnt
,str1
);
4078 char *p
= skip_string(param
,tpscnt
,str2
);
4085 struct pack_desc desc
;
4086 print_queue_struct
*queue
=NULL
;
4087 print_status_struct status
;
4090 if (!str1
|| !str2
|| !p
) {
4094 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,2,-1);
4096 memset((char *)&desc
,'\0',sizeof(desc
));
4097 memset((char *)&status
,'\0',sizeof(status
));
4099 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel
,SVAL(p
,0)));
4101 /* check it's a supported varient */
4102 if (strcmp(str1
,"WWrLh") != 0) {
4105 if (!check_printjob_info(&desc
,uLevel
,str2
)) {
4109 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
)) {
4113 snum
= lp_servicenumber( sharename
);
4114 if (snum
< 0 || !VALID_SNUM(snum
)) {
4118 count
= print_queue_status(snum
,&queue
,&status
);
4119 for (i
= 0; i
< count
; i
++) {
4120 if (queue
[i
].job
== jobid
) {
4126 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4131 desc
.buflen
= mdrcnt
;
4134 * Don't return data but need to get correct length
4135 * init_package will return wrong size if buflen=0
4137 desc
.buflen
= getlen(desc
.format
);
4138 desc
.base
= tmpdata
= (char *)SMB_MALLOC( desc
.buflen
);
4141 if (init_package(&desc
,1,0)) {
4143 fill_printjob_info(conn
,snum
,uLevel
,&desc
,&queue
[i
],i
);
4144 *rdata_len
= desc
.usedlen
;
4146 desc
.errcode
= NERR_JobNotFound
;
4152 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4156 SSVALS(*rparam
,0,desc
.errcode
);
4158 SSVAL(*rparam
,4,desc
.neededlen
);
4163 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc
.errcode
));
4168 static bool api_WPrintJobEnumerate(connection_struct
*conn
, uint16 vuid
,
4169 char *param
, int tpscnt
,
4170 char *data
, int tdscnt
,
4171 int mdrcnt
,int mprcnt
,
4172 char **rdata
,char **rparam
,
4173 int *rdata_len
,int *rparam_len
)
4175 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4176 char *str2
= skip_string(param
,tpscnt
,str1
);
4177 char *p
= skip_string(param
,tpscnt
,str2
);
4183 struct pack_desc desc
;
4184 print_queue_struct
*queue
=NULL
;
4185 print_status_struct status
;
4187 if (!str1
|| !str2
|| !p
) {
4191 memset((char *)&desc
,'\0',sizeof(desc
));
4192 memset((char *)&status
,'\0',sizeof(status
));
4194 p
= skip_string(param
,tpscnt
,p
);
4198 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4200 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel
,name
));
4202 /* check it's a supported variant */
4203 if (strcmp(str1
,"zWrLeh") != 0) {
4208 return False
; /* defined only for uLevel 0,1,2 */
4211 if (!check_printjob_info(&desc
,uLevel
,str2
)) {
4215 snum
= find_service(name
);
4216 if ( !(lp_snum_ok(snum
) && lp_print_ok(snum
)) ) {
4220 count
= print_queue_status(snum
,&queue
,&status
);
4222 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4228 desc
.buflen
= mdrcnt
;
4230 if (init_package(&desc
,count
,0)) {
4232 for (i
= 0; i
< count
; i
++) {
4233 fill_printjob_info(conn
,snum
,uLevel
,&desc
,&queue
[i
],i
);
4234 if (desc
.errcode
== NERR_Success
) {
4240 *rdata_len
= desc
.usedlen
;
4243 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4247 SSVALS(*rparam
,0,desc
.errcode
);
4249 SSVAL(*rparam
,4,succnt
);
4250 SSVAL(*rparam
,6,count
);
4254 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc
.errcode
));
4259 static int check_printdest_info(struct pack_desc
* desc
,
4260 int uLevel
, char* id
)
4262 desc
->subformat
= NULL
;
4265 desc
->format
= "B9";
4268 desc
->format
= "B9B21WWzW";
4274 desc
->format
= "zzzWWzzzWW";
4277 DEBUG(0,("check_printdest_info: invalid level %d\n",
4281 if (id
== NULL
|| strcmp(desc
->format
,id
) != 0) {
4282 DEBUG(0,("check_printdest_info: invalid string %s\n",
4283 id
? id
: "<NULL>" ));
4289 static void fill_printdest_info(connection_struct
*conn
, int snum
, int uLevel
,
4290 struct pack_desc
* desc
)
4294 strncpy(buf
,SERVICE(snum
),sizeof(buf
)-1);
4295 buf
[sizeof(buf
)-1] = 0;
4299 PACKS(desc
,"B9",buf
); /* szName */
4301 PACKS(desc
,"B21",""); /* szUserName */
4302 PACKI(desc
,"W",0); /* uJobId */
4303 PACKI(desc
,"W",0); /* fsStatus */
4304 PACKS(desc
,"z",""); /* pszStatus */
4305 PACKI(desc
,"W",0); /* time */
4309 if (uLevel
== 2 || uLevel
== 3) {
4310 PACKS(desc
,"z",buf
); /* pszPrinterName */
4312 PACKS(desc
,"z",""); /* pszUserName */
4313 PACKS(desc
,"z",""); /* pszLogAddr */
4314 PACKI(desc
,"W",0); /* uJobId */
4315 PACKI(desc
,"W",0); /* fsStatus */
4316 PACKS(desc
,"z",""); /* pszStatus */
4317 PACKS(desc
,"z",""); /* pszComment */
4318 PACKS(desc
,"z","NULL"); /* pszDrivers */
4319 PACKI(desc
,"W",0); /* time */
4320 PACKI(desc
,"W",0); /* pad1 */
4325 static bool api_WPrintDestGetInfo(connection_struct
*conn
, uint16 vuid
,
4326 char *param
, int tpscnt
,
4327 char *data
, int tdscnt
,
4328 int mdrcnt
,int mprcnt
,
4329 char **rdata
,char **rparam
,
4330 int *rdata_len
,int *rparam_len
)
4332 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4333 char *str2
= skip_string(param
,tpscnt
,str1
);
4334 char *p
= skip_string(param
,tpscnt
,str2
);
4335 char* PrinterName
= p
;
4337 struct pack_desc desc
;
4341 if (!str1
|| !str2
|| !p
) {
4345 memset((char *)&desc
,'\0',sizeof(desc
));
4347 p
= skip_string(param
,tpscnt
,p
);
4351 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4353 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel
,PrinterName
));
4355 /* check it's a supported varient */
4356 if (strcmp(str1
,"zWrLh") != 0) {
4359 if (!check_printdest_info(&desc
,uLevel
,str2
)) {
4363 snum
= find_service(PrinterName
);
4364 if ( !(lp_snum_ok(snum
) && lp_print_ok(snum
)) ) {
4366 desc
.errcode
= NERR_DestNotFound
;
4370 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4375 desc
.buflen
= mdrcnt
;
4378 * Don't return data but need to get correct length
4379 * init_package will return wrong size if buflen=0
4381 desc
.buflen
= getlen(desc
.format
);
4382 desc
.base
= tmpdata
= (char *)SMB_MALLOC( desc
.buflen
);
4384 if (init_package(&desc
,1,0)) {
4385 fill_printdest_info(conn
,snum
,uLevel
,&desc
);
4387 *rdata_len
= desc
.usedlen
;
4391 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4395 SSVALS(*rparam
,0,desc
.errcode
);
4397 SSVAL(*rparam
,4,desc
.neededlen
);
4399 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc
.errcode
));
4405 static bool api_WPrintDestEnum(connection_struct
*conn
, uint16 vuid
,
4406 char *param
, int tpscnt
,
4407 char *data
, int tdscnt
,
4408 int mdrcnt
,int mprcnt
,
4409 char **rdata
,char **rparam
,
4410 int *rdata_len
,int *rparam_len
)
4412 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4413 char *str2
= skip_string(param
,tpscnt
,str1
);
4414 char *p
= skip_string(param
,tpscnt
,str2
);
4418 struct pack_desc desc
;
4419 int services
= lp_numservices();
4421 if (!str1
|| !str2
|| !p
) {
4425 memset((char *)&desc
,'\0',sizeof(desc
));
4427 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4429 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel
));
4431 /* check it's a supported varient */
4432 if (strcmp(str1
,"WrLeh") != 0) {
4435 if (!check_printdest_info(&desc
,uLevel
,str2
)) {
4440 for (i
= 0; i
< services
; i
++) {
4441 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
)) {
4447 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4454 desc
.buflen
= mdrcnt
;
4455 if (init_package(&desc
,queuecnt
,0)) {
4458 for (i
= 0; i
< services
; i
++) {
4459 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
)) {
4460 fill_printdest_info(conn
,i
,uLevel
,&desc
);
4462 if (desc
.errcode
== NERR_Success
) {
4469 *rdata_len
= desc
.usedlen
;
4472 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4476 SSVALS(*rparam
,0,desc
.errcode
);
4478 SSVAL(*rparam
,4,succnt
);
4479 SSVAL(*rparam
,6,queuecnt
);
4481 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc
.errcode
));
4486 static bool api_WPrintDriverEnum(connection_struct
*conn
, uint16 vuid
,
4487 char *param
, int tpscnt
,
4488 char *data
, int tdscnt
,
4489 int mdrcnt
,int mprcnt
,
4490 char **rdata
,char **rparam
,
4491 int *rdata_len
,int *rparam_len
)
4493 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4494 char *str2
= skip_string(param
,tpscnt
,str1
);
4495 char *p
= skip_string(param
,tpscnt
,str2
);
4498 struct pack_desc desc
;
4500 if (!str1
|| !str2
|| !p
) {
4504 memset((char *)&desc
,'\0',sizeof(desc
));
4506 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4508 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel
));
4510 /* check it's a supported varient */
4511 if (strcmp(str1
,"WrLeh") != 0) {
4514 if (uLevel
!= 0 || strcmp(str2
,"B41") != 0) {
4519 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4525 desc
.buflen
= mdrcnt
;
4526 if (init_package(&desc
,1,0)) {
4527 PACKS(&desc
,"B41","NULL");
4530 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
4532 *rdata_len
= desc
.usedlen
;
4535 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4539 SSVALS(*rparam
,0,desc
.errcode
);
4541 SSVAL(*rparam
,4,succnt
);
4544 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc
.errcode
));
4549 static bool api_WPrintQProcEnum(connection_struct
*conn
, uint16 vuid
,
4550 char *param
, int tpscnt
,
4551 char *data
, int tdscnt
,
4552 int mdrcnt
,int mprcnt
,
4553 char **rdata
,char **rparam
,
4554 int *rdata_len
,int *rparam_len
)
4556 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4557 char *str2
= skip_string(param
,tpscnt
,str1
);
4558 char *p
= skip_string(param
,tpscnt
,str2
);
4561 struct pack_desc desc
;
4563 if (!str1
|| !str2
|| !p
) {
4566 memset((char *)&desc
,'\0',sizeof(desc
));
4568 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4570 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel
));
4572 /* check it's a supported varient */
4573 if (strcmp(str1
,"WrLeh") != 0) {
4576 if (uLevel
!= 0 || strcmp(str2
,"B13") != 0) {
4581 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4587 desc
.buflen
= mdrcnt
;
4589 if (init_package(&desc
,1,0)) {
4590 PACKS(&desc
,"B13","lpd");
4593 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
4595 *rdata_len
= desc
.usedlen
;
4598 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4602 SSVALS(*rparam
,0,desc
.errcode
);
4604 SSVAL(*rparam
,4,succnt
);
4607 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc
.errcode
));
4612 static bool api_WPrintPortEnum(connection_struct
*conn
, uint16 vuid
,
4613 char *param
, int tpscnt
,
4614 char *data
, int tdscnt
,
4615 int mdrcnt
,int mprcnt
,
4616 char **rdata
,char **rparam
,
4617 int *rdata_len
,int *rparam_len
)
4619 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4620 char *str2
= skip_string(param
,tpscnt
,str1
);
4621 char *p
= skip_string(param
,tpscnt
,str2
);
4624 struct pack_desc desc
;
4626 if (!str1
|| !str2
|| !p
) {
4630 memset((char *)&desc
,'\0',sizeof(desc
));
4632 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4634 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel
));
4636 /* check it's a supported varient */
4637 if (strcmp(str1
,"WrLeh") != 0) {
4640 if (uLevel
!= 0 || strcmp(str2
,"B9") != 0) {
4645 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4650 memset((char *)&desc
,'\0',sizeof(desc
));
4652 desc
.buflen
= mdrcnt
;
4654 if (init_package(&desc
,1,0)) {
4655 PACKS(&desc
,"B13","lp0");
4658 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
4660 *rdata_len
= desc
.usedlen
;
4663 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4667 SSVALS(*rparam
,0,desc
.errcode
);
4669 SSVAL(*rparam
,4,succnt
);
4672 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc
.errcode
));
4677 /****************************************************************************
4679 ****************************************************************************/
4681 static bool api_RNetSessionEnum(connection_struct
*conn
, uint16 vuid
,
4682 char *param
, int tpscnt
,
4683 char *data
, int tdscnt
,
4684 int mdrcnt
,int mprcnt
,
4685 char **rdata
,char **rparam
,
4686 int *rdata_len
,int *rparam_len
)
4689 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4690 char *str2
= skip_string(param
,tpscnt
,str1
);
4691 char *p
= skip_string(param
,tpscnt
,str2
);
4693 struct pack_desc desc
;
4694 struct sessionid
*session_list
;
4695 int i
, num_sessions
;
4697 if (!str1
|| !str2
|| !p
) {
4701 memset((char *)&desc
,'\0',sizeof(desc
));
4703 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4705 DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel
));
4706 DEBUG(7,("RNetSessionEnum req string=%s\n",str1
));
4707 DEBUG(7,("RNetSessionEnum ret string=%s\n",str2
));
4709 /* check it's a supported varient */
4710 if (strcmp(str1
,RAP_NetSessionEnum_REQ
) != 0) {
4713 if (uLevel
!= 2 || strcmp(str2
,RAP_SESSION_INFO_L2
) != 0) {
4717 num_sessions
= list_sessions(talloc_tos(), &session_list
);
4720 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4725 memset((char *)&desc
,'\0',sizeof(desc
));
4727 desc
.buflen
= mdrcnt
;
4729 if (!init_package(&desc
,num_sessions
,0)) {
4733 for(i
=0; i
<num_sessions
; i
++) {
4734 PACKS(&desc
, "z", session_list
[i
].remote_machine
);
4735 PACKS(&desc
, "z", session_list
[i
].username
);
4736 PACKI(&desc
, "W", 1); /* num conns */
4737 PACKI(&desc
, "W", 0); /* num opens */
4738 PACKI(&desc
, "W", 1); /* num users */
4739 PACKI(&desc
, "D", 0); /* session time */
4740 PACKI(&desc
, "D", 0); /* idle time */
4741 PACKI(&desc
, "D", 0); /* flags */
4742 PACKS(&desc
, "z", "Unknown Client"); /* client type string */
4745 *rdata_len
= desc
.usedlen
;
4748 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4752 SSVALS(*rparam
,0,desc
.errcode
);
4753 SSVAL(*rparam
,2,0); /* converter */
4754 SSVAL(*rparam
,4,num_sessions
); /* count */
4756 DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc
.errcode
));
4762 /****************************************************************************
4763 The buffer was too small.
4764 ****************************************************************************/
4766 static bool api_TooSmall(connection_struct
*conn
,uint16 vuid
, char *param
, char *data
,
4767 int mdrcnt
, int mprcnt
,
4768 char **rdata
, char **rparam
,
4769 int *rdata_len
, int *rparam_len
)
4771 *rparam_len
= MIN(*rparam_len
,mprcnt
);
4772 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4779 SSVAL(*rparam
,0,NERR_BufTooSmall
);
4781 DEBUG(3,("Supplied buffer too small in API command\n"));
4786 /****************************************************************************
4787 The request is not supported.
4788 ****************************************************************************/
4790 static bool api_Unsupported(connection_struct
*conn
, uint16 vuid
,
4791 char *param
, int tpscnt
,
4792 char *data
, int tdscnt
,
4793 int mdrcnt
, int mprcnt
,
4794 char **rdata
, char **rparam
,
4795 int *rdata_len
, int *rparam_len
)
4798 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4805 SSVAL(*rparam
,0,NERR_notsupported
);
4806 SSVAL(*rparam
,2,0); /* converter word */
4808 DEBUG(3,("Unsupported API command\n"));
4813 static const struct {
4816 bool (*fn
)(connection_struct
*, uint16
,
4819 int,int,char **,char **,int *,int *);
4820 bool auth_user
; /* Deny anonymous access? */
4821 } api_commands
[] = {
4822 {"RNetShareEnum", RAP_WshareEnum
, api_RNetShareEnum
, True
},
4823 {"RNetShareGetInfo", RAP_WshareGetInfo
, api_RNetShareGetInfo
},
4824 {"RNetShareAdd", RAP_WshareAdd
, api_RNetShareAdd
},
4825 {"RNetSessionEnum", RAP_WsessionEnum
, api_RNetSessionEnum
, True
},
4826 {"RNetServerGetInfo", RAP_WserverGetInfo
, api_RNetServerGetInfo
},
4827 {"RNetGroupEnum", RAP_WGroupEnum
, api_RNetGroupEnum
, True
},
4828 {"RNetGroupGetUsers", RAP_WGroupGetUsers
, api_RNetGroupGetUsers
, True
},
4829 {"RNetUserEnum", RAP_WUserEnum
, api_RNetUserEnum
, True
},
4830 {"RNetUserGetInfo", RAP_WUserGetInfo
, api_RNetUserGetInfo
},
4831 {"NetUserGetGroups", RAP_WUserGetGroups
, api_NetUserGetGroups
},
4832 {"NetWkstaGetInfo", RAP_WWkstaGetInfo
, api_NetWkstaGetInfo
},
4833 {"DosPrintQEnum", RAP_WPrintQEnum
, api_DosPrintQEnum
, True
},
4834 {"DosPrintQGetInfo", RAP_WPrintQGetInfo
, api_DosPrintQGetInfo
},
4835 {"WPrintQueuePause", RAP_WPrintQPause
, api_WPrintQueueCtrl
},
4836 {"WPrintQueueResume", RAP_WPrintQContinue
, api_WPrintQueueCtrl
},
4837 {"WPrintJobEnumerate",RAP_WPrintJobEnum
, api_WPrintJobEnumerate
},
4838 {"WPrintJobGetInfo", RAP_WPrintJobGetInfo
, api_WPrintJobGetInfo
},
4839 {"RDosPrintJobDel", RAP_WPrintJobDel
, api_RDosPrintJobDel
},
4840 {"RDosPrintJobPause", RAP_WPrintJobPause
, api_RDosPrintJobDel
},
4841 {"RDosPrintJobResume",RAP_WPrintJobContinue
, api_RDosPrintJobDel
},
4842 {"WPrintDestEnum", RAP_WPrintDestEnum
, api_WPrintDestEnum
},
4843 {"WPrintDestGetInfo", RAP_WPrintDestGetInfo
, api_WPrintDestGetInfo
},
4844 {"NetRemoteTOD", RAP_NetRemoteTOD
, api_NetRemoteTOD
},
4845 {"WPrintQueuePurge", RAP_WPrintQPurge
, api_WPrintQueueCtrl
},
4846 {"NetServerEnum2", RAP_NetServerEnum2
, api_RNetServerEnum2
}, /* anon OK */
4847 {"NetServerEnum3", RAP_NetServerEnum3
, api_RNetServerEnum3
}, /* anon OK */
4848 {"WAccessGetUserPerms",RAP_WAccessGetUserPerms
,api_WAccessGetUserPerms
},
4849 {"SetUserPassword", RAP_WUserPasswordSet2
, api_SetUserPassword
},
4850 {"WWkstaUserLogon", RAP_WWkstaUserLogon
, api_WWkstaUserLogon
},
4851 {"PrintJobInfo", RAP_WPrintJobSetInfo
, api_PrintJobInfo
},
4852 {"WPrintDriverEnum", RAP_WPrintDriverEnum
, api_WPrintDriverEnum
},
4853 {"WPrintQProcEnum", RAP_WPrintQProcessorEnum
,api_WPrintQProcEnum
},
4854 {"WPrintPortEnum", RAP_WPrintPortEnum
, api_WPrintPortEnum
},
4855 {"SamOEMChangePassword",RAP_SamOEMChgPasswordUser2_P
,api_SamOEMChangePassword
}, /* anon OK */
4856 {NULL
, -1, api_Unsupported
}
4857 /* The following RAP calls are not implemented by Samba:
4859 RAP_WFileEnum2 - anon not OK
4864 /****************************************************************************
4865 Handle remote api calls.
4866 ****************************************************************************/
4868 void api_reply(connection_struct
*conn
, uint16 vuid
,
4869 struct smb_request
*req
,
4870 char *data
, char *params
,
4871 int tdscnt
, int tpscnt
,
4872 int mdrcnt
, int mprcnt
)
4874 struct smbd_server_connection
*sconn
= smbd_server_conn
;
4877 char *rparam
= NULL
;
4878 const char *name1
= NULL
;
4879 const char *name2
= NULL
;
4886 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
4887 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4892 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4895 api_command
= SVAL(params
,0);
4896 /* Is there a string at position params+2 ? */
4897 if (skip_string(params
,tpscnt
,params
+2)) {
4902 name2
= skip_string(params
,tpscnt
,params
+2);
4907 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
4911 tdscnt
,tpscnt
,mdrcnt
,mprcnt
));
4913 for (i
=0;api_commands
[i
].name
;i
++) {
4914 if (api_commands
[i
].id
== api_command
&& api_commands
[i
].fn
) {
4915 DEBUG(3,("Doing %s\n",api_commands
[i
].name
));
4920 /* Check whether this api call can be done anonymously */
4922 if (api_commands
[i
].auth_user
&& lp_restrict_anonymous()) {
4923 user_struct
*user
= get_valid_user_struct(sconn
, vuid
);
4925 if (!user
|| user
->server_info
->guest
) {
4926 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4931 rdata
= (char *)SMB_MALLOC(1024);
4933 memset(rdata
,'\0',1024);
4936 rparam
= (char *)SMB_MALLOC(1024);
4938 memset(rparam
,'\0',1024);
4941 if(!rdata
|| !rparam
) {
4942 DEBUG(0,("api_reply: malloc fail !\n"));
4945 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4949 reply
= api_commands
[i
].fn(conn
,
4951 params
,tpscnt
, /* params + length */
4952 data
,tdscnt
, /* data + length */
4954 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
4957 if (rdata_len
> mdrcnt
|| rparam_len
> mprcnt
) {
4958 reply
= api_TooSmall(conn
,vuid
,params
,data
,mdrcnt
,mprcnt
,
4959 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
4962 /* if we get False back then it's actually unsupported */
4964 reply
= api_Unsupported(conn
,vuid
,params
,tpscnt
,data
,tdscnt
,mdrcnt
,mprcnt
,
4965 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
4968 /* If api_Unsupported returns false we can't return anything. */
4970 send_trans_reply(conn
, req
, rparam
, rparam_len
,
4971 rdata
, rdata_len
, False
);