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
30 extern struct current_user current_user
;
31 extern userdom_struct current_user_info
;
38 #define NERR_Success 0
39 #define NERR_badpass 86
40 #define NERR_notsupported 50
42 #define NERR_BASE (2100)
43 #define NERR_BufTooSmall (NERR_BASE+23)
44 #define NERR_JobNotFound (NERR_BASE+51)
45 #define NERR_DestNotFound (NERR_BASE+52)
47 #define ACCESS_READ 0x01
48 #define ACCESS_WRITE 0x02
49 #define ACCESS_CREATE 0x04
51 #define SHPWLEN 8 /* share password length */
53 /* Limit size of ipc replies */
55 static char *smb_realloc_limit(void *ptr
, size_t size
)
59 size
= MAX((size
),4*1024);
60 val
= (char *)SMB_REALLOC(ptr
,size
);
62 memset(val
,'\0',size
);
67 static bool api_Unsupported(connection_struct
*conn
, uint16 vuid
,
68 char *param
, int tpscnt
,
69 char *data
, int tdscnt
,
70 int mdrcnt
, int mprcnt
,
71 char **rdata
, char **rparam
,
72 int *rdata_len
, int *rparam_len
);
74 static bool api_TooSmall(connection_struct
*conn
, uint16 vuid
, char *param
, char *data
,
75 int mdrcnt
, int mprcnt
,
76 char **rdata
, char **rparam
,
77 int *rdata_len
, int *rparam_len
);
80 static int CopyExpanded(connection_struct
*conn
,
81 int snum
, char **dst
, char *src
, int *p_space_remaining
)
83 TALLOC_CTX
*ctx
= talloc_tos();
87 if (!src
|| !dst
|| !p_space_remaining
|| !(*dst
) ||
88 *p_space_remaining
<= 0) {
92 buf
= talloc_strdup(ctx
, src
);
94 *p_space_remaining
= 0;
97 buf
= talloc_string_sub(ctx
, buf
,"%S",lp_servicename(snum
));
99 *p_space_remaining
= 0;
102 buf
= talloc_sub_advanced(ctx
,
103 lp_servicename(SNUM(conn
)),
107 get_current_username(),
108 current_user_info
.domain
,
111 *p_space_remaining
= 0;
114 l
= push_ascii(*dst
,buf
,*p_space_remaining
, STR_TERMINATE
);
119 (*p_space_remaining
) -= l
;
123 static int CopyAndAdvance(char **dst
, char *src
, int *n
)
126 if (!src
|| !dst
|| !n
|| !(*dst
)) {
129 l
= push_ascii(*dst
,src
,*n
, STR_TERMINATE
);
138 static int StrlenExpanded(connection_struct
*conn
, int snum
, char *s
)
140 TALLOC_CTX
*ctx
= talloc_tos();
145 buf
= talloc_strdup(ctx
,s
);
149 buf
= talloc_string_sub(ctx
,buf
,"%S",lp_servicename(snum
));
153 buf
= talloc_sub_advanced(ctx
,
154 lp_servicename(SNUM(conn
)),
158 get_current_username(),
159 current_user_info
.domain
,
164 return strlen(buf
) + 1;
167 static char *Expand(connection_struct
*conn
, int snum
, char *s
)
169 TALLOC_CTX
*ctx
= talloc_tos();
175 buf
= talloc_strdup(ctx
,s
);
179 buf
= talloc_string_sub(ctx
,buf
,"%S",lp_servicename(snum
));
183 return talloc_sub_advanced(ctx
,
184 lp_servicename(SNUM(conn
)),
188 get_current_username(),
189 current_user_info
.domain
,
193 /*******************************************************************
194 Check a API string for validity when we only need to check the prefix.
195 ******************************************************************/
197 static bool prefix_ok(const char *str
, const char *prefix
)
199 return(strncmp(str
,prefix
,strlen(prefix
)) == 0);
203 const char *format
; /* formatstring for structure */
204 const char *subformat
; /* subformat for structure */
205 char *base
; /* baseaddress of buffer */
206 int buflen
; /* remaining size for fixed part; on init: length of base */
207 int subcount
; /* count of substructures */
208 char *structbuf
; /* pointer into buffer for remaining fixed part */
209 int stringlen
; /* remaining size for variable part */
210 char *stringbuf
; /* pointer into buffer for remaining variable part */
211 int neededlen
; /* total needed size */
212 int usedlen
; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
213 const char *curpos
; /* current position; pointer into format or subformat */
217 static int get_counter(const char **p
)
223 if (!isdigit((int)**p
)) {
229 n
= 10 * n
+ (i
- '0');
237 static int getlen(const char *p
)
246 case 'W': /* word (2 byte) */
249 case 'K': /* status word? (2 byte) */
252 case 'N': /* count of substructures (word) at end */
255 case 'D': /* double word (4 byte) */
256 case 'z': /* offset to zero terminated string (4 byte) */
257 case 'l': /* offset to user data (4 byte) */
260 case 'b': /* offset to data (with counter) (4 byte) */
264 case 'B': /* byte (with optional counter) */
265 n
+= get_counter(&p
);
272 static bool init_package(struct pack_desc
*p
, int count
, int subcount
)
277 if (!p
->format
|| !p
->base
) {
281 i
= count
* getlen(p
->format
);
283 i
+= subcount
* getlen(p
->subformat
);
285 p
->structbuf
= p
->base
;
289 p
->curpos
= p
->format
;
295 * This is the old error code we used. Aparently
296 * WinNT/2k systems return ERRbuftoosmall (2123) and
297 * OS/2 needs this. I'm leaving this here so we can revert
300 p
->errcode
= ERRmoredata
;
302 p
->errcode
= ERRbuftoosmall
;
305 p
->errcode
= NERR_Success
;
309 p
->stringbuf
= p
->base
+ i
;
311 return (p
->errcode
== NERR_Success
);
314 static int package(struct pack_desc
*p
, ...)
317 int needed
=0, stringneeded
;
318 const char *str
=NULL
;
319 int is_string
=0, stringused
;
326 p
->curpos
= p
->format
;
328 p
->curpos
= p
->subformat
;
333 str
= va_arg(args
,char*);
334 SMB_ASSERT(strncmp(str
,p
->curpos
,strlen(str
)) == 0);
343 switch( *p
->curpos
++ ) {
344 case 'W': /* word (2 byte) */
346 temp
= va_arg(args
,int);
347 if (p
->buflen
>= needed
) {
348 SSVAL(p
->structbuf
,0,temp
);
351 case 'K': /* status word? (2 byte) */
353 temp
= va_arg(args
,int);
354 if (p
->buflen
>= needed
) {
355 SSVAL(p
->structbuf
,0,temp
);
358 case 'N': /* count of substructures (word) at end */
360 p
->subcount
= va_arg(args
,int);
361 if (p
->buflen
>= needed
) {
362 SSVAL(p
->structbuf
,0,p
->subcount
);
365 case 'D': /* double word (4 byte) */
367 temp
= va_arg(args
,int);
368 if (p
->buflen
>= needed
) {
369 SIVAL(p
->structbuf
,0,temp
);
372 case 'B': /* byte (with optional counter) */
373 needed
= get_counter(&p
->curpos
);
375 char *s
= va_arg(args
,char*);
376 if (p
->buflen
>= needed
) {
377 StrnCpy(p
->structbuf
,s
?s
:"",needed
-1);
381 case 'z': /* offset to zero terminated string (4 byte) */
382 str
= va_arg(args
,char*);
383 stringneeded
= (str
? strlen(str
)+1 : 0);
386 case 'l': /* offset to user data (4 byte) */
387 str
= va_arg(args
,char*);
388 stringneeded
= va_arg(args
,int);
391 case 'b': /* offset to data (with counter) (4 byte) */
392 str
= va_arg(args
,char*);
393 stringneeded
= get_counter(&p
->curpos
);
399 if (stringneeded
>= 0) {
401 if (p
->buflen
>= needed
) {
402 stringused
= stringneeded
;
403 if (stringused
> p
->stringlen
) {
404 stringused
= (is_string
? p
->stringlen
: 0);
405 if (p
->errcode
== NERR_Success
) {
406 p
->errcode
= ERRmoredata
;
410 SIVAL(p
->structbuf
,0,0);
412 SIVAL(p
->structbuf
,0,PTR_DIFF(p
->stringbuf
,p
->base
));
413 memcpy(p
->stringbuf
,str
?str
:"",stringused
);
415 p
->stringbuf
[stringused
-1] = '\0';
417 p
->stringbuf
+= stringused
;
418 p
->stringlen
-= stringused
;
419 p
->usedlen
+= stringused
;
422 p
->neededlen
+= stringneeded
;
425 p
->neededlen
+= needed
;
426 if (p
->buflen
>= needed
) {
427 p
->structbuf
+= needed
;
429 p
->usedlen
+= needed
;
431 if (p
->errcode
== NERR_Success
) {
432 p
->errcode
= ERRmoredata
;
439 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
440 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
442 #define PACK(desc,t,v) package(desc,v)
443 #define PACKl(desc,t,v,l) package(desc,v,l)
446 static void PACKI(struct pack_desc
* desc
, const char *t
,int v
)
451 static void PACKS(struct pack_desc
* desc
,const char *t
,const char *v
)
456 /****************************************************************************
458 ****************************************************************************/
460 static void PackDriverData(struct pack_desc
* desc
)
462 char drivdata
[4+4+32];
463 SIVAL(drivdata
,0,sizeof drivdata
); /* cb */
464 SIVAL(drivdata
,4,1000); /* lVersion */
465 memset(drivdata
+8,0,32); /* szDeviceName */
466 push_ascii(drivdata
+8,"NULL",32, STR_TERMINATE
);
467 PACKl(desc
,"l",drivdata
,sizeof drivdata
); /* pDriverData */
470 static int check_printq_info(struct pack_desc
* desc
,
471 unsigned int uLevel
, char *id1
, char *id2
)
473 desc
->subformat
= NULL
;
476 desc
->format
= "B13";
479 desc
->format
= "B13BWWWzzzzzWW";
482 desc
->format
= "B13BWWWzzzzzWN";
483 desc
->subformat
= "WB21BB16B10zWWzDDz";
486 desc
->format
= "zWWWWzzzzWWzzl";
489 desc
->format
= "zWWWWzzzzWNzzl";
490 desc
->subformat
= "WWzWWDDzz";
499 desc
->format
= "WzzzzzzzzN";
500 desc
->subformat
= "z";
503 DEBUG(0,("check_printq_info: invalid level %d\n",
507 if (id1
== NULL
|| strcmp(desc
->format
,id1
) != 0) {
508 DEBUG(0,("check_printq_info: invalid format %s\n",
509 id1
? id1
: "<NULL>" ));
512 if (desc
->subformat
&& (id2
== NULL
|| strcmp(desc
->subformat
,id2
) != 0)) {
513 DEBUG(0,("check_printq_info: invalid subformat %s\n",
514 id2
? id2
: "<NULL>" ));
521 #define RAP_JOB_STATUS_QUEUED 0
522 #define RAP_JOB_STATUS_PAUSED 1
523 #define RAP_JOB_STATUS_SPOOLING 2
524 #define RAP_JOB_STATUS_PRINTING 3
525 #define RAP_JOB_STATUS_PRINTED 4
527 #define RAP_QUEUE_STATUS_PAUSED 1
528 #define RAP_QUEUE_STATUS_ERROR 2
530 /* turn a print job status into a on the wire status
532 static int printj_status(int v
)
536 return RAP_JOB_STATUS_QUEUED
;
538 return RAP_JOB_STATUS_PAUSED
;
540 return RAP_JOB_STATUS_SPOOLING
;
542 return RAP_JOB_STATUS_PRINTING
;
547 /* turn a print queue status into a on the wire status
549 static int printq_status(int v
)
555 return RAP_QUEUE_STATUS_PAUSED
;
557 return RAP_QUEUE_STATUS_ERROR
;
560 static void fill_printjob_info(connection_struct
*conn
, int snum
, int uLevel
,
561 struct pack_desc
*desc
,
562 print_queue_struct
*queue
, int n
)
564 time_t t
= queue
->time
;
566 /* the client expects localtime */
567 t
-= get_time_zone(t
);
569 PACKI(desc
,"W",pjobid_to_rap(lp_const_servicename(snum
),queue
->job
)); /* uJobId */
571 PACKS(desc
,"B21",queue
->fs_user
); /* szUserName */
572 PACKS(desc
,"B",""); /* pad */
573 PACKS(desc
,"B16",""); /* szNotifyName */
574 PACKS(desc
,"B10","PM_Q_RAW"); /* szDataType */
575 PACKS(desc
,"z",""); /* pszParms */
576 PACKI(desc
,"W",n
+1); /* uPosition */
577 PACKI(desc
,"W",printj_status(queue
->status
)); /* fsStatus */
578 PACKS(desc
,"z",""); /* pszStatus */
579 PACKI(desc
,"D",t
); /* ulSubmitted */
580 PACKI(desc
,"D",queue
->size
); /* ulSize */
581 PACKS(desc
,"z",queue
->fs_file
); /* pszComment */
583 if (uLevel
== 2 || uLevel
== 3 || uLevel
== 4) {
584 PACKI(desc
,"W",queue
->priority
); /* uPriority */
585 PACKS(desc
,"z",queue
->fs_user
); /* pszUserName */
586 PACKI(desc
,"W",n
+1); /* uPosition */
587 PACKI(desc
,"W",printj_status(queue
->status
)); /* fsStatus */
588 PACKI(desc
,"D",t
); /* ulSubmitted */
589 PACKI(desc
,"D",queue
->size
); /* ulSize */
590 PACKS(desc
,"z","Samba"); /* pszComment */
591 PACKS(desc
,"z",queue
->fs_file
); /* pszDocument */
593 PACKS(desc
,"z",""); /* pszNotifyName */
594 PACKS(desc
,"z","PM_Q_RAW"); /* pszDataType */
595 PACKS(desc
,"z",""); /* pszParms */
596 PACKS(desc
,"z",""); /* pszStatus */
597 PACKS(desc
,"z",SERVICE(snum
)); /* pszQueue */
598 PACKS(desc
,"z","lpd"); /* pszQProcName */
599 PACKS(desc
,"z",""); /* pszQProcParms */
600 PACKS(desc
,"z","NULL"); /* pszDriverName */
601 PackDriverData(desc
); /* pDriverData */
602 PACKS(desc
,"z",""); /* pszPrinterName */
603 } else if (uLevel
== 4) { /* OS2 */
604 PACKS(desc
,"z",""); /* pszSpoolFileName */
605 PACKS(desc
,"z",""); /* pszPortName */
606 PACKS(desc
,"z",""); /* pszStatus */
607 PACKI(desc
,"D",0); /* ulPagesSpooled */
608 PACKI(desc
,"D",0); /* ulPagesSent */
609 PACKI(desc
,"D",0); /* ulPagesPrinted */
610 PACKI(desc
,"D",0); /* ulTimePrinted */
611 PACKI(desc
,"D",0); /* ulExtendJobStatus */
612 PACKI(desc
,"D",0); /* ulStartPage */
613 PACKI(desc
,"D",0); /* ulEndPage */
618 /********************************************************************
619 Return a driver name given an snum.
620 Returns True if from tdb, False otherwise.
621 ********************************************************************/
623 static bool get_driver_name(int snum
, char **pp_drivername
)
625 NT_PRINTER_INFO_LEVEL
*info
= NULL
;
628 get_a_printer (NULL
, &info
, 2, lp_servicename(snum
));
630 *pp_drivername
= talloc_strdup(talloc_tos(),
631 info
->info_2
->drivername
);
633 free_a_printer(&info
, 2);
634 if (!*pp_drivername
) {
642 /********************************************************************
643 Respond to the DosPrintQInfo command with a level of 52
644 This is used to get printer driver information for Win9x clients
645 ********************************************************************/
646 static void fill_printq_info_52(connection_struct
*conn
, int snum
,
647 struct pack_desc
* desc
, int count
)
651 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
652 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
656 if ( !W_ERROR_IS_OK(get_a_printer( NULL
, &printer
, 2, lp_servicename(snum
))) ) {
657 DEBUG(3,("fill_printq_info_52: Failed to lookup printer [%s]\n",
658 lp_servicename(snum
)));
662 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
,
665 DEBUG(3,("fill_printq_info_52: Failed to lookup driver [%s]\n",
666 printer
->info_2
->drivername
));
670 trim_string(driver
.info_3
->driverpath
, "\\print$\\WIN40\\0\\", 0);
671 trim_string(driver
.info_3
->datafile
, "\\print$\\WIN40\\0\\", 0);
672 trim_string(driver
.info_3
->helpfile
, "\\print$\\WIN40\\0\\", 0);
674 PACKI(desc
, "W", 0x0400); /* don't know */
675 PACKS(desc
, "z", driver
.info_3
->name
); /* long printer name */
676 PACKS(desc
, "z", driver
.info_3
->driverpath
); /* Driverfile Name */
677 PACKS(desc
, "z", driver
.info_3
->datafile
); /* Datafile name */
678 PACKS(desc
, "z", driver
.info_3
->monitorname
); /* language monitor */
680 fstrcpy(location
, "\\\\%L\\print$\\WIN40\\0");
681 standard_sub_basic( "", "", location
, sizeof(location
)-1 );
682 PACKS(desc
,"z", location
); /* share to retrieve files */
684 PACKS(desc
,"z", driver
.info_3
->defaultdatatype
); /* default data type */
685 PACKS(desc
,"z", driver
.info_3
->helpfile
); /* helpfile name */
686 PACKS(desc
,"z", driver
.info_3
->driverpath
); /* driver name */
688 DEBUG(3,("Printer Driver Name: %s:\n",driver
.info_3
->name
));
689 DEBUG(3,("Driver: %s:\n",driver
.info_3
->driverpath
));
690 DEBUG(3,("Data File: %s:\n",driver
.info_3
->datafile
));
691 DEBUG(3,("Language Monitor: %s:\n",driver
.info_3
->monitorname
));
692 DEBUG(3,("Driver Location: %s:\n",location
));
693 DEBUG(3,("Data Type: %s:\n",driver
.info_3
->defaultdatatype
));
694 DEBUG(3,("Help File: %s:\n",driver
.info_3
->helpfile
));
695 PACKI(desc
,"N",count
); /* number of files to copy */
697 for ( i
=0; i
<count
&& driver
.info_3
->dependentfiles
&& *driver
.info_3
->dependentfiles
[i
]; i
++)
699 trim_string(driver
.info_3
->dependentfiles
[i
], "\\print$\\WIN40\\0\\", 0);
700 PACKS(desc
,"z",driver
.info_3
->dependentfiles
[i
]); /* driver files to copy */
701 DEBUG(3,("Dependent File: %s:\n",driver
.info_3
->dependentfiles
[i
]));
706 DEBUG(3,("fill_printq_info_52: file count specified by client [%d] != number of dependent files [%i]\n",
709 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n", SERVICE(snum
),i
));
711 desc
->errcode
=NERR_Success
;
715 DEBUG(3,("fill_printq_info: Can't supply driver files\n"));
716 desc
->errcode
=NERR_notsupported
;
720 free_a_printer( &printer
, 2 );
723 free_a_printer_driver( driver
, 3 );
727 static void fill_printq_info(connection_struct
*conn
, int snum
, int uLevel
,
728 struct pack_desc
* desc
,
729 int count
, print_queue_struct
* queue
,
730 print_status_struct
* status
)
735 PACKS(desc
,"B13",SERVICE(snum
));
740 PACKS(desc
,"z",Expand(conn
,snum
,SERVICE(snum
)));
743 PACKI(desc
,"K",printq_status(status
->status
));
747 if (uLevel
== 1 || uLevel
== 2) {
748 PACKS(desc
,"B",""); /* alignment */
749 PACKI(desc
,"W",5); /* priority */
750 PACKI(desc
,"W",0); /* start time */
751 PACKI(desc
,"W",0); /* until time */
752 PACKS(desc
,"z",""); /* pSepFile */
753 PACKS(desc
,"z","lpd"); /* pPrProc */
754 PACKS(desc
,"z",SERVICE(snum
)); /* pDestinations */
755 PACKS(desc
,"z",""); /* pParms */
757 PACKS(desc
,"z","UNKNOWN PRINTER");
758 PACKI(desc
,"W",LPSTAT_ERROR
);
760 else if (!status
|| !status
->message
[0]) {
761 PACKS(desc
,"z",Expand(conn
,snum
,lp_comment(snum
)));
762 PACKI(desc
,"W",LPSTAT_OK
); /* status */
764 PACKS(desc
,"z",status
->message
);
765 PACKI(desc
,"W",printq_status(status
->status
)); /* status */
767 PACKI(desc
,(uLevel
== 1 ? "W" : "N"),count
);
770 if (uLevel
== 3 || uLevel
== 4) {
771 char *drivername
= NULL
;
773 PACKI(desc
,"W",5); /* uPriority */
774 PACKI(desc
,"W",0); /* uStarttime */
775 PACKI(desc
,"W",0); /* uUntiltime */
776 PACKI(desc
,"W",5); /* pad1 */
777 PACKS(desc
,"z",""); /* pszSepFile */
778 PACKS(desc
,"z","WinPrint"); /* pszPrProc */
779 PACKS(desc
,"z",NULL
); /* pszParms */
780 PACKS(desc
,"z",NULL
); /* pszComment - don't ask.... JRA */
781 /* "don't ask" that it's done this way to fix corrupted
782 Win9X/ME printer comments. */
784 PACKI(desc
,"W",LPSTAT_OK
); /* fsStatus */
786 PACKI(desc
,"W",printq_status(status
->status
)); /* fsStatus */
788 PACKI(desc
,(uLevel
== 3 ? "W" : "N"),count
); /* cJobs */
789 PACKS(desc
,"z",SERVICE(snum
)); /* pszPrinters */
790 get_driver_name(snum
,&drivername
);
794 PACKS(desc
,"z",drivername
); /* pszDriverName */
795 PackDriverData(desc
); /* pDriverData */
798 if (uLevel
== 2 || uLevel
== 4) {
800 for (i
=0;i
<count
;i
++)
801 fill_printjob_info(conn
,snum
,uLevel
== 2 ? 1 : 2,desc
,&queue
[i
],i
);
805 fill_printq_info_52( conn
, snum
, desc
, count
);
808 /* This function returns the number of files for a given driver */
809 static int get_printerdrivernumber(int snum
)
812 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
813 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
817 if ( !W_ERROR_IS_OK(get_a_printer( NULL
, &printer
, 2, lp_servicename(snum
))) ) {
818 DEBUG(3,("get_printerdrivernumber: Failed to lookup printer [%s]\n",
819 lp_servicename(snum
)));
823 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
,
826 DEBUG(3,("get_printerdrivernumber: Failed to lookup driver [%s]\n",
827 printer
->info_2
->drivername
));
831 /* count the number of files */
832 while ( driver
.info_3
->dependentfiles
&& *driver
.info_3
->dependentfiles
[result
] )
837 free_a_printer( &printer
, 2 );
840 free_a_printer_driver( driver
, 3 );
845 static bool api_DosPrintQGetInfo(connection_struct
*conn
, uint16 vuid
,
846 char *param
, int tpscnt
,
847 char *data
, int tdscnt
,
848 int mdrcnt
,int mprcnt
,
849 char **rdata
,char **rparam
,
850 int *rdata_len
,int *rparam_len
)
852 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
853 char *str2
= skip_string(param
,tpscnt
,str1
);
854 char *p
= skip_string(param
,tpscnt
,str2
);
860 struct pack_desc desc
;
861 print_queue_struct
*queue
=NULL
;
862 print_status_struct status
;
865 if (!str1
|| !str2
|| !p
) {
868 memset((char *)&status
,'\0',sizeof(status
));
869 memset((char *)&desc
,'\0',sizeof(desc
));
871 p
= skip_string(param
,tpscnt
,p
);
875 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
876 str3
= get_safe_str_ptr(param
,tpscnt
,p
,4);
877 /* str3 may be null here and is checked in check_printq_info(). */
879 /* remove any trailing username */
880 if ((p
= strchr_m(QueueName
,'%')))
883 DEBUG(3,("api_DosPrintQGetInfo uLevel=%d name=%s\n",uLevel
,QueueName
));
885 /* check it's a supported varient */
886 if (!prefix_ok(str1
,"zWrLh"))
888 if (!check_printq_info(&desc
,uLevel
,str2
,str3
)) {
890 * Patch from Scott Moomaw <scott@bridgewater.edu>
891 * to return the 'invalid info level' error if an
892 * unknown level was requested.
896 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
900 SSVALS(*rparam
,0,ERRunknownlevel
);
906 snum
= find_service(QueueName
);
907 if ( !(lp_snum_ok(snum
) && lp_print_ok(snum
)) )
911 count
= get_printerdrivernumber(snum
);
912 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count
));
914 count
= print_queue_status(snum
, &queue
,&status
);
918 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
924 desc
.buflen
= mdrcnt
;
927 * Don't return data but need to get correct length
928 * init_package will return wrong size if buflen=0
930 desc
.buflen
= getlen(desc
.format
);
931 desc
.base
= tmpdata
= (char *) SMB_MALLOC (desc
.buflen
);
934 if (init_package(&desc
,1,count
)) {
935 desc
.subcount
= count
;
936 fill_printq_info(conn
,snum
,uLevel
,&desc
,count
,queue
,&status
);
939 *rdata_len
= desc
.usedlen
;
942 * We must set the return code to ERRbuftoosmall
943 * in order to support lanman style printing with Win NT/2k
946 if (!mdrcnt
&& lp_disable_spoolss())
947 desc
.errcode
= ERRbuftoosmall
;
949 *rdata_len
= desc
.usedlen
;
951 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
957 SSVALS(*rparam
,0,desc
.errcode
);
959 SSVAL(*rparam
,4,desc
.neededlen
);
961 DEBUG(4,("printqgetinfo: errorcode %d\n",desc
.errcode
));
969 /****************************************************************************
970 View list of all print jobs on all queues.
971 ****************************************************************************/
973 static bool api_DosPrintQEnum(connection_struct
*conn
, uint16 vuid
,
974 char *param
, int tpscnt
,
975 char *data
, int tdscnt
,
976 int mdrcnt
, int mprcnt
,
977 char **rdata
, char** rparam
,
978 int *rdata_len
, int *rparam_len
)
980 char *param_format
= get_safe_str_ptr(param
,tpscnt
,param
,2);
981 char *output_format1
= skip_string(param
,tpscnt
,param_format
);
982 char *p
= skip_string(param
,tpscnt
,output_format1
);
983 unsigned int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
984 char *output_format2
= get_safe_str_ptr(param
,tpscnt
,p
,4);
985 int services
= lp_numservices();
987 struct pack_desc desc
;
988 print_queue_struct
**queue
= NULL
;
989 print_status_struct
*status
= NULL
;
990 int *subcntarr
= NULL
;
991 int queuecnt
= 0, subcnt
= 0, succnt
= 0;
993 if (!param_format
|| !output_format1
|| !p
) {
997 memset((char *)&desc
,'\0',sizeof(desc
));
999 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel
));
1001 if (!prefix_ok(param_format
,"WrLeh")) {
1004 if (!check_printq_info(&desc
,uLevel
,output_format1
,output_format2
)) {
1006 * Patch from Scott Moomaw <scott@bridgewater.edu>
1007 * to return the 'invalid info level' error if an
1008 * unknown level was requested.
1012 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1016 SSVALS(*rparam
,0,ERRunknownlevel
);
1022 for (i
= 0; i
< services
; i
++) {
1023 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
)) {
1028 if((queue
= SMB_MALLOC_ARRAY(print_queue_struct
*, queuecnt
)) == NULL
) {
1029 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
1032 memset(queue
,0,queuecnt
*sizeof(print_queue_struct
*));
1033 if((status
= SMB_MALLOC_ARRAY(print_status_struct
,queuecnt
)) == NULL
) {
1034 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
1037 memset(status
,0,queuecnt
*sizeof(print_status_struct
));
1038 if((subcntarr
= SMB_MALLOC_ARRAY(int,queuecnt
)) == NULL
) {
1039 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
1045 for (i
= 0; i
< services
; i
++) {
1046 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
)) {
1047 subcntarr
[n
] = print_queue_status(i
, &queue
[n
],&status
[n
]);
1048 subcnt
+= subcntarr
[n
];
1054 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
1060 desc
.buflen
= mdrcnt
;
1062 if (init_package(&desc
,queuecnt
,subcnt
)) {
1065 for (i
= 0; i
< services
; i
++) {
1066 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
)) {
1067 fill_printq_info(conn
,i
,uLevel
,&desc
,subcntarr
[n
],queue
[n
],&status
[n
]);
1069 if (desc
.errcode
== NERR_Success
) {
1076 SAFE_FREE(subcntarr
);
1078 *rdata_len
= desc
.usedlen
;
1080 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1084 SSVALS(*rparam
,0,desc
.errcode
);
1086 SSVAL(*rparam
,4,succnt
);
1087 SSVAL(*rparam
,6,queuecnt
);
1089 for (i
= 0; i
< queuecnt
; i
++) {
1091 SAFE_FREE(queue
[i
]);
1102 SAFE_FREE(subcntarr
);
1103 for (i
= 0; i
< queuecnt
; i
++) {
1105 SAFE_FREE(queue
[i
]);
1114 /****************************************************************************
1115 Get info level for a server list query.
1116 ****************************************************************************/
1118 static bool check_server_info(int uLevel
, char* id
)
1122 if (strcmp(id
,"B16") != 0) {
1127 if (strcmp(id
,"B16BBDz") != 0) {
1137 struct srv_info_struct
{
1145 /*******************************************************************
1146 Get server info lists from the files saved by nmbd. Return the
1148 ******************************************************************/
1150 static int get_server_info(uint32 servertype
,
1151 struct srv_info_struct
**servers
,
1157 bool local_list_only
;
1160 lines
= file_lines_load(lock_path(SERVER_LIST
), NULL
, 0);
1162 DEBUG(4,("Can't open %s - %s\n",lock_path(SERVER_LIST
),strerror(errno
)));
1166 /* request for everything is code for request all servers */
1167 if (servertype
== SV_TYPE_ALL
) {
1168 servertype
&= ~(SV_TYPE_DOMAIN_ENUM
|SV_TYPE_LOCAL_LIST_ONLY
);
1171 local_list_only
= (servertype
& SV_TYPE_LOCAL_LIST_ONLY
);
1173 DEBUG(4,("Servertype search: %8x\n",servertype
));
1175 for (i
=0;lines
[i
];i
++) {
1177 struct srv_info_struct
*s
;
1178 const char *ptr
= lines
[i
];
1180 TALLOC_CTX
*frame
= NULL
;
1187 if (count
== alloced
) {
1189 *servers
= SMB_REALLOC_ARRAY(*servers
,struct srv_info_struct
, alloced
);
1191 DEBUG(0,("get_server_info: failed to enlarge servers info struct!\n"));
1192 file_lines_free(lines
);
1195 memset((char *)((*servers
)+count
),'\0',sizeof(**servers
)*(alloced
-count
));
1197 s
= &(*servers
)[count
];
1199 frame
= talloc_stackframe();
1201 if (!next_token_talloc(frame
,&ptr
,&p
, NULL
)) {
1205 fstrcpy(s
->name
, p
);
1208 if (!next_token_talloc(frame
,&ptr
, &p
, NULL
)) {
1214 s
->comment
[0] = '\0';
1215 if (!next_token_talloc(frame
,&ptr
, &p
, NULL
)) {
1219 fstrcpy(s
->comment
, p
);
1221 s
->domain
[0] = '\0';
1222 if (!next_token_talloc(frame
,&ptr
,&p
, NULL
)) {
1223 /* this allows us to cope with an old nmbd */
1224 fstrcpy(s
->domain
,lp_workgroup());
1226 fstrcpy(s
->domain
, p
);
1230 if (sscanf(stype
,"%X",&s
->type
) != 1) {
1231 DEBUG(4,("r:host file "));
1235 /* Filter the servers/domains we return based on what was asked for. */
1237 /* Check to see if we are being asked for a local list only. */
1238 if(local_list_only
&& ((s
->type
& SV_TYPE_LOCAL_LIST_ONLY
) == 0)) {
1239 DEBUG(4,("r: local list only"));
1243 /* doesn't match up: don't want it */
1244 if (!(servertype
& s
->type
)) {
1245 DEBUG(4,("r:serv type "));
1249 if ((servertype
& SV_TYPE_DOMAIN_ENUM
) !=
1250 (s
->type
& SV_TYPE_DOMAIN_ENUM
)) {
1251 DEBUG(4,("s: dom mismatch "));
1255 if (!strequal(domain
, s
->domain
) && !(servertype
& SV_TYPE_DOMAIN_ENUM
)) {
1259 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1260 s
->type
&= ~SV_TYPE_LOCAL_LIST_ONLY
;
1263 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1264 s
->name
, s
->type
, s
->comment
, s
->domain
));
1265 s
->server_added
= True
;
1268 DEBUG(4,("%20s %8x %25s %15s\n",
1269 s
->name
, s
->type
, s
->comment
, s
->domain
));
1273 file_lines_free(lines
);
1277 /*******************************************************************
1278 Fill in a server info structure.
1279 ******************************************************************/
1281 static int fill_srv_info(struct srv_info_struct
*service
,
1282 int uLevel
, char **buf
, int *buflen
,
1283 char **stringbuf
, int *stringspace
, char *baseaddr
)
1306 len
= strlen(service
->comment
)+1;
1310 *buflen
= struct_len
;
1312 return struct_len
+ len
;
1317 if (*buflen
< struct_len
) {
1324 p2
= p
+ struct_len
;
1325 l2
= *buflen
- struct_len
;
1333 push_ascii(p
,service
->name
, MAX_NETBIOSNAME_LEN
, STR_TERMINATE
);
1337 push_ascii(p
,service
->name
,MAX_NETBIOSNAME_LEN
, STR_TERMINATE
);
1338 SIVAL(p
,18,service
->type
);
1339 SIVAL(p
,22,PTR_DIFF(p2
,baseaddr
));
1340 len
+= CopyAndAdvance(&p2
,service
->comment
,&l2
);
1345 *buf
= p
+ struct_len
;
1346 *buflen
-= struct_len
;
1357 static bool srv_comp(struct srv_info_struct
*s1
,struct srv_info_struct
*s2
)
1359 return(strcmp(s1
->name
,s2
->name
));
1362 /****************************************************************************
1363 View list of servers available (or possibly domains). The info is
1364 extracted from lists saved by nmbd on the local host.
1365 ****************************************************************************/
1367 static bool api_RNetServerEnum(connection_struct
*conn
, uint16 vuid
,
1368 char *param
, int tpscnt
,
1369 char *data
, int tdscnt
,
1370 int mdrcnt
, int mprcnt
, char **rdata
,
1371 char **rparam
, int *rdata_len
, int *rparam_len
)
1373 char *str1
= get_safe_str_ptr(param
, tpscnt
, param
, 2);
1374 char *str2
= skip_string(param
,tpscnt
,str1
);
1375 char *p
= skip_string(param
,tpscnt
,str2
);
1376 int uLevel
= get_safe_SVAL(param
, tpscnt
, p
, 0, -1);
1377 int buf_len
= get_safe_SVAL(param
,tpscnt
, p
, 2, 0);
1378 uint32 servertype
= get_safe_IVAL(param
,tpscnt
,p
,4, 0);
1380 int data_len
, fixed_len
, string_len
;
1381 int f_len
= 0, s_len
= 0;
1382 struct srv_info_struct
*servers
=NULL
;
1383 int counted
=0,total
=0;
1386 bool domain_request
;
1389 if (!str1
|| !str2
|| !p
) {
1393 /* If someone sets all the bits they don't really mean to set
1394 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1397 if (servertype
== SV_TYPE_ALL
) {
1398 servertype
&= ~(SV_TYPE_DOMAIN_ENUM
|SV_TYPE_LOCAL_LIST_ONLY
);
1401 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1402 any other bit (they may just set this bit on its own) they
1403 want all the locally seen servers. However this bit can be
1404 set on its own so set the requested servers to be
1405 ALL - DOMAIN_ENUM. */
1407 if ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) && !(servertype
& SV_TYPE_DOMAIN_ENUM
)) {
1408 servertype
= SV_TYPE_ALL
& ~(SV_TYPE_DOMAIN_ENUM
);
1411 domain_request
= ((servertype
& SV_TYPE_DOMAIN_ENUM
) != 0);
1412 local_request
= ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) != 0);
1416 if (!prefix_ok(str1
,"WrLehD")) {
1419 if (!check_server_info(uLevel
,str2
)) {
1423 DEBUG(4, ("server request level: %s %8x ", str2
, servertype
));
1424 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request
)));
1425 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request
)));
1427 if (strcmp(str1
, "WrLehDz") == 0) {
1428 if (skip_string(param
,tpscnt
,p
) == NULL
) {
1431 pull_ascii_fstring(domain
, p
);
1433 fstrcpy(domain
, lp_workgroup());
1436 if (lp_browse_list()) {
1437 total
= get_server_info(servertype
,&servers
,domain
);
1440 data_len
= fixed_len
= string_len
= 0;
1444 qsort(servers
,total
,sizeof(servers
[0]),QSORT_CAST srv_comp
);
1448 char *lastname
=NULL
;
1450 for (i
=0;i
<total
;i
++) {
1451 struct srv_info_struct
*s
= &servers
[i
];
1453 if (lastname
&& strequal(lastname
,s
->name
)) {
1457 data_len
+= fill_srv_info(s
,uLevel
,0,&f_len
,0,&s_len
,0);
1458 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1459 s
->name
, s
->type
, s
->comment
, s
->domain
));
1461 if (data_len
<= buf_len
) {
1464 string_len
+= s_len
;
1471 *rdata_len
= fixed_len
+ string_len
;
1472 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
1477 p2
= (*rdata
) + fixed_len
; /* auxilliary data (strings) will go here */
1483 char *lastname
=NULL
;
1484 int count2
= counted
;
1486 for (i
= 0; i
< total
&& count2
;i
++) {
1487 struct srv_info_struct
*s
= &servers
[i
];
1489 if (lastname
&& strequal(lastname
,s
->name
)) {
1493 fill_srv_info(s
,uLevel
,&p
,&f_len
,&p2
,&s_len
,*rdata
);
1494 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1495 s
->name
, s
->type
, s
->comment
, s
->domain
));
1501 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1505 SSVAL(*rparam
,0,(missed
== 0 ? NERR_Success
: ERRmoredata
));
1507 SSVAL(*rparam
,4,counted
);
1508 SSVAL(*rparam
,6,counted
+missed
);
1512 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1513 domain
,uLevel
,counted
,counted
+missed
));
1518 /****************************************************************************
1519 command 0x34 - suspected of being a "Lookup Names" stub api
1520 ****************************************************************************/
1522 static bool api_RNetGroupGetUsers(connection_struct
*conn
, uint16 vuid
,
1523 char *param
, int tpscnt
,
1524 char *data
, int tdscnt
,
1525 int mdrcnt
, int mprcnt
, char **rdata
,
1526 char **rparam
, int *rdata_len
, int *rparam_len
)
1528 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
1529 char *str2
= skip_string(param
,tpscnt
,str1
);
1530 char *p
= skip_string(param
,tpscnt
,str2
);
1531 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
1532 int buf_len
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
1536 if (!str1
|| !str2
|| !p
) {
1540 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1541 str1
, str2
, p
, uLevel
, buf_len
));
1543 if (!prefix_ok(str1
,"zWrLeh")) {
1550 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1555 SSVAL(*rparam
,0,0x08AC); /* informational warning message */
1557 SSVAL(*rparam
,4,counted
);
1558 SSVAL(*rparam
,6,counted
+missed
);
1563 /****************************************************************************
1564 get info about a share
1565 ****************************************************************************/
1567 static bool check_share_info(int uLevel
, char* id
)
1571 if (strcmp(id
,"B13") != 0) {
1576 if (strcmp(id
,"B13BWz") != 0) {
1581 if (strcmp(id
,"B13BWzWWWzB9B") != 0) {
1586 if (strcmp(id
,"B13BWzWWWzB9BB9BWzWWzWW") != 0) {
1596 static int fill_share_info(connection_struct
*conn
, int snum
, int uLevel
,
1597 char** buf
, int* buflen
,
1598 char** stringbuf
, int* stringspace
, char* baseaddr
)
1628 len
+= StrlenExpanded(conn
,snum
,lp_comment(snum
));
1631 len
+= strlen(lp_pathname(snum
)) + 1;
1634 *buflen
= struct_len
;
1639 return struct_len
+ len
;
1644 if ((*buflen
) < struct_len
) {
1652 p2
= p
+ struct_len
;
1653 l2
= (*buflen
) - struct_len
;
1660 push_ascii(p
,lp_servicename(snum
),13, STR_TERMINATE
);
1666 type
= STYPE_DISKTREE
;
1667 if (lp_print_ok(snum
)) {
1668 type
= STYPE_PRINTQ
;
1670 if (strequal("IPC",lp_fstype(snum
))) {
1673 SSVAL(p
,14,type
); /* device type */
1674 SIVAL(p
,16,PTR_DIFF(p2
,baseaddr
));
1675 len
+= CopyExpanded(conn
,snum
,&p2
,lp_comment(snum
),&l2
);
1679 SSVAL(p
,20,ACCESS_READ
|ACCESS_WRITE
|ACCESS_CREATE
); /* permissions */
1680 SSVALS(p
,22,-1); /* max uses */
1681 SSVAL(p
,24,1); /* current uses */
1682 SIVAL(p
,26,PTR_DIFF(p2
,baseaddr
)); /* local pathname */
1683 len
+= CopyAndAdvance(&p2
,lp_pathname(snum
),&l2
);
1684 memset(p
+30,0,SHPWLEN
+2); /* passwd (reserved), pad field */
1688 memset(p
+40,0,SHPWLEN
+2);
1699 (*buf
) = p
+ struct_len
;
1700 (*buflen
) -= struct_len
;
1702 (*stringspace
) = l2
;
1711 static bool api_RNetShareGetInfo(connection_struct
*conn
,uint16 vuid
,
1712 char *param
, int tpscnt
,
1713 char *data
, int tdscnt
,
1714 int mdrcnt
,int mprcnt
,
1715 char **rdata
,char **rparam
,
1716 int *rdata_len
,int *rparam_len
)
1718 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
1719 char *str2
= skip_string(param
,tpscnt
,str1
);
1720 char *netname
= skip_string(param
,tpscnt
,str2
);
1721 char *p
= skip_string(param
,tpscnt
,netname
);
1722 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
1725 if (!str1
|| !str2
|| !netname
|| !p
) {
1729 snum
= find_service(netname
);
1734 /* check it's a supported varient */
1735 if (!prefix_ok(str1
,"zWrLh")) {
1738 if (!check_share_info(uLevel
,str2
)) {
1742 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
1747 *rdata_len
= fill_share_info(conn
,snum
,uLevel
,&p
,&mdrcnt
,0,0,0);
1748 if (*rdata_len
< 0) {
1753 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1757 SSVAL(*rparam
,0,NERR_Success
);
1758 SSVAL(*rparam
,2,0); /* converter word */
1759 SSVAL(*rparam
,4,*rdata_len
);
1764 /****************************************************************************
1765 View the list of available shares.
1767 This function is the server side of the NetShareEnum() RAP call.
1768 It fills the return buffer with share names and share comments.
1769 Note that the return buffer normally (in all known cases) allows only
1770 twelve byte strings for share names (plus one for a nul terminator).
1771 Share names longer than 12 bytes must be skipped.
1772 ****************************************************************************/
1774 static bool api_RNetShareEnum( connection_struct
*conn
, uint16 vuid
,
1775 char *param
, int tpscnt
,
1776 char *data
, int tdscnt
,
1784 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
1785 char *str2
= skip_string(param
,tpscnt
,str1
);
1786 char *p
= skip_string(param
,tpscnt
,str2
);
1787 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
1788 int buf_len
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
1791 int total
=0,counted
=0;
1792 bool missed
= False
;
1794 int data_len
, fixed_len
, string_len
;
1795 int f_len
= 0, s_len
= 0;
1797 if (!str1
|| !str2
|| !p
) {
1801 if (!prefix_ok(str1
,"WrLeh")) {
1804 if (!check_share_info(uLevel
,str2
)) {
1808 /* Ensure all the usershares are loaded. */
1810 load_registry_shares();
1811 count
= load_usershare_shares();
1814 data_len
= fixed_len
= string_len
= 0;
1815 for (i
=0;i
<count
;i
++) {
1816 fstring servicename_dos
;
1817 if (!(lp_browseable(i
) && lp_snum_ok(i
))) {
1820 push_ascii_fstring(servicename_dos
, lp_servicename(i
));
1821 /* Maximum name length = 13. */
1822 if( lp_browseable( i
) && lp_snum_ok( i
) && (strlen(servicename_dos
) < 13)) {
1824 data_len
+= fill_share_info(conn
,i
,uLevel
,0,&f_len
,0,&s_len
,0);
1825 if (data_len
<= buf_len
) {
1828 string_len
+= s_len
;
1835 *rdata_len
= fixed_len
+ string_len
;
1836 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
1841 p2
= (*rdata
) + fixed_len
; /* auxiliary data (strings) will go here */
1846 for( i
= 0; i
< count
; i
++ ) {
1847 fstring servicename_dos
;
1848 if (!(lp_browseable(i
) && lp_snum_ok(i
))) {
1852 push_ascii_fstring(servicename_dos
, lp_servicename(i
));
1853 if (lp_browseable(i
) && lp_snum_ok(i
) && (strlen(servicename_dos
) < 13)) {
1854 if (fill_share_info( conn
,i
,uLevel
,&p
,&f_len
,&p2
,&s_len
,*rdata
) < 0) {
1861 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1865 SSVAL(*rparam
,0,missed
? ERRmoredata
: NERR_Success
);
1867 SSVAL(*rparam
,4,counted
);
1868 SSVAL(*rparam
,6,total
);
1870 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1871 counted
,total
,uLevel
,
1872 buf_len
,*rdata_len
,mdrcnt
));
1877 /****************************************************************************
1879 ****************************************************************************/
1881 static bool api_RNetShareAdd(connection_struct
*conn
,uint16 vuid
,
1882 char *param
, int tpscnt
,
1883 char *data
, int tdscnt
,
1884 int mdrcnt
,int mprcnt
,
1885 char **rdata
,char **rparam
,
1886 int *rdata_len
,int *rparam_len
)
1888 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
1889 char *str2
= skip_string(param
,tpscnt
,str1
);
1890 char *p
= skip_string(param
,tpscnt
,str2
);
1891 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
1894 char *pathname
= NULL
;
1895 char *command
, *cmdname
;
1896 unsigned int offset
;
1900 if (!str1
|| !str2
|| !p
) {
1904 /* check it's a supported varient */
1905 if (!prefix_ok(str1
,RAP_WShareAdd_REQ
)) {
1908 if (!check_share_info(uLevel
,str2
)) {
1915 /* Do we have a string ? */
1916 if (skip_string(data
,mdrcnt
,data
) == NULL
) {
1919 pull_ascii_fstring(sharename
,data
);
1920 snum
= find_service(sharename
);
1921 if (snum
>= 0) { /* already exists */
1930 /* only support disk share adds */
1931 if (SVAL(data
,14)!=STYPE_DISKTREE
) {
1935 offset
= IVAL(data
, 16);
1936 if (offset
>= mdrcnt
) {
1937 res
= ERRinvalidparam
;
1941 /* Do we have a string ? */
1942 if (skip_string(data
,mdrcnt
,data
+offset
) == NULL
) {
1945 pull_ascii_fstring(comment
, offset
? (data
+offset
) : "");
1947 offset
= IVAL(data
, 26);
1949 if (offset
>= mdrcnt
) {
1950 res
= ERRinvalidparam
;
1954 /* Do we have a string ? */
1955 if (skip_string(data
,mdrcnt
,data
+offset
) == NULL
) {
1959 pull_ascii_talloc(talloc_tos(), &pathname
, offset
? (data
+offset
) : "");
1964 string_replace(sharename
, '"', ' ');
1965 string_replace(pathname
, '"', ' ');
1966 string_replace(comment
, '"', ' ');
1968 cmdname
= lp_add_share_cmd();
1970 if (!cmdname
|| *cmdname
== '\0') {
1974 asprintf(&command
, "%s \"%s\" \"%s\" \"%s\" \"%s\"",
1975 lp_add_share_cmd(), get_dyn_CONFIGFILE(), sharename
, pathname
, comment
);
1978 DEBUG(10,("api_RNetShareAdd: Running [%s]\n", command
));
1980 if ((res
= smbrun(command
, NULL
)) != 0) {
1981 DEBUG(1,("api_RNetShareAdd: Running [%s] returned (%d)\n", command
, res
));
1987 message_send_all(smbd_messaging_context(),
1988 MSG_SMB_CONF_UPDATED
, NULL
, 0, NULL
);
1995 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
1999 SSVAL(*rparam
,0,NERR_Success
);
2000 SSVAL(*rparam
,2,0); /* converter word */
2001 SSVAL(*rparam
,4,*rdata_len
);
2009 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2014 SSVAL(*rparam
,0,res
);
2019 /****************************************************************************
2020 view list of groups available
2021 ****************************************************************************/
2023 static bool api_RNetGroupEnum(connection_struct
*conn
,uint16 vuid
,
2024 char *param
, int tpscnt
,
2025 char *data
, int tdscnt
,
2026 int mdrcnt
,int mprcnt
,
2027 char **rdata
,char **rparam
,
2028 int *rdata_len
,int *rparam_len
)
2032 int resume_context
, cli_buf_size
;
2033 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2034 char *str2
= skip_string(param
,tpscnt
,str1
);
2035 char *p
= skip_string(param
,tpscnt
,str2
);
2037 struct pdb_search
*search
;
2038 struct samr_displayentry
*entries
;
2042 if (!str1
|| !str2
|| !p
) {
2046 if (strcmp(str1
,"WrLeh") != 0) {
2051 * W-> resume context (number of users to skip)
2052 * r -> return parameter pointer to receive buffer
2053 * L -> length of receive buffer
2054 * e -> return parameter number of entries
2055 * h -> return parameter total number of users
2058 if (strcmp("B21",str2
) != 0) {
2062 /* get list of domain groups SID_DOMAIN_GRP=2 */
2064 search
= pdb_search_groups();
2067 if (search
== NULL
) {
2068 DEBUG(3,("api_RNetGroupEnum:failed to get group list"));
2072 resume_context
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2073 cli_buf_size
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
2074 DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: "
2075 "%d\n", resume_context
, cli_buf_size
));
2078 num_entries
= pdb_search_entries(search
, resume_context
, 0xffffffff,
2082 *rdata_len
= cli_buf_size
;
2083 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2090 for(i
=0; i
<num_entries
; i
++) {
2092 fstrcpy(name
, entries
[i
].account_name
);
2093 if( ((PTR_DIFF(p
,*rdata
)+21) <= *rdata_len
) ) {
2094 /* truncate the name at 21 chars. */
2095 memcpy(p
, name
, 21);
2096 DEBUG(10,("adding entry %d group %s\n", i
, p
));
2098 p
+= 5; /* Both NT4 and W2k3SP1 do padding here.
2101 /* set overflow error */
2102 DEBUG(3,("overflow on entry %d group %s\n", i
, name
));
2108 pdb_search_destroy(search
);
2110 *rdata_len
= PTR_DIFF(p
,*rdata
);
2113 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2117 SSVAL(*rparam
, 0, errflags
);
2118 SSVAL(*rparam
, 2, 0); /* converter word */
2119 SSVAL(*rparam
, 4, i
); /* is this right?? */
2120 SSVAL(*rparam
, 6, resume_context
+num_entries
); /* is this right?? */
2125 /*******************************************************************
2126 Get groups that a user is a member of.
2127 ******************************************************************/
2129 static bool api_NetUserGetGroups(connection_struct
*conn
,uint16 vuid
,
2130 char *param
, int tpscnt
,
2131 char *data
, int tdscnt
,
2132 int mdrcnt
,int mprcnt
,
2133 char **rdata
,char **rparam
,
2134 int *rdata_len
,int *rparam_len
)
2136 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2137 char *str2
= skip_string(param
,tpscnt
,str1
);
2138 char *UserName
= skip_string(param
,tpscnt
,str2
);
2139 char *p
= skip_string(param
,tpscnt
,UserName
);
2140 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2141 const char *level_string
;
2143 struct samu
*sampw
= NULL
;
2151 enum lsa_SidType type
;
2153 TALLOC_CTX
*mem_ctx
;
2155 if (!str1
|| !str2
|| !UserName
|| !p
) {
2160 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2165 /* check it's a supported varient */
2167 if ( strcmp(str1
,"zWrLeh") != 0 )
2172 level_string
= "B21";
2178 if (strcmp(level_string
,str2
) != 0)
2181 *rdata_len
= mdrcnt
+ 1024;
2182 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2187 SSVAL(*rparam
,0,NERR_Success
);
2188 SSVAL(*rparam
,2,0); /* converter word */
2191 endp
= *rdata
+ *rdata_len
;
2193 mem_ctx
= talloc_new(NULL
);
2194 if (mem_ctx
== NULL
) {
2195 DEBUG(0, ("talloc_new failed\n"));
2199 if ( !(sampw
= samu_new(mem_ctx
)) ) {
2200 DEBUG(0, ("samu_new() failed!\n"));
2201 TALLOC_FREE(mem_ctx
);
2205 /* Lookup the user information; This should only be one of
2206 our accounts (not remote domains) */
2208 become_root(); /* ROOT BLOCK */
2210 if (!lookup_name(mem_ctx
, UserName
, LOOKUP_NAME_ALL
,
2211 NULL
, NULL
, &user_sid
, &type
)) {
2212 DEBUG(10, ("lookup_name(%s) failed\n", UserName
));
2216 if (type
!= SID_NAME_USER
) {
2217 DEBUG(10, ("%s is a %s, not a user\n", UserName
,
2218 sid_type_lookup(type
)));
2222 if ( !pdb_getsampwsid(sampw
, &user_sid
) ) {
2223 DEBUG(10, ("pdb_getsampwsid(%s) failed for user %s\n",
2224 sid_string_dbg(&user_sid
), UserName
));
2232 result
= pdb_enum_group_memberships(mem_ctx
, sampw
,
2233 &sids
, &gids
, &num_groups
);
2235 if (!NT_STATUS_IS_OK(result
)) {
2236 DEBUG(10, ("pdb_enum_group_memberships failed for %s\n",
2241 for (i
=0; i
<num_groups
; i
++) {
2242 const char *grp_name
;
2244 if ( lookup_sid(mem_ctx
, &sids
[i
], NULL
, &grp_name
, NULL
) ) {
2245 strlcpy(p
, grp_name
, PTR_DIFF(endp
,p
));
2251 *rdata_len
= PTR_DIFF(p
,*rdata
);
2253 SSVAL(*rparam
,4,count
); /* is this right?? */
2254 SSVAL(*rparam
,6,count
); /* is this right?? */
2259 unbecome_root(); /* END ROOT BLOCK */
2261 TALLOC_FREE(mem_ctx
);
2266 /*******************************************************************
2268 ******************************************************************/
2270 static bool api_RNetUserEnum(connection_struct
*conn
, uint16 vuid
,
2271 char *param
, int tpscnt
,
2272 char *data
, int tdscnt
,
2273 int mdrcnt
,int mprcnt
,
2274 char **rdata
,char **rparam
,
2275 int *rdata_len
,int *rparam_len
)
2280 int i
, resume_context
, cli_buf_size
;
2281 struct pdb_search
*search
;
2282 struct samr_displayentry
*users
;
2284 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2285 char *str2
= skip_string(param
,tpscnt
,str1
);
2286 char *p
= skip_string(param
,tpscnt
,str2
);
2289 if (!str1
|| !str2
|| !p
) {
2293 if (strcmp(str1
,"WrLeh") != 0)
2296 * W-> resume context (number of users to skip)
2297 * r -> return parameter pointer to receive buffer
2298 * L -> length of receive buffer
2299 * e -> return parameter number of entries
2300 * h -> return parameter total number of users
2303 resume_context
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2304 cli_buf_size
= get_safe_SVAL(param
,tpscnt
,p
,2,0);
2305 DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n",
2306 resume_context
, cli_buf_size
));
2309 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2314 /* check it's a supported varient */
2315 if (strcmp("B21",str2
) != 0)
2318 *rdata_len
= cli_buf_size
;
2319 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2325 endp
= *rdata
+ *rdata_len
;
2328 search
= pdb_search_users(ACB_NORMAL
);
2330 if (search
== NULL
) {
2331 DEBUG(0, ("api_RNetUserEnum:unable to open sam database.\n"));
2336 num_users
= pdb_search_entries(search
, resume_context
, 0xffffffff,
2340 errflags
=NERR_Success
;
2342 for (i
=0; i
<num_users
; i
++) {
2343 const char *name
= users
[i
].account_name
;
2345 if(((PTR_DIFF(p
,*rdata
)+21)<=*rdata_len
)&&(strlen(name
)<=21)) {
2346 strlcpy(p
,name
,PTR_DIFF(endp
,p
));
2347 DEBUG(10,("api_RNetUserEnum:adding entry %d username "
2348 "%s\n",count_sent
,p
));
2352 /* set overflow error */
2353 DEBUG(10,("api_RNetUserEnum:overflow on entry %d "
2354 "username %s\n",count_sent
,name
));
2360 pdb_search_destroy(search
);
2362 *rdata_len
= PTR_DIFF(p
,*rdata
);
2364 SSVAL(*rparam
,0,errflags
);
2365 SSVAL(*rparam
,2,0); /* converter word */
2366 SSVAL(*rparam
,4,count_sent
); /* is this right?? */
2367 SSVAL(*rparam
,6,num_users
); /* is this right?? */
2372 /****************************************************************************
2373 Get the time of day info.
2374 ****************************************************************************/
2376 static bool api_NetRemoteTOD(connection_struct
*conn
,uint16 vuid
,
2377 char *param
, int tpscnt
,
2378 char *data
, int tdscnt
,
2379 int mdrcnt
,int mprcnt
,
2380 char **rdata
,char **rparam
,
2381 int *rdata_len
,int *rparam_len
)
2384 time_t unixdate
= time(NULL
);
2388 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2394 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2399 SSVAL(*rparam
,0,NERR_Success
);
2400 SSVAL(*rparam
,2,0); /* converter word */
2404 srv_put_dos_date3(p
,0,unixdate
); /* this is the time that is looked at
2405 by NT in a "net time" operation,
2406 it seems to ignore the one below */
2408 /* the client expects to get localtime, not GMT, in this bit
2409 (I think, this needs testing) */
2410 t
= localtime(&unixdate
);
2415 SIVAL(p
,4,0); /* msecs ? */
2416 SCVAL(p
,8,t
->tm_hour
);
2417 SCVAL(p
,9,t
->tm_min
);
2418 SCVAL(p
,10,t
->tm_sec
);
2419 SCVAL(p
,11,0); /* hundredths of seconds */
2420 SSVALS(p
,12,get_time_zone(unixdate
)/60); /* timezone in minutes from GMT */
2421 SSVAL(p
,14,10000); /* timer interval in 0.0001 of sec */
2422 SCVAL(p
,16,t
->tm_mday
);
2423 SCVAL(p
,17,t
->tm_mon
+ 1);
2424 SSVAL(p
,18,1900+t
->tm_year
);
2425 SCVAL(p
,20,t
->tm_wday
);
2430 /****************************************************************************
2431 Set the user password.
2432 *****************************************************************************/
2434 static bool api_SetUserPassword(connection_struct
*conn
,uint16 vuid
,
2435 char *param
, int tpscnt
,
2436 char *data
, int tdscnt
,
2437 int mdrcnt
,int mprcnt
,
2438 char **rdata
,char **rparam
,
2439 int *rdata_len
,int *rparam_len
)
2441 char *np
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2444 fstring pass1
,pass2
;
2446 /* Skip 2 strings. */
2447 p
= skip_string(param
,tpscnt
,np
);
2448 p
= skip_string(param
,tpscnt
,p
);
2454 /* Do we have a string ? */
2455 if (skip_string(param
,tpscnt
,p
) == NULL
) {
2458 pull_ascii_fstring(user
,p
);
2460 p
= skip_string(param
,tpscnt
,p
);
2465 memset(pass1
,'\0',sizeof(pass1
));
2466 memset(pass2
,'\0',sizeof(pass2
));
2468 * We use 31 here not 32 as we're checking
2469 * the last byte we want to access is safe.
2471 if (!is_offset_safe(param
,tpscnt
,p
,31)) {
2475 memcpy(pass2
,p
+16,16);
2478 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2485 SSVAL(*rparam
,0,NERR_badpass
);
2486 SSVAL(*rparam
,2,0); /* converter word */
2488 DEBUG(3,("Set password for <%s>\n",user
));
2491 * Attempt to verify the old password against smbpasswd entries
2492 * Win98 clients send old and new password in plaintext for this call.
2496 auth_serversupplied_info
*server_info
= NULL
;
2497 DATA_BLOB password
= data_blob(pass1
, strlen(pass1
)+1);
2499 if (NT_STATUS_IS_OK(check_plaintext_password(user
,password
,&server_info
))) {
2502 if (NT_STATUS_IS_OK(change_oem_password(server_info
->sam_account
, pass1
, pass2
, False
, NULL
))) {
2503 SSVAL(*rparam
,0,NERR_Success
);
2507 TALLOC_FREE(server_info
);
2509 data_blob_clear_free(&password
);
2513 * If the plaintext change failed, attempt
2514 * the old encrypted method. NT will generate this
2515 * after trying the samr method. Note that this
2516 * method is done as a last resort as this
2517 * password change method loses the NT password hash
2518 * and cannot change the UNIX password as no plaintext
2522 if(SVAL(*rparam
,0) != NERR_Success
) {
2523 struct samu
*hnd
= NULL
;
2525 if (check_lanman_password(user
,(unsigned char *)pass1
,(unsigned char *)pass2
, &hnd
)) {
2527 if (change_lanman_password(hnd
,(uchar
*)pass2
)) {
2528 SSVAL(*rparam
,0,NERR_Success
);
2535 memset((char *)pass1
,'\0',sizeof(fstring
));
2536 memset((char *)pass2
,'\0',sizeof(fstring
));
2541 /****************************************************************************
2542 Set the user password (SamOEM version - gets plaintext).
2543 ****************************************************************************/
2545 static bool api_SamOEMChangePassword(connection_struct
*conn
,uint16 vuid
,
2546 char *param
, int tpscnt
,
2547 char *data
, int tdscnt
,
2548 int mdrcnt
,int mprcnt
,
2549 char **rdata
,char **rparam
,
2550 int *rdata_len
,int *rparam_len
)
2553 char *p
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2555 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2565 SSVAL(*rparam
,0,NERR_badpass
);
2568 * Check the parameter definition is correct.
2571 /* Do we have a string ? */
2572 if (skip_string(param
,tpscnt
,p
) == 0) {
2575 if(!strequal(p
, "zsT")) {
2576 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", p
));
2579 p
= skip_string(param
, tpscnt
, p
);
2584 /* Do we have a string ? */
2585 if (skip_string(param
,tpscnt
,p
) == 0) {
2588 if(!strequal(p
, "B516B16")) {
2589 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p
));
2592 p
= skip_string(param
,tpscnt
,p
);
2596 /* Do we have a string ? */
2597 if (skip_string(param
,tpscnt
,p
) == 0) {
2600 p
+= pull_ascii_fstring(user
,p
);
2602 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user
));
2605 * Pass the user through the NT -> unix user mapping
2609 (void)map_username(user
);
2611 if (NT_STATUS_IS_OK(pass_oem_change(user
, (uchar
*) data
, (uchar
*)&data
[516], NULL
, NULL
, NULL
))) {
2612 SSVAL(*rparam
,0,NERR_Success
);
2618 /****************************************************************************
2621 ****************************************************************************/
2623 static bool api_RDosPrintJobDel(connection_struct
*conn
,uint16 vuid
,
2624 char *param
, int tpscnt
,
2625 char *data
, int tdscnt
,
2626 int mdrcnt
,int mprcnt
,
2627 char **rdata
,char **rparam
,
2628 int *rdata_len
,int *rparam_len
)
2630 int function
= get_safe_SVAL(param
,tpscnt
,param
,0,0);
2631 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2632 char *str2
= skip_string(param
,tpscnt
,str1
);
2633 char *p
= skip_string(param
,tpscnt
,str2
);
2638 WERROR werr
= WERR_OK
;
2640 if (!str1
|| !str2
|| !p
) {
2644 * We use 1 here not 2 as we're checking
2645 * the last byte we want to access is safe.
2647 if (!is_offset_safe(param
,tpscnt
,p
,1)) {
2650 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
))
2653 /* check it's a supported varient */
2654 if (!(strcsequal(str1
,"W") && strcsequal(str2
,"")))
2658 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2664 if (!print_job_exists(sharename
, jobid
)) {
2665 errcode
= NERR_JobNotFound
;
2669 snum
= lp_servicenumber( sharename
);
2671 errcode
= NERR_DestNotFound
;
2675 errcode
= NERR_notsupported
;
2678 case 81: /* delete */
2679 if (print_job_delete(¤t_user
, snum
, jobid
, &werr
))
2680 errcode
= NERR_Success
;
2682 case 82: /* pause */
2683 if (print_job_pause(¤t_user
, snum
, jobid
, &werr
))
2684 errcode
= NERR_Success
;
2686 case 83: /* resume */
2687 if (print_job_resume(¤t_user
, snum
, jobid
, &werr
))
2688 errcode
= NERR_Success
;
2692 if (!W_ERROR_IS_OK(werr
))
2693 errcode
= W_ERROR_V(werr
);
2696 SSVAL(*rparam
,0,errcode
);
2697 SSVAL(*rparam
,2,0); /* converter word */
2702 /****************************************************************************
2703 Purge a print queue - or pause or resume it.
2704 ****************************************************************************/
2706 static bool api_WPrintQueueCtrl(connection_struct
*conn
,uint16 vuid
,
2707 char *param
, int tpscnt
,
2708 char *data
, int tdscnt
,
2709 int mdrcnt
,int mprcnt
,
2710 char **rdata
,char **rparam
,
2711 int *rdata_len
,int *rparam_len
)
2713 int function
= get_safe_SVAL(param
,tpscnt
,param
,0,0);
2714 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2715 char *str2
= skip_string(param
,tpscnt
,str1
);
2716 char *QueueName
= skip_string(param
,tpscnt
,str2
);
2717 int errcode
= NERR_notsupported
;
2719 WERROR werr
= WERR_OK
;
2721 if (!str1
|| !str2
|| !QueueName
) {
2725 /* check it's a supported varient */
2726 if (!(strcsequal(str1
,"z") && strcsequal(str2
,"")))
2730 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2736 if (skip_string(param
,tpscnt
,QueueName
) == NULL
) {
2739 snum
= print_queue_snum(QueueName
);
2742 errcode
= NERR_JobNotFound
;
2747 case 74: /* Pause queue */
2748 if (print_queue_pause(¤t_user
, snum
, &werr
)) errcode
= NERR_Success
;
2750 case 75: /* Resume queue */
2751 if (print_queue_resume(¤t_user
, snum
, &werr
)) errcode
= NERR_Success
;
2753 case 103: /* Purge */
2754 if (print_queue_purge(¤t_user
, snum
, &werr
)) errcode
= NERR_Success
;
2758 if (!W_ERROR_IS_OK(werr
)) errcode
= W_ERROR_V(werr
);
2761 SSVAL(*rparam
,0,errcode
);
2762 SSVAL(*rparam
,2,0); /* converter word */
2767 /****************************************************************************
2768 set the property of a print job (undocumented?)
2769 ? function = 0xb -> set name of print job
2770 ? function = 0x6 -> move print job up/down
2771 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
2772 or <WWsTP> <WB21BB16B10zWWzDDz>
2773 ****************************************************************************/
2775 static int check_printjob_info(struct pack_desc
* desc
,
2776 int uLevel
, char* id
)
2778 desc
->subformat
= NULL
;
2780 case 0: desc
->format
= "W"; break;
2781 case 1: desc
->format
= "WB21BB16B10zWWzDDz"; break;
2782 case 2: desc
->format
= "WWzWWDDzz"; break;
2783 case 3: desc
->format
= "WWzWWDDzzzzzzzzzzlz"; break;
2784 case 4: desc
->format
= "WWzWWDDzzzzzDDDDDDD"; break;
2786 DEBUG(0,("check_printjob_info: invalid level %d\n",
2790 if (id
== NULL
|| strcmp(desc
->format
,id
) != 0) {
2791 DEBUG(0,("check_printjob_info: invalid format %s\n",
2792 id
? id
: "<NULL>" ));
2798 static bool api_PrintJobInfo(connection_struct
*conn
, uint16 vuid
,
2799 char *param
, int tpscnt
,
2800 char *data
, int tdscnt
,
2801 int mdrcnt
,int mprcnt
,
2802 char **rdata
,char **rparam
,
2803 int *rdata_len
,int *rparam_len
)
2805 struct pack_desc desc
;
2806 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2807 char *str2
= skip_string(param
,tpscnt
,str1
);
2808 char *p
= skip_string(param
,tpscnt
,str2
);
2811 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,2,-1);
2812 int function
= get_safe_SVAL(param
,tpscnt
,p
,4,-1);
2815 if (!str1
|| !str2
|| !p
) {
2819 * We use 1 here not 2 as we're checking
2820 * the last byte we want to access is safe.
2822 if (!is_offset_safe(param
,tpscnt
,p
,1)) {
2825 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
))
2828 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
2833 if (!share_defined(sharename
)) {
2834 DEBUG(0,("api_PrintJobInfo: sharen [%s] not defined\n",
2841 /* check it's a supported varient */
2842 if ((strcmp(str1
,"WWsTP")) ||
2843 (!check_printjob_info(&desc
,uLevel
,str2
)))
2846 if (!print_job_exists(sharename
, jobid
)) {
2847 errcode
=NERR_JobNotFound
;
2851 errcode
= NERR_notsupported
;
2855 /* change job place in the queue,
2856 data gives the new place */
2857 place
= SVAL(data
,0);
2858 if (print_job_set_place(sharename
, jobid
, place
)) {
2859 errcode
=NERR_Success
;
2864 /* change print job name, data gives the name */
2865 if (print_job_set_name(sharename
, jobid
, data
)) {
2866 errcode
=NERR_Success
;
2875 SSVALS(*rparam
,0,errcode
);
2876 SSVAL(*rparam
,2,0); /* converter word */
2882 /****************************************************************************
2883 Get info about the server.
2884 ****************************************************************************/
2886 static bool api_RNetServerGetInfo(connection_struct
*conn
,uint16 vuid
,
2887 char *param
, int tpscnt
,
2888 char *data
, int tdscnt
,
2889 int mdrcnt
,int mprcnt
,
2890 char **rdata
,char **rparam
,
2891 int *rdata_len
,int *rparam_len
)
2893 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
2894 char *str2
= skip_string(param
,tpscnt
,str1
);
2895 char *p
= skip_string(param
,tpscnt
,str2
);
2896 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
2900 if (!str1
|| !str2
|| !p
) {
2904 DEBUG(4,("NetServerGetInfo level %d\n",uLevel
));
2906 /* check it's a supported varient */
2907 if (!prefix_ok(str1
,"WrLh")) {
2913 if (strcmp(str2
,"B16") != 0) {
2919 if (strcmp(str2
,"B16BBDz") != 0) {
2925 if (strcmp(str2
,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")!= 0) {
2931 if (strcmp(str2
,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz") != 0) {
2937 if (strcmp(str2
,"DN") != 0) {
2943 if (strcmp(str2
,"B16BBDzWWzzz") != 0) {
2952 *rdata_len
= mdrcnt
;
2953 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
2959 p2
= p
+ struct_len
;
2961 srvstr_push(NULL
, 0, p
,global_myname(),16,
2962 STR_ASCII
|STR_UPPER
|STR_TERMINATE
);
2966 struct srv_info_struct
*servers
=NULL
;
2968 char *comment
= NULL
;
2969 TALLOC_CTX
*ctx
= talloc_tos();
2970 uint32 servertype
= lp_default_server_announce();
2972 comment
= talloc_strdup(ctx
,lp_serverstring());
2977 if ((count
=get_server_info(SV_TYPE_ALL
,&servers
,lp_workgroup()))>0) {
2978 for (i
=0;i
<count
;i
++) {
2979 if (strequal(servers
[i
].name
,global_myname())) {
2980 servertype
= servers
[i
].type
;
2981 TALLOC_FREE(comment
);
2982 comment
= talloc_strdup(ctx
,
2983 servers
[i
].comment
);
2993 SCVAL(p
,0,lp_major_announce_version());
2994 SCVAL(p
,1,lp_minor_announce_version());
2995 SIVAL(p
,2,servertype
);
2997 if (mdrcnt
== struct_len
) {
3000 SIVAL(p
,6,PTR_DIFF(p2
,*rdata
));
3001 comment
= talloc_sub_advanced(ctx
,
3002 lp_servicename(SNUM(conn
)),
3006 get_current_username(),
3007 current_user_info
.domain
,
3012 if (mdrcnt
- struct_len
<= 0) {
3017 MIN(mdrcnt
- struct_len
,
3018 MAX_SERVER_STRING_LENGTH
),
3020 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3028 return False
; /* not yet implemented */
3031 *rdata_len
= PTR_DIFF(p2
,*rdata
);
3034 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3038 SSVAL(*rparam
,0,NERR_Success
);
3039 SSVAL(*rparam
,2,0); /* converter word */
3040 SSVAL(*rparam
,4,*rdata_len
);
3045 /****************************************************************************
3046 Get info about the server.
3047 ****************************************************************************/
3049 static bool api_NetWkstaGetInfo(connection_struct
*conn
,uint16 vuid
,
3050 char *param
, int tpscnt
,
3051 char *data
, int tdscnt
,
3052 int mdrcnt
,int mprcnt
,
3053 char **rdata
,char **rparam
,
3054 int *rdata_len
,int *rparam_len
)
3056 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3057 char *str2
= skip_string(param
,tpscnt
,str1
);
3058 char *p
= skip_string(param
,tpscnt
,str2
);
3061 int level
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3063 if (!str1
|| !str2
|| !p
) {
3067 DEBUG(4,("NetWkstaGetInfo level %d\n",level
));
3070 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3075 /* check it's a supported varient */
3076 if (!(level
==10 && strcsequal(str1
,"WrLh") && strcsequal(str2
,"zzzBBzz"))) {
3080 *rdata_len
= mdrcnt
+ 1024;
3081 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
3086 SSVAL(*rparam
,0,NERR_Success
);
3087 SSVAL(*rparam
,2,0); /* converter word */
3090 endp
= *rdata
+ *rdata_len
;
3092 p2
= get_safe_ptr(*rdata
,*rdata_len
,p
,22);
3097 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* host name */
3098 strlcpy(p2
,get_local_machine_name(),PTR_DIFF(endp
,p2
));
3100 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3106 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
));
3107 strlcpy(p2
,current_user_info
.smb_name
,PTR_DIFF(endp
,p2
));
3108 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3114 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* login domain */
3115 strlcpy(p2
,lp_workgroup(),PTR_DIFF(endp
,p2
));
3117 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3123 SCVAL(p
,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
3124 SCVAL(p
,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
3127 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
));
3128 strlcpy(p2
,lp_workgroup(),PTR_DIFF(endp
,p2
)); /* don't know. login domain?? */
3129 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3135 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* don't know */
3136 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
3137 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3143 *rdata_len
= PTR_DIFF(p2
,*rdata
);
3145 SSVAL(*rparam
,4,*rdata_len
);
3150 /****************************************************************************
3151 get info about a user
3153 struct user_info_11 {
3154 char usri11_name[21]; 0-20
3156 char *usri11_comment; 22-25
3157 char *usri11_usr_comment; 26-29
3158 unsigned short usri11_priv; 30-31
3159 unsigned long usri11_auth_flags; 32-35
3160 long usri11_password_age; 36-39
3161 char *usri11_homedir; 40-43
3162 char *usri11_parms; 44-47
3163 long usri11_last_logon; 48-51
3164 long usri11_last_logoff; 52-55
3165 unsigned short usri11_bad_pw_count; 56-57
3166 unsigned short usri11_num_logons; 58-59
3167 char *usri11_logon_server; 60-63
3168 unsigned short usri11_country_code; 64-65
3169 char *usri11_workstations; 66-69
3170 unsigned long usri11_max_storage; 70-73
3171 unsigned short usri11_units_per_week; 74-75
3172 unsigned char *usri11_logon_hours; 76-79
3173 unsigned short usri11_code_page; 80-81
3178 usri11_name specifies the user name for which information is retrieved
3180 usri11_pad aligns the next data structure element to a word boundary
3182 usri11_comment is a null terminated ASCII comment
3184 usri11_user_comment is a null terminated ASCII comment about the user
3186 usri11_priv specifies the level of the privilege assigned to the user.
3187 The possible values are:
3189 Name Value Description
3190 USER_PRIV_GUEST 0 Guest privilege
3191 USER_PRIV_USER 1 User privilege
3192 USER_PRV_ADMIN 2 Administrator privilege
3194 usri11_auth_flags specifies the account operator privileges. The
3195 possible values are:
3197 Name Value Description
3198 AF_OP_PRINT 0 Print operator
3201 Leach, Naik [Page 28]
3205 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
3208 AF_OP_COMM 1 Communications operator
3209 AF_OP_SERVER 2 Server operator
3210 AF_OP_ACCOUNTS 3 Accounts operator
3213 usri11_password_age specifies how many seconds have elapsed since the
3214 password was last changed.
3216 usri11_home_dir points to a null terminated ASCII string that contains
3217 the path name of the user's home directory.
3219 usri11_parms points to a null terminated ASCII string that is set
3220 aside for use by applications.
3222 usri11_last_logon specifies the time when the user last logged on.
3223 This value is stored as the number of seconds elapsed since
3224 00:00:00, January 1, 1970.
3226 usri11_last_logoff specifies the time when the user last logged off.
3227 This value is stored as the number of seconds elapsed since
3228 00:00:00, January 1, 1970. A value of 0 means the last logoff
3231 usri11_bad_pw_count specifies the number of incorrect passwords
3232 entered since the last successful logon.
3234 usri11_log1_num_logons specifies the number of times this user has
3235 logged on. A value of -1 means the number of logons is unknown.
3237 usri11_logon_server points to a null terminated ASCII string that
3238 contains the name of the server to which logon requests are sent.
3239 A null string indicates logon requests should be sent to the
3242 usri11_country_code specifies the country code for the user's language
3245 usri11_workstations points to a null terminated ASCII string that
3246 contains the names of workstations the user may log on from.
3247 There may be up to 8 workstations, with the names separated by
3248 commas. A null strings indicates there are no restrictions.
3250 usri11_max_storage specifies the maximum amount of disk space the user
3251 can occupy. A value of 0xffffffff indicates there are no
3254 usri11_units_per_week specifies the equal number of time units into
3255 which a week is divided. This value must be equal to 168.
3257 usri11_logon_hours points to a 21 byte (168 bits) string that
3258 specifies the time during which the user can log on. Each bit
3259 represents one unique hour in a week. The first bit (bit 0, word
3260 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
3264 Leach, Naik [Page 29]
3268 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
3271 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
3272 are no restrictions.
3274 usri11_code_page specifies the code page for the user's language of
3277 All of the pointers in this data structure need to be treated
3278 specially. The pointer is a 32 bit pointer. The higher 16 bits need
3279 to be ignored. The converter word returned in the parameters section
3280 needs to be subtracted from the lower 16 bits to calculate an offset
3281 into the return buffer where this ASCII string resides.
3283 There is no auxiliary data in the response.
3285 ****************************************************************************/
3287 #define usri11_name 0
3288 #define usri11_pad 21
3289 #define usri11_comment 22
3290 #define usri11_usr_comment 26
3291 #define usri11_full_name 30
3292 #define usri11_priv 34
3293 #define usri11_auth_flags 36
3294 #define usri11_password_age 40
3295 #define usri11_homedir 44
3296 #define usri11_parms 48
3297 #define usri11_last_logon 52
3298 #define usri11_last_logoff 56
3299 #define usri11_bad_pw_count 60
3300 #define usri11_num_logons 62
3301 #define usri11_logon_server 64
3302 #define usri11_country_code 68
3303 #define usri11_workstations 70
3304 #define usri11_max_storage 74
3305 #define usri11_units_per_week 78
3306 #define usri11_logon_hours 80
3307 #define usri11_code_page 84
3308 #define usri11_end 86
3310 #define USER_PRIV_GUEST 0
3311 #define USER_PRIV_USER 1
3312 #define USER_PRIV_ADMIN 2
3314 #define AF_OP_PRINT 0
3315 #define AF_OP_COMM 1
3316 #define AF_OP_SERVER 2
3317 #define AF_OP_ACCOUNTS 3
3320 static bool api_RNetUserGetInfo(connection_struct
*conn
, uint16 vuid
,
3321 char *param
, int tpscnt
,
3322 char *data
, int tdscnt
,
3323 int mdrcnt
,int mprcnt
,
3324 char **rdata
,char **rparam
,
3325 int *rdata_len
,int *rparam_len
)
3327 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3328 char *str2
= skip_string(param
,tpscnt
,str1
);
3329 char *UserName
= skip_string(param
,tpscnt
,str2
);
3330 char *p
= skip_string(param
,tpscnt
,UserName
);
3331 int uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3334 const char *level_string
;
3336 /* get NIS home of a previously validated user - simeon */
3337 /* With share level security vuid will always be zero.
3338 Don't depend on vuser being non-null !!. JRA */
3339 user_struct
*vuser
= get_valid_user_struct(vuid
);
3341 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser
->uid
,
3342 vuser
->user
.unix_name
));
3345 if (!str1
|| !str2
|| !UserName
|| !p
) {
3350 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3355 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel
));
3357 /* check it's a supported variant */
3358 if (strcmp(str1
,"zWrLh") != 0) {
3362 case 0: level_string
= "B21"; break;
3363 case 1: level_string
= "B21BB16DWzzWz"; break;
3364 case 2: level_string
= "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
3365 case 10: level_string
= "B21Bzzz"; break;
3366 case 11: level_string
= "B21BzzzWDDzzDDWWzWzDWb21W"; break;
3367 default: return False
;
3370 if (strcmp(level_string
,str2
) != 0) {
3374 *rdata_len
= mdrcnt
+ 1024;
3375 *rdata
= smb_realloc_limit(*rdata
,*rdata_len
);
3380 SSVAL(*rparam
,0,NERR_Success
);
3381 SSVAL(*rparam
,2,0); /* converter word */
3384 endp
= *rdata
+ *rdata_len
;
3385 p2
= get_safe_ptr(*rdata
,*rdata_len
,p
,usri11_end
);
3391 fstrcpy(p
+usri11_name
,UserName
); /* 21 bytes - user name */
3394 SCVAL(p
,usri11_pad
,0); /* padding - 1 byte */
3399 SIVAL(p
,usri11_comment
,PTR_DIFF(p2
,p
)); /* comment */
3400 strlcpy(p2
,"Comment",PTR_DIFF(endp
,p2
));
3401 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3406 SIVAL(p
,usri11_usr_comment
,PTR_DIFF(p2
,p
)); /* user_comment */
3407 strlcpy(p2
,"UserComment",PTR_DIFF(endp
,p2
));
3408 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3413 /* EEK! the cifsrap.txt doesn't have this in!!!! */
3414 SIVAL(p
,usri11_full_name
,PTR_DIFF(p2
,p
)); /* full name */
3415 strlcpy(p2
,((vuser
!= NULL
) ? vuser
->user
.full_name
: UserName
),PTR_DIFF(endp
,p2
));
3416 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3423 /* modelled after NTAS 3.51 reply */
3424 SSVAL(p
,usri11_priv
,conn
->admin_user
?USER_PRIV_ADMIN
:USER_PRIV_USER
);
3425 SIVAL(p
,usri11_auth_flags
,AF_OP_PRINT
); /* auth flags */
3426 SIVALS(p
,usri11_password_age
,-1); /* password age */
3427 SIVAL(p
,usri11_homedir
,PTR_DIFF(p2
,p
)); /* home dir */
3428 strlcpy(p2
, vuser
&& vuser
->homedir
? vuser
->homedir
: "",PTR_DIFF(endp
,p2
));
3429 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3433 SIVAL(p
,usri11_parms
,PTR_DIFF(p2
,p
)); /* parms */
3434 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
3435 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3439 SIVAL(p
,usri11_last_logon
,0); /* last logon */
3440 SIVAL(p
,usri11_last_logoff
,0); /* last logoff */
3441 SSVALS(p
,usri11_bad_pw_count
,-1); /* bad pw counts */
3442 SSVALS(p
,usri11_num_logons
,-1); /* num logons */
3443 SIVAL(p
,usri11_logon_server
,PTR_DIFF(p2
,p
)); /* logon server */
3444 strlcpy(p2
,"\\\\*",PTR_DIFF(endp
,p2
));
3445 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3449 SSVAL(p
,usri11_country_code
,0); /* country code */
3451 SIVAL(p
,usri11_workstations
,PTR_DIFF(p2
,p
)); /* workstations */
3452 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
3453 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3458 SIVALS(p
,usri11_max_storage
,-1); /* max storage */
3459 SSVAL(p
,usri11_units_per_week
,168); /* units per week */
3460 SIVAL(p
,usri11_logon_hours
,PTR_DIFF(p2
,p
)); /* logon hours */
3462 /* a simple way to get logon hours at all times. */
3464 SCVAL(p2
,21,0); /* fix zero termination */
3465 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3470 SSVAL(p
,usri11_code_page
,0); /* code page */
3473 if (uLevel
== 1 || uLevel
== 2) {
3474 memset(p
+22,' ',16); /* password */
3475 SIVALS(p
,38,-1); /* password age */
3477 conn
->admin_user
?USER_PRIV_ADMIN
:USER_PRIV_USER
);
3478 SIVAL(p
,44,PTR_DIFF(p2
,*rdata
)); /* home dir */
3479 strlcpy(p2
, vuser
&& vuser
->homedir
? vuser
->homedir
: "",PTR_DIFF(endp
,p2
));
3480 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3484 SIVAL(p
,48,PTR_DIFF(p2
,*rdata
)); /* comment */
3486 SSVAL(p
,52,0); /* flags */
3487 SIVAL(p
,54,PTR_DIFF(p2
,*rdata
)); /* script_path */
3488 strlcpy(p2
,vuser
&& vuser
->logon_script
? vuser
->logon_script
: "",PTR_DIFF(endp
,p2
));
3489 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3494 SIVAL(p
,60,0); /* auth_flags */
3495 SIVAL(p
,64,PTR_DIFF(p2
,*rdata
)); /* full_name */
3496 strlcpy(p2
,((vuser
!= NULL
) ? vuser
->user
.full_name
: UserName
),PTR_DIFF(endp
,p2
));
3497 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3501 SIVAL(p
,68,0); /* urs_comment */
3502 SIVAL(p
,72,PTR_DIFF(p2
,*rdata
)); /* parms */
3503 strlcpy(p2
,"",PTR_DIFF(endp
,p2
));
3504 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3508 SIVAL(p
,76,0); /* workstations */
3509 SIVAL(p
,80,0); /* last_logon */
3510 SIVAL(p
,84,0); /* last_logoff */
3511 SIVALS(p
,88,-1); /* acct_expires */
3512 SIVALS(p
,92,-1); /* max_storage */
3513 SSVAL(p
,96,168); /* units_per_week */
3514 SIVAL(p
,98,PTR_DIFF(p2
,*rdata
)); /* logon_hours */
3517 SSVALS(p
,102,-1); /* bad_pw_count */
3518 SSVALS(p
,104,-1); /* num_logons */
3519 SIVAL(p
,106,PTR_DIFF(p2
,*rdata
)); /* logon_server */
3521 TALLOC_CTX
*ctx
= talloc_tos();
3522 int space_rem
= *rdata_len
- (p2
- *rdata
);
3525 if (space_rem
<= 0) {
3528 tmp
= talloc_strdup(ctx
, "\\\\%L");
3532 tmp
= talloc_sub_basic(ctx
,
3545 p2
= skip_string(*rdata
,*rdata_len
,p2
);
3549 SSVAL(p
,110,49); /* country_code */
3550 SSVAL(p
,112,860); /* code page */
3554 *rdata_len
= PTR_DIFF(p2
,*rdata
);
3556 SSVAL(*rparam
,4,*rdata_len
); /* is this right?? */
3561 static bool api_WWkstaUserLogon(connection_struct
*conn
,uint16 vuid
,
3562 char *param
, int tpscnt
,
3563 char *data
, int tdscnt
,
3564 int mdrcnt
,int mprcnt
,
3565 char **rdata
,char **rparam
,
3566 int *rdata_len
,int *rparam_len
)
3568 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3569 char *str2
= skip_string(param
,tpscnt
,str1
);
3570 char *p
= skip_string(param
,tpscnt
,str2
);
3572 struct pack_desc desc
;
3574 /* With share level security vuid will always be zero.
3575 Don't depend on vuser being non-null !!. JRA */
3576 user_struct
*vuser
= get_valid_user_struct(vuid
);
3578 if (!str1
|| !str2
|| !p
) {
3583 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser
->uid
,
3584 vuser
->user
.unix_name
));
3587 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3588 name
= get_safe_str_ptr(param
,tpscnt
,p
,2);
3593 memset((char *)&desc
,'\0',sizeof(desc
));
3595 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel
,name
));
3597 /* check it's a supported varient */
3598 if (strcmp(str1
,"OOWb54WrLh") != 0) {
3601 if (uLevel
!= 1 || strcmp(str2
,"WB21BWDWWDDDDDDDzzzD") != 0) {
3605 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
3612 desc
.buflen
= mdrcnt
;
3613 desc
.subformat
= NULL
;
3616 if (init_package(&desc
,1,0)) {
3617 PACKI(&desc
,"W",0); /* code */
3618 PACKS(&desc
,"B21",name
); /* eff. name */
3619 PACKS(&desc
,"B",""); /* pad */
3620 PACKI(&desc
,"W", conn
->admin_user
?USER_PRIV_ADMIN
:USER_PRIV_USER
);
3621 PACKI(&desc
,"D",0); /* auth flags XXX */
3622 PACKI(&desc
,"W",0); /* num logons */
3623 PACKI(&desc
,"W",0); /* bad pw count */
3624 PACKI(&desc
,"D",0); /* last logon */
3625 PACKI(&desc
,"D",-1); /* last logoff */
3626 PACKI(&desc
,"D",-1); /* logoff time */
3627 PACKI(&desc
,"D",-1); /* kickoff time */
3628 PACKI(&desc
,"D",0); /* password age */
3629 PACKI(&desc
,"D",0); /* password can change */
3630 PACKI(&desc
,"D",-1); /* password must change */
3634 fstrcpy(mypath
,"\\\\");
3635 fstrcat(mypath
,get_local_machine_name());
3637 PACKS(&desc
,"z",mypath
); /* computer */
3640 PACKS(&desc
,"z",lp_workgroup());/* domain */
3641 PACKS(&desc
,"z", vuser
&& vuser
->logon_script
? vuser
->logon_script
:""); /* script path */
3642 PACKI(&desc
,"D",0x00000000); /* reserved */
3645 *rdata_len
= desc
.usedlen
;
3647 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3651 SSVALS(*rparam
,0,desc
.errcode
);
3653 SSVAL(*rparam
,4,desc
.neededlen
);
3655 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc
.errcode
));
3660 /****************************************************************************
3661 api_WAccessGetUserPerms
3662 ****************************************************************************/
3664 static bool api_WAccessGetUserPerms(connection_struct
*conn
,uint16 vuid
,
3665 char *param
, int tpscnt
,
3666 char *data
, int tdscnt
,
3667 int mdrcnt
,int mprcnt
,
3668 char **rdata
,char **rparam
,
3669 int *rdata_len
,int *rparam_len
)
3671 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3672 char *str2
= skip_string(param
,tpscnt
,str1
);
3673 char *user
= skip_string(param
,tpscnt
,str2
);
3674 char *resource
= skip_string(param
,tpscnt
,user
);
3676 if (!str1
|| !str2
|| !user
|| !resource
) {
3680 if (skip_string(param
,tpscnt
,resource
) == NULL
) {
3683 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user
,resource
));
3685 /* check it's a supported varient */
3686 if (strcmp(str1
,"zzh") != 0) {
3689 if (strcmp(str2
,"") != 0) {
3694 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3698 SSVALS(*rparam
,0,0); /* errorcode */
3699 SSVAL(*rparam
,2,0); /* converter word */
3700 SSVAL(*rparam
,4,0x7f); /* permission flags */
3705 /****************************************************************************
3706 api_WPrintJobEnumerate
3707 ****************************************************************************/
3709 static bool api_WPrintJobGetInfo(connection_struct
*conn
, uint16 vuid
,
3710 char *param
, int tpscnt
,
3711 char *data
, int tdscnt
,
3712 int mdrcnt
,int mprcnt
,
3713 char **rdata
,char **rparam
,
3714 int *rdata_len
,int *rparam_len
)
3716 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3717 char *str2
= skip_string(param
,tpscnt
,str1
);
3718 char *p
= skip_string(param
,tpscnt
,str2
);
3725 struct pack_desc desc
;
3726 print_queue_struct
*queue
=NULL
;
3727 print_status_struct status
;
3730 if (!str1
|| !str2
|| !p
) {
3734 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,2,-1);
3736 memset((char *)&desc
,'\0',sizeof(desc
));
3737 memset((char *)&status
,'\0',sizeof(status
));
3739 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel
,SVAL(p
,0)));
3741 /* check it's a supported varient */
3742 if (strcmp(str1
,"WWrLh") != 0) {
3745 if (!check_printjob_info(&desc
,uLevel
,str2
)) {
3749 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
)) {
3753 snum
= lp_servicenumber( sharename
);
3754 if (snum
< 0 || !VALID_SNUM(snum
)) {
3758 count
= print_queue_status(snum
,&queue
,&status
);
3759 for (i
= 0; i
< count
; i
++) {
3760 if (queue
[i
].job
== jobid
) {
3766 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
3771 desc
.buflen
= mdrcnt
;
3774 * Don't return data but need to get correct length
3775 * init_package will return wrong size if buflen=0
3777 desc
.buflen
= getlen(desc
.format
);
3778 desc
.base
= tmpdata
= (char *)SMB_MALLOC( desc
.buflen
);
3781 if (init_package(&desc
,1,0)) {
3783 fill_printjob_info(conn
,snum
,uLevel
,&desc
,&queue
[i
],i
);
3784 *rdata_len
= desc
.usedlen
;
3786 desc
.errcode
= NERR_JobNotFound
;
3792 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3796 SSVALS(*rparam
,0,desc
.errcode
);
3798 SSVAL(*rparam
,4,desc
.neededlen
);
3803 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc
.errcode
));
3808 static bool api_WPrintJobEnumerate(connection_struct
*conn
, uint16 vuid
,
3809 char *param
, int tpscnt
,
3810 char *data
, int tdscnt
,
3811 int mdrcnt
,int mprcnt
,
3812 char **rdata
,char **rparam
,
3813 int *rdata_len
,int *rparam_len
)
3815 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3816 char *str2
= skip_string(param
,tpscnt
,str1
);
3817 char *p
= skip_string(param
,tpscnt
,str2
);
3823 struct pack_desc desc
;
3824 print_queue_struct
*queue
=NULL
;
3825 print_status_struct status
;
3827 if (!str1
|| !str2
|| !p
) {
3831 memset((char *)&desc
,'\0',sizeof(desc
));
3832 memset((char *)&status
,'\0',sizeof(status
));
3834 p
= skip_string(param
,tpscnt
,p
);
3838 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3840 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel
,name
));
3842 /* check it's a supported variant */
3843 if (strcmp(str1
,"zWrLeh") != 0) {
3848 return False
; /* defined only for uLevel 0,1,2 */
3851 if (!check_printjob_info(&desc
,uLevel
,str2
)) {
3855 snum
= find_service(name
);
3856 if ( !(lp_snum_ok(snum
) && lp_print_ok(snum
)) ) {
3860 count
= print_queue_status(snum
,&queue
,&status
);
3862 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
3868 desc
.buflen
= mdrcnt
;
3870 if (init_package(&desc
,count
,0)) {
3872 for (i
= 0; i
< count
; i
++) {
3873 fill_printjob_info(conn
,snum
,uLevel
,&desc
,&queue
[i
],i
);
3874 if (desc
.errcode
== NERR_Success
) {
3880 *rdata_len
= desc
.usedlen
;
3883 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
3887 SSVALS(*rparam
,0,desc
.errcode
);
3889 SSVAL(*rparam
,4,succnt
);
3890 SSVAL(*rparam
,6,count
);
3894 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc
.errcode
));
3899 static int check_printdest_info(struct pack_desc
* desc
,
3900 int uLevel
, char* id
)
3902 desc
->subformat
= NULL
;
3905 desc
->format
= "B9";
3908 desc
->format
= "B9B21WWzW";
3914 desc
->format
= "zzzWWzzzWW";
3917 DEBUG(0,("check_printdest_info: invalid level %d\n",
3921 if (id
== NULL
|| strcmp(desc
->format
,id
) != 0) {
3922 DEBUG(0,("check_printdest_info: invalid string %s\n",
3923 id
? id
: "<NULL>" ));
3929 static void fill_printdest_info(connection_struct
*conn
, int snum
, int uLevel
,
3930 struct pack_desc
* desc
)
3934 strncpy(buf
,SERVICE(snum
),sizeof(buf
)-1);
3935 buf
[sizeof(buf
)-1] = 0;
3939 PACKS(desc
,"B9",buf
); /* szName */
3941 PACKS(desc
,"B21",""); /* szUserName */
3942 PACKI(desc
,"W",0); /* uJobId */
3943 PACKI(desc
,"W",0); /* fsStatus */
3944 PACKS(desc
,"z",""); /* pszStatus */
3945 PACKI(desc
,"W",0); /* time */
3949 if (uLevel
== 2 || uLevel
== 3) {
3950 PACKS(desc
,"z",buf
); /* pszPrinterName */
3952 PACKS(desc
,"z",""); /* pszUserName */
3953 PACKS(desc
,"z",""); /* pszLogAddr */
3954 PACKI(desc
,"W",0); /* uJobId */
3955 PACKI(desc
,"W",0); /* fsStatus */
3956 PACKS(desc
,"z",""); /* pszStatus */
3957 PACKS(desc
,"z",""); /* pszComment */
3958 PACKS(desc
,"z","NULL"); /* pszDrivers */
3959 PACKI(desc
,"W",0); /* time */
3960 PACKI(desc
,"W",0); /* pad1 */
3965 static bool api_WPrintDestGetInfo(connection_struct
*conn
, uint16 vuid
,
3966 char *param
, int tpscnt
,
3967 char *data
, int tdscnt
,
3968 int mdrcnt
,int mprcnt
,
3969 char **rdata
,char **rparam
,
3970 int *rdata_len
,int *rparam_len
)
3972 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
3973 char *str2
= skip_string(param
,tpscnt
,str1
);
3974 char *p
= skip_string(param
,tpscnt
,str2
);
3975 char* PrinterName
= p
;
3977 struct pack_desc desc
;
3981 if (!str1
|| !str2
|| !p
) {
3985 memset((char *)&desc
,'\0',sizeof(desc
));
3987 p
= skip_string(param
,tpscnt
,p
);
3991 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
3993 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel
,PrinterName
));
3995 /* check it's a supported varient */
3996 if (strcmp(str1
,"zWrLh") != 0) {
3999 if (!check_printdest_info(&desc
,uLevel
,str2
)) {
4003 snum
= find_service(PrinterName
);
4004 if ( !(lp_snum_ok(snum
) && lp_print_ok(snum
)) ) {
4006 desc
.errcode
= NERR_DestNotFound
;
4010 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4015 desc
.buflen
= mdrcnt
;
4018 * Don't return data but need to get correct length
4019 * init_package will return wrong size if buflen=0
4021 desc
.buflen
= getlen(desc
.format
);
4022 desc
.base
= tmpdata
= (char *)SMB_MALLOC( desc
.buflen
);
4024 if (init_package(&desc
,1,0)) {
4025 fill_printdest_info(conn
,snum
,uLevel
,&desc
);
4027 *rdata_len
= desc
.usedlen
;
4031 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4035 SSVALS(*rparam
,0,desc
.errcode
);
4037 SSVAL(*rparam
,4,desc
.neededlen
);
4039 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc
.errcode
));
4045 static bool api_WPrintDestEnum(connection_struct
*conn
, uint16 vuid
,
4046 char *param
, int tpscnt
,
4047 char *data
, int tdscnt
,
4048 int mdrcnt
,int mprcnt
,
4049 char **rdata
,char **rparam
,
4050 int *rdata_len
,int *rparam_len
)
4052 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4053 char *str2
= skip_string(param
,tpscnt
,str1
);
4054 char *p
= skip_string(param
,tpscnt
,str2
);
4058 struct pack_desc desc
;
4059 int services
= lp_numservices();
4061 if (!str1
|| !str2
|| !p
) {
4065 memset((char *)&desc
,'\0',sizeof(desc
));
4067 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4069 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel
));
4071 /* check it's a supported varient */
4072 if (strcmp(str1
,"WrLeh") != 0) {
4075 if (!check_printdest_info(&desc
,uLevel
,str2
)) {
4080 for (i
= 0; i
< services
; i
++) {
4081 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
)) {
4087 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4094 desc
.buflen
= mdrcnt
;
4095 if (init_package(&desc
,queuecnt
,0)) {
4098 for (i
= 0; i
< services
; i
++) {
4099 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
)) {
4100 fill_printdest_info(conn
,i
,uLevel
,&desc
);
4102 if (desc
.errcode
== NERR_Success
) {
4109 *rdata_len
= desc
.usedlen
;
4112 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4116 SSVALS(*rparam
,0,desc
.errcode
);
4118 SSVAL(*rparam
,4,succnt
);
4119 SSVAL(*rparam
,6,queuecnt
);
4121 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc
.errcode
));
4126 static bool api_WPrintDriverEnum(connection_struct
*conn
, uint16 vuid
,
4127 char *param
, int tpscnt
,
4128 char *data
, int tdscnt
,
4129 int mdrcnt
,int mprcnt
,
4130 char **rdata
,char **rparam
,
4131 int *rdata_len
,int *rparam_len
)
4133 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4134 char *str2
= skip_string(param
,tpscnt
,str1
);
4135 char *p
= skip_string(param
,tpscnt
,str2
);
4138 struct pack_desc desc
;
4140 if (!str1
|| !str2
|| !p
) {
4144 memset((char *)&desc
,'\0',sizeof(desc
));
4146 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4148 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel
));
4150 /* check it's a supported varient */
4151 if (strcmp(str1
,"WrLeh") != 0) {
4154 if (uLevel
!= 0 || strcmp(str2
,"B41") != 0) {
4159 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4165 desc
.buflen
= mdrcnt
;
4166 if (init_package(&desc
,1,0)) {
4167 PACKS(&desc
,"B41","NULL");
4170 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
4172 *rdata_len
= desc
.usedlen
;
4175 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4179 SSVALS(*rparam
,0,desc
.errcode
);
4181 SSVAL(*rparam
,4,succnt
);
4184 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc
.errcode
));
4189 static bool api_WPrintQProcEnum(connection_struct
*conn
, uint16 vuid
,
4190 char *param
, int tpscnt
,
4191 char *data
, int tdscnt
,
4192 int mdrcnt
,int mprcnt
,
4193 char **rdata
,char **rparam
,
4194 int *rdata_len
,int *rparam_len
)
4196 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4197 char *str2
= skip_string(param
,tpscnt
,str1
);
4198 char *p
= skip_string(param
,tpscnt
,str2
);
4201 struct pack_desc desc
;
4203 if (!str1
|| !str2
|| !p
) {
4206 memset((char *)&desc
,'\0',sizeof(desc
));
4208 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4210 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel
));
4212 /* check it's a supported varient */
4213 if (strcmp(str1
,"WrLeh") != 0) {
4216 if (uLevel
!= 0 || strcmp(str2
,"B13") != 0) {
4221 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4227 desc
.buflen
= mdrcnt
;
4229 if (init_package(&desc
,1,0)) {
4230 PACKS(&desc
,"B13","lpd");
4233 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
4235 *rdata_len
= desc
.usedlen
;
4238 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4242 SSVALS(*rparam
,0,desc
.errcode
);
4244 SSVAL(*rparam
,4,succnt
);
4247 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc
.errcode
));
4252 static bool api_WPrintPortEnum(connection_struct
*conn
, uint16 vuid
,
4253 char *param
, int tpscnt
,
4254 char *data
, int tdscnt
,
4255 int mdrcnt
,int mprcnt
,
4256 char **rdata
,char **rparam
,
4257 int *rdata_len
,int *rparam_len
)
4259 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4260 char *str2
= skip_string(param
,tpscnt
,str1
);
4261 char *p
= skip_string(param
,tpscnt
,str2
);
4264 struct pack_desc desc
;
4266 if (!str1
|| !str2
|| !p
) {
4270 memset((char *)&desc
,'\0',sizeof(desc
));
4272 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4274 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel
));
4276 /* check it's a supported varient */
4277 if (strcmp(str1
,"WrLeh") != 0) {
4280 if (uLevel
!= 0 || strcmp(str2
,"B9") != 0) {
4285 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4290 memset((char *)&desc
,'\0',sizeof(desc
));
4292 desc
.buflen
= mdrcnt
;
4294 if (init_package(&desc
,1,0)) {
4295 PACKS(&desc
,"B13","lp0");
4298 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
4300 *rdata_len
= desc
.usedlen
;
4303 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4307 SSVALS(*rparam
,0,desc
.errcode
);
4309 SSVAL(*rparam
,4,succnt
);
4312 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc
.errcode
));
4317 /****************************************************************************
4319 ****************************************************************************/
4321 static bool api_RNetSessionEnum(connection_struct
*conn
, uint16 vuid
,
4322 char *param
, int tpscnt
,
4323 char *data
, int tdscnt
,
4324 int mdrcnt
,int mprcnt
,
4325 char **rdata
,char **rparam
,
4326 int *rdata_len
,int *rparam_len
)
4329 char *str1
= get_safe_str_ptr(param
,tpscnt
,param
,2);
4330 char *str2
= skip_string(param
,tpscnt
,str1
);
4331 char *p
= skip_string(param
,tpscnt
,str2
);
4333 struct pack_desc desc
;
4334 struct sessionid
*session_list
;
4335 int i
, num_sessions
;
4337 if (!str1
|| !str2
|| !p
) {
4341 memset((char *)&desc
,'\0',sizeof(desc
));
4343 uLevel
= get_safe_SVAL(param
,tpscnt
,p
,0,-1);
4345 DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel
));
4346 DEBUG(7,("RNetSessionEnum req string=%s\n",str1
));
4347 DEBUG(7,("RNetSessionEnum ret string=%s\n",str2
));
4349 /* check it's a supported varient */
4350 if (strcmp(str1
,RAP_NetSessionEnum_REQ
) != 0) {
4353 if (uLevel
!= 2 || strcmp(str2
,RAP_SESSION_INFO_L2
) != 0) {
4357 num_sessions
= list_sessions(talloc_tos(), &session_list
);
4360 *rdata
= smb_realloc_limit(*rdata
,mdrcnt
);
4365 memset((char *)&desc
,'\0',sizeof(desc
));
4367 desc
.buflen
= mdrcnt
;
4369 if (!init_package(&desc
,num_sessions
,0)) {
4373 for(i
=0; i
<num_sessions
; i
++) {
4374 PACKS(&desc
, "z", session_list
[i
].remote_machine
);
4375 PACKS(&desc
, "z", session_list
[i
].username
);
4376 PACKI(&desc
, "W", 1); /* num conns */
4377 PACKI(&desc
, "W", 0); /* num opens */
4378 PACKI(&desc
, "W", 1); /* num users */
4379 PACKI(&desc
, "D", 0); /* session time */
4380 PACKI(&desc
, "D", 0); /* idle time */
4381 PACKI(&desc
, "D", 0); /* flags */
4382 PACKS(&desc
, "z", "Unknown Client"); /* client type string */
4385 *rdata_len
= desc
.usedlen
;
4388 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4392 SSVALS(*rparam
,0,desc
.errcode
);
4393 SSVAL(*rparam
,2,0); /* converter */
4394 SSVAL(*rparam
,4,num_sessions
); /* count */
4396 DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc
.errcode
));
4402 /****************************************************************************
4403 The buffer was too small.
4404 ****************************************************************************/
4406 static bool api_TooSmall(connection_struct
*conn
,uint16 vuid
, char *param
, char *data
,
4407 int mdrcnt
, int mprcnt
,
4408 char **rdata
, char **rparam
,
4409 int *rdata_len
, int *rparam_len
)
4411 *rparam_len
= MIN(*rparam_len
,mprcnt
);
4412 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4419 SSVAL(*rparam
,0,NERR_BufTooSmall
);
4421 DEBUG(3,("Supplied buffer too small in API command\n"));
4426 /****************************************************************************
4427 The request is not supported.
4428 ****************************************************************************/
4430 static bool api_Unsupported(connection_struct
*conn
, uint16 vuid
,
4431 char *param
, int tpscnt
,
4432 char *data
, int tdscnt
,
4433 int mdrcnt
, int mprcnt
,
4434 char **rdata
, char **rparam
,
4435 int *rdata_len
, int *rparam_len
)
4438 *rparam
= smb_realloc_limit(*rparam
,*rparam_len
);
4445 SSVAL(*rparam
,0,NERR_notsupported
);
4446 SSVAL(*rparam
,2,0); /* converter word */
4448 DEBUG(3,("Unsupported API command\n"));
4453 static const struct {
4456 bool (*fn
)(connection_struct
*, uint16
,
4459 int,int,char **,char **,int *,int *);
4460 bool auth_user
; /* Deny anonymous access? */
4461 } api_commands
[] = {
4462 {"RNetShareEnum", RAP_WshareEnum
, api_RNetShareEnum
, True
},
4463 {"RNetShareGetInfo", RAP_WshareGetInfo
, api_RNetShareGetInfo
},
4464 {"RNetShareAdd", RAP_WshareAdd
, api_RNetShareAdd
},
4465 {"RNetSessionEnum", RAP_WsessionEnum
, api_RNetSessionEnum
, True
},
4466 {"RNetServerGetInfo", RAP_WserverGetInfo
, api_RNetServerGetInfo
},
4467 {"RNetGroupEnum", RAP_WGroupEnum
, api_RNetGroupEnum
, True
},
4468 {"RNetGroupGetUsers", RAP_WGroupGetUsers
, api_RNetGroupGetUsers
, True
},
4469 {"RNetUserEnum", RAP_WUserEnum
, api_RNetUserEnum
, True
},
4470 {"RNetUserGetInfo", RAP_WUserGetInfo
, api_RNetUserGetInfo
},
4471 {"NetUserGetGroups", RAP_WUserGetGroups
, api_NetUserGetGroups
},
4472 {"NetWkstaGetInfo", RAP_WWkstaGetInfo
, api_NetWkstaGetInfo
},
4473 {"DosPrintQEnum", RAP_WPrintQEnum
, api_DosPrintQEnum
, True
},
4474 {"DosPrintQGetInfo", RAP_WPrintQGetInfo
, api_DosPrintQGetInfo
},
4475 {"WPrintQueuePause", RAP_WPrintQPause
, api_WPrintQueueCtrl
},
4476 {"WPrintQueueResume", RAP_WPrintQContinue
, api_WPrintQueueCtrl
},
4477 {"WPrintJobEnumerate",RAP_WPrintJobEnum
, api_WPrintJobEnumerate
},
4478 {"WPrintJobGetInfo", RAP_WPrintJobGetInfo
, api_WPrintJobGetInfo
},
4479 {"RDosPrintJobDel", RAP_WPrintJobDel
, api_RDosPrintJobDel
},
4480 {"RDosPrintJobPause", RAP_WPrintJobPause
, api_RDosPrintJobDel
},
4481 {"RDosPrintJobResume",RAP_WPrintJobContinue
, api_RDosPrintJobDel
},
4482 {"WPrintDestEnum", RAP_WPrintDestEnum
, api_WPrintDestEnum
},
4483 {"WPrintDestGetInfo", RAP_WPrintDestGetInfo
, api_WPrintDestGetInfo
},
4484 {"NetRemoteTOD", RAP_NetRemoteTOD
, api_NetRemoteTOD
},
4485 {"WPrintQueuePurge", RAP_WPrintQPurge
, api_WPrintQueueCtrl
},
4486 {"NetServerEnum", RAP_NetServerEnum2
, api_RNetServerEnum
}, /* anon OK */
4487 {"WAccessGetUserPerms",RAP_WAccessGetUserPerms
,api_WAccessGetUserPerms
},
4488 {"SetUserPassword", RAP_WUserPasswordSet2
, api_SetUserPassword
},
4489 {"WWkstaUserLogon", RAP_WWkstaUserLogon
, api_WWkstaUserLogon
},
4490 {"PrintJobInfo", RAP_WPrintJobSetInfo
, api_PrintJobInfo
},
4491 {"WPrintDriverEnum", RAP_WPrintDriverEnum
, api_WPrintDriverEnum
},
4492 {"WPrintQProcEnum", RAP_WPrintQProcessorEnum
,api_WPrintQProcEnum
},
4493 {"WPrintPortEnum", RAP_WPrintPortEnum
, api_WPrintPortEnum
},
4494 {"SamOEMChangePassword",RAP_SamOEMChgPasswordUser2_P
,api_SamOEMChangePassword
}, /* anon OK */
4495 {NULL
, -1, api_Unsupported
}
4496 /* The following RAP calls are not implemented by Samba:
4498 RAP_WFileEnum2 - anon not OK
4503 /****************************************************************************
4504 Handle remote api calls.
4505 ****************************************************************************/
4507 void api_reply(connection_struct
*conn
, uint16 vuid
,
4508 struct smb_request
*req
,
4509 char *data
, char *params
,
4510 int tdscnt
, int tpscnt
,
4511 int mdrcnt
, int mprcnt
)
4515 char *rparam
= NULL
;
4516 const char *name1
= NULL
;
4517 const char *name2
= NULL
;
4524 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
4525 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4530 reply_nterror(req
, NT_STATUS_INVALID_PARAMETER
);
4533 api_command
= SVAL(params
,0);
4534 /* Is there a string at position params+2 ? */
4535 if (skip_string(params
,tpscnt
,params
+2)) {
4540 name2
= skip_string(params
,tpscnt
,params
+2);
4545 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
4549 tdscnt
,tpscnt
,mdrcnt
,mprcnt
));
4551 for (i
=0;api_commands
[i
].name
;i
++) {
4552 if (api_commands
[i
].id
== api_command
&& api_commands
[i
].fn
) {
4553 DEBUG(3,("Doing %s\n",api_commands
[i
].name
));
4558 /* Check whether this api call can be done anonymously */
4560 if (api_commands
[i
].auth_user
&& lp_restrict_anonymous()) {
4561 user_struct
*user
= get_valid_user_struct(vuid
);
4563 if (!user
|| user
->guest
) {
4564 reply_nterror(req
, NT_STATUS_ACCESS_DENIED
);
4569 rdata
= (char *)SMB_MALLOC(1024);
4571 memset(rdata
,'\0',1024);
4574 rparam
= (char *)SMB_MALLOC(1024);
4576 memset(rparam
,'\0',1024);
4579 if(!rdata
|| !rparam
) {
4580 DEBUG(0,("api_reply: malloc fail !\n"));
4583 reply_nterror(req
, NT_STATUS_NO_MEMORY
);
4587 reply
= api_commands
[i
].fn(conn
,
4589 params
,tpscnt
, /* params + length */
4590 data
,tdscnt
, /* data + length */
4592 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
4595 if (rdata_len
> mdrcnt
|| rparam_len
> mprcnt
) {
4596 reply
= api_TooSmall(conn
,vuid
,params
,data
,mdrcnt
,mprcnt
,
4597 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
4600 /* if we get False back then it's actually unsupported */
4602 reply
= api_Unsupported(conn
,vuid
,params
,tpscnt
,data
,tdscnt
,mdrcnt
,mprcnt
,
4603 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
4606 /* If api_Unsupported returns false we can't return anything. */
4608 send_trans_reply(conn
, req
, rparam
, rparam_len
,
4609 rdata
, rdata_len
, False
);