2 Unix SMB/CIFS implementation.
3 Inter-process communication and named pipe handling
4 Copyright (C) Andrew Tridgell 1992-1998
7 Copyright (C) John H Terpstra 1995-1998
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 This file handles the named pipe and mailslot calls
25 in the SMBtrans protocol
35 extern fstring local_machine
;
37 #define NERR_Success 0
38 #define NERR_badpass 86
39 #define NERR_notsupported 50
41 #define NERR_BASE (2100)
42 #define NERR_BufTooSmall (NERR_BASE+23)
43 #define NERR_JobNotFound (NERR_BASE+51)
44 #define NERR_DestNotFound (NERR_BASE+52)
46 #define ACCESS_READ 0x01
47 #define ACCESS_WRITE 0x02
48 #define ACCESS_CREATE 0x04
50 #define SHPWLEN 8 /* share password length */
52 static BOOL
api_Unsupported(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
53 int mdrcnt
,int mprcnt
,
54 char **rdata
,char **rparam
,
55 int *rdata_len
,int *rparam_len
);
56 static BOOL
api_TooSmall(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
57 int mdrcnt
,int mprcnt
,
58 char **rdata
,char **rparam
,
59 int *rdata_len
,int *rparam_len
);
62 static int CopyExpanded(connection_struct
*conn
,
63 int snum
, char** dst
, char* src
, int* n
)
68 if (!src
|| !dst
|| !n
|| !(*dst
)) return(0);
70 StrnCpy(buf
,src
,sizeof(buf
)/2);
71 pstring_sub(buf
,"%S",lp_servicename(snum
));
72 standard_sub_conn(conn
,buf
,sizeof(buf
));
73 l
= push_ascii(*dst
,buf
,*n
, STR_TERMINATE
);
79 static int CopyAndAdvance(char** dst
, char* src
, int* n
)
82 if (!src
|| !dst
|| !n
|| !(*dst
)) return(0);
83 l
= push_ascii(*dst
,src
,*n
, STR_TERMINATE
);
89 static int StrlenExpanded(connection_struct
*conn
, int snum
, char* s
)
93 StrnCpy(buf
,s
,sizeof(buf
)/2);
94 pstring_sub(buf
,"%S",lp_servicename(snum
));
95 standard_sub_conn(conn
,buf
,sizeof(buf
));
96 return strlen(buf
) + 1;
99 static char* Expand(connection_struct
*conn
, int snum
, char* s
)
102 if (!s
) return(NULL
);
103 StrnCpy(buf
,s
,sizeof(buf
)/2);
104 pstring_sub(buf
,"%S",lp_servicename(snum
));
105 standard_sub_conn(conn
,buf
,sizeof(buf
));
109 /*******************************************************************
110 check a API string for validity when we only need to check the prefix
111 ******************************************************************/
112 static BOOL
prefix_ok(const char *str
, const char *prefix
)
114 return(strncmp(str
,prefix
,strlen(prefix
)) == 0);
118 const char* format
; /* formatstring for structure */
119 const char* subformat
; /* subformat for structure */
120 char* base
; /* baseaddress of buffer */
121 int buflen
; /* remaining size for fixed part; on init: length of base */
122 int subcount
; /* count of substructures */
123 char* structbuf
; /* pointer into buffer for remaining fixed part */
124 int stringlen
; /* remaining size for variable part */
125 char* stringbuf
; /* pointer into buffer for remaining variable part */
126 int neededlen
; /* total needed size */
127 int usedlen
; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
128 const char* curpos
; /* current position; pointer into format or subformat */
132 static int get_counter(const char** p
)
135 if (!p
|| !(*p
)) return(1);
136 if (!isdigit((int)**p
)) return 1;
140 n
= 10 * n
+ (i
- '0');
147 static int getlen(const char* p
)
153 case 'W': /* word (2 byte) */
156 case 'K': /* status word? (2 byte) */
159 case 'N': /* count of substructures (word) at end */
162 case 'D': /* double word (4 byte) */
163 case 'z': /* offset to zero terminated string (4 byte) */
164 case 'l': /* offset to user data (4 byte) */
167 case 'b': /* offset to data (with counter) (4 byte) */
171 case 'B': /* byte (with optional counter) */
172 n
+= get_counter(&p
);
179 static BOOL
init_package(struct pack_desc
* p
, int count
, int subcount
)
184 if (!p
->format
|| !p
->base
) return(False
);
186 i
= count
* getlen(p
->format
);
187 if (p
->subformat
) i
+= subcount
* getlen(p
->subformat
);
188 p
->structbuf
= p
->base
;
192 p
->curpos
= p
->format
;
198 * This is the old error code we used. Aparently
199 * WinNT/2k systems return ERRbuftoosmall (2123) and
200 * OS/2 needs this. I'm leaving this here so we can revert
203 p
->errcode
= ERRmoredata
;
205 p
->errcode
= ERRbuftoosmall
;
209 p
->errcode
= NERR_Success
;
212 p
->stringbuf
= p
->base
+ i
;
214 return(p
->errcode
== NERR_Success
);
217 static int package(struct pack_desc
* p
, ...)
220 int needed
=0, stringneeded
;
221 const char* str
=NULL
;
222 int is_string
=0, stringused
;
229 p
->curpos
= p
->format
;
231 p
->curpos
= p
->subformat
;
236 str
= va_arg(args
,char*);
237 SMB_ASSERT(strncmp(str
,p
->curpos
,strlen(str
)) == 0);
246 switch( *p
->curpos
++ ) {
247 case 'W': /* word (2 byte) */
249 temp
= va_arg(args
,int);
250 if (p
->buflen
>= needed
) SSVAL(p
->structbuf
,0,temp
);
252 case 'K': /* status word? (2 byte) */
254 temp
= va_arg(args
,int);
255 if (p
->buflen
>= needed
) SSVAL(p
->structbuf
,0,temp
);
257 case 'N': /* count of substructures (word) at end */
259 p
->subcount
= va_arg(args
,int);
260 if (p
->buflen
>= needed
) SSVAL(p
->structbuf
,0,p
->subcount
);
262 case 'D': /* double word (4 byte) */
264 temp
= va_arg(args
,int);
265 if (p
->buflen
>= needed
) SIVAL(p
->structbuf
,0,temp
);
267 case 'B': /* byte (with optional counter) */
268 needed
= get_counter(&p
->curpos
);
270 char *s
= va_arg(args
,char*);
271 if (p
->buflen
>= needed
) StrnCpy(p
->structbuf
,s
?s
:"",needed
-1);
274 case 'z': /* offset to zero terminated string (4 byte) */
275 str
= va_arg(args
,char*);
276 stringneeded
= (str
? strlen(str
)+1 : 0);
279 case 'l': /* offset to user data (4 byte) */
280 str
= va_arg(args
,char*);
281 stringneeded
= va_arg(args
,int);
284 case 'b': /* offset to data (with counter) (4 byte) */
285 str
= va_arg(args
,char*);
286 stringneeded
= get_counter(&p
->curpos
);
291 if (stringneeded
>= 0) {
293 if (p
->buflen
>= needed
) {
294 stringused
= stringneeded
;
295 if (stringused
> p
->stringlen
) {
296 stringused
= (is_string
? p
->stringlen
: 0);
297 if (p
->errcode
== NERR_Success
) p
->errcode
= ERRmoredata
;
300 SIVAL(p
->structbuf
,0,0);
302 SIVAL(p
->structbuf
,0,PTR_DIFF(p
->stringbuf
,p
->base
));
303 memcpy(p
->stringbuf
,str
?str
:"",stringused
);
304 if (is_string
) p
->stringbuf
[stringused
-1] = '\0';
305 p
->stringbuf
+= stringused
;
306 p
->stringlen
-= stringused
;
307 p
->usedlen
+= stringused
;
310 p
->neededlen
+= stringneeded
;
312 p
->neededlen
+= needed
;
313 if (p
->buflen
>= needed
) {
314 p
->structbuf
+= needed
;
316 p
->usedlen
+= needed
;
319 if (p
->errcode
== NERR_Success
) p
->errcode
= ERRmoredata
;
325 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
326 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
328 #define PACK(desc,t,v) package(desc,v)
329 #define PACKl(desc,t,v,l) package(desc,v,l)
332 static void PACKI(struct pack_desc
* desc
, const char *t
,int v
)
337 static void PACKS(struct pack_desc
* desc
,const char *t
,const char *v
)
343 /****************************************************************************
345 ****************************************************************************/
346 static void PackDriverData(struct pack_desc
* desc
)
348 char drivdata
[4+4+32];
349 SIVAL(drivdata
,0,sizeof drivdata
); /* cb */
350 SIVAL(drivdata
,4,1000); /* lVersion */
351 memset(drivdata
+8,0,32); /* szDeviceName */
352 push_ascii(drivdata
+8,"NULL",-1, STR_TERMINATE
);
353 PACKl(desc
,"l",drivdata
,sizeof drivdata
); /* pDriverData */
356 static int check_printq_info(struct pack_desc
* desc
,
357 int uLevel
, char *id1
, char *id2
)
359 desc
->subformat
= NULL
;
362 desc
->format
= "B13";
365 desc
->format
= "B13BWWWzzzzzWW";
368 desc
->format
= "B13BWWWzzzzzWN";
369 desc
->subformat
= "WB21BB16B10zWWzDDz";
372 desc
->format
= "zWWWWzzzzWWzzl";
375 desc
->format
= "zWWWWzzzzWNzzl";
376 desc
->subformat
= "WWzWWDDzz";
385 desc
->format
= "WzzzzzzzzN";
386 desc
->subformat
= "z";
388 default: return False
;
390 if (strcmp(desc
->format
,id1
) != 0) return False
;
391 if (desc
->subformat
&& strcmp(desc
->subformat
,id2
) != 0) return False
;
396 #define RAP_JOB_STATUS_QUEUED 0
397 #define RAP_JOB_STATUS_PAUSED 1
398 #define RAP_JOB_STATUS_SPOOLING 2
399 #define RAP_JOB_STATUS_PRINTING 3
400 #define RAP_JOB_STATUS_PRINTED 4
402 #define RAP_QUEUE_STATUS_PAUSED 1
403 #define RAP_QUEUE_STATUS_ERROR 2
405 /* turn a print job status into a on the wire status
407 static int printj_status(int v
)
411 return RAP_JOB_STATUS_QUEUED
;
413 return RAP_JOB_STATUS_PAUSED
;
415 return RAP_JOB_STATUS_SPOOLING
;
417 return RAP_JOB_STATUS_PRINTING
;
422 /* turn a print queue status into a on the wire status
424 static int printq_status(int v
)
430 return RAP_QUEUE_STATUS_PAUSED
;
432 return RAP_QUEUE_STATUS_ERROR
;
435 static void fill_printjob_info(connection_struct
*conn
, int snum
, int uLevel
,
436 struct pack_desc
* desc
,
437 print_queue_struct
* queue
, int n
)
439 time_t t
= queue
->time
;
441 /* the client expects localtime */
444 PACKI(desc
,"W",pjobid_to_rap(lp_const_servicename(snum
),queue
->job
)); /* uJobId */
446 PACKS(desc
,"B21",queue
->fs_user
); /* szUserName */
447 PACKS(desc
,"B",""); /* pad */
448 PACKS(desc
,"B16",""); /* szNotifyName */
449 PACKS(desc
,"B10","PM_Q_RAW"); /* szDataType */
450 PACKS(desc
,"z",""); /* pszParms */
451 PACKI(desc
,"W",n
+1); /* uPosition */
452 PACKI(desc
,"W",printj_status(queue
->status
)); /* fsStatus */
453 PACKS(desc
,"z",""); /* pszStatus */
454 PACKI(desc
,"D",t
); /* ulSubmitted */
455 PACKI(desc
,"D",queue
->size
); /* ulSize */
456 PACKS(desc
,"z",queue
->fs_file
); /* pszComment */
458 if (uLevel
== 2 || uLevel
== 3 || uLevel
== 4) {
459 PACKI(desc
,"W",queue
->priority
); /* uPriority */
460 PACKS(desc
,"z",queue
->fs_user
); /* pszUserName */
461 PACKI(desc
,"W",n
+1); /* uPosition */
462 PACKI(desc
,"W",printj_status(queue
->status
)); /* fsStatus */
463 PACKI(desc
,"D",t
); /* ulSubmitted */
464 PACKI(desc
,"D",queue
->size
); /* ulSize */
465 PACKS(desc
,"z","Samba"); /* pszComment */
466 PACKS(desc
,"z",queue
->fs_file
); /* pszDocument */
468 PACKS(desc
,"z",""); /* pszNotifyName */
469 PACKS(desc
,"z","PM_Q_RAW"); /* pszDataType */
470 PACKS(desc
,"z",""); /* pszParms */
471 PACKS(desc
,"z",""); /* pszStatus */
472 PACKS(desc
,"z",SERVICE(snum
)); /* pszQueue */
473 PACKS(desc
,"z","lpd"); /* pszQProcName */
474 PACKS(desc
,"z",""); /* pszQProcParms */
475 PACKS(desc
,"z","NULL"); /* pszDriverName */
476 PackDriverData(desc
); /* pDriverData */
477 PACKS(desc
,"z",""); /* pszPrinterName */
478 } else if (uLevel
== 4) { /* OS2 */
479 PACKS(desc
,"z",""); /* pszSpoolFileName */
480 PACKS(desc
,"z",""); /* pszPortName */
481 PACKS(desc
,"z",""); /* pszStatus */
482 PACKI(desc
,"D",0); /* ulPagesSpooled */
483 PACKI(desc
,"D",0); /* ulPagesSent */
484 PACKI(desc
,"D",0); /* ulPagesPrinted */
485 PACKI(desc
,"D",0); /* ulTimePrinted */
486 PACKI(desc
,"D",0); /* ulExtendJobStatus */
487 PACKI(desc
,"D",0); /* ulStartPage */
488 PACKI(desc
,"D",0); /* ulEndPage */
493 /********************************************************************
494 Return a driver name given an snum.
495 Returns True if from tdb, False otherwise.
496 ********************************************************************/
498 static BOOL
get_driver_name(int snum
, pstring drivername
)
500 NT_PRINTER_INFO_LEVEL
*info
= NULL
;
503 get_a_printer (NULL
, &info
, 2, lp_servicename(snum
));
505 pstrcpy( drivername
, info
->info_2
->drivername
);
507 free_a_printer(&info
, 2);
513 /********************************************************************
514 Respond to the DosPrintQInfo command with a level of 52
515 This is used to get printer driver information for Win9x clients
516 ********************************************************************/
517 static void fill_printq_info_52(connection_struct
*conn
, int snum
,
518 struct pack_desc
* desc
, int count
)
522 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
523 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
527 if ( !W_ERROR_IS_OK(get_a_printer( NULL
, &printer
, 2, lp_servicename(snum
))) ) {
528 DEBUG(3,("fill_printq_info_52: Failed to lookup printer [%s]\n",
529 lp_servicename(snum
)));
533 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
,
536 DEBUG(3,("fill_printq_info_52: Failed to lookup driver [%s]\n",
537 printer
->info_2
->drivername
));
541 trim_string(driver
.info_3
->driverpath
, "\\print$\\WIN40\\0\\", 0);
542 trim_string(driver
.info_3
->datafile
, "\\print$\\WIN40\\0\\", 0);
543 trim_string(driver
.info_3
->helpfile
, "\\print$\\WIN40\\0\\", 0);
545 PACKI(desc
, "W", 0x0400); /* don't know */
546 PACKS(desc
, "z", driver
.info_3
->name
); /* long printer name */
547 PACKS(desc
, "z", driver
.info_3
->driverpath
); /* Driverfile Name */
548 PACKS(desc
, "z", driver
.info_3
->datafile
); /* Datafile name */
549 PACKS(desc
, "z", driver
.info_3
->monitorname
); /* language monitor */
551 fstrcpy(location
, "\\\\%L\\print$\\WIN40\\0");
552 standard_sub_basic( "", location
, sizeof(location
)-1 );
553 PACKS(desc
,"z", location
); /* share to retrieve files */
555 PACKS(desc
,"z", driver
.info_3
->defaultdatatype
); /* default data type */
556 PACKS(desc
,"z", driver
.info_3
->helpfile
); /* helpfile name */
557 PACKS(desc
,"z", driver
.info_3
->driverpath
); /* driver name */
559 DEBUG(3,("Printer Driver Name: %s:\n",driver
.info_3
->name
));
560 DEBUG(3,("Driver: %s:\n",driver
.info_3
->driverpath
));
561 DEBUG(3,("Data File: %s:\n",driver
.info_3
->datafile
));
562 DEBUG(3,("Language Monitor: %s:\n",driver
.info_3
->monitorname
));
563 DEBUG(3,("Driver Location: %s:\n",location
));
564 DEBUG(3,("Data Type: %s:\n",driver
.info_3
->defaultdatatype
));
565 DEBUG(3,("Help File: %s:\n",driver
.info_3
->helpfile
));
566 PACKI(desc
,"N",count
); /* number of files to copy */
568 for ( i
=0; i
<count
&& driver
.info_3
->dependentfiles
&& *driver
.info_3
->dependentfiles
[i
]; i
++)
570 trim_string(driver
.info_3
->dependentfiles
[i
], "\\print$\\WIN40\\0\\", 0);
571 PACKS(desc
,"z",driver
.info_3
->dependentfiles
[i
]); /* driver files to copy */
572 DEBUG(3,("Dependent File: %s:\n",driver
.info_3
->dependentfiles
[i
]));
577 DEBUG(3,("fill_printq_info_52: file count specified by client [%d] != number of dependent files [%i]\n",
580 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n", SERVICE(snum
),i
));
582 desc
->errcode
=NERR_Success
;
586 DEBUG(3,("fill_printq_info: Can't supply driver files\n"));
587 desc
->errcode
=NERR_notsupported
;
591 free_a_printer( &printer
, 2 );
594 free_a_printer_driver( driver
, 3 );
598 static void fill_printq_info(connection_struct
*conn
, int snum
, int uLevel
,
599 struct pack_desc
* desc
,
600 int count
, print_queue_struct
* queue
,
601 print_status_struct
* status
)
606 PACKS(desc
,"B13",SERVICE(snum
));
611 PACKS(desc
,"z",Expand(conn
,snum
,SERVICE(snum
)));
614 PACKI(desc
,"K",printq_status(status
->status
));
618 if (uLevel
== 1 || uLevel
== 2) {
619 PACKS(desc
,"B",""); /* alignment */
620 PACKI(desc
,"W",5); /* priority */
621 PACKI(desc
,"W",0); /* start time */
622 PACKI(desc
,"W",0); /* until time */
623 PACKS(desc
,"z",""); /* pSepFile */
624 PACKS(desc
,"z","lpd"); /* pPrProc */
625 PACKS(desc
,"z",SERVICE(snum
)); /* pDestinations */
626 PACKS(desc
,"z",""); /* pParms */
628 PACKS(desc
,"z","UNKNOWN PRINTER");
629 PACKI(desc
,"W",LPSTAT_ERROR
);
631 else if (!status
|| !status
->message
[0]) {
632 PACKS(desc
,"z",Expand(conn
,snum
,lp_comment(snum
)));
633 PACKI(desc
,"W",LPSTAT_OK
); /* status */
635 PACKS(desc
,"z",status
->message
);
636 PACKI(desc
,"W",printq_status(status
->status
)); /* status */
638 PACKI(desc
,(uLevel
== 1 ? "W" : "N"),count
);
641 if (uLevel
== 3 || uLevel
== 4) {
644 PACKI(desc
,"W",5); /* uPriority */
645 PACKI(desc
,"W",0); /* uStarttime */
646 PACKI(desc
,"W",0); /* uUntiltime */
647 PACKI(desc
,"W",5); /* pad1 */
648 PACKS(desc
,"z",""); /* pszSepFile */
649 PACKS(desc
,"z","WinPrint"); /* pszPrProc */
650 PACKS(desc
,"z",NULL
); /* pszParms */
651 PACKS(desc
,"z",NULL
); /* pszComment - don't ask.... JRA */
652 /* "don't ask" that it's done this way to fix corrupted
653 Win9X/ME printer comments. */
655 PACKI(desc
,"W",LPSTAT_OK
); /* fsStatus */
657 PACKI(desc
,"W",printq_status(status
->status
)); /* fsStatus */
659 PACKI(desc
,(uLevel
== 3 ? "W" : "N"),count
); /* cJobs */
660 PACKS(desc
,"z",SERVICE(snum
)); /* pszPrinters */
661 get_driver_name(snum
,drivername
);
662 PACKS(desc
,"z",drivername
); /* pszDriverName */
663 PackDriverData(desc
); /* pDriverData */
666 if (uLevel
== 2 || uLevel
== 4) {
668 for (i
=0;i
<count
;i
++)
669 fill_printjob_info(conn
,snum
,uLevel
== 2 ? 1 : 2,desc
,&queue
[i
],i
);
673 fill_printq_info_52( conn
, snum
, desc
, count
);
676 /* This function returns the number of files for a given driver */
677 static int get_printerdrivernumber(int snum
)
680 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
681 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
685 if ( !W_ERROR_IS_OK(get_a_printer( NULL
, &printer
, 2, lp_servicename(snum
))) ) {
686 DEBUG(3,("get_printerdrivernumber: Failed to lookup printer [%s]\n",
687 lp_servicename(snum
)));
691 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
,
694 DEBUG(3,("get_printerdrivernumber: Failed to lookup driver [%s]\n",
695 printer
->info_2
->drivername
));
699 /* count the number of files */
700 while ( driver
.info_3
->dependentfiles
&& *driver
.info_3
->dependentfiles
[result
] )
705 free_a_printer( &printer
, 2 );
708 free_a_printer_driver( driver
, 3 );
713 static BOOL
api_DosPrintQGetInfo(connection_struct
*conn
,
714 uint16 vuid
, char *param
,char *data
,
715 int mdrcnt
,int mprcnt
,
716 char **rdata
,char **rparam
,
717 int *rdata_len
,int *rparam_len
)
719 char *str1
= param
+2;
720 char *str2
= skip_string(str1
,1);
721 char *p
= skip_string(str2
,1);
727 struct pack_desc desc
;
728 print_queue_struct
*queue
=NULL
;
729 print_status_struct status
;
732 memset((char *)&status
,'\0',sizeof(status
));
733 memset((char *)&desc
,'\0',sizeof(desc
));
735 p
= skip_string(p
,1);
739 /* remove any trailing username */
740 if ((p
= strchr_m(QueueName
,'%')))
743 DEBUG(3,("api_DosPrintQGetInfo uLevel=%d name=%s\n",uLevel
,QueueName
));
745 /* check it's a supported varient */
746 if (!prefix_ok(str1
,"zWrLh"))
748 if (!check_printq_info(&desc
,uLevel
,str2
,str3
)) {
750 * Patch from Scott Moomaw <scott@bridgewater.edu>
751 * to return the 'invalid info level' error if an
752 * unknown level was requested.
756 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
757 SSVALS(*rparam
,0,ERRunknownlevel
);
763 snum
= find_service(QueueName
);
764 if ( !(lp_snum_ok(snum
) && lp_print_ok(snum
)) )
768 count
= get_printerdrivernumber(snum
);
769 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count
));
771 count
= print_queue_status(snum
, &queue
,&status
);
775 *rdata
= SMB_REALLOC_LIMIT(*rdata
,mdrcnt
);
777 desc
.buflen
= mdrcnt
;
780 * Don't return data but need to get correct length
781 * init_package will return wrong size if buflen=0
783 desc
.buflen
= getlen(desc
.format
);
784 desc
.base
= tmpdata
= (char *) SMB_MALLOC (desc
.buflen
);
787 if (init_package(&desc
,1,count
)) {
788 desc
.subcount
= count
;
789 fill_printq_info(conn
,snum
,uLevel
,&desc
,count
,queue
,&status
);
792 *rdata_len
= desc
.usedlen
;
795 * We must set the return code to ERRbuftoosmall
796 * in order to support lanman style printing with Win NT/2k
799 if (!mdrcnt
&& lp_disable_spoolss())
800 desc
.errcode
= ERRbuftoosmall
;
802 *rdata_len
= desc
.usedlen
;
804 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
805 SSVALS(*rparam
,0,desc
.errcode
);
807 SSVAL(*rparam
,4,desc
.neededlen
);
809 DEBUG(4,("printqgetinfo: errorcode %d\n",desc
.errcode
));
817 /****************************************************************************
818 View list of all print jobs on all queues.
819 ****************************************************************************/
821 static BOOL
api_DosPrintQEnum(connection_struct
*conn
, uint16 vuid
, char* param
, char* data
,
822 int mdrcnt
, int mprcnt
,
823 char **rdata
, char** rparam
,
824 int *rdata_len
, int *rparam_len
)
826 char *param_format
= param
+2;
827 char *output_format1
= skip_string(param_format
,1);
828 char *p
= skip_string(output_format1
,1);
829 int uLevel
= SVAL(p
,0);
830 char *output_format2
= p
+ 4;
831 int services
= lp_numservices();
833 struct pack_desc desc
;
834 print_queue_struct
**queue
= NULL
;
835 print_status_struct
*status
= NULL
;
836 int* subcntarr
= NULL
;
837 int queuecnt
, subcnt
=0, succnt
=0;
839 memset((char *)&desc
,'\0',sizeof(desc
));
841 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel
));
843 if (!prefix_ok(param_format
,"WrLeh")) return False
;
844 if (!check_printq_info(&desc
,uLevel
,output_format1
,output_format2
)) {
846 * Patch from Scott Moomaw <scott@bridgewater.edu>
847 * to return the 'invalid info level' error if an
848 * unknown level was requested.
852 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
853 SSVALS(*rparam
,0,ERRunknownlevel
);
860 for (i
= 0; i
< services
; i
++)
861 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
))
864 if((queue
= SMB_MALLOC_ARRAY(print_queue_struct
*, queuecnt
)) == NULL
) {
865 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
868 memset(queue
,0,queuecnt
*sizeof(print_queue_struct
*));
869 if((status
= SMB_MALLOC_ARRAY(print_status_struct
,queuecnt
)) == NULL
) {
870 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
873 memset(status
,0,queuecnt
*sizeof(print_status_struct
));
874 if((subcntarr
= SMB_MALLOC_ARRAY(int,queuecnt
)) == NULL
) {
875 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
880 for (i
= 0; i
< services
; i
++)
881 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
)) {
882 subcntarr
[n
] = print_queue_status(i
, &queue
[n
],&status
[n
]);
883 subcnt
+= subcntarr
[n
];
887 if (mdrcnt
> 0) *rdata
= SMB_REALLOC_LIMIT(*rdata
,mdrcnt
);
889 desc
.buflen
= mdrcnt
;
891 if (init_package(&desc
,queuecnt
,subcnt
)) {
894 for (i
= 0; i
< services
; i
++)
895 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
)) {
896 fill_printq_info(conn
,i
,uLevel
,&desc
,subcntarr
[n
],queue
[n
],&status
[n
]);
898 if (desc
.errcode
== NERR_Success
) succnt
= n
;
902 SAFE_FREE(subcntarr
);
904 *rdata_len
= desc
.usedlen
;
906 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
907 SSVALS(*rparam
,0,desc
.errcode
);
909 SSVAL(*rparam
,4,succnt
);
910 SSVAL(*rparam
,6,queuecnt
);
912 for (i
= 0; i
< queuecnt
; i
++) {
913 if (queue
) SAFE_FREE(queue
[i
]);
922 /****************************************************************************
923 get info level for a server list query
924 ****************************************************************************/
925 static BOOL
check_server_info(int uLevel
, char* id
)
929 if (strcmp(id
,"B16") != 0) return False
;
932 if (strcmp(id
,"B16BBDz") != 0) return False
;
940 struct srv_info_struct
950 /*******************************************************************
951 get server info lists from the files saved by nmbd. Return the
953 ******************************************************************/
954 static int get_server_info(uint32 servertype
,
955 struct srv_info_struct
**servers
,
961 BOOL local_list_only
;
964 lines
= file_lines_load(lock_path(SERVER_LIST
), NULL
);
966 DEBUG(4,("Can't open %s - %s\n",lock_path(SERVER_LIST
),strerror(errno
)));
970 /* request for everything is code for request all servers */
971 if (servertype
== SV_TYPE_ALL
)
972 servertype
&= ~(SV_TYPE_DOMAIN_ENUM
|SV_TYPE_LOCAL_LIST_ONLY
);
974 local_list_only
= (servertype
& SV_TYPE_LOCAL_LIST_ONLY
);
976 DEBUG(4,("Servertype search: %8x\n",servertype
));
978 for (i
=0;lines
[i
];i
++) {
980 struct srv_info_struct
*s
;
981 const char *ptr
= lines
[i
];
986 if (count
== alloced
) {
987 struct srv_info_struct
*ts
;
990 ts
= SMB_REALLOC_ARRAY(*servers
,struct srv_info_struct
, alloced
);
992 DEBUG(0,("get_server_info: failed to enlarge servers info struct!\n"));
996 memset((char *)((*servers
)+count
),'\0',sizeof(**servers
)*(alloced
-count
));
998 s
= &(*servers
)[count
];
1000 if (!next_token(&ptr
,s
->name
, NULL
, sizeof(s
->name
))) continue;
1001 if (!next_token(&ptr
,stype
, NULL
, sizeof(stype
))) continue;
1002 if (!next_token(&ptr
,s
->comment
, NULL
, sizeof(s
->comment
))) continue;
1003 if (!next_token(&ptr
,s
->domain
, NULL
, sizeof(s
->domain
))) {
1004 /* this allows us to cope with an old nmbd */
1005 fstrcpy(s
->domain
,lp_workgroup());
1008 if (sscanf(stype
,"%X",&s
->type
) != 1) {
1009 DEBUG(4,("r:host file "));
1013 /* Filter the servers/domains we return based on what was asked for. */
1015 /* Check to see if we are being asked for a local list only. */
1016 if(local_list_only
&& ((s
->type
& SV_TYPE_LOCAL_LIST_ONLY
) == 0)) {
1017 DEBUG(4,("r: local list only"));
1021 /* doesn't match up: don't want it */
1022 if (!(servertype
& s
->type
)) {
1023 DEBUG(4,("r:serv type "));
1027 if ((servertype
& SV_TYPE_DOMAIN_ENUM
) !=
1028 (s
->type
& SV_TYPE_DOMAIN_ENUM
))
1030 DEBUG(4,("s: dom mismatch "));
1034 if (!strequal(domain
, s
->domain
) && !(servertype
& SV_TYPE_DOMAIN_ENUM
))
1039 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1040 s
->type
&= ~SV_TYPE_LOCAL_LIST_ONLY
;
1044 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1045 s
->name
, s
->type
, s
->comment
, s
->domain
));
1047 s
->server_added
= True
;
1052 DEBUG(4,("%20s %8x %25s %15s\n",
1053 s
->name
, s
->type
, s
->comment
, s
->domain
));
1057 file_lines_free(lines
);
1062 /*******************************************************************
1063 fill in a server info structure
1064 ******************************************************************/
1065 static int fill_srv_info(struct srv_info_struct
*service
,
1066 int uLevel
, char **buf
, int *buflen
,
1067 char **stringbuf
, int *stringspace
, char *baseaddr
)
1076 case 0: struct_len
= 16; break;
1077 case 1: struct_len
= 26; break;
1087 len
= strlen(service
->comment
)+1;
1091 if (buflen
) *buflen
= struct_len
;
1092 if (stringspace
) *stringspace
= len
;
1093 return struct_len
+ len
;
1098 if (*buflen
< struct_len
) return -1;
1106 p2
= p
+ struct_len
;
1107 l2
= *buflen
- struct_len
;
1109 if (!baseaddr
) baseaddr
= p
;
1114 push_ascii(p
,service
->name
, MAX_NETBIOSNAME_LEN
, STR_TERMINATE
);
1118 push_ascii(p
,service
->name
,MAX_NETBIOSNAME_LEN
, STR_TERMINATE
);
1119 SIVAL(p
,18,service
->type
);
1120 SIVAL(p
,22,PTR_DIFF(p2
,baseaddr
));
1121 len
+= CopyAndAdvance(&p2
,service
->comment
,&l2
);
1127 *buf
= p
+ struct_len
;
1128 *buflen
-= struct_len
;
1141 static BOOL
srv_comp(struct srv_info_struct
*s1
,struct srv_info_struct
*s2
)
1143 return(strcmp(s1
->name
,s2
->name
));
1146 /****************************************************************************
1147 view list of servers available (or possibly domains). The info is
1148 extracted from lists saved by nmbd on the local host
1149 ****************************************************************************/
1150 static BOOL
api_RNetServerEnum(connection_struct
*conn
, uint16 vuid
, char *param
, char *data
,
1151 int mdrcnt
, int mprcnt
, char **rdata
,
1152 char **rparam
, int *rdata_len
, int *rparam_len
)
1154 char *str1
= param
+2;
1155 char *str2
= skip_string(str1
,1);
1156 char *p
= skip_string(str2
,1);
1157 int uLevel
= SVAL(p
,0);
1158 int buf_len
= SVAL(p
,2);
1159 uint32 servertype
= IVAL(p
,4);
1161 int data_len
, fixed_len
, string_len
;
1162 int f_len
= 0, s_len
= 0;
1163 struct srv_info_struct
*servers
=NULL
;
1164 int counted
=0,total
=0;
1167 BOOL domain_request
;
1170 /* If someone sets all the bits they don't really mean to set
1171 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1174 if (servertype
== SV_TYPE_ALL
)
1175 servertype
&= ~(SV_TYPE_DOMAIN_ENUM
|SV_TYPE_LOCAL_LIST_ONLY
);
1177 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1178 any other bit (they may just set this bit on it's own) they
1179 want all the locally seen servers. However this bit can be
1180 set on its own so set the requested servers to be
1181 ALL - DOMAIN_ENUM. */
1183 if ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) && !(servertype
& SV_TYPE_DOMAIN_ENUM
))
1184 servertype
= SV_TYPE_ALL
& ~(SV_TYPE_DOMAIN_ENUM
);
1186 domain_request
= ((servertype
& SV_TYPE_DOMAIN_ENUM
) != 0);
1187 local_request
= ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) != 0);
1191 if (!prefix_ok(str1
,"WrLehD")) return False
;
1192 if (!check_server_info(uLevel
,str2
)) return False
;
1194 DEBUG(4, ("server request level: %s %8x ", str2
, servertype
));
1195 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request
)));
1196 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request
)));
1198 if (strcmp(str1
, "WrLehDz") == 0) {
1199 pull_ascii_fstring(domain
, p
);
1201 fstrcpy(domain
, lp_workgroup());
1204 if (lp_browse_list())
1205 total
= get_server_info(servertype
,&servers
,domain
);
1207 data_len
= fixed_len
= string_len
= 0;
1211 qsort(servers
,total
,sizeof(servers
[0]),QSORT_CAST srv_comp
);
1214 char *lastname
=NULL
;
1216 for (i
=0;i
<total
;i
++)
1218 struct srv_info_struct
*s
= &servers
[i
];
1219 if (lastname
&& strequal(lastname
,s
->name
)) continue;
1221 data_len
+= fill_srv_info(s
,uLevel
,0,&f_len
,0,&s_len
,0);
1222 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1223 s
->name
, s
->type
, s
->comment
, s
->domain
));
1225 if (data_len
<= buf_len
) {
1228 string_len
+= s_len
;
1235 *rdata_len
= fixed_len
+ string_len
;
1236 *rdata
= SMB_REALLOC_LIMIT(*rdata
,*rdata_len
);
1237 memset(*rdata
,'\0',*rdata_len
);
1239 p2
= (*rdata
) + fixed_len
; /* auxilliary data (strings) will go here */
1245 char *lastname
=NULL
;
1246 int count2
= counted
;
1247 for (i
= 0; i
< total
&& count2
;i
++)
1249 struct srv_info_struct
*s
= &servers
[i
];
1250 if (lastname
&& strequal(lastname
,s
->name
)) continue;
1252 fill_srv_info(s
,uLevel
,&p
,&f_len
,&p2
,&s_len
,*rdata
);
1253 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1254 s
->name
, s
->type
, s
->comment
, s
->domain
));
1260 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
1261 SSVAL(*rparam
,0,(missed
== 0 ? NERR_Success
: ERRmoredata
));
1263 SSVAL(*rparam
,4,counted
);
1264 SSVAL(*rparam
,6,counted
+missed
);
1268 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1269 domain
,uLevel
,counted
,counted
+missed
));
1274 /****************************************************************************
1275 command 0x34 - suspected of being a "Lookup Names" stub api
1276 ****************************************************************************/
1277 static BOOL
api_RNetGroupGetUsers(connection_struct
*conn
, uint16 vuid
, char *param
, char *data
,
1278 int mdrcnt
, int mprcnt
, char **rdata
,
1279 char **rparam
, int *rdata_len
, int *rparam_len
)
1281 char *str1
= param
+2;
1282 char *str2
= skip_string(str1
,1);
1283 char *p
= skip_string(str2
,1);
1284 int uLevel
= SVAL(p
,0);
1285 int buf_len
= SVAL(p
,2);
1289 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1290 str1
, str2
, p
, uLevel
, buf_len
));
1292 if (!prefix_ok(str1
,"zWrLeh")) return False
;
1297 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
1299 SSVAL(*rparam
,0,0x08AC); /* informational warning message */
1301 SSVAL(*rparam
,4,counted
);
1302 SSVAL(*rparam
,6,counted
+missed
);
1307 /****************************************************************************
1308 get info about a share
1309 ****************************************************************************/
1310 static BOOL
check_share_info(int uLevel
, char* id
)
1314 if (strcmp(id
,"B13") != 0) return False
;
1317 if (strcmp(id
,"B13BWz") != 0) return False
;
1320 if (strcmp(id
,"B13BWzWWWzB9B") != 0) return False
;
1323 if (strcmp(id
,"B13BWzWWWzB9BB9BWzWWzWW") != 0) return False
;
1325 default: return False
;
1330 static int fill_share_info(connection_struct
*conn
, int snum
, int uLevel
,
1331 char** buf
, int* buflen
,
1332 char** stringbuf
, int* stringspace
, char* baseaddr
)
1341 case 0: struct_len
= 13; break;
1342 case 1: struct_len
= 20; break;
1343 case 2: struct_len
= 40; break;
1344 case 91: struct_len
= 68; break;
1352 if (uLevel
> 0) len
+= StrlenExpanded(conn
,snum
,lp_comment(snum
));
1353 if (uLevel
> 1) len
+= strlen(lp_pathname(snum
)) + 1;
1354 if (buflen
) *buflen
= struct_len
;
1355 if (stringspace
) *stringspace
= len
;
1356 return struct_len
+ len
;
1361 if ((*buflen
) < struct_len
) return -1;
1369 p2
= p
+ struct_len
;
1370 l2
= (*buflen
) - struct_len
;
1372 if (!baseaddr
) baseaddr
= p
;
1374 push_ascii(p
,lp_servicename(snum
),13, STR_TERMINATE
);
1380 type
= STYPE_DISKTREE
;
1381 if (lp_print_ok(snum
)) type
= STYPE_PRINTQ
;
1382 if (strequal("IPC",lp_fstype(snum
))) type
= STYPE_IPC
;
1383 SSVAL(p
,14,type
); /* device type */
1384 SIVAL(p
,16,PTR_DIFF(p2
,baseaddr
));
1385 len
+= CopyExpanded(conn
,snum
,&p2
,lp_comment(snum
),&l2
);
1390 SSVAL(p
,20,ACCESS_READ
|ACCESS_WRITE
|ACCESS_CREATE
); /* permissions */
1391 SSVALS(p
,22,-1); /* max uses */
1392 SSVAL(p
,24,1); /* current uses */
1393 SIVAL(p
,26,PTR_DIFF(p2
,baseaddr
)); /* local pathname */
1394 len
+= CopyAndAdvance(&p2
,lp_pathname(snum
),&l2
);
1395 memset(p
+30,0,SHPWLEN
+2); /* passwd (reserved), pad field */
1400 memset(p
+40,0,SHPWLEN
+2);
1412 (*buf
) = p
+ struct_len
;
1413 (*buflen
) -= struct_len
;
1415 (*stringspace
) = l2
;
1425 static BOOL
api_RNetShareGetInfo(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
1426 int mdrcnt
,int mprcnt
,
1427 char **rdata
,char **rparam
,
1428 int *rdata_len
,int *rparam_len
)
1430 char *str1
= param
+2;
1431 char *str2
= skip_string(str1
,1);
1432 char *netname
= skip_string(str2
,1);
1433 char *p
= skip_string(netname
,1);
1434 int uLevel
= SVAL(p
,0);
1435 int snum
= find_service(netname
);
1437 if (snum
< 0) return False
;
1439 /* check it's a supported varient */
1440 if (!prefix_ok(str1
,"zWrLh")) return False
;
1441 if (!check_share_info(uLevel
,str2
)) return False
;
1443 *rdata
= SMB_REALLOC_LIMIT(*rdata
,mdrcnt
);
1445 *rdata_len
= fill_share_info(conn
,snum
,uLevel
,&p
,&mdrcnt
,0,0,0);
1446 if (*rdata_len
< 0) return False
;
1449 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
1450 SSVAL(*rparam
,0,NERR_Success
);
1451 SSVAL(*rparam
,2,0); /* converter word */
1452 SSVAL(*rparam
,4,*rdata_len
);
1457 /****************************************************************************
1458 View the list of available shares.
1460 This function is the server side of the NetShareEnum() RAP call.
1461 It fills the return buffer with share names and share comments.
1462 Note that the return buffer normally (in all known cases) allows only
1463 twelve byte strings for share names (plus one for a nul terminator).
1464 Share names longer than 12 bytes must be skipped.
1465 ****************************************************************************/
1466 static BOOL
api_RNetShareEnum( connection_struct
*conn
,
1477 char *str1
= param
+2;
1478 char *str2
= skip_string(str1
,1);
1479 char *p
= skip_string(str2
,1);
1480 int uLevel
= SVAL(p
,0);
1481 int buf_len
= SVAL(p
,2);
1483 int count
=lp_numservices();
1484 int total
=0,counted
=0;
1485 BOOL missed
= False
;
1487 int data_len
, fixed_len
, string_len
;
1488 int f_len
= 0, s_len
= 0;
1490 if (!prefix_ok(str1
,"WrLeh")) return False
;
1491 if (!check_share_info(uLevel
,str2
)) return False
;
1493 data_len
= fixed_len
= string_len
= 0;
1494 for (i
=0;i
<count
;i
++) {
1495 fstring servicename_dos
;
1496 if (!(lp_browseable(i
) && lp_snum_ok(i
)))
1498 push_ascii_fstring(servicename_dos
, lp_servicename(i
));
1499 if( lp_browseable( i
)
1501 && (strlen(servicename_dos
) < 13) ) /* Maximum name length. */
1504 data_len
+= fill_share_info(conn
,i
,uLevel
,0,&f_len
,0,&s_len
,0);
1505 if (data_len
<= buf_len
)
1509 string_len
+= s_len
;
1515 *rdata_len
= fixed_len
+ string_len
;
1516 *rdata
= SMB_REALLOC_LIMIT(*rdata
,*rdata_len
);
1517 memset(*rdata
,0,*rdata_len
);
1519 p2
= (*rdata
) + fixed_len
; /* auxiliary data (strings) will go here */
1523 for( i
= 0; i
< count
; i
++ )
1525 fstring servicename_dos
;
1526 if (!(lp_browseable(i
) && lp_snum_ok(i
)))
1528 push_ascii_fstring(servicename_dos
, lp_servicename(i
));
1529 if( lp_browseable( i
)
1531 && (strlen(servicename_dos
) < 13) )
1533 if( fill_share_info( conn
,i
,uLevel
,&p
,&f_len
,&p2
,&s_len
,*rdata
) < 0 )
1539 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
1540 SSVAL(*rparam
,0,missed
? ERRmoredata
: NERR_Success
);
1542 SSVAL(*rparam
,4,counted
);
1543 SSVAL(*rparam
,6,total
);
1545 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1546 counted
,total
,uLevel
,
1547 buf_len
,*rdata_len
,mdrcnt
));
1549 } /* api_RNetShareEnum */
1551 /****************************************************************************
1553 ****************************************************************************/
1554 static BOOL
api_RNetShareAdd(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
1555 int mdrcnt
,int mprcnt
,
1556 char **rdata
,char **rparam
,
1557 int *rdata_len
,int *rparam_len
)
1559 char *str1
= param
+2;
1560 char *str2
= skip_string(str1
,1);
1561 char *p
= skip_string(str2
,1);
1562 int uLevel
= SVAL(p
,0);
1566 char *command
, *cmdname
;
1567 unsigned int offset
;
1571 /* check it's a supported varient */
1572 if (!prefix_ok(str1
,RAP_WShareAdd_REQ
)) return False
;
1573 if (!check_share_info(uLevel
,str2
)) return False
;
1574 if (uLevel
!= 2) return False
;
1576 pull_ascii_fstring(sharename
,data
);
1577 snum
= find_service(sharename
);
1578 if (snum
>= 0) { /* already exists */
1583 /* only support disk share adds */
1584 if (SVAL(data
,14)!=STYPE_DISKTREE
) return False
;
1586 offset
= IVAL(data
, 16);
1587 if (offset
>= mdrcnt
) {
1588 res
= ERRinvalidparam
;
1591 pull_ascii_fstring(comment
, offset
? (data
+offset
) : "");
1593 offset
= IVAL(data
, 26);
1594 if (offset
>= mdrcnt
) {
1595 res
= ERRinvalidparam
;
1598 pull_ascii_pstring(pathname
, offset
? (data
+offset
) : "");
1600 string_replace(sharename
, '"', ' ');
1601 string_replace(pathname
, '"', ' ');
1602 string_replace(comment
, '"', ' ');
1604 cmdname
= lp_add_share_cmd();
1606 if (!cmdname
|| *cmdname
== '\0') return False
;
1608 asprintf(&command
, "%s \"%s\" \"%s\" \"%s\" \"%s\"",
1609 lp_add_share_cmd(), dyn_CONFIGFILE
, sharename
, pathname
, comment
);
1612 DEBUG(10,("api_RNetShareAdd: Running [%s]\n", command
));
1613 if ((res
= smbrun(command
, NULL
)) != 0) {
1614 DEBUG(1,("api_RNetShareAdd: Running [%s] returned (%d)\n", command
, res
));
1620 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED
, NULL
, 0, False
, NULL
);
1622 } else return False
;
1625 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
1626 SSVAL(*rparam
,0,NERR_Success
);
1627 SSVAL(*rparam
,2,0); /* converter word */
1628 SSVAL(*rparam
,4,*rdata_len
);
1635 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
1637 SSVAL(*rparam
,0,res
);
1643 /****************************************************************************
1644 view list of groups available
1645 ****************************************************************************/
1646 static BOOL
api_RNetGroupEnum(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
1647 int mdrcnt
,int mprcnt
,
1648 char **rdata
,char **rparam
,
1649 int *rdata_len
,int *rparam_len
)
1653 int resume_context
, cli_buf_size
;
1654 char *str1
= param
+2;
1655 char *str2
= skip_string(str1
,1);
1656 char *p
= skip_string(str2
,1);
1659 GROUP_MAP
*group_list
;
1662 if (strcmp(str1
,"WrLeh") != 0)
1666 * W-> resume context (number of users to skip)
1667 * r -> return parameter pointer to receive buffer
1668 * L -> length of receive buffer
1669 * e -> return parameter number of entries
1670 * h -> return parameter total number of users
1672 if (strcmp("B21",str2
) != 0)
1675 /* get list of domain groups SID_DOMAIN_GRP=2 */
1677 ret
= pdb_enum_group_mapping(SID_NAME_DOM_GRP
, &group_list
, &num_entries
, False
);
1681 DEBUG(3,("api_RNetGroupEnum:failed to get group list"));
1685 resume_context
= SVAL(p
,0);
1686 cli_buf_size
=SVAL(p
+2,0);
1687 DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: %d\n", resume_context
, cli_buf_size
));
1689 *rdata_len
= cli_buf_size
;
1690 *rdata
= SMB_REALLOC_LIMIT(*rdata
,*rdata_len
);
1694 for(i
=resume_context
; i
<num_entries
; i
++) {
1695 char* name
=group_list
[i
].nt_name
;
1696 if( ((PTR_DIFF(p
,*rdata
)+21) <= *rdata_len
) ) {
1697 /* truncate the name at 21 chars. */
1698 memcpy(p
, name
, 21);
1699 DEBUG(10,("adding entry %d group %s\n", i
, p
));
1702 /* set overflow error */
1703 DEBUG(3,("overflow on entry %d group %s\n", i
, name
));
1709 *rdata_len
= PTR_DIFF(p
,*rdata
);
1712 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
1714 SSVAL(*rparam
, 0, errflags
);
1715 SSVAL(*rparam
, 2, 0); /* converter word */
1716 SSVAL(*rparam
, 4, i
-resume_context
); /* is this right?? */
1717 SSVAL(*rparam
, 6, num_entries
); /* is this right?? */
1722 /*******************************************************************
1723 get groups that a user is a member of
1724 ******************************************************************/
1725 static BOOL
api_NetUserGetGroups(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
1726 int mdrcnt
,int mprcnt
,
1727 char **rdata
,char **rparam
,
1728 int *rdata_len
,int *rparam_len
)
1730 char *str1
= param
+2;
1731 char *str2
= skip_string(str1
,1);
1732 char *UserName
= skip_string(str2
,1);
1733 char *p
= skip_string(UserName
,1);
1734 int uLevel
= SVAL(p
,0);
1735 const char *level_string
;
1737 SAM_ACCOUNT
*sampw
= NULL
;
1745 enum SID_NAME_USE grp_type
;
1746 struct passwd
*passwd
;
1750 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
1752 /* check it's a supported varient */
1754 if ( strcmp(str1
,"zWrLeh") != 0 )
1759 level_string
= "B21";
1765 if (strcmp(level_string
,str2
) != 0)
1768 *rdata_len
= mdrcnt
+ 1024;
1769 *rdata
= SMB_REALLOC_LIMIT(*rdata
,*rdata_len
);
1771 SSVAL(*rparam
,0,NERR_Success
);
1772 SSVAL(*rparam
,2,0); /* converter word */
1776 /* Lookup the user information; This should only be one of
1777 our accounts (not remote domains) */
1779 passwd
= getpwnam_alloc(UserName
);
1784 pdb_init_sam( &sampw
);
1786 become_root(); /* ROOT BLOCK */
1788 if ( !pdb_getsampwnam(sampw
, UserName
) )
1794 result
= pdb_enum_group_memberships(pdb_get_username(sampw
),
1796 &sids
, &gids
, &num_groups
);
1798 if (!NT_STATUS_IS_OK(result
))
1801 for (i
=0; i
<num_groups
; i
++) {
1803 if ( lookup_sid(&sids
[i
], grp_domain
, grp_name
, &grp_type
) ) {
1804 pstrcpy(p
, grp_name
);
1812 *rdata_len
= PTR_DIFF(p
,*rdata
);
1814 SSVAL(*rparam
,4,count
); /* is this right?? */
1815 SSVAL(*rparam
,6,count
); /* is this right?? */
1820 unbecome_root(); /* END ROOT BLOCK */
1822 pdb_free_sam( &sampw
);
1823 passwd_free(&passwd
);
1828 /*******************************************************************
1830 ******************************************************************/
1831 static BOOL
api_RNetUserEnum(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
1832 int mdrcnt
,int mprcnt
,
1833 char **rdata
,char **rparam
,
1834 int *rdata_len
,int *rparam_len
)
1836 SAM_ACCOUNT
*pwd
=NULL
;
1840 int resume_context
, cli_buf_size
;
1842 char *str1
= param
+2;
1843 char *str2
= skip_string(str1
,1);
1844 char *p
= skip_string(str2
,1);
1846 if (strcmp(str1
,"WrLeh") != 0)
1849 * W-> resume context (number of users to skip)
1850 * r -> return parameter pointer to receive buffer
1851 * L -> length of receive buffer
1852 * e -> return parameter number of entries
1853 * h -> return parameter total number of users
1856 resume_context
= SVAL(p
,0);
1857 cli_buf_size
=SVAL(p
+2,0);
1858 DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n", resume_context
, cli_buf_size
));
1861 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
1863 /* check it's a supported varient */
1864 if (strcmp("B21",str2
) != 0)
1867 *rdata_len
= cli_buf_size
;
1868 *rdata
= SMB_REALLOC_LIMIT(*rdata
,*rdata_len
);
1872 /* to get user list enumerations for NetUserEnum in B21 format */
1875 /* Open the passgrp file - not for update. */
1877 if(!pdb_setsampwent(False
)) {
1878 DEBUG(0, ("api_RNetUserEnum:unable to open sam database.\n"));
1882 errflags
=NERR_Success
;
1884 while ( pdb_getsampwent(pwd
) ) {
1885 const char *name
=pdb_get_username(pwd
);
1886 if ((name
) && (*(name
+strlen(name
)-1)!='$')) {
1888 if(count_total
>=resume_context
) {
1889 if( ((PTR_DIFF(p
,*rdata
)+21)<=*rdata_len
)&&(strlen(name
)<=21) ) {
1891 DEBUG(10,("api_RNetUserEnum:adding entry %d username %s\n",count_sent
,p
));
1895 /* set overflow error */
1896 DEBUG(10,("api_RNetUserEnum:overflow on entry %d username %s\n",count_sent
,name
));
1909 *rdata_len
= PTR_DIFF(p
,*rdata
);
1911 SSVAL(*rparam
,0,errflags
);
1912 SSVAL(*rparam
,2,0); /* converter word */
1913 SSVAL(*rparam
,4,count_sent
); /* is this right?? */
1914 SSVAL(*rparam
,6,count_total
); /* is this right?? */
1921 /****************************************************************************
1922 get the time of day info
1923 ****************************************************************************/
1924 static BOOL
api_NetRemoteTOD(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
1925 int mdrcnt
,int mprcnt
,
1926 char **rdata
,char **rparam
,
1927 int *rdata_len
,int *rparam_len
)
1931 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
1934 *rdata
= SMB_REALLOC_LIMIT(*rdata
,*rdata_len
);
1936 SSVAL(*rparam
,0,NERR_Success
);
1937 SSVAL(*rparam
,2,0); /* converter word */
1943 time_t unixdate
= time(NULL
);
1945 put_dos_date3(p
,0,unixdate
); /* this is the time that is looked at
1946 by NT in a "net time" operation,
1947 it seems to ignore the one below */
1949 /* the client expects to get localtime, not GMT, in this bit
1950 (I think, this needs testing) */
1951 t
= LocalTime(&unixdate
);
1953 SIVAL(p
,4,0); /* msecs ? */
1954 SCVAL(p
,8,t
->tm_hour
);
1955 SCVAL(p
,9,t
->tm_min
);
1956 SCVAL(p
,10,t
->tm_sec
);
1957 SCVAL(p
,11,0); /* hundredths of seconds */
1958 SSVALS(p
,12,TimeDiff(unixdate
)/60); /* timezone in minutes from GMT */
1959 SSVAL(p
,14,10000); /* timer interval in 0.0001 of sec */
1960 SCVAL(p
,16,t
->tm_mday
);
1961 SCVAL(p
,17,t
->tm_mon
+ 1);
1962 SSVAL(p
,18,1900+t
->tm_year
);
1963 SCVAL(p
,20,t
->tm_wday
);
1970 /****************************************************************************
1971 Set the user password.
1972 *****************************************************************************/
1974 static BOOL
api_SetUserPassword(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
1975 int mdrcnt
,int mprcnt
,
1976 char **rdata
,char **rparam
,
1977 int *rdata_len
,int *rparam_len
)
1979 char *p
= skip_string(param
+2,2);
1981 fstring pass1
,pass2
;
1983 pull_ascii_fstring(user
,p
);
1985 p
= skip_string(p
,1);
1987 memset(pass1
,'\0',sizeof(pass1
));
1988 memset(pass2
,'\0',sizeof(pass2
));
1990 memcpy(pass2
,p
+16,16);
1993 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
1997 SSVAL(*rparam
,0,NERR_badpass
);
1998 SSVAL(*rparam
,2,0); /* converter word */
2000 DEBUG(3,("Set password for <%s>\n",user
));
2003 * Attempt to verify the old password against smbpasswd entries
2004 * Win98 clients send old and new password in plaintext for this call.
2008 auth_serversupplied_info
*server_info
= NULL
;
2009 DATA_BLOB password
= data_blob(pass1
, strlen(pass1
)+1);
2011 if (NT_STATUS_IS_OK(check_plaintext_password(user
,password
,&server_info
))) {
2014 if (NT_STATUS_IS_OK(change_oem_password(server_info
->sam_account
, pass1
, pass2
, False
))) {
2015 SSVAL(*rparam
,0,NERR_Success
);
2019 free_server_info(&server_info
);
2021 data_blob_clear_free(&password
);
2025 * If the plaintext change failed, attempt
2026 * the old encrypted method. NT will generate this
2027 * after trying the samr method. Note that this
2028 * method is done as a last resort as this
2029 * password change method loses the NT password hash
2030 * and cannot change the UNIX password as no plaintext
2034 if(SVAL(*rparam
,0) != NERR_Success
) {
2035 SAM_ACCOUNT
*hnd
= NULL
;
2037 if (check_lanman_password(user
,(unsigned char *)pass1
,(unsigned char *)pass2
, &hnd
)) {
2039 if (change_lanman_password(hnd
,(uchar
*)pass2
)) {
2040 SSVAL(*rparam
,0,NERR_Success
);
2047 memset((char *)pass1
,'\0',sizeof(fstring
));
2048 memset((char *)pass2
,'\0',sizeof(fstring
));
2053 /****************************************************************************
2054 Set the user password (SamOEM version - gets plaintext).
2055 ****************************************************************************/
2057 static BOOL
api_SamOEMChangePassword(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
2058 int mdrcnt
,int mprcnt
,
2059 char **rdata
,char **rparam
,
2060 int *rdata_len
,int *rparam_len
)
2063 char *p
= param
+ 2;
2065 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
2069 SSVAL(*rparam
,0,NERR_badpass
);
2072 * Check the parameter definition is correct.
2075 if(!strequal(param
+ 2, "zsT")) {
2076 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", param
+ 2));
2079 p
= skip_string(p
, 1);
2081 if(!strequal(p
, "B516B16")) {
2082 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p
));
2085 p
= skip_string(p
,1);
2086 p
+= pull_ascii_fstring(user
,p
);
2088 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user
));
2091 * Pass the user through the NT -> unix user mapping
2095 (void)map_username(user
);
2097 if (NT_STATUS_IS_OK(pass_oem_change(user
, (uchar
*) data
, (uchar
*)&data
[516], NULL
, NULL
))) {
2098 SSVAL(*rparam
,0,NERR_Success
);
2104 /****************************************************************************
2107 ****************************************************************************/
2108 static BOOL
api_RDosPrintJobDel(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
2109 int mdrcnt
,int mprcnt
,
2110 char **rdata
,char **rparam
,
2111 int *rdata_len
,int *rparam_len
)
2113 int function
= SVAL(param
,0);
2114 char *str1
= param
+2;
2115 char *str2
= skip_string(str1
,1);
2116 char *p
= skip_string(str2
,1);
2121 extern struct current_user current_user
;
2122 WERROR werr
= WERR_OK
;
2124 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
))
2127 /* check it's a supported varient */
2128 if (!(strcsequal(str1
,"W") && strcsequal(str2
,"")))
2132 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
2135 if (!print_job_exists(sharename
, jobid
)) {
2136 errcode
= NERR_JobNotFound
;
2140 snum
= lp_servicenumber( sharename
);
2142 errcode
= NERR_DestNotFound
;
2146 errcode
= NERR_notsupported
;
2149 case 81: /* delete */
2150 if (print_job_delete(¤t_user
, snum
, jobid
, &werr
))
2151 errcode
= NERR_Success
;
2153 case 82: /* pause */
2154 if (print_job_pause(¤t_user
, snum
, jobid
, &werr
))
2155 errcode
= NERR_Success
;
2157 case 83: /* resume */
2158 if (print_job_resume(¤t_user
, snum
, jobid
, &werr
))
2159 errcode
= NERR_Success
;
2163 if (!W_ERROR_IS_OK(werr
))
2164 errcode
= W_ERROR_V(werr
);
2167 SSVAL(*rparam
,0,errcode
);
2168 SSVAL(*rparam
,2,0); /* converter word */
2173 /****************************************************************************
2174 Purge a print queue - or pause or resume it.
2175 ****************************************************************************/
2176 static BOOL
api_WPrintQueueCtrl(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
2177 int mdrcnt
,int mprcnt
,
2178 char **rdata
,char **rparam
,
2179 int *rdata_len
,int *rparam_len
)
2181 int function
= SVAL(param
,0);
2182 char *str1
= param
+2;
2183 char *str2
= skip_string(str1
,1);
2184 char *QueueName
= skip_string(str2
,1);
2185 int errcode
= NERR_notsupported
;
2187 WERROR werr
= WERR_OK
;
2188 extern struct current_user current_user
;
2190 /* check it's a supported varient */
2191 if (!(strcsequal(str1
,"z") && strcsequal(str2
,"")))
2195 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
2198 snum
= print_queue_snum(QueueName
);
2201 errcode
= NERR_JobNotFound
;
2206 case 74: /* Pause queue */
2207 if (print_queue_pause(¤t_user
, snum
, &werr
)) errcode
= NERR_Success
;
2209 case 75: /* Resume queue */
2210 if (print_queue_resume(¤t_user
, snum
, &werr
)) errcode
= NERR_Success
;
2212 case 103: /* Purge */
2213 if (print_queue_purge(¤t_user
, snum
, &werr
)) errcode
= NERR_Success
;
2217 if (!W_ERROR_IS_OK(werr
)) errcode
= W_ERROR_V(werr
);
2220 SSVAL(*rparam
,0,errcode
);
2221 SSVAL(*rparam
,2,0); /* converter word */
2227 /****************************************************************************
2228 set the property of a print job (undocumented?)
2229 ? function = 0xb -> set name of print job
2230 ? function = 0x6 -> move print job up/down
2231 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
2232 or <WWsTP> <WB21BB16B10zWWzDDz>
2233 ****************************************************************************/
2234 static int check_printjob_info(struct pack_desc
* desc
,
2235 int uLevel
, char* id
)
2237 desc
->subformat
= NULL
;
2239 case 0: desc
->format
= "W"; break;
2240 case 1: desc
->format
= "WB21BB16B10zWWzDDz"; break;
2241 case 2: desc
->format
= "WWzWWDDzz"; break;
2242 case 3: desc
->format
= "WWzWWDDzzzzzzzzzzlz"; break;
2243 case 4: desc
->format
= "WWzWWDDzzzzzDDDDDDD"; break;
2244 default: return False
;
2246 if (strcmp(desc
->format
,id
) != 0) return False
;
2250 static BOOL
api_PrintJobInfo(connection_struct
*conn
,uint16 vuid
,char *param
,char *data
,
2251 int mdrcnt
,int mprcnt
,
2252 char **rdata
,char **rparam
,
2253 int *rdata_len
,int *rparam_len
)
2255 struct pack_desc desc
;
2256 char *str1
= param
+2;
2257 char *str2
= skip_string(str1
,1);
2258 char *p
= skip_string(str2
,1);
2262 int uLevel
= SVAL(p
,2);
2263 int function
= SVAL(p
,4);
2266 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
))
2269 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
2271 if ( (snum
= lp_servicenumber(sharename
)) == -1 ) {
2272 DEBUG(0,("api_PrintJobInfo: unable to get service number from sharename [%s]\n",
2279 /* check it's a supported varient */
2280 if ((strcmp(str1
,"WWsTP")) ||
2281 (!check_printjob_info(&desc
,uLevel
,str2
)))
2284 if (!print_job_exists(sharename
, jobid
)) {
2285 errcode
=NERR_JobNotFound
;
2289 errcode
= NERR_notsupported
;
2293 /* change job place in the queue,
2294 data gives the new place */
2295 place
= SVAL(data
,0);
2296 if (print_job_set_place(snum
, jobid
, place
)) {
2297 errcode
=NERR_Success
;
2302 /* change print job name, data gives the name */
2303 if (print_job_set_name(snum
, jobid
, data
)) {
2304 errcode
=NERR_Success
;
2313 SSVALS(*rparam
,0,errcode
);
2314 SSVAL(*rparam
,2,0); /* converter word */
2320 /****************************************************************************
2321 get info about the server
2322 ****************************************************************************/
2323 static BOOL
api_RNetServerGetInfo(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
2324 int mdrcnt
,int mprcnt
,
2325 char **rdata
,char **rparam
,
2326 int *rdata_len
,int *rparam_len
)
2328 char *str1
= param
+2;
2329 char *str2
= skip_string(str1
,1);
2330 char *p
= skip_string(str2
,1);
2331 int uLevel
= SVAL(p
,0);
2335 DEBUG(4,("NetServerGetInfo level %d\n",uLevel
));
2337 /* check it's a supported varient */
2338 if (!prefix_ok(str1
,"WrLh")) return False
;
2341 if (strcmp(str2
,"B16") != 0) return False
;
2345 if (strcmp(str2
,"B16BBDz") != 0) return False
;
2349 if (strcmp(str2
,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")
2354 if (strcmp(str2
,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz")
2359 if (strcmp(str2
,"DN") != 0) return False
;
2363 if (strcmp(str2
,"B16BBDzWWzzz") != 0) return False
;
2366 default: return False
;
2369 *rdata_len
= mdrcnt
;
2370 *rdata
= SMB_REALLOC_LIMIT(*rdata
,*rdata_len
);
2373 p2
= p
+ struct_len
;
2375 srvstr_push(NULL
, p
,local_machine
,16,
2376 STR_ASCII
|STR_UPPER
|STR_TERMINATE
);
2381 struct srv_info_struct
*servers
=NULL
;
2384 uint32 servertype
= lp_default_server_announce();
2386 push_ascii(comment
,lp_serverstring(), MAX_SERVER_STRING_LENGTH
,STR_TERMINATE
);
2388 if ((count
=get_server_info(SV_TYPE_ALL
,&servers
,lp_workgroup()))>0) {
2389 for (i
=0;i
<count
;i
++) {
2390 if (strequal(servers
[i
].name
,local_machine
)) {
2391 servertype
= servers
[i
].type
;
2392 push_ascii(comment
,servers
[i
].comment
,sizeof(pstring
),STR_TERMINATE
);
2398 SCVAL(p
,0,lp_major_announce_version());
2399 SCVAL(p
,1,lp_minor_announce_version());
2400 SIVAL(p
,2,servertype
);
2402 if (mdrcnt
== struct_len
) {
2405 SIVAL(p
,6,PTR_DIFF(p2
,*rdata
));
2406 standard_sub_conn(conn
,comment
,sizeof(comment
));
2407 StrnCpy(p2
,comment
,MAX(mdrcnt
- struct_len
,0));
2408 p2
= skip_string(p2
,1);
2413 return False
; /* not yet implemented */
2416 *rdata_len
= PTR_DIFF(p2
,*rdata
);
2419 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
2420 SSVAL(*rparam
,0,NERR_Success
);
2421 SSVAL(*rparam
,2,0); /* converter word */
2422 SSVAL(*rparam
,4,*rdata_len
);
2428 /****************************************************************************
2429 get info about the server
2430 ****************************************************************************/
2431 static BOOL
api_NetWkstaGetInfo(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
2432 int mdrcnt
,int mprcnt
,
2433 char **rdata
,char **rparam
,
2434 int *rdata_len
,int *rparam_len
)
2436 char *str1
= param
+2;
2437 char *str2
= skip_string(str1
,1);
2438 char *p
= skip_string(str2
,1);
2440 extern userdom_struct current_user_info
;
2441 int level
= SVAL(p
,0);
2443 DEBUG(4,("NetWkstaGetInfo level %d\n",level
));
2446 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
2448 /* check it's a supported varient */
2449 if (!(level
==10 && strcsequal(str1
,"WrLh") && strcsequal(str2
,"zzzBBzz")))
2452 *rdata_len
= mdrcnt
+ 1024;
2453 *rdata
= SMB_REALLOC_LIMIT(*rdata
,*rdata_len
);
2455 SSVAL(*rparam
,0,NERR_Success
);
2456 SSVAL(*rparam
,2,0); /* converter word */
2462 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* host name */
2463 pstrcpy(p2
,local_machine
);
2465 p2
= skip_string(p2
,1);
2468 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
));
2469 pstrcpy(p2
,current_user_info
.smb_name
);
2470 p2
= skip_string(p2
,1);
2473 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* login domain */
2474 pstrcpy(p2
,lp_workgroup());
2476 p2
= skip_string(p2
,1);
2479 SCVAL(p
,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
2480 SCVAL(p
,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
2483 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
));
2484 pstrcpy(p2
,lp_workgroup()); /* don't know. login domain?? */
2485 p2
= skip_string(p2
,1);
2488 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* don't know */
2490 p2
= skip_string(p2
,1);
2493 *rdata_len
= PTR_DIFF(p2
,*rdata
);
2495 SSVAL(*rparam
,4,*rdata_len
);
2500 /****************************************************************************
2501 get info about a user
2503 struct user_info_11 {
2504 char usri11_name[21]; 0-20
2506 char *usri11_comment; 22-25
2507 char *usri11_usr_comment; 26-29
2508 unsigned short usri11_priv; 30-31
2509 unsigned long usri11_auth_flags; 32-35
2510 long usri11_password_age; 36-39
2511 char *usri11_homedir; 40-43
2512 char *usri11_parms; 44-47
2513 long usri11_last_logon; 48-51
2514 long usri11_last_logoff; 52-55
2515 unsigned short usri11_bad_pw_count; 56-57
2516 unsigned short usri11_num_logons; 58-59
2517 char *usri11_logon_server; 60-63
2518 unsigned short usri11_country_code; 64-65
2519 char *usri11_workstations; 66-69
2520 unsigned long usri11_max_storage; 70-73
2521 unsigned short usri11_units_per_week; 74-75
2522 unsigned char *usri11_logon_hours; 76-79
2523 unsigned short usri11_code_page; 80-81
2528 usri11_name specifies the user name for which information is retireved
2530 usri11_pad aligns the next data structure element to a word boundary
2532 usri11_comment is a null terminated ASCII comment
2534 usri11_user_comment is a null terminated ASCII comment about the user
2536 usri11_priv specifies the level of the privilege assigned to the user.
2537 The possible values are:
2539 Name Value Description
2540 USER_PRIV_GUEST 0 Guest privilege
2541 USER_PRIV_USER 1 User privilege
2542 USER_PRV_ADMIN 2 Administrator privilege
2544 usri11_auth_flags specifies the account operator privileges. The
2545 possible values are:
2547 Name Value Description
2548 AF_OP_PRINT 0 Print operator
2551 Leach, Naik [Page 28]
2555 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2558 AF_OP_COMM 1 Communications operator
2559 AF_OP_SERVER 2 Server operator
2560 AF_OP_ACCOUNTS 3 Accounts operator
2563 usri11_password_age specifies how many seconds have elapsed since the
2564 password was last changed.
2566 usri11_home_dir points to a null terminated ASCII string that contains
2567 the path name of the user's home directory.
2569 usri11_parms points to a null terminated ASCII string that is set
2570 aside for use by applications.
2572 usri11_last_logon specifies the time when the user last logged on.
2573 This value is stored as the number of seconds elapsed since
2574 00:00:00, January 1, 1970.
2576 usri11_last_logoff specifies the time when the user last logged off.
2577 This value is stored as the number of seconds elapsed since
2578 00:00:00, January 1, 1970. A value of 0 means the last logoff
2581 usri11_bad_pw_count specifies the number of incorrect passwords
2582 entered since the last successful logon.
2584 usri11_log1_num_logons specifies the number of times this user has
2585 logged on. A value of -1 means the number of logons is unknown.
2587 usri11_logon_server points to a null terminated ASCII string that
2588 contains the name of the server to which logon requests are sent.
2589 A null string indicates logon requests should be sent to the
2592 usri11_country_code specifies the country code for the user's language
2595 usri11_workstations points to a null terminated ASCII string that
2596 contains the names of workstations the user may log on from.
2597 There may be up to 8 workstations, with the names separated by
2598 commas. A null strings indicates there are no restrictions.
2600 usri11_max_storage specifies the maximum amount of disk space the user
2601 can occupy. A value of 0xffffffff indicates there are no
2604 usri11_units_per_week specifies the equal number of time units into
2605 which a week is divided. This value must be equal to 168.
2607 usri11_logon_hours points to a 21 byte (168 bits) string that
2608 specifies the time during which the user can log on. Each bit
2609 represents one unique hour in a week. The first bit (bit 0, word
2610 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
2614 Leach, Naik [Page 29]
2618 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2621 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
2622 are no restrictions.
2624 usri11_code_page specifies the code page for the user's language of
2627 All of the pointers in this data structure need to be treated
2628 specially. The pointer is a 32 bit pointer. The higher 16 bits need
2629 to be ignored. The converter word returned in the parameters section
2630 needs to be subtracted from the lower 16 bits to calculate an offset
2631 into the return buffer where this ASCII string resides.
2633 There is no auxiliary data in the response.
2635 ****************************************************************************/
2637 #define usri11_name 0
2638 #define usri11_pad 21
2639 #define usri11_comment 22
2640 #define usri11_usr_comment 26
2641 #define usri11_full_name 30
2642 #define usri11_priv 34
2643 #define usri11_auth_flags 36
2644 #define usri11_password_age 40
2645 #define usri11_homedir 44
2646 #define usri11_parms 48
2647 #define usri11_last_logon 52
2648 #define usri11_last_logoff 56
2649 #define usri11_bad_pw_count 60
2650 #define usri11_num_logons 62
2651 #define usri11_logon_server 64
2652 #define usri11_country_code 68
2653 #define usri11_workstations 70
2654 #define usri11_max_storage 74
2655 #define usri11_units_per_week 78
2656 #define usri11_logon_hours 80
2657 #define usri11_code_page 84
2658 #define usri11_end 86
2660 #define USER_PRIV_GUEST 0
2661 #define USER_PRIV_USER 1
2662 #define USER_PRIV_ADMIN 2
2664 #define AF_OP_PRINT 0
2665 #define AF_OP_COMM 1
2666 #define AF_OP_SERVER 2
2667 #define AF_OP_ACCOUNTS 3
2670 static BOOL
api_RNetUserGetInfo(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
2671 int mdrcnt
,int mprcnt
,
2672 char **rdata
,char **rparam
,
2673 int *rdata_len
,int *rparam_len
)
2675 char *str1
= param
+2;
2676 char *str2
= skip_string(str1
,1);
2677 char *UserName
= skip_string(str2
,1);
2678 char *p
= skip_string(UserName
,1);
2679 int uLevel
= SVAL(p
,0);
2681 const char *level_string
;
2683 /* get NIS home of a previously validated user - simeon */
2684 /* With share level security vuid will always be zero.
2685 Don't depend on vuser being non-null !!. JRA */
2686 user_struct
*vuser
= get_valid_user_struct(vuid
);
2688 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser
->uid
,
2689 vuser
->user
.unix_name
));
2692 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
2694 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel
));
2696 /* check it's a supported variant */
2697 if (strcmp(str1
,"zWrLh") != 0) return False
;
2700 case 0: level_string
= "B21"; break;
2701 case 1: level_string
= "B21BB16DWzzWz"; break;
2702 case 2: level_string
= "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
2703 case 10: level_string
= "B21Bzzz"; break;
2704 case 11: level_string
= "B21BzzzWDDzzDDWWzWzDWb21W"; break;
2705 default: return False
;
2708 if (strcmp(level_string
,str2
) != 0) return False
;
2710 *rdata_len
= mdrcnt
+ 1024;
2711 *rdata
= SMB_REALLOC_LIMIT(*rdata
,*rdata_len
);
2713 SSVAL(*rparam
,0,NERR_Success
);
2714 SSVAL(*rparam
,2,0); /* converter word */
2717 p2
= p
+ usri11_end
;
2720 fstrcpy(p
+usri11_name
,UserName
); /* 21 bytes - user name */
2724 SCVAL(p
,usri11_pad
,0); /* padding - 1 byte */
2729 SIVAL(p
,usri11_comment
,PTR_DIFF(p2
,p
)); /* comment */
2730 pstrcpy(p2
,"Comment");
2731 p2
= skip_string(p2
,1);
2733 SIVAL(p
,usri11_usr_comment
,PTR_DIFF(p2
,p
)); /* user_comment */
2734 pstrcpy(p2
,"UserComment");
2735 p2
= skip_string(p2
,1);
2737 /* EEK! the cifsrap.txt doesn't have this in!!!! */
2738 SIVAL(p
,usri11_full_name
,PTR_DIFF(p2
,p
)); /* full name */
2739 pstrcpy(p2
,((vuser
!= NULL
) ? vuser
->user
.full_name
: UserName
));
2740 p2
= skip_string(p2
,1);
2743 if (uLevel
== 11) /* modelled after NTAS 3.51 reply */
2745 SSVAL(p
,usri11_priv
,conn
->admin_user
?USER_PRIV_ADMIN
:USER_PRIV_USER
);
2746 SIVAL(p
,usri11_auth_flags
,AF_OP_PRINT
); /* auth flags */
2747 SIVALS(p
,usri11_password_age
,-1); /* password age */
2748 SIVAL(p
,usri11_homedir
,PTR_DIFF(p2
,p
)); /* home dir */
2749 pstrcpy(p2
, vuser
&& vuser
->homedir
? vuser
->homedir
: "");
2750 p2
= skip_string(p2
,1);
2751 SIVAL(p
,usri11_parms
,PTR_DIFF(p2
,p
)); /* parms */
2753 p2
= skip_string(p2
,1);
2754 SIVAL(p
,usri11_last_logon
,0); /* last logon */
2755 SIVAL(p
,usri11_last_logoff
,0); /* last logoff */
2756 SSVALS(p
,usri11_bad_pw_count
,-1); /* bad pw counts */
2757 SSVALS(p
,usri11_num_logons
,-1); /* num logons */
2758 SIVAL(p
,usri11_logon_server
,PTR_DIFF(p2
,p
)); /* logon server */
2759 pstrcpy(p2
,"\\\\*");
2760 p2
= skip_string(p2
,1);
2761 SSVAL(p
,usri11_country_code
,0); /* country code */
2763 SIVAL(p
,usri11_workstations
,PTR_DIFF(p2
,p
)); /* workstations */
2765 p2
= skip_string(p2
,1);
2767 SIVALS(p
,usri11_max_storage
,-1); /* max storage */
2768 SSVAL(p
,usri11_units_per_week
,168); /* units per week */
2769 SIVAL(p
,usri11_logon_hours
,PTR_DIFF(p2
,p
)); /* logon hours */
2771 /* a simple way to get logon hours at all times. */
2773 SCVAL(p2
,21,0); /* fix zero termination */
2774 p2
= skip_string(p2
,1);
2776 SSVAL(p
,usri11_code_page
,0); /* code page */
2778 if (uLevel
== 1 || uLevel
== 2)
2780 memset(p
+22,' ',16); /* password */
2781 SIVALS(p
,38,-1); /* password age */
2783 conn
->admin_user
?USER_PRIV_ADMIN
:USER_PRIV_USER
);
2784 SIVAL(p
,44,PTR_DIFF(p2
,*rdata
)); /* home dir */
2785 pstrcpy(p2
, vuser
&& vuser
->homedir
? vuser
->homedir
: "");
2786 p2
= skip_string(p2
,1);
2787 SIVAL(p
,48,PTR_DIFF(p2
,*rdata
)); /* comment */
2789 SSVAL(p
,52,0); /* flags */
2790 SIVAL(p
,54,PTR_DIFF(p2
,*rdata
)); /* script_path */
2791 pstrcpy(p2
,vuser
&& vuser
->logon_script
? vuser
->logon_script
: "");
2792 p2
= skip_string(p2
,1);
2795 SIVAL(p
,60,0); /* auth_flags */
2796 SIVAL(p
,64,PTR_DIFF(p2
,*rdata
)); /* full_name */
2797 pstrcpy(p2
,((vuser
!= NULL
) ? vuser
->user
.full_name
: UserName
));
2798 p2
= skip_string(p2
,1);
2799 SIVAL(p
,68,0); /* urs_comment */
2800 SIVAL(p
,72,PTR_DIFF(p2
,*rdata
)); /* parms */
2802 p2
= skip_string(p2
,1);
2803 SIVAL(p
,76,0); /* workstations */
2804 SIVAL(p
,80,0); /* last_logon */
2805 SIVAL(p
,84,0); /* last_logoff */
2806 SIVALS(p
,88,-1); /* acct_expires */
2807 SIVALS(p
,92,-1); /* max_storage */
2808 SSVAL(p
,96,168); /* units_per_week */
2809 SIVAL(p
,98,PTR_DIFF(p2
,*rdata
)); /* logon_hours */
2812 SSVALS(p
,102,-1); /* bad_pw_count */
2813 SSVALS(p
,104,-1); /* num_logons */
2814 SIVAL(p
,106,PTR_DIFF(p2
,*rdata
)); /* logon_server */
2815 pstrcpy(p2
,"\\\\%L");
2816 standard_sub_conn(conn
, p2
,0);
2817 p2
= skip_string(p2
,1);
2818 SSVAL(p
,110,49); /* country_code */
2819 SSVAL(p
,112,860); /* code page */
2823 *rdata_len
= PTR_DIFF(p2
,*rdata
);
2825 SSVAL(*rparam
,4,*rdata_len
); /* is this right?? */
2830 static BOOL
api_WWkstaUserLogon(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
2831 int mdrcnt
,int mprcnt
,
2832 char **rdata
,char **rparam
,
2833 int *rdata_len
,int *rparam_len
)
2835 char *str1
= param
+2;
2836 char *str2
= skip_string(str1
,1);
2837 char *p
= skip_string(str2
,1);
2839 struct pack_desc desc
;
2841 /* With share level security vuid will always be zero.
2842 Don't depend on vuser being non-null !!. JRA */
2843 user_struct
*vuser
= get_valid_user_struct(vuid
);
2845 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser
->uid
,
2846 vuser
->user
.unix_name
));
2851 memset((char *)&desc
,'\0',sizeof(desc
));
2853 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel
,name
));
2855 /* check it's a supported varient */
2856 if (strcmp(str1
,"OOWb54WrLh") != 0) return False
;
2857 if (uLevel
!= 1 || strcmp(str2
,"WB21BWDWWDDDDDDDzzzD") != 0) return False
;
2858 if (mdrcnt
> 0) *rdata
= SMB_REALLOC_LIMIT(*rdata
,mdrcnt
);
2860 desc
.buflen
= mdrcnt
;
2861 desc
.subformat
= NULL
;
2864 if (init_package(&desc
,1,0))
2866 PACKI(&desc
,"W",0); /* code */
2867 PACKS(&desc
,"B21",name
); /* eff. name */
2868 PACKS(&desc
,"B",""); /* pad */
2870 conn
->admin_user
?USER_PRIV_ADMIN
:USER_PRIV_USER
);
2871 PACKI(&desc
,"D",0); /* auth flags XXX */
2872 PACKI(&desc
,"W",0); /* num logons */
2873 PACKI(&desc
,"W",0); /* bad pw count */
2874 PACKI(&desc
,"D",0); /* last logon */
2875 PACKI(&desc
,"D",-1); /* last logoff */
2876 PACKI(&desc
,"D",-1); /* logoff time */
2877 PACKI(&desc
,"D",-1); /* kickoff time */
2878 PACKI(&desc
,"D",0); /* password age */
2879 PACKI(&desc
,"D",0); /* password can change */
2880 PACKI(&desc
,"D",-1); /* password must change */
2883 fstrcpy(mypath
,"\\\\");
2884 fstrcat(mypath
,local_machine
);
2886 PACKS(&desc
,"z",mypath
); /* computer */
2888 PACKS(&desc
,"z",lp_workgroup());/* domain */
2890 PACKS(&desc
,"z", vuser
&& vuser
->logon_script
? vuser
->logon_script
:""); /* script path */
2892 PACKI(&desc
,"D",0x00000000); /* reserved */
2895 *rdata_len
= desc
.usedlen
;
2897 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
2898 SSVALS(*rparam
,0,desc
.errcode
);
2900 SSVAL(*rparam
,4,desc
.neededlen
);
2902 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc
.errcode
));
2907 /****************************************************************************
2908 api_WAccessGetUserPerms
2909 ****************************************************************************/
2910 static BOOL
api_WAccessGetUserPerms(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
2911 int mdrcnt
,int mprcnt
,
2912 char **rdata
,char **rparam
,
2913 int *rdata_len
,int *rparam_len
)
2915 char *str1
= param
+2;
2916 char *str2
= skip_string(str1
,1);
2917 char *user
= skip_string(str2
,1);
2918 char *resource
= skip_string(user
,1);
2920 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user
,resource
));
2922 /* check it's a supported varient */
2923 if (strcmp(str1
,"zzh") != 0) return False
;
2924 if (strcmp(str2
,"") != 0) return False
;
2927 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
2928 SSVALS(*rparam
,0,0); /* errorcode */
2929 SSVAL(*rparam
,2,0); /* converter word */
2930 SSVAL(*rparam
,4,0x7f); /* permission flags */
2935 /****************************************************************************
2936 api_WPrintJobEnumerate
2937 ****************************************************************************/
2938 static BOOL
api_WPrintJobGetInfo(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
2939 int mdrcnt
,int mprcnt
,
2940 char **rdata
,char **rparam
,
2941 int *rdata_len
,int *rparam_len
)
2943 char *str1
= param
+2;
2944 char *str2
= skip_string(str1
,1);
2945 char *p
= skip_string(str2
,1);
2952 struct pack_desc desc
;
2953 print_queue_struct
*queue
=NULL
;
2954 print_status_struct status
;
2959 memset((char *)&desc
,'\0',sizeof(desc
));
2960 memset((char *)&status
,'\0',sizeof(status
));
2962 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel
,SVAL(p
,0)));
2964 /* check it's a supported varient */
2965 if (strcmp(str1
,"WWrLh") != 0) return False
;
2966 if (!check_printjob_info(&desc
,uLevel
,str2
)) return False
;
2968 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
))
2971 snum
= lp_servicenumber( sharename
);
2972 if (snum
< 0 || !VALID_SNUM(snum
)) return(False
);
2974 count
= print_queue_status(snum
,&queue
,&status
);
2975 for (i
= 0; i
< count
; i
++) {
2976 if (queue
[i
].job
== jobid
) break;
2980 *rdata
= SMB_REALLOC_LIMIT(*rdata
,mdrcnt
);
2982 desc
.buflen
= mdrcnt
;
2985 * Don't return data but need to get correct length
2986 * init_package will return wrong size if buflen=0
2988 desc
.buflen
= getlen(desc
.format
);
2989 desc
.base
= tmpdata
= (char *)SMB_MALLOC( desc
.buflen
);
2992 if (init_package(&desc
,1,0)) {
2994 fill_printjob_info(conn
,snum
,uLevel
,&desc
,&queue
[i
],i
);
2995 *rdata_len
= desc
.usedlen
;
2998 desc
.errcode
= NERR_JobNotFound
;
3004 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
3005 SSVALS(*rparam
,0,desc
.errcode
);
3007 SSVAL(*rparam
,4,desc
.neededlen
);
3012 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc
.errcode
));
3016 static BOOL
api_WPrintJobEnumerate(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
3017 int mdrcnt
,int mprcnt
,
3018 char **rdata
,char **rparam
,
3019 int *rdata_len
,int *rparam_len
)
3021 char *str1
= param
+2;
3022 char *str2
= skip_string(str1
,1);
3023 char *p
= skip_string(str2
,1);
3029 struct pack_desc desc
;
3030 print_queue_struct
*queue
=NULL
;
3031 print_status_struct status
;
3033 memset((char *)&desc
,'\0',sizeof(desc
));
3034 memset((char *)&status
,'\0',sizeof(status
));
3036 p
= skip_string(p
,1);
3039 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel
,name
));
3041 /* check it's a supported variant */
3042 if (strcmp(str1
,"zWrLeh") != 0)
3046 return False
; /* defined only for uLevel 0,1,2 */
3048 if (!check_printjob_info(&desc
,uLevel
,str2
))
3051 snum
= find_service(name
);
3052 if ( !(lp_snum_ok(snum
) && lp_print_ok(snum
)) )
3055 count
= print_queue_status(snum
,&queue
,&status
);
3056 if (mdrcnt
> 0) *rdata
= SMB_REALLOC_LIMIT(*rdata
,mdrcnt
);
3058 desc
.buflen
= mdrcnt
;
3060 if (init_package(&desc
,count
,0)) {
3062 for (i
= 0; i
< count
; i
++) {
3063 fill_printjob_info(conn
,snum
,uLevel
,&desc
,&queue
[i
],i
);
3064 if (desc
.errcode
== NERR_Success
) succnt
= i
+1;
3068 *rdata_len
= desc
.usedlen
;
3071 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
3072 SSVALS(*rparam
,0,desc
.errcode
);
3074 SSVAL(*rparam
,4,succnt
);
3075 SSVAL(*rparam
,6,count
);
3079 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc
.errcode
));
3083 static int check_printdest_info(struct pack_desc
* desc
,
3084 int uLevel
, char* id
)
3086 desc
->subformat
= NULL
;
3088 case 0: desc
->format
= "B9"; break;
3089 case 1: desc
->format
= "B9B21WWzW"; break;
3090 case 2: desc
->format
= "z"; break;
3091 case 3: desc
->format
= "zzzWWzzzWW"; break;
3092 default: return False
;
3094 if (strcmp(desc
->format
,id
) != 0) return False
;
3098 static void fill_printdest_info(connection_struct
*conn
, int snum
, int uLevel
,
3099 struct pack_desc
* desc
)
3102 strncpy(buf
,SERVICE(snum
),sizeof(buf
)-1);
3103 buf
[sizeof(buf
)-1] = 0;
3106 PACKS(desc
,"B9",buf
); /* szName */
3108 PACKS(desc
,"B21",""); /* szUserName */
3109 PACKI(desc
,"W",0); /* uJobId */
3110 PACKI(desc
,"W",0); /* fsStatus */
3111 PACKS(desc
,"z",""); /* pszStatus */
3112 PACKI(desc
,"W",0); /* time */
3115 if (uLevel
== 2 || uLevel
== 3) {
3116 PACKS(desc
,"z",buf
); /* pszPrinterName */
3118 PACKS(desc
,"z",""); /* pszUserName */
3119 PACKS(desc
,"z",""); /* pszLogAddr */
3120 PACKI(desc
,"W",0); /* uJobId */
3121 PACKI(desc
,"W",0); /* fsStatus */
3122 PACKS(desc
,"z",""); /* pszStatus */
3123 PACKS(desc
,"z",""); /* pszComment */
3124 PACKS(desc
,"z","NULL"); /* pszDrivers */
3125 PACKI(desc
,"W",0); /* time */
3126 PACKI(desc
,"W",0); /* pad1 */
3131 static BOOL
api_WPrintDestGetInfo(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
3132 int mdrcnt
,int mprcnt
,
3133 char **rdata
,char **rparam
,
3134 int *rdata_len
,int *rparam_len
)
3136 char *str1
= param
+2;
3137 char *str2
= skip_string(str1
,1);
3138 char *p
= skip_string(str2
,1);
3139 char* PrinterName
= p
;
3141 struct pack_desc desc
;
3145 memset((char *)&desc
,'\0',sizeof(desc
));
3147 p
= skip_string(p
,1);
3150 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel
,PrinterName
));
3152 /* check it's a supported varient */
3153 if (strcmp(str1
,"zWrLh") != 0) return False
;
3154 if (!check_printdest_info(&desc
,uLevel
,str2
)) return False
;
3156 snum
= find_service(PrinterName
);
3157 if ( !(lp_snum_ok(snum
) && lp_print_ok(snum
)) ) {
3159 desc
.errcode
= NERR_DestNotFound
;
3164 *rdata
= SMB_REALLOC_LIMIT(*rdata
,mdrcnt
);
3166 desc
.buflen
= mdrcnt
;
3169 * Don't return data but need to get correct length
3170 * init_package will return wrong size if buflen=0
3172 desc
.buflen
= getlen(desc
.format
);
3173 desc
.base
= tmpdata
= (char *)SMB_MALLOC( desc
.buflen
);
3175 if (init_package(&desc
,1,0)) {
3176 fill_printdest_info(conn
,snum
,uLevel
,&desc
);
3178 *rdata_len
= desc
.usedlen
;
3182 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
3183 SSVALS(*rparam
,0,desc
.errcode
);
3185 SSVAL(*rparam
,4,desc
.neededlen
);
3187 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc
.errcode
));
3192 static BOOL
api_WPrintDestEnum(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
3193 int mdrcnt
,int mprcnt
,
3194 char **rdata
,char **rparam
,
3195 int *rdata_len
,int *rparam_len
)
3197 char *str1
= param
+2;
3198 char *str2
= skip_string(str1
,1);
3199 char *p
= skip_string(str2
,1);
3203 struct pack_desc desc
;
3204 int services
= lp_numservices();
3206 memset((char *)&desc
,'\0',sizeof(desc
));
3210 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel
));
3212 /* check it's a supported varient */
3213 if (strcmp(str1
,"WrLeh") != 0) return False
;
3214 if (!check_printdest_info(&desc
,uLevel
,str2
)) return False
;
3217 for (i
= 0; i
< services
; i
++)
3218 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
))
3221 if (mdrcnt
> 0) *rdata
= SMB_REALLOC_LIMIT(*rdata
,mdrcnt
);
3223 desc
.buflen
= mdrcnt
;
3224 if (init_package(&desc
,queuecnt
,0)) {
3227 for (i
= 0; i
< services
; i
++) {
3228 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
)) {
3229 fill_printdest_info(conn
,i
,uLevel
,&desc
);
3231 if (desc
.errcode
== NERR_Success
) succnt
= n
;
3236 *rdata_len
= desc
.usedlen
;
3239 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
3240 SSVALS(*rparam
,0,desc
.errcode
);
3242 SSVAL(*rparam
,4,succnt
);
3243 SSVAL(*rparam
,6,queuecnt
);
3245 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc
.errcode
));
3249 static BOOL
api_WPrintDriverEnum(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
3250 int mdrcnt
,int mprcnt
,
3251 char **rdata
,char **rparam
,
3252 int *rdata_len
,int *rparam_len
)
3254 char *str1
= param
+2;
3255 char *str2
= skip_string(str1
,1);
3256 char *p
= skip_string(str2
,1);
3259 struct pack_desc desc
;
3261 memset((char *)&desc
,'\0',sizeof(desc
));
3265 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel
));
3267 /* check it's a supported varient */
3268 if (strcmp(str1
,"WrLeh") != 0) return False
;
3269 if (uLevel
!= 0 || strcmp(str2
,"B41") != 0) return False
;
3271 if (mdrcnt
> 0) *rdata
= SMB_REALLOC_LIMIT(*rdata
,mdrcnt
);
3273 desc
.buflen
= mdrcnt
;
3274 if (init_package(&desc
,1,0)) {
3275 PACKS(&desc
,"B41","NULL");
3278 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
3280 *rdata_len
= desc
.usedlen
;
3283 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
3284 SSVALS(*rparam
,0,desc
.errcode
);
3286 SSVAL(*rparam
,4,succnt
);
3289 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc
.errcode
));
3293 static BOOL
api_WPrintQProcEnum(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
3294 int mdrcnt
,int mprcnt
,
3295 char **rdata
,char **rparam
,
3296 int *rdata_len
,int *rparam_len
)
3298 char *str1
= param
+2;
3299 char *str2
= skip_string(str1
,1);
3300 char *p
= skip_string(str2
,1);
3303 struct pack_desc desc
;
3305 memset((char *)&desc
,'\0',sizeof(desc
));
3309 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel
));
3311 /* check it's a supported varient */
3312 if (strcmp(str1
,"WrLeh") != 0) return False
;
3313 if (uLevel
!= 0 || strcmp(str2
,"B13") != 0) return False
;
3315 if (mdrcnt
> 0) *rdata
= SMB_REALLOC_LIMIT(*rdata
,mdrcnt
);
3317 desc
.buflen
= mdrcnt
;
3319 if (init_package(&desc
,1,0)) {
3320 PACKS(&desc
,"B13","lpd");
3323 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
3325 *rdata_len
= desc
.usedlen
;
3328 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
3329 SSVALS(*rparam
,0,desc
.errcode
);
3331 SSVAL(*rparam
,4,succnt
);
3334 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc
.errcode
));
3338 static BOOL
api_WPrintPortEnum(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
3339 int mdrcnt
,int mprcnt
,
3340 char **rdata
,char **rparam
,
3341 int *rdata_len
,int *rparam_len
)
3343 char *str1
= param
+2;
3344 char *str2
= skip_string(str1
,1);
3345 char *p
= skip_string(str2
,1);
3348 struct pack_desc desc
;
3350 memset((char *)&desc
,'\0',sizeof(desc
));
3354 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel
));
3356 /* check it's a supported varient */
3357 if (strcmp(str1
,"WrLeh") != 0) return False
;
3358 if (uLevel
!= 0 || strcmp(str2
,"B9") != 0) return False
;
3360 if (mdrcnt
> 0) *rdata
= SMB_REALLOC_LIMIT(*rdata
,mdrcnt
);
3361 memset((char *)&desc
,'\0',sizeof(desc
));
3363 desc
.buflen
= mdrcnt
;
3365 if (init_package(&desc
,1,0)) {
3366 PACKS(&desc
,"B13","lp0");
3369 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
3371 *rdata_len
= desc
.usedlen
;
3374 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
3375 SSVALS(*rparam
,0,desc
.errcode
);
3377 SSVAL(*rparam
,4,succnt
);
3380 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc
.errcode
));
3385 /****************************************************************************
3387 ****************************************************************************/
3388 static BOOL
api_RNetSessionEnum(connection_struct
*conn
,uint16 vuid
, char *param
, char *data
,
3389 int mdrcnt
,int mprcnt
,
3390 char **rdata
,char **rparam
,
3391 int *rdata_len
,int *rparam_len
)
3394 char *str1
= param
+2;
3395 char *str2
= skip_string(str1
,1);
3396 char *p
= skip_string(str2
,1);
3398 struct pack_desc desc
;
3399 struct sessionid
*session_list
;
3400 int i
, num_sessions
;
3402 memset((char *)&desc
,'\0',sizeof(desc
));
3406 DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel
));
3407 DEBUG(7,("RNetSessionEnum req string=%s\n",str1
));
3408 DEBUG(7,("RNetSessionEnum ret string=%s\n",str2
));
3410 /* check it's a supported varient */
3411 if (strcmp(str1
,RAP_NetSessionEnum_REQ
) != 0) return False
;
3412 if (uLevel
!= 2 || strcmp(str2
,RAP_SESSION_INFO_L2
) != 0) return False
;
3414 num_sessions
= list_sessions(&session_list
);
3416 if (mdrcnt
> 0) *rdata
= SMB_REALLOC_LIMIT(*rdata
,mdrcnt
);
3417 memset((char *)&desc
,'\0',sizeof(desc
));
3419 desc
.buflen
= mdrcnt
;
3421 if (!init_package(&desc
,num_sessions
,0)) {
3425 for(i
=0; i
<num_sessions
; i
++) {
3426 PACKS(&desc
, "z", session_list
[i
].remote_machine
);
3427 PACKS(&desc
, "z", session_list
[i
].username
);
3428 PACKI(&desc
, "W", 1); /* num conns */
3429 PACKI(&desc
, "W", 0); /* num opens */
3430 PACKI(&desc
, "W", 1); /* num users */
3431 PACKI(&desc
, "D", 0); /* session time */
3432 PACKI(&desc
, "D", 0); /* idle time */
3433 PACKI(&desc
, "D", 0); /* flags */
3434 PACKS(&desc
, "z", "Unknown Client"); /* client type string */
3437 *rdata_len
= desc
.usedlen
;
3440 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
3441 SSVALS(*rparam
,0,desc
.errcode
);
3442 SSVAL(*rparam
,2,0); /* converter */
3443 SSVAL(*rparam
,4,num_sessions
); /* count */
3445 DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc
.errcode
));
3450 /****************************************************************************
3451 The buffer was too small
3452 ****************************************************************************/
3454 static BOOL
api_TooSmall(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
3455 int mdrcnt
,int mprcnt
,
3456 char **rdata
,char **rparam
,
3457 int *rdata_len
,int *rparam_len
)
3459 *rparam_len
= MIN(*rparam_len
,mprcnt
);
3460 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
3464 SSVAL(*rparam
,0,NERR_BufTooSmall
);
3466 DEBUG(3,("Supplied buffer too small in API command\n"));
3472 /****************************************************************************
3473 The request is not supported
3474 ****************************************************************************/
3476 static BOOL
api_Unsupported(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
3477 int mdrcnt
,int mprcnt
,
3478 char **rdata
,char **rparam
,
3479 int *rdata_len
,int *rparam_len
)
3482 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
3486 SSVAL(*rparam
,0,NERR_notsupported
);
3487 SSVAL(*rparam
,2,0); /* converter word */
3489 DEBUG(3,("Unsupported API command\n"));
3501 BOOL (*fn
)(connection_struct
*,uint16
,char *,char *,
3502 int,int,char **,char **,int *,int *);
3503 BOOL auth_user
; /* Deny anonymous access? */
3504 } api_commands
[] = {
3505 {"RNetShareEnum", RAP_WshareEnum
, api_RNetShareEnum
, True
},
3506 {"RNetShareGetInfo", RAP_WshareGetInfo
, api_RNetShareGetInfo
},
3507 {"RNetShareAdd", RAP_WshareAdd
, api_RNetShareAdd
},
3508 {"RNetSessionEnum", RAP_WsessionEnum
, api_RNetSessionEnum
, True
},
3509 {"RNetServerGetInfo", RAP_WserverGetInfo
, api_RNetServerGetInfo
},
3510 {"RNetGroupEnum", RAP_WGroupEnum
, api_RNetGroupEnum
, True
},
3511 {"RNetGroupGetUsers", RAP_WGroupGetUsers
, api_RNetGroupGetUsers
, True
},
3512 {"RNetUserEnum", RAP_WUserEnum
, api_RNetUserEnum
, True
},
3513 {"RNetUserGetInfo", RAP_WUserGetInfo
, api_RNetUserGetInfo
},
3514 {"NetUserGetGroups", RAP_WUserGetGroups
, api_NetUserGetGroups
},
3515 {"NetWkstaGetInfo", RAP_WWkstaGetInfo
, api_NetWkstaGetInfo
},
3516 {"DosPrintQEnum", RAP_WPrintQEnum
, api_DosPrintQEnum
, True
},
3517 {"DosPrintQGetInfo", RAP_WPrintQGetInfo
, api_DosPrintQGetInfo
},
3518 {"WPrintQueuePause", RAP_WPrintQPause
, api_WPrintQueueCtrl
},
3519 {"WPrintQueueResume", RAP_WPrintQContinue
, api_WPrintQueueCtrl
},
3520 {"WPrintJobEnumerate",RAP_WPrintJobEnum
, api_WPrintJobEnumerate
},
3521 {"WPrintJobGetInfo", RAP_WPrintJobGetInfo
, api_WPrintJobGetInfo
},
3522 {"RDosPrintJobDel", RAP_WPrintJobDel
, api_RDosPrintJobDel
},
3523 {"RDosPrintJobPause", RAP_WPrintJobPause
, api_RDosPrintJobDel
},
3524 {"RDosPrintJobResume",RAP_WPrintJobContinue
, api_RDosPrintJobDel
},
3525 {"WPrintDestEnum", RAP_WPrintDestEnum
, api_WPrintDestEnum
},
3526 {"WPrintDestGetInfo", RAP_WPrintDestGetInfo
, api_WPrintDestGetInfo
},
3527 {"NetRemoteTOD", RAP_NetRemoteTOD
, api_NetRemoteTOD
},
3528 {"WPrintQueuePurge", RAP_WPrintQPurge
, api_WPrintQueueCtrl
},
3529 {"NetServerEnum", RAP_NetServerEnum2
, api_RNetServerEnum
}, /* anon OK */
3530 {"WAccessGetUserPerms",RAP_WAccessGetUserPerms
,api_WAccessGetUserPerms
},
3531 {"SetUserPassword", RAP_WUserPasswordSet2
, api_SetUserPassword
},
3532 {"WWkstaUserLogon", RAP_WWkstaUserLogon
, api_WWkstaUserLogon
},
3533 {"PrintJobInfo", RAP_WPrintJobSetInfo
, api_PrintJobInfo
},
3534 {"WPrintDriverEnum", RAP_WPrintDriverEnum
, api_WPrintDriverEnum
},
3535 {"WPrintQProcEnum", RAP_WPrintQProcessorEnum
,api_WPrintQProcEnum
},
3536 {"WPrintPortEnum", RAP_WPrintPortEnum
, api_WPrintPortEnum
},
3537 {"SamOEMChangePassword",RAP_SamOEMChgPasswordUser2_P
,api_SamOEMChangePassword
}, /* anon OK */
3538 {NULL
, -1, api_Unsupported
}};
3540 /* The following RAP calls are not implemented by Samba:
3542 RAP_WFileEnum2 - anon not OK
3545 /****************************************************************************
3546 Handle remote api calls
3547 ****************************************************************************/
3549 int api_reply(connection_struct
*conn
,uint16 vuid
,char *outbuf
,char *data
,char *params
,
3550 int tdscnt
,int tpscnt
,int mdrcnt
,int mprcnt
)
3554 char *rparam
= NULL
;
3561 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
3565 api_command
= SVAL(params
,0);
3567 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
3570 skip_string(params
+2,1),
3571 tdscnt
,tpscnt
,mdrcnt
,mprcnt
));
3573 for (i
=0;api_commands
[i
].name
;i
++) {
3574 if (api_commands
[i
].id
== api_command
&& api_commands
[i
].fn
) {
3575 DEBUG(3,("Doing %s\n",api_commands
[i
].name
));
3580 /* Check whether this api call can be done anonymously */
3582 if (api_commands
[i
].auth_user
&& lp_restrict_anonymous()) {
3583 user_struct
*user
= get_valid_user_struct(vuid
);
3585 if (!user
|| user
->guest
)
3586 return ERROR_NT(NT_STATUS_ACCESS_DENIED
);
3589 rdata
= (char *)SMB_MALLOC(1024);
3591 memset(rdata
,'\0',1024);
3593 rparam
= (char *)SMB_MALLOC(1024);
3595 memset(rparam
,'\0',1024);
3597 if(!rdata
|| !rparam
) {
3598 DEBUG(0,("api_reply: malloc fail !\n"));
3602 reply
= api_commands
[i
].fn(conn
,vuid
,params
,data
,mdrcnt
,mprcnt
,
3603 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
3606 if (rdata_len
> mdrcnt
||
3607 rparam_len
> mprcnt
) {
3608 reply
= api_TooSmall(conn
,vuid
,params
,data
,mdrcnt
,mprcnt
,
3609 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
3612 /* if we get False back then it's actually unsupported */
3614 api_Unsupported(conn
,vuid
,params
,data
,mdrcnt
,mprcnt
,
3615 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
3617 send_trans_reply(outbuf
, rparam
, rparam_len
, rdata
, rdata_len
, False
);