2 Unix SMB/CIFS implementation.
3 Inter-process communication and named pipe handling
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Jeremy Allison 2007.
8 Copyright (C) John H Terpstra 1995-1998
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 This file handles the named pipe and mailslot calls
25 in the SMBtrans protocol
29 #include "smbd/globals.h"
30 #include "../librpc/gen_ndr/cli_samr.h"
31 #include "../librpc/gen_ndr/srv_samr.h"
32 #include "../lib/util/binsearch.h"
39 #define NERR_Success 0
40 #define NERR_badpass 86
41 #define NERR_notsupported 50
43 #define NERR_BASE (2100)
44 #define NERR_BufTooSmall (NERR_BASE+23)
45 #define NERR_JobNotFound (NERR_BASE+51)
46 #define NERR_DestNotFound (NERR_BASE+52)
48 #define ACCESS_READ 0x01
49 #define ACCESS_WRITE 0x02
50 #define ACCESS_CREATE 0x04
52 #define SHPWLEN 8 /* share password length */
54 /* Limit size of ipc replies */
56 static char *smb_realloc_limit(void *ptr
, size_t size
)
60 size
= MAX((size
),4*1024);
61 val
= (char *)SMB_REALLOC(ptr
,size
);
63 memset(val
,'\0',size
);
68 static bool api_Unsupported(connection_struct
*conn
, uint16 vuid
,
69 char *param
, int tpscnt
,
70 char *data
, int tdscnt
,
71 int mdrcnt
, int mprcnt
,
72 char **rdata
, char **rparam
,
73 int *rdata_len
, int *rparam_len
);
75 static bool api_TooSmall(connection_struct
*conn
, uint16 vuid
, char *param
, char *data
,
76 int mdrcnt
, int mprcnt
,
77 char **rdata
, char **rparam
,
78 int *rdata_len
, int *rparam_len
);
81 static int CopyExpanded(connection_struct
*conn
,
82 int snum
, char **dst
, char *src
, int *p_space_remaining
)
84 TALLOC_CTX
*ctx
= talloc_tos();
88 if (!src
|| !dst
|| !p_space_remaining
|| !(*dst
) ||
89 *p_space_remaining
<= 0) {
93 buf
= talloc_strdup(ctx
, src
);
95 *p_space_remaining
= 0;
98 buf
= talloc_string_sub(ctx
, buf
,"%S",lp_servicename(snum
));
100 *p_space_remaining
= 0;
103 buf
= talloc_sub_advanced(ctx
,
104 lp_servicename(SNUM(conn
)),
105 conn
->server_info
->unix_name
,
107 conn
->server_info
->utok
.gid
,
108 conn
->server_info
->sanitized_username
,
109 pdb_get_domain(conn
->server_info
->sam_account
),
112 *p_space_remaining
= 0;
115 l
= push_ascii(*dst
,buf
,*p_space_remaining
, STR_TERMINATE
);
120 (*p_space_remaining
) -= l
;
124 static int CopyAndAdvance(char **dst
, char *src
, int *n
)
127 if (!src
|| !dst
|| !n
|| !(*dst
)) {
130 l
= push_ascii(*dst
,src
,*n
, STR_TERMINATE
);
139 static int StrlenExpanded(connection_struct
*conn
, int snum
, char *s
)
141 TALLOC_CTX
*ctx
= talloc_tos();
146 buf
= talloc_strdup(ctx
,s
);
150 buf
= talloc_string_sub(ctx
,buf
,"%S",lp_servicename(snum
));
154 buf
= talloc_sub_advanced(ctx
,
155 lp_servicename(SNUM(conn
)),
156 conn
->server_info
->unix_name
,
158 conn
->server_info
->utok
.gid
,
159 conn
->server_info
->sanitized_username
,
160 pdb_get_domain(conn
->server_info
->sam_account
),
165 return strlen(buf
) + 1;
168 static char *Expand(connection_struct
*conn
, int snum
, char *s
)
170 TALLOC_CTX
*ctx
= talloc_tos();
176 buf
= talloc_strdup(ctx
,s
);
180 buf
= talloc_string_sub(ctx
,buf
,"%S",lp_servicename(snum
));
184 return talloc_sub_advanced(ctx
,
185 lp_servicename(SNUM(conn
)),
186 conn
->server_info
->unix_name
,
188 conn
->server_info
->utok
.gid
,
189 conn
->server_info
->sanitized_username
,
190 pdb_get_domain(conn
->server_info
->sam_account
),
194 /*******************************************************************
195 Check a API string for validity when we only need to check the prefix.
196 ******************************************************************/
198 static bool prefix_ok(const char *str
, const char *prefix
)
200 return(strncmp(str
,prefix
,strlen(prefix
)) == 0);
204 const char *format
; /* formatstring for structure */
205 const char *subformat
; /* subformat for structure */
206 char *base
; /* baseaddress of buffer */
207 int buflen
; /* remaining size for fixed part; on init: length of base */
208 int subcount
; /* count of substructures */
209 char *structbuf
; /* pointer into buffer for remaining fixed part */
210 int stringlen
; /* remaining size for variable part */
211 char *stringbuf
; /* pointer into buffer for remaining variable part */
212 int neededlen
; /* total needed size */
213 int usedlen
; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
214 const char *curpos
; /* current position; pointer into format or subformat */
218 static int get_counter(const char **p
)
224 if (!isdigit((int)**p
)) {
230 n
= 10 * n
+ (i
- '0');
238 static int getlen(const char *p
)
247 case 'W': /* word (2 byte) */
250 case 'K': /* status word? (2 byte) */
253 case 'N': /* count of substructures (word) at end */
256 case 'D': /* double word (4 byte) */
257 case 'z': /* offset to zero terminated string (4 byte) */
258 case 'l': /* offset to user data (4 byte) */
261 case 'b': /* offset to data (with counter) (4 byte) */
265 case 'B': /* byte (with optional counter) */
266 n
+= get_counter(&p
);
273 static bool init_package(struct pack_desc
*p
, int count
, int subcount
)
278 if (!p
->format
|| !p
->base
) {
282 i
= count
* getlen(p
->format
);
284 i
+= subcount
* getlen(p
->subformat
);
286 p
->structbuf
= p
->base
;
290 p
->curpos
= p
->format
;
296 * This is the old error code we used. Aparently
297 * WinNT/2k systems return ERRbuftoosmall (2123) and
298 * OS/2 needs this. I'm leaving this here so we can revert
301 p
->errcode
= ERRmoredata
;
303 p
->errcode
= ERRbuftoosmall
;
306 p
->errcode
= NERR_Success
;
310 p
->stringbuf
= p
->base
+ i
;
312 return (p
->errcode
== NERR_Success
);
315 static int package(struct pack_desc
*p
, ...)
318 int needed
=0, stringneeded
;
319 const char *str
=NULL
;
320 int is_string
=0, stringused
;
327 p
->curpos
= p
->format
;
329 p
->curpos
= p
->subformat
;
334 str
= va_arg(args
,char*);
335 SMB_ASSERT(strncmp(str
,p
->curpos
,strlen(str
)) == 0);
344 switch( *p
->curpos
++ ) {
345 case 'W': /* word (2 byte) */
347 temp
= va_arg(args
,int);
348 if (p
->buflen
>= needed
) {
349 SSVAL(p
->structbuf
,0,temp
);
352 case 'K': /* status word? (2 byte) */
354 temp
= va_arg(args
,int);
355 if (p
->buflen
>= needed
) {
356 SSVAL(p
->structbuf
,0,temp
);
359 case 'N': /* count of substructures (word) at end */
361 p
->subcount
= va_arg(args
,int);
362 if (p
->buflen
>= needed
) {
363 SSVAL(p
->structbuf
,0,p
->subcount
);
366 case 'D': /* double word (4 byte) */
368 temp
= va_arg(args
,int);
369 if (p
->buflen
>= needed
) {
370 SIVAL(p
->structbuf
,0,temp
);
373 case 'B': /* byte (with optional counter) */
374 needed
= get_counter(&p
->curpos
);
376 char *s
= va_arg(args
,char*);
377 if (p
->buflen
>= needed
) {
378 StrnCpy(p
->structbuf
,s
?s
:"",needed
-1);
382 case 'z': /* offset to zero terminated string (4 byte) */
383 str
= va_arg(args
,char*);
384 stringneeded
= (str
? strlen(str
)+1 : 0);
387 case 'l': /* offset to user data (4 byte) */
388 str
= va_arg(args
,char*);
389 stringneeded
= va_arg(args
,int);
392 case 'b': /* offset to data (with counter) (4 byte) */
393 str
= va_arg(args
,char*);
394 stringneeded
= get_counter(&p
->curpos
);
400 if (stringneeded
>= 0) {
402 if (p
->buflen
>= needed
) {
403 stringused
= stringneeded
;
404 if (stringused
> p
->stringlen
) {
405 stringused
= (is_string
? p
->stringlen
: 0);
406 if (p
->errcode
== NERR_Success
) {
407 p
->errcode
= ERRmoredata
;
411 SIVAL(p
->structbuf
,0,0);
413 SIVAL(p
->structbuf
,0,PTR_DIFF(p
->stringbuf
,p
->base
));
414 memcpy(p
->stringbuf
,str
?str
:"",stringused
);
416 p
->stringbuf
[stringused
-1] = '\0';
418 p
->stringbuf
+= stringused
;
419 p
->stringlen
-= stringused
;
420 p
->usedlen
+= stringused
;
423 p
->neededlen
+= stringneeded
;
426 p
->neededlen
+= needed
;
427 if (p
->buflen
>= needed
) {
428 p
->structbuf
+= needed
;
430 p
->usedlen
+= needed
;
432 if (p
->errcode
== NERR_Success
) {
433 p
->errcode
= ERRmoredata
;
440 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
441 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
443 #define PACK(desc,t,v) package(desc,v)
444 #define PACKl(desc,t,v,l) package(desc,v,l)
447 static void PACKI(struct pack_desc
* desc
, const char *t
,int v
)
452 static void PACKS(struct pack_desc
* desc
,const char *t
,const char *v
)
457 /****************************************************************************
459 ****************************************************************************/
461 static void PackDriverData(struct pack_desc
* desc
)
463 char drivdata
[4+4+32];
464 SIVAL(drivdata
,0,sizeof drivdata
); /* cb */
465 SIVAL(drivdata
,4,1000); /* lVersion */
466 memset(drivdata
+8,0,32); /* szDeviceName */
467 push_ascii(drivdata
+8,"NULL",32, STR_TERMINATE
);
468 PACKl(desc
,"l",drivdata
,sizeof drivdata
); /* pDriverData */
471 static int check_printq_info(struct pack_desc
* desc
,
472 unsigned int uLevel
, char *id1
, char *id2
)
474 desc
->subformat
= NULL
;
477 desc
->format
= "B13";
480 desc
->format
= "B13BWWWzzzzzWW";
483 desc
->format
= "B13BWWWzzzzzWN";
484 desc
->subformat
= "WB21BB16B10zWWzDDz";
487 desc
->format
= "zWWWWzzzzWWzzl";
490 desc
->format
= "zWWWWzzzzWNzzl";
491 desc
->subformat
= "WWzWWDDzz";
500 desc
->format
= "WzzzzzzzzN";
501 desc
->subformat
= "z";
504 DEBUG(0,("check_printq_info: invalid level %d\n",
508 if (id1
== NULL
|| strcmp(desc
->format
,id1
) != 0) {
509 DEBUG(0,("check_printq_info: invalid format %s\n",
510 id1
? id1
: "<NULL>" ));
513 if (desc
->subformat
&& (id2
== NULL
|| strcmp(desc
->subformat
,id2
) != 0)) {
514 DEBUG(0,("check_printq_info: invalid subformat %s\n",
515 id2
? id2
: "<NULL>" ));
522 #define RAP_JOB_STATUS_QUEUED 0
523 #define RAP_JOB_STATUS_PAUSED 1
524 #define RAP_JOB_STATUS_SPOOLING 2
525 #define RAP_JOB_STATUS_PRINTING 3
526 #define RAP_JOB_STATUS_PRINTED 4
528 #define RAP_QUEUE_STATUS_PAUSED 1
529 #define RAP_QUEUE_STATUS_ERROR 2
531 /* turn a print job status into a on the wire status
533 static int printj_status(int v
)
537 return RAP_JOB_STATUS_QUEUED
;
539 return RAP_JOB_STATUS_PAUSED
;
541 return RAP_JOB_STATUS_SPOOLING
;
543 return RAP_JOB_STATUS_PRINTING
;
548 /* turn a print queue status into a on the wire status
550 static int printq_status(int v
)
556 return RAP_QUEUE_STATUS_PAUSED
;
558 return RAP_QUEUE_STATUS_ERROR
;
561 static void fill_printjob_info(connection_struct
*conn
, int snum
, int uLevel
,
562 struct pack_desc
*desc
,
563 print_queue_struct
*queue
, int n
)
565 time_t t
= queue
->time
;
567 /* the client expects localtime */
568 t
-= get_time_zone(t
);
570 PACKI(desc
,"W",pjobid_to_rap(lp_const_servicename(snum
),queue
->job
)); /* uJobId */
572 PACKS(desc
,"B21",queue
->fs_user
); /* szUserName */
573 PACKS(desc
,"B",""); /* pad */
574 PACKS(desc
,"B16",""); /* szNotifyName */
575 PACKS(desc
,"B10","PM_Q_RAW"); /* szDataType */
576 PACKS(desc
,"z",""); /* pszParms */
577 PACKI(desc
,"W",n
+1); /* uPosition */
578 PACKI(desc
,"W",printj_status(queue
->status
)); /* fsStatus */
579 PACKS(desc
,"z",""); /* pszStatus */
580 PACKI(desc
,"D",t
); /* ulSubmitted */
581 PACKI(desc
,"D",queue
->size
); /* ulSize */
582 PACKS(desc
,"z",queue
->fs_file
); /* pszComment */
584 if (uLevel
== 2 || uLevel
== 3 || uLevel
== 4) {
585 PACKI(desc
,"W",queue
->priority
); /* uPriority */
586 PACKS(desc
,"z",queue
->fs_user
); /* pszUserName */
587 PACKI(desc
,"W",n
+1); /* uPosition */
588 PACKI(desc
,"W",printj_status(queue
->status
)); /* fsStatus */
589 PACKI(desc
,"D",t
); /* ulSubmitted */
590 PACKI(desc
,"D",queue
->size
); /* ulSize */
591 PACKS(desc
,"z","Samba"); /* pszComment */
592 PACKS(desc
,"z",queue
->fs_file
); /* pszDocument */
594 PACKS(desc
,"z",""); /* pszNotifyName */
595 PACKS(desc
,"z","PM_Q_RAW"); /* pszDataType */
596 PACKS(desc
,"z",""); /* pszParms */
597 PACKS(desc
,"z",""); /* pszStatus */
598 PACKS(desc
,"z",SERVICE(snum
)); /* pszQueue */
599 PACKS(desc
,"z","lpd"); /* pszQProcName */
600 PACKS(desc
,"z",""); /* pszQProcParms */
601 PACKS(desc
,"z","NULL"); /* pszDriverName */
602 PackDriverData(desc
); /* pDriverData */
603 PACKS(desc
,"z",""); /* pszPrinterName */
604 } else if (uLevel
== 4) { /* OS2 */
605 PACKS(desc
,"z",""); /* pszSpoolFileName */
606 PACKS(desc
,"z",""); /* pszPortName */
607 PACKS(desc
,"z",""); /* pszStatus */
608 PACKI(desc
,"D",0); /* ulPagesSpooled */
609 PACKI(desc
,"D",0); /* ulPagesSent */
610 PACKI(desc
,"D",0); /* ulPagesPrinted */
611 PACKI(desc
,"D",0); /* ulTimePrinted */
612 PACKI(desc
,"D",0); /* ulExtendJobStatus */
613 PACKI(desc
,"D",0); /* ulStartPage */
614 PACKI(desc
,"D",0); /* ulEndPage */
619 /********************************************************************
620 Return a driver name given an snum.
621 Returns True if from tdb, False otherwise.
622 ********************************************************************/
624 static bool get_driver_name(int snum
, char **pp_drivername
)
626 NT_PRINTER_INFO_LEVEL
*info
= NULL
;
629 get_a_printer (NULL
, &info
, 2, lp_servicename(snum
));
631 *pp_drivername
= talloc_strdup(talloc_tos(),
632 info
->info_2
->drivername
);
634 free_a_printer(&info
, 2);
635 if (!*pp_drivername
) {
643 /********************************************************************
644 Respond to the DosPrintQInfo command with a level of 52
645 This is used to get printer driver information for Win9x clients
646 ********************************************************************/
647 static void fill_printq_info_52(connection_struct
*conn
, int snum
,
648 struct pack_desc
* desc
, int count
)
652 struct spoolss_DriverInfo8
*driver
= NULL
;
653 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
655 if ( !W_ERROR_IS_OK(get_a_printer( NULL
, &printer
, 2, lp_servicename(snum
))) ) {
656 DEBUG(3,("fill_printq_info_52: Failed to lookup printer [%s]\n",
657 lp_servicename(snum
)));
661 if (!W_ERROR_IS_OK(get_a_printer_driver(talloc_tos(), &driver
, printer
->info_2
->drivername
,
664 DEBUG(3,("fill_printq_info_52: Failed to lookup driver [%s]\n",
665 printer
->info_2
->drivername
));
669 trim_string((char *)driver
->driver_path
, "\\print$\\WIN40\\0\\", 0);
670 trim_string((char *)driver
->data_file
, "\\print$\\WIN40\\0\\", 0);
671 trim_string((char *)driver
->help_file
, "\\print$\\WIN40\\0\\", 0);
673 PACKI(desc
, "W", 0x0400); /* don't know */
674 PACKS(desc
, "z", driver
->driver_name
); /* long printer name */
675 PACKS(desc
, "z", driver
->driver_path
); /* Driverfile Name */
676 PACKS(desc
, "z", driver
->data_file
); /* Datafile name */
677 PACKS(desc
, "z", driver
->monitor_name
); /* language monitor */
679 fstrcpy(location
, "\\\\%L\\print$\\WIN40\\0");
680 standard_sub_basic( "", "", location
, sizeof(location
)-1 );
681 PACKS(desc
,"z", location
); /* share to retrieve files */
683 PACKS(desc
,"z", driver
->default_datatype
); /* default data type */
684 PACKS(desc
,"z", driver
->help_file
); /* helpfile name */
685 PACKS(desc
,"z", driver
->driver_path
); /* driver name */
687 DEBUG(3,("Printer Driver Name: %s:\n",driver
->driver_name
));
688 DEBUG(3,("Driver: %s:\n",driver
->driver_path
));
689 DEBUG(3,("Data File: %s:\n",driver
->data_file
));
690 DEBUG(3,("Language Monitor: %s:\n",driver
->monitor_name
));
691 DEBUG(3,("Driver Location: %s:\n",location
));
692 DEBUG(3,("Data Type: %s:\n",driver
->default_datatype
));
693 DEBUG(3,("Help File: %s:\n",driver
->help_file
));
694 PACKI(desc
,"N",count
); /* number of files to copy */
696 for ( i
=0; i
<count
&& driver
->dependent_files
&& *driver
->dependent_files
[i
]; i
++)
698 trim_string((char *)driver
->dependent_files
[i
], "\\print$\\WIN40\\0\\", 0);
699 PACKS(desc
,"z",driver
->dependent_files
[i
]); /* driver files to copy */
700 DEBUG(3,("Dependent File: %s:\n", driver
->dependent_files
[i
]));
705 DEBUG(3,("fill_printq_info_52: file count specified by client [%d] != number of dependent files [%i]\n",
708 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n", SERVICE(snum
),i
));
710 desc
->errcode
=NERR_Success
;
714 DEBUG(3,("fill_printq_info: Can't supply driver files\n"));
715 desc
->errcode
=NERR_notsupported
;
719 free_a_printer( &printer
, 2 );
721 free_a_printer_driver(driver
);
725 static void fill_printq_info(connection_struct
*conn
, int snum
, int uLevel
,
726 struct pack_desc
* desc
,
727 int count
, print_queue_struct
* queue
,
728 print_status_struct
* status
)
733 PACKS(desc
,"B13",SERVICE(snum
));
738 PACKS(desc
,"z",Expand(conn
,snum
,SERVICE(snum
)));
741 PACKI(desc
,"K",printq_status(status
->status
));
745 if (uLevel
== 1 || uLevel
== 2) {
746 PACKS(desc
,"B",""); /* alignment */
747 PACKI(desc
,"W",5); /* priority */
748 PACKI(desc
,"W",0); /* start time */
749 PACKI(desc
,"W",0); /* until time */
750 PACKS(desc
,"z",""); /* pSepFile */
751 PACKS(desc
,"z","lpd"); /* pPrProc */
752 PACKS(desc
,"z",SERVICE(snum
)); /* pDestinations */
753 PACKS(desc
,"z",""); /* pParms */
755 PACKS(desc
,"z","UNKNOWN PRINTER");
756 PACKI(desc
,"W",LPSTAT_ERROR
);
758 else if (!status
|| !status
->message
[0]) {
759 PACKS(desc
,"z",Expand(conn
,snum
,lp_comment(snum
)));
760 PACKI(desc
,"W",LPSTAT_OK
); /* status */
762 PACKS(desc
,"z",status
->message
);
763 PACKI(desc
,"W",printq_status(status
->status
)); /* status */
765 PACKI(desc
,(uLevel
== 1 ? "W" : "N"),count
);
768 if (uLevel
== 3 || uLevel
== 4) {
769 char *drivername
= NULL
;
771 PACKI(desc
,"W",5); /* uPriority */
772 PACKI(desc
,"W",0); /* uStarttime */
773 PACKI(desc
,"W",0); /* uUntiltime */
774 PACKI(desc
,"W",5); /* pad1 */
775 PACKS(desc
,"z",""); /* pszSepFile */
776 PACKS(desc
,"z","WinPrint"); /* pszPrProc */
777 PACKS(desc
,"z",NULL
); /* pszParms */
778 PACKS(desc
,"z",NULL
); /* pszComment - don't ask.... JRA */
779 /* "don't ask" that it's done this way to fix corrupted
780 Win9X/ME printer comments. */
782 PACKI(desc
,"W",LPSTAT_OK
); /* fsStatus */
784 PACKI(desc
,"W",printq_status(status
->status
)); /* fsStatus */
786 PACKI(desc
,(uLevel
== 3 ? "W" : "N"),count
); /* cJobs */
787 PACKS(desc
,"z",SERVICE(snum
)); /* pszPrinters */
788 get_driver_name(snum
,&drivername
);
792 PACKS(desc
,"z",drivername
); /* pszDriverName */
793 PackDriverData(desc
); /* pDriverData */
796 if (uLevel
== 2 || uLevel
== 4) {
798 for (i
=0;i
<count
;i
++)
799 fill_printjob_info(conn
,snum
,uLevel
== 2 ? 1 : 2,desc
,&queue
[i
],i
);
803 fill_printq_info_52( conn
, snum
, desc
, count
);
806 /* This function returns the number of files for a given driver */
807 static int get_printerdrivernumber(int snum
)
810 struct spoolss_DriverInfo8
*driver
;
811 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
815 if ( !W_ERROR_IS_OK(get_a_printer( NULL
, &printer
, 2, lp_servicename(snum
))) ) {
816 DEBUG(3,("get_printerdrivernumber: Failed to lookup printer [%s]\n",
817 lp_servicename(snum
)));
821 if (!W_ERROR_IS_OK(get_a_printer_driver(talloc_tos(), &driver
, printer
->info_2
->drivername
,
824 DEBUG(3,("get_printerdrivernumber: Failed to lookup driver [%s]\n",
825 printer
->info_2
->drivername
));
829 /* count the number of files */
830 while (driver
->dependent_files
&& *driver
->dependent_files
[result
])
834 free_a_printer( &printer
, 2 );
836 free_a_printer_driver(driver
);
841 static bool api_DosPrintQGetInfo(connection_struct
*conn
, uint16 vuid
,
842 char *param
, int tpscnt
,
843 char *data
, int tdscnt
,
844 int mdrcnt
,int mprcnt
,
845 char **rdata
,char **rparam
,
846 int *rdata_len
,int *rparam_len
)
848 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
849 char *str2
= skip_string(param
,tpscnt
,str1
);
850 char *p
= skip_string(param
,tpscnt
,str2
);
856 struct pack_desc desc
;
857 print_queue_struct
*queue
=NULL
;
858 print_status_struct status
;
861 if (!str1
|| !str2
|| !p
) {
864 memset((char *)&status
,'\0',sizeof(status
));
865 memset((char *)&desc
,'\0',sizeof(desc
));
867 p
= skip_string(param
,tpscnt
,p
);
871 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
872 str3
= get_safe_str_ptr(param
,tpscnt
,p
,4);
873 /* str3 may be null here and is checked in check_printq_info(). */
875 /* remove any trailing username */
876 if ((p
= strchr_m(QueueName
,'%')))
879 DEBUG(3,("api_DosPrintQGetInfo uLevel=%d name=%s\n",uLevel
,QueueName
));
881 /* check it's a supported varient */
882 if (!prefix_ok(str1
,"zWrLh"))
884 if (!check_printq_info(&desc
,uLevel
,str2
,str3
)) {
886 * Patch from Scott Moomaw <scott@bridgewater.edu>
887 * to return the 'invalid info level' error if an
888 * unknown level was requested.
892 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
896 SSVALS(*rparam
,0,ERRunknownlevel
);
902 snum
= find_service(QueueName
);
903 if ( !(lp_snum_ok(snum
) && lp_print_ok(snum
)) )
907 count
= get_printerdrivernumber(snum
);
908 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count
));
910 count
= print_queue_status(snum
, &queue
,&status
);
914 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
920 desc
.buflen
= mdrcnt
;
923 * Don't return data but need to get correct length
924 * init_package will return wrong size if buflen=0
926 desc
.buflen
= getlen(desc
.format
);
927 desc
.base
= tmpdata
= (char *) SMB_MALLOC (desc
.buflen
);
930 if (init_package(&desc
,1,count
)) {
931 desc
.subcount
= count
;
932 fill_printq_info(conn
,snum
,uLevel
,&desc
,count
,queue
,&status
);
935 *rdata_len
= desc
.usedlen
;
938 * We must set the return code to ERRbuftoosmall
939 * in order to support lanman style printing with Win NT/2k
942 if (!mdrcnt
&& lp_disable_spoolss())
943 desc
.errcode
= ERRbuftoosmall
;
945 *rdata_len
= desc
.usedlen
;
947 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
953 SSVALS(*rparam
,0,desc
.errcode
);
955 SSVAL(*rparam
,4,desc
.neededlen
);
957 DEBUG(4,("printqgetinfo: errorcode %d\n",desc
.errcode
));
965 /****************************************************************************
966 View list of all print jobs on all queues.
967 ****************************************************************************/
969 static bool api_DosPrintQEnum(connection_struct
*conn
, uint16 vuid
,
970 char *param
, int tpscnt
,
971 char *data
, int tdscnt
,
972 int mdrcnt
, int mprcnt
,
973 char **rdata
, char** rparam
,
974 int *rdata_len
, int *rparam_len
)
976 char *param_format
= get_safe_str_ptr(param
,tpscnt
,param
,2);
977 char *output_format1
= skip_string(param
,tpscnt
,param_format
);
978 char *p
= skip_string(param
,tpscnt
,output_format1
);
979 unsigned int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
980 char *output_format2
= get_safe_str_ptr(param
,tpscnt
,p
,4);
981 int services
= lp_numservices();
983 struct pack_desc desc
;
984 print_queue_struct
**queue
= NULL
;
985 print_status_struct
*status
= NULL
;
986 int *subcntarr
= NULL
;
987 int queuecnt
= 0, subcnt
= 0, succnt
= 0;
989 if (!param_format
|| !output_format1
|| !p
) {
993 memset((char *)&desc
,'\0',sizeof(desc
));
995 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel
));
997 if (!prefix_ok(param_format
,"WrLeh")) {
1000 if (!check_printq_info(&desc
,uLevel
,output_format1
,output_format2
)) {
1002 * Patch from Scott Moomaw <scott@bridgewater.edu>
1003 * to return the 'invalid info level' error if an
1004 * unknown level was requested.
1008 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1012 SSVALS(*rparam
,0,ERRunknownlevel
);
1018 for (i
= 0; i
< services
; i
++) {
1019 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
)) {
1024 if((queue
= SMB_MALLOC_ARRAY(print_queue_struct
*, queuecnt
)) == NULL
) {
1025 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
1028 memset(queue
,0,queuecnt
*sizeof(print_queue_struct
*));
1029 if((status
= SMB_MALLOC_ARRAY(print_status_struct
,queuecnt
)) == NULL
) {
1030 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
1033 memset(status
,0,queuecnt
*sizeof(print_status_struct
));
1034 if((subcntarr
= SMB_MALLOC_ARRAY(int,queuecnt
)) == NULL
) {
1035 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
1041 for (i
= 0; i
< services
; i
++) {
1042 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
)) {
1043 subcntarr
[n
] = print_queue_status(i
, &queue
[n
],&status
[n
]);
1044 subcnt
+= subcntarr
[n
];
1050 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
1056 desc
.buflen
= mdrcnt
;
1058 if (init_package(&desc
,queuecnt
,subcnt
)) {
1061 for (i
= 0; i
< services
; i
++) {
1062 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
)) {
1063 fill_printq_info(conn
,i
,uLevel
,&desc
,subcntarr
[n
],queue
[n
],&status
[n
]);
1065 if (desc
.errcode
== NERR_Success
) {
1072 SAFE_FREE(subcntarr
);
1074 *rdata_len
= desc
.usedlen
;
1076 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1080 SSVALS(*rparam
,0,desc
.errcode
);
1082 SSVAL(*rparam
,4,succnt
);
1083 SSVAL(*rparam
,6,queuecnt
);
1085 for (i
= 0; i
< queuecnt
; i
++) {
1087 SAFE_FREE(queue
[i
]);
1098 SAFE_FREE(subcntarr
);
1099 for (i
= 0; i
< queuecnt
; i
++) {
1101 SAFE_FREE(queue
[i
]);
1110 /****************************************************************************
1111 Get info level for a server list query.
1112 ****************************************************************************/
1114 static bool check_server_info(int uLevel
, char* id
)
1118 if (strcmp(id
,"B16") != 0) {
1123 if (strcmp(id
,"B16BBDz") != 0) {
1133 struct srv_info_struct
{
1141 /*******************************************************************
1142 Get server info lists from the files saved by nmbd. Return the
1144 ******************************************************************/
1146 static int get_server_info(uint32 servertype
,
1147 struct srv_info_struct
**servers
,
1153 bool local_list_only
;
1156 lines
= file_lines_load(cache_path(SERVER_LIST
), NULL
, 0, NULL
);
1158 DEBUG(4,("Can't open %s - %s\n",cache_path(SERVER_LIST
),strerror(errno
)));
1162 /* request for everything is code for request all servers */
1163 if (servertype
== SV_TYPE_ALL
) {
1164 servertype
&= ~(SV_TYPE_DOMAIN_ENUM
|SV_TYPE_LOCAL_LIST_ONLY
);
1167 local_list_only
= (servertype
& SV_TYPE_LOCAL_LIST_ONLY
);
1169 DEBUG(4,("Servertype search: %8x\n",servertype
));
1171 for (i
=0;lines
[i
];i
++) {
1173 struct srv_info_struct
*s
;
1174 const char *ptr
= lines
[i
];
1176 TALLOC_CTX
*frame
= NULL
;
1183 if (count
== alloced
) {
1185 *servers
= SMB_REALLOC_ARRAY(*servers
,struct srv_info_struct
, alloced
);
1187 DEBUG(0,("get_server_info: failed to enlarge servers info struct!\n"));
1191 memset((char *)((*servers
)+count
),'\0',sizeof(**servers
)*(alloced
-count
));
1193 s
= &(*servers
)[count
];
1195 frame
= talloc_stackframe();
1197 if (!next_token_talloc(frame
,&ptr
,&p
, NULL
)) {
1201 fstrcpy(s
->name
, p
);
1204 if (!next_token_talloc(frame
,&ptr
, &p
, NULL
)) {
1210 s
->comment
[0] = '\0';
1211 if (!next_token_talloc(frame
,&ptr
, &p
, NULL
)) {
1215 fstrcpy(s
->comment
, p
);
1216 string_truncate(s
->comment
, MAX_SERVER_STRING_LENGTH
);
1218 s
->domain
[0] = '\0';
1219 if (!next_token_talloc(frame
,&ptr
,&p
, NULL
)) {
1220 /* this allows us to cope with an old nmbd */
1221 fstrcpy(s
->domain
,lp_workgroup());
1223 fstrcpy(s
->domain
, p
);
1227 if (sscanf(stype
,"%X",&s
->type
) != 1) {
1228 DEBUG(4,("r:host file "));
1232 /* Filter the servers/domains we return based on what was asked for. */
1234 /* Check to see if we are being asked for a local list only. */
1235 if(local_list_only
&& ((s
->type
& SV_TYPE_LOCAL_LIST_ONLY
) == 0)) {
1236 DEBUG(4,("r: local list only"));
1240 /* doesn't match up: don't want it */
1241 if (!(servertype
& s
->type
)) {
1242 DEBUG(4,("r:serv type "));
1246 if ((servertype
& SV_TYPE_DOMAIN_ENUM
) !=
1247 (s
->type
& SV_TYPE_DOMAIN_ENUM
)) {
1248 DEBUG(4,("s: dom mismatch "));
1252 if (!strequal(domain
, s
->domain
) && !(servertype
& SV_TYPE_DOMAIN_ENUM
)) {
1256 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1257 s
->type
&= ~SV_TYPE_LOCAL_LIST_ONLY
;
1260 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1261 s
->name
, s
->type
, s
->comment
, s
->domain
));
1262 s
->server_added
= True
;
1265 DEBUG(4,("%20s %8x %25s %15s\n",
1266 s
->name
, s
->type
, s
->comment
, s
->domain
));
1274 /*******************************************************************
1275 Fill in a server info structure.
1276 ******************************************************************/
1278 static int fill_srv_info(struct srv_info_struct
*service
,
1279 int uLevel
, char **buf
, int *buflen
,
1280 char **stringbuf
, int *stringspace
, char *baseaddr
)
1303 len
= strlen(service
->comment
)+1;
1307 *buflen
= struct_len
;
1309 return struct_len
+ len
;
1314 if (*buflen
< struct_len
) {
1321 p2
= p
+ struct_len
;
1322 l2
= *buflen
- struct_len
;
1330 push_ascii(p
,service
->name
, MAX_NETBIOSNAME_LEN
, STR_TERMINATE
);
1334 push_ascii(p
,service
->name
,MAX_NETBIOSNAME_LEN
, STR_TERMINATE
);
1335 SIVAL(p
,18,service
->type
);
1336 SIVAL(p
,22,PTR_DIFF(p2
,baseaddr
));
1337 len
+= CopyAndAdvance(&p2
,service
->comment
,&l2
);
1342 *buf
= p
+ struct_len
;
1343 *buflen
-= struct_len
;
1354 static int srv_comp(struct srv_info_struct
*s1
,struct srv_info_struct
*s2
)
1356 return StrCaseCmp(s1
->name
,s2
->name
);
1359 /****************************************************************************
1360 View list of servers available (or possibly domains). The info is
1361 extracted from lists saved by nmbd on the local host.
1362 ****************************************************************************/
1364 static bool api_RNetServerEnum2(connection_struct
*conn
, uint16 vuid
,
1365 char *param
, int tpscnt
,
1366 char *data
, int tdscnt
,
1367 int mdrcnt
, int mprcnt
, char **rdata
,
1368 char **rparam
, int *rdata_len
, int *rparam_len
)
1370 char *str1
= get_safe_str_ptr(param
, tpscnt
, param
, 2);
1371 char *str2
= skip_string(param
,tpscnt
,str1
);
1372 char *p
= skip_string(param
,tpscnt
,str2
);
1373 int uLevel
= get_safe_SVAL(param
, tpscnt
, p
, 0, -1);
1374 int buf_len
= get_safe_SVAL(param
,tpscnt
, p
, 2, 0);
1375 uint32 servertype
= get_safe_IVAL(param
,tpscnt
,p
,4, 0);
1377 int data_len
, fixed_len
, string_len
;
1378 int f_len
= 0, s_len
= 0;
1379 struct srv_info_struct
*servers
=NULL
;
1380 int counted
=0,total
=0;
1383 bool domain_request
;
1386 if (!str1
|| !str2
|| !p
) {
1390 /* If someone sets all the bits they don't really mean to set
1391 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1394 if (servertype
== SV_TYPE_ALL
) {
1395 servertype
&= ~(SV_TYPE_DOMAIN_ENUM
|SV_TYPE_LOCAL_LIST_ONLY
);
1398 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1399 any other bit (they may just set this bit on its own) they
1400 want all the locally seen servers. However this bit can be
1401 set on its own so set the requested servers to be
1402 ALL - DOMAIN_ENUM. */
1404 if ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) && !(servertype
& SV_TYPE_DOMAIN_ENUM
)) {
1405 servertype
= SV_TYPE_ALL
& ~(SV_TYPE_DOMAIN_ENUM
);
1408 domain_request
= ((servertype
& SV_TYPE_DOMAIN_ENUM
) != 0);
1409 local_request
= ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) != 0);
1413 if (!prefix_ok(str1
,"WrLehD")) {
1416 if (!check_server_info(uLevel
,str2
)) {
1420 DEBUG(4, ("server request level: %s %8x ", str2
, servertype
));
1421 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request
)));
1422 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request
)));
1424 if (strcmp(str1
, "WrLehDz") == 0) {
1425 if (skip_string(param
,tpscnt
,p
) == NULL
) {
1428 pull_ascii_fstring(domain
, p
);
1430 fstrcpy(domain
, lp_workgroup());
1433 DEBUG(4, ("domain [%s]\n", domain
));
1435 if (lp_browse_list()) {
1436 total
= get_server_info(servertype
,&servers
,domain
);
1439 data_len
= fixed_len
= string_len
= 0;
1442 TYPESAFE_QSORT(servers
, total
, srv_comp
);
1445 char *lastname
=NULL
;
1447 for (i
=0;i
<total
;i
++) {
1448 struct srv_info_struct
*s
= &servers
[i
];
1450 if (lastname
&& strequal(lastname
,s
->name
)) {
1454 data_len
+= fill_srv_info(s
,uLevel
,0,&f_len
,0,&s_len
,0);
1455 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1456 i
, s
->name
, s
->type
, s
->comment
, s
->domain
));
1458 if (data_len
< buf_len
) {
1461 string_len
+= s_len
;
1468 *rdata_len
= fixed_len
+ string_len
;
1469 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
1474 p2
= (*rdata
) + fixed_len
; /* auxilliary data (strings) will go here */
1480 char *lastname
=NULL
;
1481 int count2
= counted
;
1483 for (i
= 0; i
< total
&& count2
;i
++) {
1484 struct srv_info_struct
*s
= &servers
[i
];
1486 if (lastname
&& strequal(lastname
,s
->name
)) {
1490 fill_srv_info(s
,uLevel
,&p
,&f_len
,&p2
,&s_len
,*rdata
);
1491 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1492 i
, s
->name
, s
->type
, s
->comment
, s
->domain
));
1498 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1502 SSVAL(*rparam
,0,(missed
== 0 ? NERR_Success
: ERRmoredata
));
1504 SSVAL(*rparam
,4,counted
);
1505 SSVAL(*rparam
,6,counted
+missed
);
1509 DEBUG(3,("NetServerEnum2 domain = %s uLevel=%d counted=%d total=%d\n",
1510 domain
,uLevel
,counted
,counted
+missed
));
1515 static int srv_name_match(const char *n1
, const char *n2
)
1518 * [MS-RAP] footnote <88> for Section 3.2.5.15 says:
1520 * In Windows, FirstNameToReturn need not be an exact match:
1521 * the server will return a list of servers that exist on
1522 * the network greater than or equal to the FirstNameToReturn.
1524 int ret
= StrCaseCmp(n1
, n2
);
1533 static bool api_RNetServerEnum3(connection_struct
*conn
, uint16 vuid
,
1534 char *param
, int tpscnt
,
1535 char *data
, int tdscnt
,
1536 int mdrcnt
, int mprcnt
, char **rdata
,
1537 char **rparam
, int *rdata_len
, int *rparam_len
)
1539 char *str1
= get_safe_str_ptr(param
, tpscnt
, param
, 2);
1540 char *str2
= skip_string(param
,tpscnt
,str1
);
1541 char *p
= skip_string(param
,tpscnt
,str2
);
1542 int uLevel
= get_safe_SVAL(param
, tpscnt
, p
, 0, -1);
1543 int buf_len
= get_safe_SVAL(param
,tpscnt
, p
, 2, 0);
1544 uint32 servertype
= get_safe_IVAL(param
,tpscnt
,p
,4, 0);
1546 int data_len
, fixed_len
, string_len
;
1547 int f_len
= 0, s_len
= 0;
1548 struct srv_info_struct
*servers
=NULL
;
1549 int counted
=0,first
=0,total
=0;
1553 bool domain_request
;
1556 if (!str1
|| !str2
|| !p
) {
1560 /* If someone sets all the bits they don't really mean to set
1561 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1564 if (servertype
== SV_TYPE_ALL
) {
1565 servertype
&= ~(SV_TYPE_DOMAIN_ENUM
|SV_TYPE_LOCAL_LIST_ONLY
);
1568 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1569 any other bit (they may just set this bit on its own) they
1570 want all the locally seen servers. However this bit can be
1571 set on its own so set the requested servers to be
1572 ALL - DOMAIN_ENUM. */
1574 if ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) && !(servertype
& SV_TYPE_DOMAIN_ENUM
)) {
1575 servertype
= SV_TYPE_ALL
& ~(SV_TYPE_DOMAIN_ENUM
);
1578 domain_request
= ((servertype
& SV_TYPE_DOMAIN_ENUM
) != 0);
1579 local_request
= ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) != 0);
1583 if (strcmp(str1
, "WrLehDzz") != 0) {
1586 if (!check_server_info(uLevel
,str2
)) {
1590 DEBUG(4, ("server request level: %s %8x ", str2
, servertype
));
1591 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request
)));
1592 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request
)));
1594 if (skip_string(param
,tpscnt
,p
) == NULL
) {
1597 pull_ascii_fstring(domain
, p
);
1598 if (domain
[0] == '\0') {
1599 fstrcpy(domain
, lp_workgroup());
1601 p
= skip_string(param
,tpscnt
,p
);
1602 if (skip_string(param
,tpscnt
,p
) == NULL
) {
1605 pull_ascii_fstring(first_name
, p
);
1607 DEBUG(4, ("domain: '%s' first_name: '%s'\n",
1608 domain
, first_name
));
1610 if (lp_browse_list()) {
1611 total
= get_server_info(servertype
,&servers
,domain
);
1614 data_len
= fixed_len
= string_len
= 0;
1617 TYPESAFE_QSORT(servers
, total
, srv_comp
);
1619 if (first_name
[0] != '\0') {
1620 struct srv_info_struct
*first_server
= NULL
;
1622 BINARY_ARRAY_SEARCH(servers
, total
, name
, first_name
,
1623 srv_name_match
, first_server
);
1625 first
= PTR_DIFF(first_server
, servers
) / sizeof(*servers
);
1627 * The binary search may not find the exact match
1628 * so we need to search backward to find the first match
1630 * This implements the strange matching windows
1631 * implements. (see the comment in srv_name_match().
1635 ret
= StrCaseCmp(first_name
,
1636 servers
[first
-1].name
);
1643 /* we should return no entries */
1649 char *lastname
=NULL
;
1651 for (i
=first
;i
<total
;i
++) {
1652 struct srv_info_struct
*s
= &servers
[i
];
1654 if (lastname
&& strequal(lastname
,s
->name
)) {
1658 data_len
+= fill_srv_info(s
,uLevel
,0,&f_len
,0,&s_len
,0);
1659 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1660 i
, s
->name
, s
->type
, s
->comment
, s
->domain
));
1662 if (data_len
< buf_len
) {
1665 string_len
+= s_len
;
1672 *rdata_len
= fixed_len
+ string_len
;
1673 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
1678 p2
= (*rdata
) + fixed_len
; /* auxilliary data (strings) will go here */
1684 char *lastname
=NULL
;
1685 int count2
= counted
;
1687 for (i
= first
; i
< total
&& count2
;i
++) {
1688 struct srv_info_struct
*s
= &servers
[i
];
1690 if (lastname
&& strequal(lastname
,s
->name
)) {
1694 fill_srv_info(s
,uLevel
,&p
,&f_len
,&p2
,&s_len
,*rdata
);
1695 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1696 i
, s
->name
, s
->type
, s
->comment
, s
->domain
));
1702 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1706 SSVAL(*rparam
,0,(missed
== 0 ? NERR_Success
: ERRmoredata
));
1708 SSVAL(*rparam
,4,counted
);
1709 SSVAL(*rparam
,6,counted
+missed
);
1711 DEBUG(3,("NetServerEnum3 domain = %s uLevel=%d first=%d[%s => %s] counted=%d total=%d\n",
1712 domain
,uLevel
,first
,first_name
,
1713 first
< total
? servers
[first
].name
: "",
1714 counted
,counted
+missed
));
1721 /****************************************************************************
1722 command 0x34 - suspected of being a "Lookup Names" stub api
1723 ****************************************************************************/
1725 static bool api_RNetGroupGetUsers(connection_struct
*conn
, uint16 vuid
,
1726 char *param
, int tpscnt
,
1727 char *data
, int tdscnt
,
1728 int mdrcnt
, int mprcnt
, char **rdata
,
1729 char **rparam
, int *rdata_len
, int *rparam_len
)
1731 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
1732 char *str2
= skip_string(param
,tpscnt
,str1
);
1733 char *p
= skip_string(param
,tpscnt
,str2
);
1734 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
1735 int buf_len
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
1739 if (!str1
|| !str2
|| !p
) {
1743 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1744 str1
, str2
, p
, uLevel
, buf_len
));
1746 if (!prefix_ok(str1
,"zWrLeh")) {
1753 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1758 SSVAL(*rparam
,0,0x08AC); /* informational warning message */
1760 SSVAL(*rparam
,4,counted
);
1761 SSVAL(*rparam
,6,counted
+missed
);
1766 /****************************************************************************
1767 get info about a share
1768 ****************************************************************************/
1770 static bool check_share_info(int uLevel
, char* id
)
1774 if (strcmp(id
,"B13") != 0) {
1779 /* Level-2 descriptor is allowed (and ignored) */
1780 if (strcmp(id
,"B13BWz") != 0 &&
1781 strcmp(id
,"B13BWzWWWzB9B") != 0) {
1786 if (strcmp(id
,"B13BWzWWWzB9B") != 0) {
1791 if (strcmp(id
,"B13BWzWWWzB9BB9BWzWWzWW") != 0) {
1801 static int fill_share_info(connection_struct
*conn
, int snum
, int uLevel
,
1802 char** buf
, int* buflen
,
1803 char** stringbuf
, int* stringspace
, char* baseaddr
)
1832 len
+= StrlenExpanded(conn
,snum
,lp_comment(snum
));
1835 len
+= strlen(lp_pathname(snum
)) + 1;
1838 *buflen
= struct_len
;
1843 return struct_len
+ len
;
1848 if ((*buflen
) < struct_len
) {
1856 p2
= p
+ struct_len
;
1857 l2
= (*buflen
) - struct_len
;
1864 push_ascii(p
,lp_servicename(snum
),13, STR_TERMINATE
);
1870 type
= STYPE_DISKTREE
;
1871 if (lp_print_ok(snum
)) {
1872 type
= STYPE_PRINTQ
;
1874 if (strequal("IPC",lp_fstype(snum
))) {
1877 SSVAL(p
,14,type
); /* device type */
1878 SIVAL(p
,16,PTR_DIFF(p2
,baseaddr
));
1879 len
+= CopyExpanded(conn
,snum
,&p2
,lp_comment(snum
),&l2
);
1883 SSVAL(p
,20,ACCESS_READ
|ACCESS_WRITE
|ACCESS_CREATE
); /* permissions */
1884 SSVALS(p
,22,-1); /* max uses */
1885 SSVAL(p
,24,1); /* current uses */
1886 SIVAL(p
,26,PTR_DIFF(p2
,baseaddr
)); /* local pathname */
1887 len
+= CopyAndAdvance(&p2
,lp_pathname(snum
),&l2
);
1888 memset(p
+30,0,SHPWLEN
+2); /* passwd (reserved), pad field */
1892 memset(p
+40,0,SHPWLEN
+2);
1903 (*buf
) = p
+ struct_len
;
1904 (*buflen
) -= struct_len
;
1906 (*stringspace
) = l2
;
1915 static bool api_RNetShareGetInfo(connection_struct
*conn
,uint16 vuid
,
1916 char *param
, int tpscnt
,
1917 char *data
, int tdscnt
,
1918 int mdrcnt
,int mprcnt
,
1919 char **rdata
,char **rparam
,
1920 int *rdata_len
,int *rparam_len
)
1922 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
1923 char *str2
= skip_string(param
,tpscnt
,str1
);
1924 char *netname
= skip_string(param
,tpscnt
,str2
);
1925 char *p
= skip_string(param
,tpscnt
,netname
);
1926 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
1929 if (!str1
|| !str2
|| !netname
|| !p
) {
1933 snum
= find_service(netname
);
1938 /* check it's a supported varient */
1939 if (!prefix_ok(str1
,"zWrLh")) {
1942 if (!check_share_info(uLevel
,str2
)) {
1946 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
1951 *rdata_len
= fill_share_info(conn
,snum
,uLevel
,&p
,&mdrcnt
,0,0,0);
1952 if (*rdata_len
< 0) {
1957 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1961 SSVAL(*rparam
,0,NERR_Success
);
1962 SSVAL(*rparam
,2,0); /* converter word */
1963 SSVAL(*rparam
,4,*rdata_len
);
1968 /****************************************************************************
1969 View the list of available shares.
1971 This function is the server side of the NetShareEnum() RAP call.
1972 It fills the return buffer with share names and share comments.
1973 Note that the return buffer normally (in all known cases) allows only
1974 twelve byte strings for share names (plus one for a nul terminator).
1975 Share names longer than 12 bytes must be skipped.
1976 ****************************************************************************/
1978 static bool api_RNetShareEnum( connection_struct
*conn
, uint16 vuid
,
1979 char *param
, int tpscnt
,
1980 char *data
, int tdscnt
,
1988 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
1989 char *str2
= skip_string(param
,tpscnt
,str1
);
1990 char *p
= skip_string(param
,tpscnt
,str2
);
1991 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
1992 int buf_len
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
1995 int total
=0,counted
=0;
1996 bool missed
= False
;
1998 int data_len
, fixed_len
, string_len
;
1999 int f_len
= 0, s_len
= 0;
2001 if (!str1
|| !str2
|| !p
) {
2005 if (!prefix_ok(str1
,"WrLeh")) {
2008 if (!check_share_info(uLevel
,str2
)) {
2012 /* Ensure all the usershares are loaded. */
2014 load_registry_shares();
2015 count
= load_usershare_shares();
2018 data_len
= fixed_len
= string_len
= 0;
2019 for (i
=0;i
<count
;i
++) {
2020 fstring servicename_dos
;
2021 if (!(lp_browseable(i
) && lp_snum_ok(i
))) {
2024 push_ascii_fstring(servicename_dos
, lp_servicename(i
));
2025 /* Maximum name length = 13. */
2026 if( lp_browseable( i
) && lp_snum_ok( i
) && (strlen(servicename_dos
) < 13)) {
2028 data_len
+= fill_share_info(conn
,i
,uLevel
,0,&f_len
,0,&s_len
,0);
2029 if (data_len
< buf_len
) {
2032 string_len
+= s_len
;
2039 *rdata_len
= fixed_len
+ string_len
;
2040 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2045 p2
= (*rdata
) + fixed_len
; /* auxiliary data (strings) will go here */
2050 for( i
= 0; i
< count
; i
++ ) {
2051 fstring servicename_dos
;
2052 if (!(lp_browseable(i
) && lp_snum_ok(i
))) {
2056 push_ascii_fstring(servicename_dos
, lp_servicename(i
));
2057 if (lp_browseable(i
) && lp_snum_ok(i
) && (strlen(servicename_dos
) < 13)) {
2058 if (fill_share_info( conn
,i
,uLevel
,&p
,&f_len
,&p2
,&s_len
,*rdata
) < 0) {
2065 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2069 SSVAL(*rparam
,0,missed
? ERRmoredata
: NERR_Success
);
2071 SSVAL(*rparam
,4,counted
);
2072 SSVAL(*rparam
,6,total
);
2074 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
2075 counted
,total
,uLevel
,
2076 buf_len
,*rdata_len
,mdrcnt
));
2081 /****************************************************************************
2083 ****************************************************************************/
2085 static bool api_RNetShareAdd(connection_struct
*conn
,uint16 vuid
,
2086 char *param
, int tpscnt
,
2087 char *data
, int tdscnt
,
2088 int mdrcnt
,int mprcnt
,
2089 char **rdata
,char **rparam
,
2090 int *rdata_len
,int *rparam_len
)
2092 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2093 char *str2
= skip_string(param
,tpscnt
,str1
);
2094 char *p
= skip_string(param
,tpscnt
,str2
);
2095 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2098 char *pathname
= NULL
;
2099 char *command
, *cmdname
;
2100 unsigned int offset
;
2103 size_t converted_size
;
2105 if (!str1
|| !str2
|| !p
) {
2109 /* check it's a supported varient */
2110 if (!prefix_ok(str1
,RAP_WShareAdd_REQ
)) {
2113 if (!check_share_info(uLevel
,str2
)) {
2120 /* Do we have a string ? */
2121 if (skip_string(data
,mdrcnt
,data
) == NULL
) {
2124 pull_ascii_fstring(sharename
,data
);
2125 snum
= find_service(sharename
);
2126 if (snum
>= 0) { /* already exists */
2135 /* only support disk share adds */
2136 if (SVAL(data
,14)!=STYPE_DISKTREE
) {
2140 offset
= IVAL(data
, 16);
2141 if (offset
>= mdrcnt
) {
2142 res
= ERRinvalidparam
;
2146 /* Do we have a string ? */
2147 if (skip_string(data
,mdrcnt
,data
+offset
) == NULL
) {
2150 pull_ascii_fstring(comment
, offset
? (data
+offset
) : "");
2152 offset
= IVAL(data
, 26);
2154 if (offset
>= mdrcnt
) {
2155 res
= ERRinvalidparam
;
2159 /* Do we have a string ? */
2160 if (skip_string(data
,mdrcnt
,data
+offset
) == NULL
) {
2164 if (!pull_ascii_talloc(talloc_tos(), &pathname
,
2165 offset
? (data
+offset
) : "", &converted_size
))
2167 DEBUG(0,("api_RNetShareAdd: pull_ascii_talloc failed: %s",
2175 string_replace(sharename
, '"', ' ');
2176 string_replace(pathname
, '"', ' ');
2177 string_replace(comment
, '"', ' ');
2179 cmdname
= lp_add_share_cmd();
2181 if (!cmdname
|| *cmdname
== '\0') {
2185 if (asprintf(&command
, "%s \"%s\" \"%s\" \"%s\" \"%s\"",
2186 lp_add_share_cmd(), get_dyn_CONFIGFILE(), sharename
,
2187 pathname
, comment
) == -1) {
2191 DEBUG(10,("api_RNetShareAdd: Running [%s]\n", command
));
2193 if ((res
= smbrun(command
, NULL
)) != 0) {
2194 DEBUG(1,("api_RNetShareAdd: Running [%s] returned (%d)\n",
2201 message_send_all(smbd_messaging_context(),
2202 MSG_SMB_CONF_UPDATED
, NULL
, 0, NULL
);
2206 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2210 SSVAL(*rparam
,0,NERR_Success
);
2211 SSVAL(*rparam
,2,0); /* converter word */
2212 SSVAL(*rparam
,4,*rdata_len
);
2220 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2225 SSVAL(*rparam
,0,res
);
2230 /****************************************************************************
2231 view list of groups available
2232 ****************************************************************************/
2234 static bool api_RNetGroupEnum(connection_struct
*conn
,uint16 vuid
,
2235 char *param
, int tpscnt
,
2236 char *data
, int tdscnt
,
2237 int mdrcnt
,int mprcnt
,
2238 char **rdata
,char **rparam
,
2239 int *rdata_len
,int *rparam_len
)
2243 int resume_context
, cli_buf_size
;
2244 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2245 char *str2
= skip_string(param
,tpscnt
,str1
);
2246 char *p
= skip_string(param
,tpscnt
,str2
);
2248 uint32_t num_groups
;
2249 uint32_t resume_handle
;
2250 struct rpc_pipe_client
*samr_pipe
;
2251 struct policy_handle samr_handle
, domain_handle
;
2254 if (!str1
|| !str2
|| !p
) {
2258 if (strcmp(str1
,"WrLeh") != 0) {
2263 * W-> resume context (number of users to skip)
2264 * r -> return parameter pointer to receive buffer
2265 * L -> length of receive buffer
2266 * e -> return parameter number of entries
2267 * h -> return parameter total number of users
2270 if (strcmp("B21",str2
) != 0) {
2274 status
= rpc_pipe_open_internal(
2275 talloc_tos(), &ndr_table_samr
.syntax_id
, rpc_samr_dispatch
,
2276 conn
->server_info
, &samr_pipe
);
2277 if (!NT_STATUS_IS_OK(status
)) {
2278 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2279 nt_errstr(status
)));
2283 status
= rpccli_samr_Connect2(samr_pipe
, talloc_tos(), global_myname(),
2284 SAMR_ACCESS_LOOKUP_DOMAIN
, &samr_handle
);
2285 if (!NT_STATUS_IS_OK(status
)) {
2286 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2287 nt_errstr(status
)));
2291 status
= rpccli_samr_OpenDomain(samr_pipe
, talloc_tos(), &samr_handle
,
2292 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS
,
2293 get_global_sam_sid(), &domain_handle
);
2294 if (!NT_STATUS_IS_OK(status
)) {
2295 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2296 nt_errstr(status
)));
2297 rpccli_samr_Close(samr_pipe
, talloc_tos(), &samr_handle
);
2301 resume_context
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2302 cli_buf_size
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
2303 DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: "
2304 "%d\n", resume_context
, cli_buf_size
));
2306 *rdata_len
= cli_buf_size
;
2307 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2314 errflags
= NERR_Success
;
2319 struct samr_SamArray
*sam_entries
;
2320 uint32_t num_entries
;
2322 status
= rpccli_samr_EnumDomainGroups(samr_pipe
, talloc_tos(),
2327 if (!NT_STATUS_IS_OK(status
)) {
2328 DEBUG(10, ("rpccli_samr_EnumDomainGroups returned "
2329 "%s\n", nt_errstr(status
)));
2333 if (num_entries
== 0) {
2334 DEBUG(10, ("rpccli_samr_EnumDomainGroups returned "
2335 "no entries -- done\n"));
2339 for(i
=0; i
<num_entries
; i
++) {
2342 name
= sam_entries
->entries
[i
].name
.string
;
2344 if( ((PTR_DIFF(p
,*rdata
)+21) > *rdata_len
) ) {
2345 /* set overflow error */
2346 DEBUG(3,("overflow on entry %d group %s\n", i
,
2352 /* truncate the name at 21 chars. */
2354 strlcpy(p
, name
, 21);
2355 DEBUG(10,("adding entry %d group %s\n", i
, p
));
2357 p
+= 5; /* Both NT4 and W2k3SP1 do padding here. No
2362 if (errflags
!= NERR_Success
) {
2366 TALLOC_FREE(sam_entries
);
2369 rpccli_samr_Close(samr_pipe
, talloc_tos(), &domain_handle
);
2370 rpccli_samr_Close(samr_pipe
, talloc_tos(), &samr_handle
);
2372 *rdata_len
= PTR_DIFF(p
,*rdata
);
2375 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2379 SSVAL(*rparam
, 0, errflags
);
2380 SSVAL(*rparam
, 2, 0); /* converter word */
2381 SSVAL(*rparam
, 4, num_groups
); /* is this right?? */
2382 SSVAL(*rparam
, 6, resume_context
+num_groups
); /* is this right?? */
2387 /*******************************************************************
2388 Get groups that a user is a member of.
2389 ******************************************************************/
2391 static bool api_NetUserGetGroups(connection_struct
*conn
,uint16 vuid
,
2392 char *param
, int tpscnt
,
2393 char *data
, int tdscnt
,
2394 int mdrcnt
,int mprcnt
,
2395 char **rdata
,char **rparam
,
2396 int *rdata_len
,int *rparam_len
)
2398 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2399 char *str2
= skip_string(param
,tpscnt
,str1
);
2400 char *UserName
= skip_string(param
,tpscnt
,str2
);
2401 char *p
= skip_string(param
,tpscnt
,UserName
);
2402 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2403 const char *level_string
;
2409 struct rpc_pipe_client
*samr_pipe
;
2410 struct policy_handle samr_handle
, domain_handle
, user_handle
;
2411 struct lsa_String name
;
2412 struct lsa_Strings names
;
2413 struct samr_Ids type
, rid
;
2414 struct samr_RidWithAttributeArray
*rids
;
2417 if (!str1
|| !str2
|| !UserName
|| !p
) {
2422 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2427 /* check it's a supported varient */
2429 if ( strcmp(str1
,"zWrLeh") != 0 )
2434 level_string
= "B21";
2440 if (strcmp(level_string
,str2
) != 0)
2443 *rdata_len
= mdrcnt
+ 1024;
2444 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2449 SSVAL(*rparam
,0,NERR_Success
);
2450 SSVAL(*rparam
,2,0); /* converter word */
2453 endp
= *rdata
+ *rdata_len
;
2455 status
= rpc_pipe_open_internal(
2456 talloc_tos(), &ndr_table_samr
.syntax_id
, rpc_samr_dispatch
,
2457 conn
->server_info
, &samr_pipe
);
2458 if (!NT_STATUS_IS_OK(status
)) {
2459 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2460 nt_errstr(status
)));
2464 status
= rpccli_samr_Connect2(samr_pipe
, talloc_tos(), global_myname(),
2465 SAMR_ACCESS_LOOKUP_DOMAIN
, &samr_handle
);
2466 if (!NT_STATUS_IS_OK(status
)) {
2467 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2468 nt_errstr(status
)));
2472 status
= rpccli_samr_OpenDomain(samr_pipe
, talloc_tos(), &samr_handle
,
2473 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT
,
2474 get_global_sam_sid(), &domain_handle
);
2475 if (!NT_STATUS_IS_OK(status
)) {
2476 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2477 nt_errstr(status
)));
2481 name
.string
= UserName
;
2483 status
= rpccli_samr_LookupNames(samr_pipe
, talloc_tos(),
2484 &domain_handle
, 1, &name
,
2486 if (!NT_STATUS_IS_OK(status
)) {
2487 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2488 nt_errstr(status
)));
2492 if (type
.ids
[0] != SID_NAME_USER
) {
2493 DEBUG(10, ("%s is a %s, not a user\n", UserName
,
2494 sid_type_lookup(type
.ids
[0])));
2498 status
= rpccli_samr_OpenUser(samr_pipe
, talloc_tos(),
2500 SAMR_USER_ACCESS_GET_GROUPS
,
2501 rid
.ids
[0], &user_handle
);
2502 if (!NT_STATUS_IS_OK(status
)) {
2503 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2504 nt_errstr(status
)));
2508 status
= rpccli_samr_GetGroupsForUser(samr_pipe
, talloc_tos(),
2509 &user_handle
, &rids
);
2510 if (!NT_STATUS_IS_OK(status
)) {
2511 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2512 nt_errstr(status
)));
2516 for (i
=0; i
<rids
->count
; i
++) {
2518 status
= rpccli_samr_LookupRids(samr_pipe
, talloc_tos(),
2520 1, &rids
->rids
[i
].rid
,
2522 if (NT_STATUS_IS_OK(status
) && (names
.count
== 1)) {
2523 strlcpy(p
, names
.names
[0].string
, PTR_DIFF(endp
,p
));
2529 *rdata_len
= PTR_DIFF(p
,*rdata
);
2531 SSVAL(*rparam
,4,count
); /* is this right?? */
2532 SSVAL(*rparam
,6,count
); /* is this right?? */
2537 rpccli_samr_Close(samr_pipe
, talloc_tos(), &user_handle
);
2539 rpccli_samr_Close(samr_pipe
, talloc_tos(), &domain_handle
);
2541 rpccli_samr_Close(samr_pipe
, talloc_tos(), &samr_handle
);
2546 /*******************************************************************
2548 ******************************************************************/
2550 static bool api_RNetUserEnum(connection_struct
*conn
, uint16 vuid
,
2551 char *param
, int tpscnt
,
2552 char *data
, int tdscnt
,
2553 int mdrcnt
,int mprcnt
,
2554 char **rdata
,char **rparam
,
2555 int *rdata_len
,int *rparam_len
)
2560 int i
, resume_context
, cli_buf_size
;
2561 uint32_t resume_handle
;
2563 struct rpc_pipe_client
*samr_pipe
;
2564 struct policy_handle samr_handle
, domain_handle
;
2567 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2568 char *str2
= skip_string(param
,tpscnt
,str1
);
2569 char *p
= skip_string(param
,tpscnt
,str2
);
2572 if (!str1
|| !str2
|| !p
) {
2576 if (strcmp(str1
,"WrLeh") != 0)
2579 * W-> resume context (number of users to skip)
2580 * r -> return parameter pointer to receive buffer
2581 * L -> length of receive buffer
2582 * e -> return parameter number of entries
2583 * h -> return parameter total number of users
2586 resume_context
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2587 cli_buf_size
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
2588 DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n",
2589 resume_context
, cli_buf_size
));
2592 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2597 /* check it's a supported varient */
2598 if (strcmp("B21",str2
) != 0)
2601 *rdata_len
= cli_buf_size
;
2602 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2608 endp
= *rdata
+ *rdata_len
;
2610 status
= rpc_pipe_open_internal(
2611 talloc_tos(), &ndr_table_samr
.syntax_id
, rpc_samr_dispatch
,
2612 conn
->server_info
, &samr_pipe
);
2613 if (!NT_STATUS_IS_OK(status
)) {
2614 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2615 nt_errstr(status
)));
2619 status
= rpccli_samr_Connect2(samr_pipe
, talloc_tos(), global_myname(),
2620 SAMR_ACCESS_LOOKUP_DOMAIN
, &samr_handle
);
2621 if (!NT_STATUS_IS_OK(status
)) {
2622 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2623 nt_errstr(status
)));
2627 status
= rpccli_samr_OpenDomain(samr_pipe
, talloc_tos(), &samr_handle
,
2628 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS
,
2629 get_global_sam_sid(), &domain_handle
);
2630 if (!NT_STATUS_IS_OK(status
)) {
2631 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2632 nt_errstr(status
)));
2633 rpccli_samr_Close(samr_pipe
, talloc_tos(), &samr_handle
);
2637 errflags
=NERR_Success
;
2642 struct samr_SamArray
*sam_entries
;
2643 uint32_t num_entries
;
2645 status
= rpccli_samr_EnumDomainUsers(samr_pipe
, talloc_tos(),
2651 if (!NT_STATUS_IS_OK(status
)) {
2652 DEBUG(10, ("rpccli_samr_EnumDomainUsers returned "
2653 "%s\n", nt_errstr(status
)));
2657 if (num_entries
== 0) {
2658 DEBUG(10, ("rpccli_samr_EnumDomainUsers returned "
2659 "no entries -- done\n"));
2663 for (i
=0; i
<num_entries
; i
++) {
2666 name
= sam_entries
->entries
[i
].name
.string
;
2668 if(((PTR_DIFF(p
,*rdata
)+21)<=*rdata_len
)
2669 &&(strlen(name
)<=21)) {
2670 strlcpy(p
,name
,PTR_DIFF(endp
,p
));
2671 DEBUG(10,("api_RNetUserEnum:adding entry %d "
2672 "username %s\n",count_sent
,p
));
2676 /* set overflow error */
2677 DEBUG(10,("api_RNetUserEnum:overflow on entry %d "
2678 "username %s\n",count_sent
,name
));
2684 if (errflags
!= NERR_Success
) {
2688 TALLOC_FREE(sam_entries
);
2691 rpccli_samr_Close(samr_pipe
, talloc_tos(), &domain_handle
);
2692 rpccli_samr_Close(samr_pipe
, talloc_tos(), &samr_handle
);
2694 *rdata_len
= PTR_DIFF(p
,*rdata
);
2696 SSVAL(*rparam
,0,errflags
);
2697 SSVAL(*rparam
,2,0); /* converter word */
2698 SSVAL(*rparam
,4,count_sent
); /* is this right?? */
2699 SSVAL(*rparam
,6,num_users
); /* is this right?? */
2704 /****************************************************************************
2705 Get the time of day info.
2706 ****************************************************************************/
2708 static bool api_NetRemoteTOD(connection_struct
*conn
,uint16 vuid
,
2709 char *param
, int tpscnt
,
2710 char *data
, int tdscnt
,
2711 int mdrcnt
,int mprcnt
,
2712 char **rdata
,char **rparam
,
2713 int *rdata_len
,int *rparam_len
)
2716 time_t unixdate
= time(NULL
);
2720 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2726 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2731 SSVAL(*rparam
,0,NERR_Success
);
2732 SSVAL(*rparam
,2,0); /* converter word */
2736 srv_put_dos_date3(p
,0,unixdate
); /* this is the time that is looked at
2737 by NT in a "net time" operation,
2738 it seems to ignore the one below */
2740 /* the client expects to get localtime, not GMT, in this bit
2741 (I think, this needs testing) */
2742 t
= localtime(&unixdate
);
2747 SIVAL(p
,4,0); /* msecs ? */
2748 SCVAL(p
,8,t
->tm_hour
);
2749 SCVAL(p
,9,t
->tm_min
);
2750 SCVAL(p
,10,t
->tm_sec
);
2751 SCVAL(p
,11,0); /* hundredths of seconds */
2752 SSVALS(p
,12,get_time_zone(unixdate
)/60); /* timezone in minutes from GMT */
2753 SSVAL(p
,14,10000); /* timer interval in 0.0001 of sec */
2754 SCVAL(p
,16,t
->tm_mday
);
2755 SCVAL(p
,17,t
->tm_mon
+ 1);
2756 SSVAL(p
,18,1900+t
->tm_year
);
2757 SCVAL(p
,20,t
->tm_wday
);
2762 /****************************************************************************
2763 Set the user password.
2764 *****************************************************************************/
2766 static bool api_SetUserPassword(connection_struct
*conn
,uint16 vuid
,
2767 char *param
, int tpscnt
,
2768 char *data
, int tdscnt
,
2769 int mdrcnt
,int mprcnt
,
2770 char **rdata
,char **rparam
,
2771 int *rdata_len
,int *rparam_len
)
2773 char *np
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2776 fstring pass1
,pass2
;
2778 /* Skip 2 strings. */
2779 p
= skip_string(param
,tpscnt
,np
);
2780 p
= skip_string(param
,tpscnt
,p
);
2786 /* Do we have a string ? */
2787 if (skip_string(param
,tpscnt
,p
) == NULL
) {
2790 pull_ascii_fstring(user
,p
);
2792 p
= skip_string(param
,tpscnt
,p
);
2797 memset(pass1
,'\0',sizeof(pass1
));
2798 memset(pass2
,'\0',sizeof(pass2
));
2800 * We use 31 here not 32 as we're checking
2801 * the last byte we want to access is safe.
2803 if (!is_offset_safe(param
,tpscnt
,p
,31)) {
2807 memcpy(pass2
,p
+16,16);
2810 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2817 SSVAL(*rparam
,0,NERR_badpass
);
2818 SSVAL(*rparam
,2,0); /* converter word */
2820 DEBUG(3,("Set password for <%s>\n",user
));
2823 * Attempt to verify the old password against smbpasswd entries
2824 * Win98 clients send old and new password in plaintext for this call.
2828 struct auth_serversupplied_info
*server_info
= NULL
;
2829 DATA_BLOB password
= data_blob(pass1
, strlen(pass1
)+1);
2831 if (NT_STATUS_IS_OK(check_plaintext_password(user
,password
,&server_info
))) {
2834 if (NT_STATUS_IS_OK(change_oem_password(server_info
->sam_account
, pass1
, pass2
, False
, NULL
))) {
2835 SSVAL(*rparam
,0,NERR_Success
);
2839 TALLOC_FREE(server_info
);
2841 data_blob_clear_free(&password
);
2845 * If the plaintext change failed, attempt
2846 * the old encrypted method. NT will generate this
2847 * after trying the samr method. Note that this
2848 * method is done as a last resort as this
2849 * password change method loses the NT password hash
2850 * and cannot change the UNIX password as no plaintext
2854 if(SVAL(*rparam
,0) != NERR_Success
) {
2855 struct samu
*hnd
= NULL
;
2857 if (check_lanman_password(user
,(unsigned char *)pass1
,(unsigned char *)pass2
, &hnd
)) {
2859 if (change_lanman_password(hnd
,(uchar
*)pass2
)) {
2860 SSVAL(*rparam
,0,NERR_Success
);
2867 memset((char *)pass1
,'\0',sizeof(fstring
));
2868 memset((char *)pass2
,'\0',sizeof(fstring
));
2873 /****************************************************************************
2874 Set the user password (SamOEM version - gets plaintext).
2875 ****************************************************************************/
2877 static bool api_SamOEMChangePassword(connection_struct
*conn
,uint16 vuid
,
2878 char *param
, int tpscnt
,
2879 char *data
, int tdscnt
,
2880 int mdrcnt
,int mprcnt
,
2881 char **rdata
,char **rparam
,
2882 int *rdata_len
,int *rparam_len
)
2884 struct smbd_server_connection
*sconn
= smbd_server_conn
;
2886 char *p
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2888 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2898 SSVAL(*rparam
,0,NERR_badpass
);
2901 * Check the parameter definition is correct.
2904 /* Do we have a string ? */
2905 if (skip_string(param
,tpscnt
,p
) == 0) {
2908 if(!strequal(p
, "zsT")) {
2909 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", p
));
2912 p
= skip_string(param
, tpscnt
, p
);
2917 /* Do we have a string ? */
2918 if (skip_string(param
,tpscnt
,p
) == 0) {
2921 if(!strequal(p
, "B516B16")) {
2922 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p
));
2925 p
= skip_string(param
,tpscnt
,p
);
2929 /* Do we have a string ? */
2930 if (skip_string(param
,tpscnt
,p
) == 0) {
2933 p
+= pull_ascii_fstring(user
,p
);
2935 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user
));
2938 * Pass the user through the NT -> unix user mapping
2942 (void)map_username(sconn
, user
);
2944 if (NT_STATUS_IS_OK(pass_oem_change(user
, (uchar
*) data
, (uchar
*)&data
[516], NULL
, NULL
, NULL
))) {
2945 SSVAL(*rparam
,0,NERR_Success
);
2951 /****************************************************************************
2954 ****************************************************************************/
2956 static bool api_RDosPrintJobDel(connection_struct
*conn
,uint16 vuid
,
2957 char *param
, int tpscnt
,
2958 char *data
, int tdscnt
,
2959 int mdrcnt
,int mprcnt
,
2960 char **rdata
,char **rparam
,
2961 int *rdata_len
,int *rparam_len
)
2963 int function
= get_safe_SVAL(param
,tpscnt
,param
,0,0);
2964 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2965 char *str2
= skip_string(param
,tpscnt
,str1
);
2966 char *p
= skip_string(param
,tpscnt
,str2
);
2971 WERROR werr
= WERR_OK
;
2973 if (!str1
|| !str2
|| !p
) {
2977 * We use 1 here not 2 as we're checking
2978 * the last byte we want to access is safe.
2980 if (!is_offset_safe(param
,tpscnt
,p
,1)) {
2983 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
))
2986 /* check it's a supported varient */
2987 if (!(strcsequal(str1
,"W") && strcsequal(str2
,"")))
2991 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2997 if (!print_job_exists(sharename
, jobid
)) {
2998 errcode
= NERR_JobNotFound
;
3002 snum
= lp_servicenumber( sharename
);
3004 errcode
= NERR_DestNotFound
;
3008 errcode
= NERR_notsupported
;
3011 case 81: /* delete */
3012 if (print_job_delete(conn
->server_info
, snum
, jobid
, &werr
))
3013 errcode
= NERR_Success
;
3015 case 82: /* pause */
3016 if (print_job_pause(conn
->server_info
, snum
, jobid
, &werr
))
3017 errcode
= NERR_Success
;
3019 case 83: /* resume */
3020 if (print_job_resume(conn
->server_info
, snum
, jobid
, &werr
))
3021 errcode
= NERR_Success
;
3025 if (!W_ERROR_IS_OK(werr
))
3026 errcode
= W_ERROR_V(werr
);
3029 SSVAL(*rparam
,0,errcode
);
3030 SSVAL(*rparam
,2,0); /* converter word */
3035 /****************************************************************************
3036 Purge a print queue - or pause or resume it.
3037 ****************************************************************************/
3039 static bool api_WPrintQueueCtrl(connection_struct
*conn
,uint16 vuid
,
3040 char *param
, int tpscnt
,
3041 char *data
, int tdscnt
,
3042 int mdrcnt
,int mprcnt
,
3043 char **rdata
,char **rparam
,
3044 int *rdata_len
,int *rparam_len
)
3046 int function
= get_safe_SVAL(param
,tpscnt
,param
,0,0);
3047 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3048 char *str2
= skip_string(param
,tpscnt
,str1
);
3049 char *QueueName
= skip_string(param
,tpscnt
,str2
);
3050 int errcode
= NERR_notsupported
;
3052 WERROR werr
= WERR_OK
;
3054 if (!str1
|| !str2
|| !QueueName
) {
3058 /* check it's a supported varient */
3059 if (!(strcsequal(str1
,"z") && strcsequal(str2
,"")))
3063 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3069 if (skip_string(param
,tpscnt
,QueueName
) == NULL
) {
3072 snum
= print_queue_snum(QueueName
);
3075 errcode
= NERR_JobNotFound
;
3080 case 74: /* Pause queue */
3081 werr
= print_queue_pause(conn
->server_info
, snum
);
3083 case 75: /* Resume queue */
3084 werr
= print_queue_resume(conn
->server_info
, snum
);
3086 case 103: /* Purge */
3087 werr
= print_queue_purge(conn
->server_info
, snum
);
3090 werr
= WERR_NOT_SUPPORTED
;
3094 errcode
= W_ERROR_V(werr
);
3097 SSVAL(*rparam
,0,errcode
);
3098 SSVAL(*rparam
,2,0); /* converter word */
3103 /****************************************************************************
3104 set the property of a print job (undocumented?)
3105 ? function = 0xb -> set name of print job
3106 ? function = 0x6 -> move print job up/down
3107 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
3108 or <WWsTP> <WB21BB16B10zWWzDDz>
3109 ****************************************************************************/
3111 static int check_printjob_info(struct pack_desc
* desc
,
3112 int uLevel
, char* id
)
3114 desc
->subformat
= NULL
;
3116 case 0: desc
->format
= "W"; break;
3117 case 1: desc
->format
= "WB21BB16B10zWWzDDz"; break;
3118 case 2: desc
->format
= "WWzWWDDzz"; break;
3119 case 3: desc
->format
= "WWzWWDDzzzzzzzzzzlz"; break;
3120 case 4: desc
->format
= "WWzWWDDzzzzzDDDDDDD"; break;
3122 DEBUG(0,("check_printjob_info: invalid level %d\n",
3126 if (id
== NULL
|| strcmp(desc
->format
,id
) != 0) {
3127 DEBUG(0,("check_printjob_info: invalid format %s\n",
3128 id
? id
: "<NULL>" ));
3134 static bool api_PrintJobInfo(connection_struct
*conn
, uint16 vuid
,
3135 char *param
, int tpscnt
,
3136 char *data
, int tdscnt
,
3137 int mdrcnt
,int mprcnt
,
3138 char **rdata
,char **rparam
,
3139 int *rdata_len
,int *rparam_len
)
3141 struct pack_desc desc
;
3142 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3143 char *str2
= skip_string(param
,tpscnt
,str1
);
3144 char *p
= skip_string(param
,tpscnt
,str2
);
3147 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,2,-1);
3148 int function
= get_safe_SVAL(param
,tpscnt
,p
,4,-1);
3151 if (!str1
|| !str2
|| !p
) {
3155 * We use 1 here not 2 as we're checking
3156 * the last byte we want to access is safe.
3158 if (!is_offset_safe(param
,tpscnt
,p
,1)) {
3161 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
))
3164 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3169 if (!share_defined(sharename
)) {
3170 DEBUG(0,("api_PrintJobInfo: sharen [%s] not defined\n",
3177 /* check it's a supported varient */
3178 if ((strcmp(str1
,"WWsTP")) ||
3179 (!check_printjob_info(&desc
,uLevel
,str2
)))
3182 if (!print_job_exists(sharename
, jobid
)) {
3183 errcode
=NERR_JobNotFound
;
3187 errcode
= NERR_notsupported
;
3191 /* change job place in the queue,
3192 data gives the new place */
3193 place
= SVAL(data
,0);
3194 if (print_job_set_place(sharename
, jobid
, place
)) {
3195 errcode
=NERR_Success
;
3200 /* change print job name, data gives the name */
3201 if (print_job_set_name(sharename
, jobid
, data
)) {
3202 errcode
=NERR_Success
;
3211 SSVALS(*rparam
,0,errcode
);
3212 SSVAL(*rparam
,2,0); /* converter word */
3218 /****************************************************************************
3219 Get info about the server.
3220 ****************************************************************************/
3222 static bool api_RNetServerGetInfo(connection_struct
*conn
,uint16 vuid
,
3223 char *param
, int tpscnt
,
3224 char *data
, int tdscnt
,
3225 int mdrcnt
,int mprcnt
,
3226 char **rdata
,char **rparam
,
3227 int *rdata_len
,int *rparam_len
)
3229 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3230 char *str2
= skip_string(param
,tpscnt
,str1
);
3231 char *p
= skip_string(param
,tpscnt
,str2
);
3232 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3236 if (!str1
|| !str2
|| !p
) {
3240 DEBUG(4,("NetServerGetInfo level %d\n",uLevel
));
3242 /* check it's a supported varient */
3243 if (!prefix_ok(str1
,"WrLh")) {
3249 if (strcmp(str2
,"B16") != 0) {
3255 if (strcmp(str2
,"B16BBDz") != 0) {
3261 if (strcmp(str2
,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")!= 0) {
3267 if (strcmp(str2
,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz") != 0) {
3273 if (strcmp(str2
,"DN") != 0) {
3279 if (strcmp(str2
,"B16BBDzWWzzz") != 0) {
3288 *rdata_len
= mdrcnt
;
3289 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
3295 p2
= p
+ struct_len
;
3297 srvstr_push(NULL
, 0, p
,global_myname(),16,
3298 STR_ASCII
|STR_UPPER
|STR_TERMINATE
);
3302 struct srv_info_struct
*servers
=NULL
;
3304 char *comment
= NULL
;
3305 TALLOC_CTX
*ctx
= talloc_tos();
3306 uint32 servertype
= lp_default_server_announce();
3308 comment
= talloc_strdup(ctx
,lp_serverstring());
3313 if ((count
=get_server_info(SV_TYPE_ALL
,&servers
,lp_workgroup()))>0) {
3314 for (i
=0;i
<count
;i
++) {
3315 if (strequal(servers
[i
].name
,global_myname())) {
3316 servertype
= servers
[i
].type
;
3317 TALLOC_FREE(comment
);
3318 comment
= talloc_strdup(ctx
,
3319 servers
[i
].comment
);
3329 SCVAL(p
,0,lp_major_announce_version());
3330 SCVAL(p
,1,lp_minor_announce_version());
3331 SIVAL(p
,2,servertype
);
3333 if (mdrcnt
== struct_len
) {
3336 SIVAL(p
,6,PTR_DIFF(p2
,*rdata
));
3337 comment
= talloc_sub_advanced(
3339 lp_servicename(SNUM(conn
)),
3340 conn
->server_info
->unix_name
,
3342 conn
->server_info
->utok
.gid
,
3343 conn
->server_info
->sanitized_username
,
3344 pdb_get_domain(conn
->server_info
->sam_account
),
3349 if (mdrcnt
- struct_len
<= 0) {
3354 MIN(mdrcnt
- struct_len
,
3355 MAX_SERVER_STRING_LENGTH
),
3357 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3365 return False
; /* not yet implemented */
3368 *rdata_len
= PTR_DIFF(p2
,*rdata
);
3371 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3375 SSVAL(*rparam
,0,NERR_Success
);
3376 SSVAL(*rparam
,2,0); /* converter word */
3377 SSVAL(*rparam
,4,*rdata_len
);
3382 /****************************************************************************
3383 Get info about the server.
3384 ****************************************************************************/
3386 static bool api_NetWkstaGetInfo(connection_struct
*conn
,uint16 vuid
,
3387 char *param
, int tpscnt
,
3388 char *data
, int tdscnt
,
3389 int mdrcnt
,int mprcnt
,
3390 char **rdata
,char **rparam
,
3391 int *rdata_len
,int *rparam_len
)
3393 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3394 char *str2
= skip_string(param
,tpscnt
,str1
);
3395 char *p
= skip_string(param
,tpscnt
,str2
);
3398 int level
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3400 if (!str1
|| !str2
|| !p
) {
3404 DEBUG(4,("NetWkstaGetInfo level %d\n",level
));
3407 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3412 /* check it's a supported varient */
3413 if (!(level
==10 && strcsequal(str1
,"WrLh") && strcsequal(str2
,"zzzBBzz"))) {
3417 *rdata_len
= mdrcnt
+ 1024;
3418 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
3423 SSVAL(*rparam
,0,NERR_Success
);
3424 SSVAL(*rparam
,2,0); /* converter word */
3427 endp
= *rdata
+ *rdata_len
;
3429 p2
= get_safe_ptr(*rdata
,*rdata_len
,p
,22);
3434 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* host name */
3435 strlcpy(p2
,get_local_machine_name(),PTR_DIFF(endp
,p2
));
3437 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3443 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
));
3444 strlcpy(p2
,conn
->server_info
->sanitized_username
,PTR_DIFF(endp
,p2
));
3445 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3451 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* login domain */
3452 strlcpy(p2
,lp_workgroup(),PTR_DIFF(endp
,p2
));
3454 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3460 SCVAL(p
,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
3461 SCVAL(p
,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
3464 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
));
3465 strlcpy(p2
,lp_workgroup(),PTR_DIFF(endp
,p2
)); /* don't know. login domain?? */
3466 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3472 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* don't know */
3473 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
3474 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3480 *rdata_len
= PTR_DIFF(p2
,*rdata
);
3482 SSVAL(*rparam
,4,*rdata_len
);
3487 /****************************************************************************
3488 get info about a user
3490 struct user_info_11 {
3491 char usri11_name[21]; 0-20
3493 char *usri11_comment; 22-25
3494 char *usri11_usr_comment; 26-29
3495 unsigned short usri11_priv; 30-31
3496 unsigned long usri11_auth_flags; 32-35
3497 long usri11_password_age; 36-39
3498 char *usri11_homedir; 40-43
3499 char *usri11_parms; 44-47
3500 long usri11_last_logon; 48-51
3501 long usri11_last_logoff; 52-55
3502 unsigned short usri11_bad_pw_count; 56-57
3503 unsigned short usri11_num_logons; 58-59
3504 char *usri11_logon_server; 60-63
3505 unsigned short usri11_country_code; 64-65
3506 char *usri11_workstations; 66-69
3507 unsigned long usri11_max_storage; 70-73
3508 unsigned short usri11_units_per_week; 74-75
3509 unsigned char *usri11_logon_hours; 76-79
3510 unsigned short usri11_code_page; 80-81
3515 usri11_name specifies the user name for which information is retrieved
3517 usri11_pad aligns the next data structure element to a word boundary
3519 usri11_comment is a null terminated ASCII comment
3521 usri11_user_comment is a null terminated ASCII comment about the user
3523 usri11_priv specifies the level of the privilege assigned to the user.
3524 The possible values are:
3526 Name Value Description
3527 USER_PRIV_GUEST 0 Guest privilege
3528 USER_PRIV_USER 1 User privilege
3529 USER_PRV_ADMIN 2 Administrator privilege
3531 usri11_auth_flags specifies the account operator privileges. The
3532 possible values are:
3534 Name Value Description
3535 AF_OP_PRINT 0 Print operator
3538 Leach, Naik [Page 28]
3542 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
3545 AF_OP_COMM 1 Communications operator
3546 AF_OP_SERVER 2 Server operator
3547 AF_OP_ACCOUNTS 3 Accounts operator
3550 usri11_password_age specifies how many seconds have elapsed since the
3551 password was last changed.
3553 usri11_home_dir points to a null terminated ASCII string that contains
3554 the path name of the user's home directory.
3556 usri11_parms points to a null terminated ASCII string that is set
3557 aside for use by applications.
3559 usri11_last_logon specifies the time when the user last logged on.
3560 This value is stored as the number of seconds elapsed since
3561 00:00:00, January 1, 1970.
3563 usri11_last_logoff specifies the time when the user last logged off.
3564 This value is stored as the number of seconds elapsed since
3565 00:00:00, January 1, 1970. A value of 0 means the last logoff
3568 usri11_bad_pw_count specifies the number of incorrect passwords
3569 entered since the last successful logon.
3571 usri11_log1_num_logons specifies the number of times this user has
3572 logged on. A value of -1 means the number of logons is unknown.
3574 usri11_logon_server points to a null terminated ASCII string that
3575 contains the name of the server to which logon requests are sent.
3576 A null string indicates logon requests should be sent to the
3579 usri11_country_code specifies the country code for the user's language
3582 usri11_workstations points to a null terminated ASCII string that
3583 contains the names of workstations the user may log on from.
3584 There may be up to 8 workstations, with the names separated by
3585 commas. A null strings indicates there are no restrictions.
3587 usri11_max_storage specifies the maximum amount of disk space the user
3588 can occupy. A value of 0xffffffff indicates there are no
3591 usri11_units_per_week specifies the equal number of time units into
3592 which a week is divided. This value must be equal to 168.
3594 usri11_logon_hours points to a 21 byte (168 bits) string that
3595 specifies the time during which the user can log on. Each bit
3596 represents one unique hour in a week. The first bit (bit 0, word
3597 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
3601 Leach, Naik [Page 29]
3605 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
3608 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
3609 are no restrictions.
3611 usri11_code_page specifies the code page for the user's language of
3614 All of the pointers in this data structure need to be treated
3615 specially. The pointer is a 32 bit pointer. The higher 16 bits need
3616 to be ignored. The converter word returned in the parameters section
3617 needs to be subtracted from the lower 16 bits to calculate an offset
3618 into the return buffer where this ASCII string resides.
3620 There is no auxiliary data in the response.
3622 ****************************************************************************/
3624 #define usri11_name 0
3625 #define usri11_pad 21
3626 #define usri11_comment 22
3627 #define usri11_usr_comment 26
3628 #define usri11_full_name 30
3629 #define usri11_priv 34
3630 #define usri11_auth_flags 36
3631 #define usri11_password_age 40
3632 #define usri11_homedir 44
3633 #define usri11_parms 48
3634 #define usri11_last_logon 52
3635 #define usri11_last_logoff 56
3636 #define usri11_bad_pw_count 60
3637 #define usri11_num_logons 62
3638 #define usri11_logon_server 64
3639 #define usri11_country_code 68
3640 #define usri11_workstations 70
3641 #define usri11_max_storage 74
3642 #define usri11_units_per_week 78
3643 #define usri11_logon_hours 80
3644 #define usri11_code_page 84
3645 #define usri11_end 86
3647 #define USER_PRIV_GUEST 0
3648 #define USER_PRIV_USER 1
3649 #define USER_PRIV_ADMIN 2
3651 #define AF_OP_PRINT 0
3652 #define AF_OP_COMM 1
3653 #define AF_OP_SERVER 2
3654 #define AF_OP_ACCOUNTS 3
3657 static bool api_RNetUserGetInfo(connection_struct
*conn
, uint16 vuid
,
3658 char *param
, int tpscnt
,
3659 char *data
, int tdscnt
,
3660 int mdrcnt
,int mprcnt
,
3661 char **rdata
,char **rparam
,
3662 int *rdata_len
,int *rparam_len
)
3664 struct smbd_server_connection
*sconn
= smbd_server_conn
;
3665 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3666 char *str2
= skip_string(param
,tpscnt
,str1
);
3667 char *UserName
= skip_string(param
,tpscnt
,str2
);
3668 char *p
= skip_string(param
,tpscnt
,UserName
);
3669 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3672 const char *level_string
;
3674 /* get NIS home of a previously validated user - simeon */
3675 /* With share level security vuid will always be zero.
3676 Don't depend on vuser being non-null !!. JRA */
3677 user_struct
*vuser
= get_valid_user_struct(sconn
, vuid
);
3679 DEBUG(3,(" Username of UID %d is %s\n",
3680 (int)vuser
->server_info
->utok
.uid
,
3681 vuser
->server_info
->unix_name
));
3684 if (!str1
|| !str2
|| !UserName
|| !p
) {
3689 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3694 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel
));
3696 /* check it's a supported variant */
3697 if (strcmp(str1
,"zWrLh") != 0) {
3701 case 0: level_string
= "B21"; break;
3702 case 1: level_string
= "B21BB16DWzzWz"; break;
3703 case 2: level_string
= "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
3704 case 10: level_string
= "B21Bzzz"; break;
3705 case 11: level_string
= "B21BzzzWDDzzDDWWzWzDWb21W"; break;
3706 default: return False
;
3709 if (strcmp(level_string
,str2
) != 0) {
3713 *rdata_len
= mdrcnt
+ 1024;
3714 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
3719 SSVAL(*rparam
,0,NERR_Success
);
3720 SSVAL(*rparam
,2,0); /* converter word */
3723 endp
= *rdata
+ *rdata_len
;
3724 p2
= get_safe_ptr(*rdata
,*rdata_len
,p
,usri11_end
);
3730 fstrcpy(p
+usri11_name
,UserName
); /* 21 bytes - user name */
3733 SCVAL(p
,usri11_pad
,0); /* padding - 1 byte */
3738 SIVAL(p
,usri11_comment
,PTR_DIFF(p2
,p
)); /* comment */
3739 strlcpy(p2
,"Comment",PTR_DIFF(endp
,p2
));
3740 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3745 SIVAL(p
,usri11_usr_comment
,PTR_DIFF(p2
,p
)); /* user_comment */
3746 strlcpy(p2
,"UserComment",PTR_DIFF(endp
,p2
));
3747 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3752 /* EEK! the cifsrap.txt doesn't have this in!!!! */
3753 SIVAL(p
,usri11_full_name
,PTR_DIFF(p2
,p
)); /* full name */
3754 strlcpy(p2
,((vuser
!= NULL
)
3755 ? pdb_get_fullname(vuser
->server_info
->sam_account
)
3756 : UserName
),PTR_DIFF(endp
,p2
));
3757 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3764 const char *homedir
= "";
3765 if (vuser
!= NULL
) {
3766 homedir
= pdb_get_homedir(
3767 vuser
->server_info
->sam_account
);
3769 /* modelled after NTAS 3.51 reply */
3770 SSVAL(p
,usri11_priv
,
3771 (get_current_uid(conn
) == sec_initial_uid())?
3772 USER_PRIV_ADMIN
:USER_PRIV_USER
);
3773 SIVAL(p
,usri11_auth_flags
,AF_OP_PRINT
); /* auth flags */
3774 SIVALS(p
,usri11_password_age
,-1); /* password age */
3775 SIVAL(p
,usri11_homedir
,PTR_DIFF(p2
,p
)); /* home dir */
3776 strlcpy(p2
, homedir
, PTR_DIFF(endp
,p2
));
3777 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3781 SIVAL(p
,usri11_parms
,PTR_DIFF(p2
,p
)); /* parms */
3782 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
3783 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3787 SIVAL(p
,usri11_last_logon
,0); /* last logon */
3788 SIVAL(p
,usri11_last_logoff
,0); /* last logoff */
3789 SSVALS(p
,usri11_bad_pw_count
,-1); /* bad pw counts */
3790 SSVALS(p
,usri11_num_logons
,-1); /* num logons */
3791 SIVAL(p
,usri11_logon_server
,PTR_DIFF(p2
,p
)); /* logon server */
3792 strlcpy(p2
,"\\\\*",PTR_DIFF(endp
,p2
));
3793 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3797 SSVAL(p
,usri11_country_code
,0); /* country code */
3799 SIVAL(p
,usri11_workstations
,PTR_DIFF(p2
,p
)); /* workstations */
3800 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
3801 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3806 SIVALS(p
,usri11_max_storage
,-1); /* max storage */
3807 SSVAL(p
,usri11_units_per_week
,168); /* units per week */
3808 SIVAL(p
,usri11_logon_hours
,PTR_DIFF(p2
,p
)); /* logon hours */
3810 /* a simple way to get logon hours at all times. */
3812 SCVAL(p2
,21,0); /* fix zero termination */
3813 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3818 SSVAL(p
,usri11_code_page
,0); /* code page */
3821 if (uLevel
== 1 || uLevel
== 2) {
3822 memset(p
+22,' ',16); /* password */
3823 SIVALS(p
,38,-1); /* password age */
3825 (get_current_uid(conn
) == sec_initial_uid())?
3826 USER_PRIV_ADMIN
:USER_PRIV_USER
);
3827 SIVAL(p
,44,PTR_DIFF(p2
,*rdata
)); /* home dir */
3828 strlcpy(p2
, vuser
? pdb_get_homedir(
3829 vuser
->server_info
->sam_account
) : "",
3831 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3835 SIVAL(p
,48,PTR_DIFF(p2
,*rdata
)); /* comment */
3837 SSVAL(p
,52,0); /* flags */
3838 SIVAL(p
,54,PTR_DIFF(p2
,*rdata
)); /* script_path */
3839 strlcpy(p2
, vuser
? pdb_get_logon_script(
3840 vuser
->server_info
->sam_account
) : "",
3842 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3847 SIVAL(p
,60,0); /* auth_flags */
3848 SIVAL(p
,64,PTR_DIFF(p2
,*rdata
)); /* full_name */
3849 strlcpy(p2
,((vuser
!= NULL
)
3850 ? pdb_get_fullname(vuser
->server_info
->sam_account
)
3851 : UserName
),PTR_DIFF(endp
,p2
));
3852 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3856 SIVAL(p
,68,0); /* urs_comment */
3857 SIVAL(p
,72,PTR_DIFF(p2
,*rdata
)); /* parms */
3858 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
3859 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3863 SIVAL(p
,76,0); /* workstations */
3864 SIVAL(p
,80,0); /* last_logon */
3865 SIVAL(p
,84,0); /* last_logoff */
3866 SIVALS(p
,88,-1); /* acct_expires */
3867 SIVALS(p
,92,-1); /* max_storage */
3868 SSVAL(p
,96,168); /* units_per_week */
3869 SIVAL(p
,98,PTR_DIFF(p2
,*rdata
)); /* logon_hours */
3872 SSVALS(p
,102,-1); /* bad_pw_count */
3873 SSVALS(p
,104,-1); /* num_logons */
3874 SIVAL(p
,106,PTR_DIFF(p2
,*rdata
)); /* logon_server */
3876 TALLOC_CTX
*ctx
= talloc_tos();
3877 int space_rem
= *rdata_len
- (p2
- *rdata
);
3880 if (space_rem
<= 0) {
3883 tmp
= talloc_strdup(ctx
, "\\\\%L");
3887 tmp
= talloc_sub_basic(ctx
,
3900 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3904 SSVAL(p
,110,49); /* country_code */
3905 SSVAL(p
,112,860); /* code page */
3909 *rdata_len
= PTR_DIFF(p2
,*rdata
);
3911 SSVAL(*rparam
,4,*rdata_len
); /* is this right?? */
3916 static bool api_WWkstaUserLogon(connection_struct
*conn
,uint16 vuid
,
3917 char *param
, int tpscnt
,
3918 char *data
, int tdscnt
,
3919 int mdrcnt
,int mprcnt
,
3920 char **rdata
,char **rparam
,
3921 int *rdata_len
,int *rparam_len
)
3923 struct smbd_server_connection
*sconn
= smbd_server_conn
;
3924 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3925 char *str2
= skip_string(param
,tpscnt
,str1
);
3926 char *p
= skip_string(param
,tpscnt
,str2
);
3928 struct pack_desc desc
;
3930 /* With share level security vuid will always be zero.
3931 Don't depend on vuser being non-null !!. JRA */
3932 user_struct
*vuser
= get_valid_user_struct(sconn
, vuid
);
3934 if (!str1
|| !str2
|| !p
) {
3939 DEBUG(3,(" Username of UID %d is %s\n",
3940 (int)vuser
->server_info
->utok
.uid
,
3941 vuser
->server_info
->unix_name
));
3944 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3945 name
= get_safe_str_ptr(param
,tpscnt
,p
,2);
3950 memset((char *)&desc
,'\0',sizeof(desc
));
3952 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel
,name
));
3954 /* check it's a supported varient */
3955 if (strcmp(str1
,"OOWb54WrLh") != 0) {
3958 if (uLevel
!= 1 || strcmp(str2
,"WB21BWDWWDDDDDDDzzzD") != 0) {
3962 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
3969 desc
.buflen
= mdrcnt
;
3970 desc
.subformat
= NULL
;
3973 if (init_package(&desc
,1,0)) {
3974 PACKI(&desc
,"W",0); /* code */
3975 PACKS(&desc
,"B21",name
); /* eff. name */
3976 PACKS(&desc
,"B",""); /* pad */
3978 (get_current_uid(conn
) == sec_initial_uid())?
3979 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
);