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 #define NERR_Success 0
36 #define NERR_badpass 86
37 #define NERR_notsupported 50
39 #define NERR_BASE (2100)
40 #define NERR_BufTooSmall (NERR_BASE+23)
41 #define NERR_JobNotFound (NERR_BASE+51)
42 #define NERR_DestNotFound (NERR_BASE+52)
44 #define ACCESS_READ 0x01
45 #define ACCESS_WRITE 0x02
46 #define ACCESS_CREATE 0x04
48 #define SHPWLEN 8 /* share password length */
50 static BOOL
api_Unsupported(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
51 int mdrcnt
,int mprcnt
,
52 char **rdata
,char **rparam
,
53 int *rdata_len
,int *rparam_len
);
54 static BOOL
api_TooSmall(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
55 int mdrcnt
,int mprcnt
,
56 char **rdata
,char **rparam
,
57 int *rdata_len
,int *rparam_len
);
60 static int CopyExpanded(connection_struct
*conn
,
61 int snum
, char** dst
, char* src
, int* n
)
66 if (!src
|| !dst
|| !n
|| !(*dst
)) return(0);
68 StrnCpy(buf
,src
,sizeof(buf
)/2);
69 pstring_sub(buf
,"%S",lp_servicename(snum
));
70 standard_sub_conn(conn
,buf
,sizeof(buf
));
71 l
= push_ascii(*dst
,buf
,*n
, STR_TERMINATE
);
77 static int CopyAndAdvance(char** dst
, char* src
, int* n
)
80 if (!src
|| !dst
|| !n
|| !(*dst
)) return(0);
81 l
= push_ascii(*dst
,src
,*n
, STR_TERMINATE
);
87 static int StrlenExpanded(connection_struct
*conn
, int snum
, char* s
)
91 StrnCpy(buf
,s
,sizeof(buf
)/2);
92 pstring_sub(buf
,"%S",lp_servicename(snum
));
93 standard_sub_conn(conn
,buf
,sizeof(buf
));
94 return strlen(buf
) + 1;
97 static char* Expand(connection_struct
*conn
, int snum
, char* s
)
100 if (!s
) return(NULL
);
101 StrnCpy(buf
,s
,sizeof(buf
)/2);
102 pstring_sub(buf
,"%S",lp_servicename(snum
));
103 standard_sub_conn(conn
,buf
,sizeof(buf
));
107 /*******************************************************************
108 check a API string for validity when we only need to check the prefix
109 ******************************************************************/
110 static BOOL
prefix_ok(const char *str
, const char *prefix
)
112 return(strncmp(str
,prefix
,strlen(prefix
)) == 0);
116 const char* format
; /* formatstring for structure */
117 const char* subformat
; /* subformat for structure */
118 char* base
; /* baseaddress of buffer */
119 int buflen
; /* remaining size for fixed part; on init: length of base */
120 int subcount
; /* count of substructures */
121 char* structbuf
; /* pointer into buffer for remaining fixed part */
122 int stringlen
; /* remaining size for variable part */
123 char* stringbuf
; /* pointer into buffer for remaining variable part */
124 int neededlen
; /* total needed size */
125 int usedlen
; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
126 const char* curpos
; /* current position; pointer into format or subformat */
130 static int get_counter(const char** p
)
133 if (!p
|| !(*p
)) return(1);
134 if (!isdigit((int)**p
)) return 1;
138 n
= 10 * n
+ (i
- '0');
145 static int getlen(const char* p
)
151 case 'W': /* word (2 byte) */
154 case 'K': /* status word? (2 byte) */
157 case 'N': /* count of substructures (word) at end */
160 case 'D': /* double word (4 byte) */
161 case 'z': /* offset to zero terminated string (4 byte) */
162 case 'l': /* offset to user data (4 byte) */
165 case 'b': /* offset to data (with counter) (4 byte) */
169 case 'B': /* byte (with optional counter) */
170 n
+= get_counter(&p
);
177 static BOOL
init_package(struct pack_desc
* p
, int count
, int subcount
)
182 if (!p
->format
|| !p
->base
) return(False
);
184 i
= count
* getlen(p
->format
);
185 if (p
->subformat
) i
+= subcount
* getlen(p
->subformat
);
186 p
->structbuf
= p
->base
;
190 p
->curpos
= p
->format
;
196 * This is the old error code we used. Aparently
197 * WinNT/2k systems return ERRbuftoosmall (2123) and
198 * OS/2 needs this. I'm leaving this here so we can revert
201 p
->errcode
= ERRmoredata
;
203 p
->errcode
= ERRbuftoosmall
;
207 p
->errcode
= NERR_Success
;
210 p
->stringbuf
= p
->base
+ i
;
212 return(p
->errcode
== NERR_Success
);
215 static int package(struct pack_desc
* p
, ...)
218 int needed
=0, stringneeded
;
219 const char* str
=NULL
;
220 int is_string
=0, stringused
;
227 p
->curpos
= p
->format
;
229 p
->curpos
= p
->subformat
;
234 str
= va_arg(args
,char*);
235 SMB_ASSERT(strncmp(str
,p
->curpos
,strlen(str
)) == 0);
244 switch( *p
->curpos
++ ) {
245 case 'W': /* word (2 byte) */
247 temp
= va_arg(args
,int);
248 if (p
->buflen
>= needed
) SSVAL(p
->structbuf
,0,temp
);
250 case 'K': /* status word? (2 byte) */
252 temp
= va_arg(args
,int);
253 if (p
->buflen
>= needed
) SSVAL(p
->structbuf
,0,temp
);
255 case 'N': /* count of substructures (word) at end */
257 p
->subcount
= va_arg(args
,int);
258 if (p
->buflen
>= needed
) SSVAL(p
->structbuf
,0,p
->subcount
);
260 case 'D': /* double word (4 byte) */
262 temp
= va_arg(args
,int);
263 if (p
->buflen
>= needed
) SIVAL(p
->structbuf
,0,temp
);
265 case 'B': /* byte (with optional counter) */
266 needed
= get_counter(&p
->curpos
);
268 char *s
= va_arg(args
,char*);
269 if (p
->buflen
>= needed
) StrnCpy(p
->structbuf
,s
?s
:"",needed
-1);
272 case 'z': /* offset to zero terminated string (4 byte) */
273 str
= va_arg(args
,char*);
274 stringneeded
= (str
? strlen(str
)+1 : 0);
277 case 'l': /* offset to user data (4 byte) */
278 str
= va_arg(args
,char*);
279 stringneeded
= va_arg(args
,int);
282 case 'b': /* offset to data (with counter) (4 byte) */
283 str
= va_arg(args
,char*);
284 stringneeded
= get_counter(&p
->curpos
);
289 if (stringneeded
>= 0) {
291 if (p
->buflen
>= needed
) {
292 stringused
= stringneeded
;
293 if (stringused
> p
->stringlen
) {
294 stringused
= (is_string
? p
->stringlen
: 0);
295 if (p
->errcode
== NERR_Success
) p
->errcode
= ERRmoredata
;
298 SIVAL(p
->structbuf
,0,0);
300 SIVAL(p
->structbuf
,0,PTR_DIFF(p
->stringbuf
,p
->base
));
301 memcpy(p
->stringbuf
,str
?str
:"",stringused
);
302 if (is_string
) p
->stringbuf
[stringused
-1] = '\0';
303 p
->stringbuf
+= stringused
;
304 p
->stringlen
-= stringused
;
305 p
->usedlen
+= stringused
;
308 p
->neededlen
+= stringneeded
;
310 p
->neededlen
+= needed
;
311 if (p
->buflen
>= needed
) {
312 p
->structbuf
+= needed
;
314 p
->usedlen
+= needed
;
317 if (p
->errcode
== NERR_Success
) p
->errcode
= ERRmoredata
;
323 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
324 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
326 #define PACK(desc,t,v) package(desc,v)
327 #define PACKl(desc,t,v,l) package(desc,v,l)
330 static void PACKI(struct pack_desc
* desc
, const char *t
,int v
)
335 static void PACKS(struct pack_desc
* desc
,const char *t
,const char *v
)
341 /****************************************************************************
343 ****************************************************************************/
344 static void PackDriverData(struct pack_desc
* desc
)
346 char drivdata
[4+4+32];
347 SIVAL(drivdata
,0,sizeof drivdata
); /* cb */
348 SIVAL(drivdata
,4,1000); /* lVersion */
349 memset(drivdata
+8,0,32); /* szDeviceName */
350 push_ascii(drivdata
+8,"NULL",-1, STR_TERMINATE
);
351 PACKl(desc
,"l",drivdata
,sizeof drivdata
); /* pDriverData */
354 static int check_printq_info(struct pack_desc
* desc
,
355 int uLevel
, char *id1
, char *id2
)
357 desc
->subformat
= NULL
;
360 desc
->format
= "B13";
363 desc
->format
= "B13BWWWzzzzzWW";
366 desc
->format
= "B13BWWWzzzzzWN";
367 desc
->subformat
= "WB21BB16B10zWWzDDz";
370 desc
->format
= "zWWWWzzzzWWzzl";
373 desc
->format
= "zWWWWzzzzWNzzl";
374 desc
->subformat
= "WWzWWDDzz";
383 desc
->format
= "WzzzzzzzzN";
384 desc
->subformat
= "z";
386 default: return False
;
388 if (strcmp(desc
->format
,id1
) != 0) return False
;
389 if (desc
->subformat
&& strcmp(desc
->subformat
,id2
) != 0) return False
;
394 #define RAP_JOB_STATUS_QUEUED 0
395 #define RAP_JOB_STATUS_PAUSED 1
396 #define RAP_JOB_STATUS_SPOOLING 2
397 #define RAP_JOB_STATUS_PRINTING 3
398 #define RAP_JOB_STATUS_PRINTED 4
400 #define RAP_QUEUE_STATUS_PAUSED 1
401 #define RAP_QUEUE_STATUS_ERROR 2
403 /* turn a print job status into a on the wire status
405 static int printj_status(int v
)
409 return RAP_JOB_STATUS_QUEUED
;
411 return RAP_JOB_STATUS_PAUSED
;
413 return RAP_JOB_STATUS_SPOOLING
;
415 return RAP_JOB_STATUS_PRINTING
;
420 /* turn a print queue status into a on the wire status
422 static int printq_status(int v
)
428 return RAP_QUEUE_STATUS_PAUSED
;
430 return RAP_QUEUE_STATUS_ERROR
;
433 static void fill_printjob_info(connection_struct
*conn
, int snum
, int uLevel
,
434 struct pack_desc
* desc
,
435 print_queue_struct
* queue
, int n
)
437 time_t t
= queue
->time
;
439 /* the client expects localtime */
442 PACKI(desc
,"W",pjobid_to_rap(lp_const_servicename(snum
),queue
->job
)); /* uJobId */
444 PACKS(desc
,"B21",queue
->fs_user
); /* szUserName */
445 PACKS(desc
,"B",""); /* pad */
446 PACKS(desc
,"B16",""); /* szNotifyName */
447 PACKS(desc
,"B10","PM_Q_RAW"); /* szDataType */
448 PACKS(desc
,"z",""); /* pszParms */
449 PACKI(desc
,"W",n
+1); /* uPosition */
450 PACKI(desc
,"W",printj_status(queue
->status
)); /* fsStatus */
451 PACKS(desc
,"z",""); /* pszStatus */
452 PACKI(desc
,"D",t
); /* ulSubmitted */
453 PACKI(desc
,"D",queue
->size
); /* ulSize */
454 PACKS(desc
,"z",queue
->fs_file
); /* pszComment */
456 if (uLevel
== 2 || uLevel
== 3 || uLevel
== 4) {
457 PACKI(desc
,"W",queue
->priority
); /* uPriority */
458 PACKS(desc
,"z",queue
->fs_user
); /* pszUserName */
459 PACKI(desc
,"W",n
+1); /* uPosition */
460 PACKI(desc
,"W",printj_status(queue
->status
)); /* fsStatus */
461 PACKI(desc
,"D",t
); /* ulSubmitted */
462 PACKI(desc
,"D",queue
->size
); /* ulSize */
463 PACKS(desc
,"z","Samba"); /* pszComment */
464 PACKS(desc
,"z",queue
->fs_file
); /* pszDocument */
466 PACKS(desc
,"z",""); /* pszNotifyName */
467 PACKS(desc
,"z","PM_Q_RAW"); /* pszDataType */
468 PACKS(desc
,"z",""); /* pszParms */
469 PACKS(desc
,"z",""); /* pszStatus */
470 PACKS(desc
,"z",SERVICE(snum
)); /* pszQueue */
471 PACKS(desc
,"z","lpd"); /* pszQProcName */
472 PACKS(desc
,"z",""); /* pszQProcParms */
473 PACKS(desc
,"z","NULL"); /* pszDriverName */
474 PackDriverData(desc
); /* pDriverData */
475 PACKS(desc
,"z",""); /* pszPrinterName */
476 } else if (uLevel
== 4) { /* OS2 */
477 PACKS(desc
,"z",""); /* pszSpoolFileName */
478 PACKS(desc
,"z",""); /* pszPortName */
479 PACKS(desc
,"z",""); /* pszStatus */
480 PACKI(desc
,"D",0); /* ulPagesSpooled */
481 PACKI(desc
,"D",0); /* ulPagesSent */
482 PACKI(desc
,"D",0); /* ulPagesPrinted */
483 PACKI(desc
,"D",0); /* ulTimePrinted */
484 PACKI(desc
,"D",0); /* ulExtendJobStatus */
485 PACKI(desc
,"D",0); /* ulStartPage */
486 PACKI(desc
,"D",0); /* ulEndPage */
491 /********************************************************************
492 Return a driver name given an snum.
493 Returns True if from tdb, False otherwise.
494 ********************************************************************/
496 static BOOL
get_driver_name(int snum
, pstring drivername
)
498 NT_PRINTER_INFO_LEVEL
*info
= NULL
;
501 get_a_printer (NULL
, &info
, 2, lp_servicename(snum
));
503 pstrcpy( drivername
, info
->info_2
->drivername
);
505 free_a_printer(&info
, 2);
511 /********************************************************************
512 Respond to the DosPrintQInfo command with a level of 52
513 This is used to get printer driver information for Win9x clients
514 ********************************************************************/
515 static void fill_printq_info_52(connection_struct
*conn
, int snum
,
516 struct pack_desc
* desc
, int count
)
520 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
521 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
525 if ( !W_ERROR_IS_OK(get_a_printer( NULL
, &printer
, 2, lp_servicename(snum
))) ) {
526 DEBUG(3,("fill_printq_info_52: Failed to lookup printer [%s]\n",
527 lp_servicename(snum
)));
531 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
,
534 DEBUG(3,("fill_printq_info_52: Failed to lookup driver [%s]\n",
535 printer
->info_2
->drivername
));
539 trim_string(driver
.info_3
->driverpath
, "\\print$\\WIN40\\0\\", 0);
540 trim_string(driver
.info_3
->datafile
, "\\print$\\WIN40\\0\\", 0);
541 trim_string(driver
.info_3
->helpfile
, "\\print$\\WIN40\\0\\", 0);
543 PACKI(desc
, "W", 0x0400); /* don't know */
544 PACKS(desc
, "z", driver
.info_3
->name
); /* long printer name */
545 PACKS(desc
, "z", driver
.info_3
->driverpath
); /* Driverfile Name */
546 PACKS(desc
, "z", driver
.info_3
->datafile
); /* Datafile name */
547 PACKS(desc
, "z", driver
.info_3
->monitorname
); /* language monitor */
549 fstrcpy(location
, "\\\\%L\\print$\\WIN40\\0");
550 standard_sub_basic( "", location
, sizeof(location
)-1 );
551 PACKS(desc
,"z", location
); /* share to retrieve files */
553 PACKS(desc
,"z", driver
.info_3
->defaultdatatype
); /* default data type */
554 PACKS(desc
,"z", driver
.info_3
->helpfile
); /* helpfile name */
555 PACKS(desc
,"z", driver
.info_3
->driverpath
); /* driver name */
557 DEBUG(3,("Printer Driver Name: %s:\n",driver
.info_3
->name
));
558 DEBUG(3,("Driver: %s:\n",driver
.info_3
->driverpath
));
559 DEBUG(3,("Data File: %s:\n",driver
.info_3
->datafile
));
560 DEBUG(3,("Language Monitor: %s:\n",driver
.info_3
->monitorname
));
561 DEBUG(3,("Driver Location: %s:\n",location
));
562 DEBUG(3,("Data Type: %s:\n",driver
.info_3
->defaultdatatype
));
563 DEBUG(3,("Help File: %s:\n",driver
.info_3
->helpfile
));
564 PACKI(desc
,"N",count
); /* number of files to copy */
566 for ( i
=0; i
<count
&& driver
.info_3
->dependentfiles
&& *driver
.info_3
->dependentfiles
[i
]; i
++)
568 trim_string(driver
.info_3
->dependentfiles
[i
], "\\print$\\WIN40\\0\\", 0);
569 PACKS(desc
,"z",driver
.info_3
->dependentfiles
[i
]); /* driver files to copy */
570 DEBUG(3,("Dependent File: %s:\n",driver
.info_3
->dependentfiles
[i
]));
575 DEBUG(3,("fill_printq_info_52: file count specified by client [%d] != number of dependent files [%i]\n",
578 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n", SERVICE(snum
),i
));
580 desc
->errcode
=NERR_Success
;
584 DEBUG(3,("fill_printq_info: Can't supply driver files\n"));
585 desc
->errcode
=NERR_notsupported
;
589 free_a_printer( &printer
, 2 );
592 free_a_printer_driver( driver
, 3 );
596 static void fill_printq_info(connection_struct
*conn
, int snum
, int uLevel
,
597 struct pack_desc
* desc
,
598 int count
, print_queue_struct
* queue
,
599 print_status_struct
* status
)
604 PACKS(desc
,"B13",SERVICE(snum
));
609 PACKS(desc
,"z",Expand(conn
,snum
,SERVICE(snum
)));
612 PACKI(desc
,"K",printq_status(status
->status
));
616 if (uLevel
== 1 || uLevel
== 2) {
617 PACKS(desc
,"B",""); /* alignment */
618 PACKI(desc
,"W",5); /* priority */
619 PACKI(desc
,"W",0); /* start time */
620 PACKI(desc
,"W",0); /* until time */
621 PACKS(desc
,"z",""); /* pSepFile */
622 PACKS(desc
,"z","lpd"); /* pPrProc */
623 PACKS(desc
,"z",SERVICE(snum
)); /* pDestinations */
624 PACKS(desc
,"z",""); /* pParms */
626 PACKS(desc
,"z","UNKNOWN PRINTER");
627 PACKI(desc
,"W",LPSTAT_ERROR
);
629 else if (!status
|| !status
->message
[0]) {
630 PACKS(desc
,"z",Expand(conn
,snum
,lp_comment(snum
)));
631 PACKI(desc
,"W",LPSTAT_OK
); /* status */
633 PACKS(desc
,"z",status
->message
);
634 PACKI(desc
,"W",printq_status(status
->status
)); /* status */
636 PACKI(desc
,(uLevel
== 1 ? "W" : "N"),count
);
639 if (uLevel
== 3 || uLevel
== 4) {
642 PACKI(desc
,"W",5); /* uPriority */
643 PACKI(desc
,"W",0); /* uStarttime */
644 PACKI(desc
,"W",0); /* uUntiltime */
645 PACKI(desc
,"W",5); /* pad1 */
646 PACKS(desc
,"z",""); /* pszSepFile */
647 PACKS(desc
,"z","WinPrint"); /* pszPrProc */
648 PACKS(desc
,"z",NULL
); /* pszParms */
649 PACKS(desc
,"z",NULL
); /* pszComment - don't ask.... JRA */
650 /* "don't ask" that it's done this way to fix corrupted
651 Win9X/ME printer comments. */
653 PACKI(desc
,"W",LPSTAT_OK
); /* fsStatus */
655 PACKI(desc
,"W",printq_status(status
->status
)); /* fsStatus */
657 PACKI(desc
,(uLevel
== 3 ? "W" : "N"),count
); /* cJobs */
658 PACKS(desc
,"z",SERVICE(snum
)); /* pszPrinters */
659 get_driver_name(snum
,drivername
);
660 PACKS(desc
,"z",drivername
); /* pszDriverName */
661 PackDriverData(desc
); /* pDriverData */
664 if (uLevel
== 2 || uLevel
== 4) {
666 for (i
=0;i
<count
;i
++)
667 fill_printjob_info(conn
,snum
,uLevel
== 2 ? 1 : 2,desc
,&queue
[i
],i
);
671 fill_printq_info_52( conn
, snum
, desc
, count
);
674 /* This function returns the number of files for a given driver */
675 static int get_printerdrivernumber(int snum
)
678 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
679 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
683 if ( !W_ERROR_IS_OK(get_a_printer( NULL
, &printer
, 2, lp_servicename(snum
))) ) {
684 DEBUG(3,("get_printerdrivernumber: Failed to lookup printer [%s]\n",
685 lp_servicename(snum
)));
689 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
,
692 DEBUG(3,("get_printerdrivernumber: Failed to lookup driver [%s]\n",
693 printer
->info_2
->drivername
));
697 /* count the number of files */
698 while ( driver
.info_3
->dependentfiles
&& *driver
.info_3
->dependentfiles
[result
] )
703 free_a_printer( &printer
, 2 );
706 free_a_printer_driver( driver
, 3 );
711 static BOOL
api_DosPrintQGetInfo(connection_struct
*conn
,
712 uint16 vuid
, char *param
,char *data
,
713 int mdrcnt
,int mprcnt
,
714 char **rdata
,char **rparam
,
715 int *rdata_len
,int *rparam_len
)
717 char *str1
= param
+2;
718 char *str2
= skip_string(str1
,1);
719 char *p
= skip_string(str2
,1);
725 struct pack_desc desc
;
726 print_queue_struct
*queue
=NULL
;
727 print_status_struct status
;
730 memset((char *)&status
,'\0',sizeof(status
));
731 memset((char *)&desc
,'\0',sizeof(desc
));
733 p
= skip_string(p
,1);
737 /* remove any trailing username */
738 if ((p
= strchr_m(QueueName
,'%')))
741 DEBUG(3,("api_DosPrintQGetInfo uLevel=%d name=%s\n",uLevel
,QueueName
));
743 /* check it's a supported varient */
744 if (!prefix_ok(str1
,"zWrLh"))
746 if (!check_printq_info(&desc
,uLevel
,str2
,str3
)) {
748 * Patch from Scott Moomaw <scott@bridgewater.edu>
749 * to return the 'invalid info level' error if an
750 * unknown level was requested.
754 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
755 SSVALS(*rparam
,0,ERRunknownlevel
);
761 snum
= find_service(QueueName
);
762 if ( !(lp_snum_ok(snum
) && lp_print_ok(snum
)) )
766 count
= get_printerdrivernumber(snum
);
767 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count
));
769 count
= print_queue_status(snum
, &queue
,&status
);
773 *rdata
= SMB_REALLOC_LIMIT(*rdata
,mdrcnt
);
775 desc
.buflen
= mdrcnt
;
778 * Don't return data but need to get correct length
779 * init_package will return wrong size if buflen=0
781 desc
.buflen
= getlen(desc
.format
);
782 desc
.base
= tmpdata
= (char *) SMB_MALLOC (desc
.buflen
);
785 if (init_package(&desc
,1,count
)) {
786 desc
.subcount
= count
;
787 fill_printq_info(conn
,snum
,uLevel
,&desc
,count
,queue
,&status
);
790 *rdata_len
= desc
.usedlen
;
793 * We must set the return code to ERRbuftoosmall
794 * in order to support lanman style printing with Win NT/2k
797 if (!mdrcnt
&& lp_disable_spoolss())
798 desc
.errcode
= ERRbuftoosmall
;
800 *rdata_len
= desc
.usedlen
;
802 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
803 SSVALS(*rparam
,0,desc
.errcode
);
805 SSVAL(*rparam
,4,desc
.neededlen
);
807 DEBUG(4,("printqgetinfo: errorcode %d\n",desc
.errcode
));
815 /****************************************************************************
816 View list of all print jobs on all queues.
817 ****************************************************************************/
819 static BOOL
api_DosPrintQEnum(connection_struct
*conn
, uint16 vuid
, char* param
, char* data
,
820 int mdrcnt
, int mprcnt
,
821 char **rdata
, char** rparam
,
822 int *rdata_len
, int *rparam_len
)
824 char *param_format
= param
+2;
825 char *output_format1
= skip_string(param_format
,1);
826 char *p
= skip_string(output_format1
,1);
827 int uLevel
= SVAL(p
,0);
828 char *output_format2
= p
+ 4;
829 int services
= lp_numservices();
831 struct pack_desc desc
;
832 print_queue_struct
**queue
= NULL
;
833 print_status_struct
*status
= NULL
;
834 int* subcntarr
= NULL
;
835 int queuecnt
, subcnt
=0, succnt
=0;
837 memset((char *)&desc
,'\0',sizeof(desc
));
839 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel
));
841 if (!prefix_ok(param_format
,"WrLeh")) return False
;
842 if (!check_printq_info(&desc
,uLevel
,output_format1
,output_format2
)) {
844 * Patch from Scott Moomaw <scott@bridgewater.edu>
845 * to return the 'invalid info level' error if an
846 * unknown level was requested.
850 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
851 SSVALS(*rparam
,0,ERRunknownlevel
);
858 for (i
= 0; i
< services
; i
++)
859 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
))
862 if((queue
= SMB_MALLOC_ARRAY(print_queue_struct
*, queuecnt
)) == NULL
) {
863 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
866 memset(queue
,0,queuecnt
*sizeof(print_queue_struct
*));
867 if((status
= SMB_MALLOC_ARRAY(print_status_struct
,queuecnt
)) == NULL
) {
868 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
871 memset(status
,0,queuecnt
*sizeof(print_status_struct
));
872 if((subcntarr
= SMB_MALLOC_ARRAY(int,queuecnt
)) == NULL
) {
873 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
878 for (i
= 0; i
< services
; i
++)
879 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
)) {
880 subcntarr
[n
] = print_queue_status(i
, &queue
[n
],&status
[n
]);
881 subcnt
+= subcntarr
[n
];
885 if (mdrcnt
> 0) *rdata
= SMB_REALLOC_LIMIT(*rdata
,mdrcnt
);
887 desc
.buflen
= mdrcnt
;
889 if (init_package(&desc
,queuecnt
,subcnt
)) {
892 for (i
= 0; i
< services
; i
++)
893 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
)) {
894 fill_printq_info(conn
,i
,uLevel
,&desc
,subcntarr
[n
],queue
[n
],&status
[n
]);
896 if (desc
.errcode
== NERR_Success
) succnt
= n
;
900 SAFE_FREE(subcntarr
);
902 *rdata_len
= desc
.usedlen
;
904 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
905 SSVALS(*rparam
,0,desc
.errcode
);
907 SSVAL(*rparam
,4,succnt
);
908 SSVAL(*rparam
,6,queuecnt
);
910 for (i
= 0; i
< queuecnt
; i
++) {
911 if (queue
) SAFE_FREE(queue
[i
]);
920 /****************************************************************************
921 get info level for a server list query
922 ****************************************************************************/
923 static BOOL
check_server_info(int uLevel
, char* id
)
927 if (strcmp(id
,"B16") != 0) return False
;
930 if (strcmp(id
,"B16BBDz") != 0) return False
;
938 struct srv_info_struct
948 /*******************************************************************
949 get server info lists from the files saved by nmbd. Return the
951 ******************************************************************/
952 static int get_server_info(uint32 servertype
,
953 struct srv_info_struct
**servers
,
959 BOOL local_list_only
;
962 lines
= file_lines_load(lock_path(SERVER_LIST
), NULL
);
964 DEBUG(4,("Can't open %s - %s\n",lock_path(SERVER_LIST
),strerror(errno
)));
968 /* request for everything is code for request all servers */
969 if (servertype
== SV_TYPE_ALL
)
970 servertype
&= ~(SV_TYPE_DOMAIN_ENUM
|SV_TYPE_LOCAL_LIST_ONLY
);
972 local_list_only
= (servertype
& SV_TYPE_LOCAL_LIST_ONLY
);
974 DEBUG(4,("Servertype search: %8x\n",servertype
));
976 for (i
=0;lines
[i
];i
++) {
978 struct srv_info_struct
*s
;
979 const char *ptr
= lines
[i
];
984 if (count
== alloced
) {
985 struct srv_info_struct
*ts
;
988 ts
= SMB_REALLOC_ARRAY(*servers
,struct srv_info_struct
, alloced
);
990 DEBUG(0,("get_server_info: failed to enlarge servers info struct!\n"));
994 memset((char *)((*servers
)+count
),'\0',sizeof(**servers
)*(alloced
-count
));
996 s
= &(*servers
)[count
];
998 if (!next_token(&ptr
,s
->name
, NULL
, sizeof(s
->name
))) continue;
999 if (!next_token(&ptr
,stype
, NULL
, sizeof(stype
))) continue;
1000 if (!next_token(&ptr
,s
->comment
, NULL
, sizeof(s
->comment
))) continue;
1001 if (!next_token(&ptr
,s
->domain
, NULL
, sizeof(s
->domain
))) {
1002 /* this allows us to cope with an old nmbd */
1003 fstrcpy(s
->domain
,lp_workgroup());
1006 if (sscanf(stype
,"%X",&s
->type
) != 1) {
1007 DEBUG(4,("r:host file "));
1011 /* Filter the servers/domains we return based on what was asked for. */
1013 /* Check to see if we are being asked for a local list only. */
1014 if(local_list_only
&& ((s
->type
& SV_TYPE_LOCAL_LIST_ONLY
) == 0)) {
1015 DEBUG(4,("r: local list only"));
1019 /* doesn't match up: don't want it */
1020 if (!(servertype
& s
->type
)) {
1021 DEBUG(4,("r:serv type "));
1025 if ((servertype
& SV_TYPE_DOMAIN_ENUM
) !=
1026 (s
->type
& SV_TYPE_DOMAIN_ENUM
))
1028 DEBUG(4,("s: dom mismatch "));
1032 if (!strequal(domain
, s
->domain
) && !(servertype
& SV_TYPE_DOMAIN_ENUM
))
1037 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1038 s
->type
&= ~SV_TYPE_LOCAL_LIST_ONLY
;
1042 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1043 s
->name
, s
->type
, s
->comment
, s
->domain
));
1045 s
->server_added
= True
;
1050 DEBUG(4,("%20s %8x %25s %15s\n",
1051 s
->name
, s
->type
, s
->comment
, s
->domain
));
1055 file_lines_free(lines
);
1060 /*******************************************************************
1061 fill in a server info structure
1062 ******************************************************************/
1063 static int fill_srv_info(struct srv_info_struct
*service
,
1064 int uLevel
, char **buf
, int *buflen
,
1065 char **stringbuf
, int *stringspace
, char *baseaddr
)
1074 case 0: struct_len
= 16; break;
1075 case 1: struct_len
= 26; break;
1085 len
= strlen(service
->comment
)+1;
1089 if (buflen
) *buflen
= struct_len
;
1090 if (stringspace
) *stringspace
= len
;
1091 return struct_len
+ len
;
1096 if (*buflen
< struct_len
) return -1;
1104 p2
= p
+ struct_len
;
1105 l2
= *buflen
- struct_len
;
1107 if (!baseaddr
) baseaddr
= p
;
1112 push_ascii(p
,service
->name
, MAX_NETBIOSNAME_LEN
, STR_TERMINATE
);
1116 push_ascii(p
,service
->name
,MAX_NETBIOSNAME_LEN
, STR_TERMINATE
);
1117 SIVAL(p
,18,service
->type
);
1118 SIVAL(p
,22,PTR_DIFF(p2
,baseaddr
));
1119 len
+= CopyAndAdvance(&p2
,service
->comment
,&l2
);
1125 *buf
= p
+ struct_len
;
1126 *buflen
-= struct_len
;
1139 static BOOL
srv_comp(struct srv_info_struct
*s1
,struct srv_info_struct
*s2
)
1141 return(strcmp(s1
->name
,s2
->name
));
1144 /****************************************************************************
1145 view list of servers available (or possibly domains). The info is
1146 extracted from lists saved by nmbd on the local host
1147 ****************************************************************************/
1148 static BOOL
api_RNetServerEnum(connection_struct
*conn
, uint16 vuid
, char *param
, char *data
,
1149 int mdrcnt
, int mprcnt
, char **rdata
,
1150 char **rparam
, int *rdata_len
, int *rparam_len
)
1152 char *str1
= param
+2;
1153 char *str2
= skip_string(str1
,1);
1154 char *p
= skip_string(str2
,1);
1155 int uLevel
= SVAL(p
,0);
1156 int buf_len
= SVAL(p
,2);
1157 uint32 servertype
= IVAL(p
,4);
1159 int data_len
, fixed_len
, string_len
;
1160 int f_len
= 0, s_len
= 0;
1161 struct srv_info_struct
*servers
=NULL
;
1162 int counted
=0,total
=0;
1165 BOOL domain_request
;
1168 /* If someone sets all the bits they don't really mean to set
1169 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1172 if (servertype
== SV_TYPE_ALL
)
1173 servertype
&= ~(SV_TYPE_DOMAIN_ENUM
|SV_TYPE_LOCAL_LIST_ONLY
);
1175 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1176 any other bit (they may just set this bit on it's own) they
1177 want all the locally seen servers. However this bit can be
1178 set on its own so set the requested servers to be
1179 ALL - DOMAIN_ENUM. */
1181 if ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) && !(servertype
& SV_TYPE_DOMAIN_ENUM
))
1182 servertype
= SV_TYPE_ALL
& ~(SV_TYPE_DOMAIN_ENUM
);
1184 domain_request
= ((servertype
& SV_TYPE_DOMAIN_ENUM
) != 0);
1185 local_request
= ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) != 0);
1189 if (!prefix_ok(str1
,"WrLehD")) return False
;
1190 if (!check_server_info(uLevel
,str2
)) return False
;
1192 DEBUG(4, ("server request level: %s %8x ", str2
, servertype
));
1193 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request
)));
1194 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request
)));
1196 if (strcmp(str1
, "WrLehDz") == 0) {
1197 pull_ascii_fstring(domain
, p
);
1199 fstrcpy(domain
, lp_workgroup());
1202 if (lp_browse_list())
1203 total
= get_server_info(servertype
,&servers
,domain
);
1205 data_len
= fixed_len
= string_len
= 0;
1209 qsort(servers
,total
,sizeof(servers
[0]),QSORT_CAST srv_comp
);
1212 char *lastname
=NULL
;
1214 for (i
=0;i
<total
;i
++)
1216 struct srv_info_struct
*s
= &servers
[i
];
1217 if (lastname
&& strequal(lastname
,s
->name
)) continue;
1219 data_len
+= fill_srv_info(s
,uLevel
,0,&f_len
,0,&s_len
,0);
1220 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1221 s
->name
, s
->type
, s
->comment
, s
->domain
));
1223 if (data_len
<= buf_len
) {
1226 string_len
+= s_len
;
1233 *rdata_len
= fixed_len
+ string_len
;
1234 *rdata
= SMB_REALLOC_LIMIT(*rdata
,*rdata_len
);
1235 memset(*rdata
,'\0',*rdata_len
);
1237 p2
= (*rdata
) + fixed_len
; /* auxilliary data (strings) will go here */
1243 char *lastname
=NULL
;
1244 int count2
= counted
;
1245 for (i
= 0; i
< total
&& count2
;i
++)
1247 struct srv_info_struct
*s
= &servers
[i
];
1248 if (lastname
&& strequal(lastname
,s
->name
)) continue;
1250 fill_srv_info(s
,uLevel
,&p
,&f_len
,&p2
,&s_len
,*rdata
);
1251 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1252 s
->name
, s
->type
, s
->comment
, s
->domain
));
1258 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
1259 SSVAL(*rparam
,0,(missed
== 0 ? NERR_Success
: ERRmoredata
));
1261 SSVAL(*rparam
,4,counted
);
1262 SSVAL(*rparam
,6,counted
+missed
);
1266 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1267 domain
,uLevel
,counted
,counted
+missed
));
1272 /****************************************************************************
1273 command 0x34 - suspected of being a "Lookup Names" stub api
1274 ****************************************************************************/
1275 static BOOL
api_RNetGroupGetUsers(connection_struct
*conn
, uint16 vuid
, char *param
, char *data
,
1276 int mdrcnt
, int mprcnt
, char **rdata
,
1277 char **rparam
, int *rdata_len
, int *rparam_len
)
1279 char *str1
= param
+2;
1280 char *str2
= skip_string(str1
,1);
1281 char *p
= skip_string(str2
,1);
1282 int uLevel
= SVAL(p
,0);
1283 int buf_len
= SVAL(p
,2);
1287 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1288 str1
, str2
, p
, uLevel
, buf_len
));
1290 if (!prefix_ok(str1
,"zWrLeh")) return False
;
1295 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
1297 SSVAL(*rparam
,0,0x08AC); /* informational warning message */
1299 SSVAL(*rparam
,4,counted
);
1300 SSVAL(*rparam
,6,counted
+missed
);
1305 /****************************************************************************
1306 get info about a share
1307 ****************************************************************************/
1308 static BOOL
check_share_info(int uLevel
, char* id
)
1312 if (strcmp(id
,"B13") != 0) return False
;
1315 if (strcmp(id
,"B13BWz") != 0) return False
;
1318 if (strcmp(id
,"B13BWzWWWzB9B") != 0) return False
;
1321 if (strcmp(id
,"B13BWzWWWzB9BB9BWzWWzWW") != 0) return False
;
1323 default: return False
;
1328 static int fill_share_info(connection_struct
*conn
, int snum
, int uLevel
,
1329 char** buf
, int* buflen
,
1330 char** stringbuf
, int* stringspace
, char* baseaddr
)
1339 case 0: struct_len
= 13; break;
1340 case 1: struct_len
= 20; break;
1341 case 2: struct_len
= 40; break;
1342 case 91: struct_len
= 68; break;
1350 if (uLevel
> 0) len
+= StrlenExpanded(conn
,snum
,lp_comment(snum
));
1351 if (uLevel
> 1) len
+= strlen(lp_pathname(snum
)) + 1;
1352 if (buflen
) *buflen
= struct_len
;
1353 if (stringspace
) *stringspace
= len
;
1354 return struct_len
+ len
;
1359 if ((*buflen
) < struct_len
) return -1;
1367 p2
= p
+ struct_len
;
1368 l2
= (*buflen
) - struct_len
;
1370 if (!baseaddr
) baseaddr
= p
;
1372 push_ascii(p
,lp_servicename(snum
),13, STR_TERMINATE
);
1378 type
= STYPE_DISKTREE
;
1379 if (lp_print_ok(snum
)) type
= STYPE_PRINTQ
;
1380 if (strequal("IPC",lp_fstype(snum
))) type
= STYPE_IPC
;
1381 SSVAL(p
,14,type
); /* device type */
1382 SIVAL(p
,16,PTR_DIFF(p2
,baseaddr
));
1383 len
+= CopyExpanded(conn
,snum
,&p2
,lp_comment(snum
),&l2
);
1388 SSVAL(p
,20,ACCESS_READ
|ACCESS_WRITE
|ACCESS_CREATE
); /* permissions */
1389 SSVALS(p
,22,-1); /* max uses */
1390 SSVAL(p
,24,1); /* current uses */
1391 SIVAL(p
,26,PTR_DIFF(p2
,baseaddr
)); /* local pathname */
1392 len
+= CopyAndAdvance(&p2
,lp_pathname(snum
),&l2
);
1393 memset(p
+30,0,SHPWLEN
+2); /* passwd (reserved), pad field */
1398 memset(p
+40,0,SHPWLEN
+2);
1410 (*buf
) = p
+ struct_len
;
1411 (*buflen
) -= struct_len
;
1413 (*stringspace
) = l2
;
1423 static BOOL
api_RNetShareGetInfo(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
1424 int mdrcnt
,int mprcnt
,
1425 char **rdata
,char **rparam
,
1426 int *rdata_len
,int *rparam_len
)
1428 char *str1
= param
+2;
1429 char *str2
= skip_string(str1
,1);
1430 char *netname
= skip_string(str2
,1);
1431 char *p
= skip_string(netname
,1);
1432 int uLevel
= SVAL(p
,0);
1433 int snum
= find_service(netname
);
1435 if (snum
< 0) return False
;
1437 /* check it's a supported varient */
1438 if (!prefix_ok(str1
,"zWrLh")) return False
;
1439 if (!check_share_info(uLevel
,str2
)) return False
;
1441 *rdata
= SMB_REALLOC_LIMIT(*rdata
,mdrcnt
);
1443 *rdata_len
= fill_share_info(conn
,snum
,uLevel
,&p
,&mdrcnt
,0,0,0);
1444 if (*rdata_len
< 0) return False
;
1447 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
1448 SSVAL(*rparam
,0,NERR_Success
);
1449 SSVAL(*rparam
,2,0); /* converter word */
1450 SSVAL(*rparam
,4,*rdata_len
);
1455 /****************************************************************************
1456 View the list of available shares.
1458 This function is the server side of the NetShareEnum() RAP call.
1459 It fills the return buffer with share names and share comments.
1460 Note that the return buffer normally (in all known cases) allows only
1461 twelve byte strings for share names (plus one for a nul terminator).
1462 Share names longer than 12 bytes must be skipped.
1463 ****************************************************************************/
1464 static BOOL
api_RNetShareEnum( connection_struct
*conn
,
1475 char *str1
= param
+2;
1476 char *str2
= skip_string(str1
,1);
1477 char *p
= skip_string(str2
,1);
1478 int uLevel
= SVAL(p
,0);
1479 int buf_len
= SVAL(p
,2);
1481 int count
=lp_numservices();
1482 int total
=0,counted
=0;
1483 BOOL missed
= False
;
1485 int data_len
, fixed_len
, string_len
;
1486 int f_len
= 0, s_len
= 0;
1488 if (!prefix_ok(str1
,"WrLeh")) return False
;
1489 if (!check_share_info(uLevel
,str2
)) return False
;
1491 data_len
= fixed_len
= string_len
= 0;
1492 for (i
=0;i
<count
;i
++) {
1493 fstring servicename_dos
;
1494 if (!(lp_browseable(i
) && lp_snum_ok(i
)))
1496 push_ascii_fstring(servicename_dos
, lp_servicename(i
));
1497 if( lp_browseable( i
)
1499 && (strlen(servicename_dos
) < 13) ) /* Maximum name length. */
1502 data_len
+= fill_share_info(conn
,i
,uLevel
,0,&f_len
,0,&s_len
,0);
1503 if (data_len
<= buf_len
)
1507 string_len
+= s_len
;
1513 *rdata_len
= fixed_len
+ string_len
;
1514 *rdata
= SMB_REALLOC_LIMIT(*rdata
,*rdata_len
);
1515 memset(*rdata
,0,*rdata_len
);
1517 p2
= (*rdata
) + fixed_len
; /* auxiliary data (strings) will go here */
1521 for( i
= 0; i
< count
; i
++ )
1523 fstring servicename_dos
;
1524 if (!(lp_browseable(i
) && lp_snum_ok(i
)))
1526 push_ascii_fstring(servicename_dos
, lp_servicename(i
));
1527 if( lp_browseable( i
)
1529 && (strlen(servicename_dos
) < 13) )
1531 if( fill_share_info( conn
,i
,uLevel
,&p
,&f_len
,&p2
,&s_len
,*rdata
) < 0 )
1537 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
1538 SSVAL(*rparam
,0,missed
? ERRmoredata
: NERR_Success
);
1540 SSVAL(*rparam
,4,counted
);
1541 SSVAL(*rparam
,6,total
);
1543 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1544 counted
,total
,uLevel
,
1545 buf_len
,*rdata_len
,mdrcnt
));
1547 } /* api_RNetShareEnum */
1549 /****************************************************************************
1551 ****************************************************************************/
1552 static BOOL
api_RNetShareAdd(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
1553 int mdrcnt
,int mprcnt
,
1554 char **rdata
,char **rparam
,
1555 int *rdata_len
,int *rparam_len
)
1557 char *str1
= param
+2;
1558 char *str2
= skip_string(str1
,1);
1559 char *p
= skip_string(str2
,1);
1560 int uLevel
= SVAL(p
,0);
1564 char *command
, *cmdname
;
1565 unsigned int offset
;
1569 /* check it's a supported varient */
1570 if (!prefix_ok(str1
,RAP_WShareAdd_REQ
)) return False
;
1571 if (!check_share_info(uLevel
,str2
)) return False
;
1572 if (uLevel
!= 2) return False
;
1574 pull_ascii_fstring(sharename
,data
);
1575 snum
= find_service(sharename
);
1576 if (snum
>= 0) { /* already exists */
1581 /* only support disk share adds */
1582 if (SVAL(data
,14)!=STYPE_DISKTREE
) return False
;
1584 offset
= IVAL(data
, 16);
1585 if (offset
>= mdrcnt
) {
1586 res
= ERRinvalidparam
;
1589 pull_ascii_fstring(comment
, offset
? (data
+offset
) : "");
1591 offset
= IVAL(data
, 26);
1592 if (offset
>= mdrcnt
) {
1593 res
= ERRinvalidparam
;
1596 pull_ascii_pstring(pathname
, offset
? (data
+offset
) : "");
1598 string_replace(sharename
, '"', ' ');
1599 string_replace(pathname
, '"', ' ');
1600 string_replace(comment
, '"', ' ');
1602 cmdname
= lp_add_share_cmd();
1604 if (!cmdname
|| *cmdname
== '\0') return False
;
1606 asprintf(&command
, "%s \"%s\" \"%s\" \"%s\" \"%s\"",
1607 lp_add_share_cmd(), dyn_CONFIGFILE
, sharename
, pathname
, comment
);
1610 DEBUG(10,("api_RNetShareAdd: Running [%s]\n", command
));
1611 if ((res
= smbrun(command
, NULL
)) != 0) {
1612 DEBUG(1,("api_RNetShareAdd: Running [%s] returned (%d)\n", command
, res
));
1618 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED
, NULL
, 0, False
, NULL
);
1620 } else return False
;
1623 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
1624 SSVAL(*rparam
,0,NERR_Success
);
1625 SSVAL(*rparam
,2,0); /* converter word */
1626 SSVAL(*rparam
,4,*rdata_len
);
1633 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
1635 SSVAL(*rparam
,0,res
);
1641 /****************************************************************************
1642 view list of groups available
1643 ****************************************************************************/
1644 static BOOL
api_RNetGroupEnum(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
1645 int mdrcnt
,int mprcnt
,
1646 char **rdata
,char **rparam
,
1647 int *rdata_len
,int *rparam_len
)
1651 int resume_context
, cli_buf_size
;
1652 char *str1
= param
+2;
1653 char *str2
= skip_string(str1
,1);
1654 char *p
= skip_string(str2
,1);
1657 GROUP_MAP
*group_list
;
1660 if (strcmp(str1
,"WrLeh") != 0)
1664 * W-> resume context (number of users to skip)
1665 * r -> return parameter pointer to receive buffer
1666 * L -> length of receive buffer
1667 * e -> return parameter number of entries
1668 * h -> return parameter total number of users
1670 if (strcmp("B21",str2
) != 0)
1673 /* get list of domain groups SID_DOMAIN_GRP=2 */
1675 ret
= pdb_enum_group_mapping(SID_NAME_DOM_GRP
, &group_list
, &num_entries
, False
);
1679 DEBUG(3,("api_RNetGroupEnum:failed to get group list"));
1683 resume_context
= SVAL(p
,0);
1684 cli_buf_size
=SVAL(p
+2,0);
1685 DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: %d\n", resume_context
, cli_buf_size
));
1687 *rdata_len
= cli_buf_size
;
1688 *rdata
= SMB_REALLOC_LIMIT(*rdata
,*rdata_len
);
1692 for(i
=resume_context
; i
<num_entries
; i
++) {
1693 char* name
=group_list
[i
].nt_name
;
1694 if( ((PTR_DIFF(p
,*rdata
)+21) <= *rdata_len
) ) {
1695 /* truncate the name at 21 chars. */
1696 memcpy(p
, name
, 21);
1697 DEBUG(10,("adding entry %d group %s\n", i
, p
));
1700 /* set overflow error */
1701 DEBUG(3,("overflow on entry %d group %s\n", i
, name
));
1707 *rdata_len
= PTR_DIFF(p
,*rdata
);
1710 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
1712 SSVAL(*rparam
, 0, errflags
);
1713 SSVAL(*rparam
, 2, 0); /* converter word */
1714 SSVAL(*rparam
, 4, i
-resume_context
); /* is this right?? */
1715 SSVAL(*rparam
, 6, num_entries
); /* is this right?? */
1720 /*******************************************************************
1721 get groups that a user is a member of
1722 ******************************************************************/
1723 static BOOL
api_NetUserGetGroups(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
1724 int mdrcnt
,int mprcnt
,
1725 char **rdata
,char **rparam
,
1726 int *rdata_len
,int *rparam_len
)
1728 char *str1
= param
+2;
1729 char *str2
= skip_string(str1
,1);
1730 char *UserName
= skip_string(str2
,1);
1731 char *p
= skip_string(UserName
,1);
1732 int uLevel
= SVAL(p
,0);
1733 const char *level_string
;
1735 SAM_ACCOUNT
*sampw
= NULL
;
1743 enum SID_NAME_USE grp_type
;
1744 struct passwd
*passwd
;
1748 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
1750 /* check it's a supported varient */
1752 if ( strcmp(str1
,"zWrLeh") != 0 )
1757 level_string
= "B21";
1763 if (strcmp(level_string
,str2
) != 0)
1766 *rdata_len
= mdrcnt
+ 1024;
1767 *rdata
= SMB_REALLOC_LIMIT(*rdata
,*rdata_len
);
1769 SSVAL(*rparam
,0,NERR_Success
);
1770 SSVAL(*rparam
,2,0); /* converter word */
1774 /* Lookup the user information; This should only be one of
1775 our accounts (not remote domains) */
1777 passwd
= getpwnam_alloc(UserName
);
1782 pdb_init_sam( &sampw
);
1784 become_root(); /* ROOT BLOCK */
1786 if ( !pdb_getsampwnam(sampw
, UserName
) )
1792 result
= pdb_enum_group_memberships(pdb_get_username(sampw
),
1794 &sids
, &gids
, &num_groups
);
1796 if (!NT_STATUS_IS_OK(result
))
1799 for (i
=0; i
<num_groups
; i
++) {
1801 if ( lookup_sid(&sids
[i
], grp_domain
, grp_name
, &grp_type
) ) {
1802 pstrcpy(p
, grp_name
);
1810 *rdata_len
= PTR_DIFF(p
,*rdata
);
1812 SSVAL(*rparam
,4,count
); /* is this right?? */
1813 SSVAL(*rparam
,6,count
); /* is this right?? */
1818 unbecome_root(); /* END ROOT BLOCK */
1820 pdb_free_sam( &sampw
);
1821 passwd_free(&passwd
);
1826 /*******************************************************************
1828 ******************************************************************/
1829 static BOOL
api_RNetUserEnum(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
1830 int mdrcnt
,int mprcnt
,
1831 char **rdata
,char **rparam
,
1832 int *rdata_len
,int *rparam_len
)
1834 SAM_ACCOUNT
*pwd
=NULL
;
1838 int resume_context
, cli_buf_size
;
1840 char *str1
= param
+2;
1841 char *str2
= skip_string(str1
,1);
1842 char *p
= skip_string(str2
,1);
1844 if (strcmp(str1
,"WrLeh") != 0)
1847 * W-> resume context (number of users to skip)
1848 * r -> return parameter pointer to receive buffer
1849 * L -> length of receive buffer
1850 * e -> return parameter number of entries
1851 * h -> return parameter total number of users
1854 resume_context
= SVAL(p
,0);
1855 cli_buf_size
=SVAL(p
+2,0);
1856 DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n", resume_context
, cli_buf_size
));
1859 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
1861 /* check it's a supported varient */
1862 if (strcmp("B21",str2
) != 0)
1865 *rdata_len
= cli_buf_size
;
1866 *rdata
= SMB_REALLOC_LIMIT(*rdata
,*rdata_len
);
1870 /* to get user list enumerations for NetUserEnum in B21 format */
1873 /* Open the passgrp file - not for update. */
1875 if(!pdb_setsampwent(False
, 0)) {
1876 DEBUG(0, ("api_RNetUserEnum:unable to open sam database.\n"));
1880 errflags
=NERR_Success
;
1882 while ( pdb_getsampwent(pwd
) ) {
1883 const char *name
=pdb_get_username(pwd
);
1884 if ((name
) && (*(name
+strlen(name
)-1)!='$')) {
1886 if(count_total
>=resume_context
) {
1887 if( ((PTR_DIFF(p
,*rdata
)+21)<=*rdata_len
)&&(strlen(name
)<=21) ) {
1889 DEBUG(10,("api_RNetUserEnum:adding entry %d username %s\n",count_sent
,p
));
1893 /* set overflow error */
1894 DEBUG(10,("api_RNetUserEnum:overflow on entry %d username %s\n",count_sent
,name
));
1907 *rdata_len
= PTR_DIFF(p
,*rdata
);
1909 SSVAL(*rparam
,0,errflags
);
1910 SSVAL(*rparam
,2,0); /* converter word */
1911 SSVAL(*rparam
,4,count_sent
); /* is this right?? */
1912 SSVAL(*rparam
,6,count_total
); /* is this right?? */
1919 /****************************************************************************
1920 get the time of day info
1921 ****************************************************************************/
1922 static BOOL
api_NetRemoteTOD(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
1923 int mdrcnt
,int mprcnt
,
1924 char **rdata
,char **rparam
,
1925 int *rdata_len
,int *rparam_len
)
1929 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
1932 *rdata
= SMB_REALLOC_LIMIT(*rdata
,*rdata_len
);
1934 SSVAL(*rparam
,0,NERR_Success
);
1935 SSVAL(*rparam
,2,0); /* converter word */
1941 time_t unixdate
= time(NULL
);
1943 put_dos_date3(p
,0,unixdate
); /* this is the time that is looked at
1944 by NT in a "net time" operation,
1945 it seems to ignore the one below */
1947 /* the client expects to get localtime, not GMT, in this bit
1948 (I think, this needs testing) */
1949 t
= LocalTime(&unixdate
);
1951 SIVAL(p
,4,0); /* msecs ? */
1952 SCVAL(p
,8,t
->tm_hour
);
1953 SCVAL(p
,9,t
->tm_min
);
1954 SCVAL(p
,10,t
->tm_sec
);
1955 SCVAL(p
,11,0); /* hundredths of seconds */
1956 SSVALS(p
,12,TimeDiff(unixdate
)/60); /* timezone in minutes from GMT */
1957 SSVAL(p
,14,10000); /* timer interval in 0.0001 of sec */
1958 SCVAL(p
,16,t
->tm_mday
);
1959 SCVAL(p
,17,t
->tm_mon
+ 1);
1960 SSVAL(p
,18,1900+t
->tm_year
);
1961 SCVAL(p
,20,t
->tm_wday
);
1968 /****************************************************************************
1969 Set the user password.
1970 *****************************************************************************/
1972 static BOOL
api_SetUserPassword(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
1973 int mdrcnt
,int mprcnt
,
1974 char **rdata
,char **rparam
,
1975 int *rdata_len
,int *rparam_len
)
1977 char *p
= skip_string(param
+2,2);
1979 fstring pass1
,pass2
;
1981 pull_ascii_fstring(user
,p
);
1983 p
= skip_string(p
,1);
1985 memset(pass1
,'\0',sizeof(pass1
));
1986 memset(pass2
,'\0',sizeof(pass2
));
1988 memcpy(pass2
,p
+16,16);
1991 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
1995 SSVAL(*rparam
,0,NERR_badpass
);
1996 SSVAL(*rparam
,2,0); /* converter word */
1998 DEBUG(3,("Set password for <%s>\n",user
));
2001 * Attempt to verify the old password against smbpasswd entries
2002 * Win98 clients send old and new password in plaintext for this call.
2006 auth_serversupplied_info
*server_info
= NULL
;
2007 DATA_BLOB password
= data_blob(pass1
, strlen(pass1
)+1);
2009 if (NT_STATUS_IS_OK(check_plaintext_password(user
,password
,&server_info
))) {
2012 if (NT_STATUS_IS_OK(change_oem_password(server_info
->sam_account
, pass1
, pass2
, False
))) {
2013 SSVAL(*rparam
,0,NERR_Success
);
2017 free_server_info(&server_info
);
2019 data_blob_clear_free(&password
);
2023 * If the plaintext change failed, attempt
2024 * the old encrypted method. NT will generate this
2025 * after trying the samr method. Note that this
2026 * method is done as a last resort as this
2027 * password change method loses the NT password hash
2028 * and cannot change the UNIX password as no plaintext
2032 if(SVAL(*rparam
,0) != NERR_Success
) {
2033 SAM_ACCOUNT
*hnd
= NULL
;
2035 if (check_lanman_password(user
,(unsigned char *)pass1
,(unsigned char *)pass2
, &hnd
)) {
2037 if (change_lanman_password(hnd
,(uchar
*)pass2
)) {
2038 SSVAL(*rparam
,0,NERR_Success
);
2045 memset((char *)pass1
,'\0',sizeof(fstring
));
2046 memset((char *)pass2
,'\0',sizeof(fstring
));
2051 /****************************************************************************
2052 Set the user password (SamOEM version - gets plaintext).
2053 ****************************************************************************/
2055 static BOOL
api_SamOEMChangePassword(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
2056 int mdrcnt
,int mprcnt
,
2057 char **rdata
,char **rparam
,
2058 int *rdata_len
,int *rparam_len
)
2061 char *p
= param
+ 2;
2063 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
2067 SSVAL(*rparam
,0,NERR_badpass
);
2070 * Check the parameter definition is correct.
2073 if(!strequal(param
+ 2, "zsT")) {
2074 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", param
+ 2));
2077 p
= skip_string(p
, 1);
2079 if(!strequal(p
, "B516B16")) {
2080 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p
));
2083 p
= skip_string(p
,1);
2084 p
+= pull_ascii_fstring(user
,p
);
2086 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user
));
2089 * Pass the user through the NT -> unix user mapping
2093 (void)map_username(user
);
2095 if (NT_STATUS_IS_OK(pass_oem_change(user
, (uchar
*) data
, (uchar
*)&data
[516], NULL
, NULL
))) {
2096 SSVAL(*rparam
,0,NERR_Success
);
2102 /****************************************************************************
2105 ****************************************************************************/
2106 static BOOL
api_RDosPrintJobDel(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
2107 int mdrcnt
,int mprcnt
,
2108 char **rdata
,char **rparam
,
2109 int *rdata_len
,int *rparam_len
)
2111 int function
= SVAL(param
,0);
2112 char *str1
= param
+2;
2113 char *str2
= skip_string(str1
,1);
2114 char *p
= skip_string(str2
,1);
2119 extern struct current_user current_user
;
2120 WERROR werr
= WERR_OK
;
2122 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
))
2125 /* check it's a supported varient */
2126 if (!(strcsequal(str1
,"W") && strcsequal(str2
,"")))
2130 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
2133 if (!print_job_exists(sharename
, jobid
)) {
2134 errcode
= NERR_JobNotFound
;
2138 snum
= lp_servicenumber( sharename
);
2140 errcode
= NERR_DestNotFound
;
2144 errcode
= NERR_notsupported
;
2147 case 81: /* delete */
2148 if (print_job_delete(¤t_user
, snum
, jobid
, &werr
))
2149 errcode
= NERR_Success
;
2151 case 82: /* pause */
2152 if (print_job_pause(¤t_user
, snum
, jobid
, &werr
))
2153 errcode
= NERR_Success
;
2155 case 83: /* resume */
2156 if (print_job_resume(¤t_user
, snum
, jobid
, &werr
))
2157 errcode
= NERR_Success
;
2161 if (!W_ERROR_IS_OK(werr
))
2162 errcode
= W_ERROR_V(werr
);
2165 SSVAL(*rparam
,0,errcode
);
2166 SSVAL(*rparam
,2,0); /* converter word */
2171 /****************************************************************************
2172 Purge a print queue - or pause or resume it.
2173 ****************************************************************************/
2174 static BOOL
api_WPrintQueueCtrl(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
2175 int mdrcnt
,int mprcnt
,
2176 char **rdata
,char **rparam
,
2177 int *rdata_len
,int *rparam_len
)
2179 int function
= SVAL(param
,0);
2180 char *str1
= param
+2;
2181 char *str2
= skip_string(str1
,1);
2182 char *QueueName
= skip_string(str2
,1);
2183 int errcode
= NERR_notsupported
;
2185 WERROR werr
= WERR_OK
;
2186 extern struct current_user current_user
;
2188 /* check it's a supported varient */
2189 if (!(strcsequal(str1
,"z") && strcsequal(str2
,"")))
2193 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
2196 snum
= print_queue_snum(QueueName
);
2199 errcode
= NERR_JobNotFound
;
2204 case 74: /* Pause queue */
2205 if (print_queue_pause(¤t_user
, snum
, &werr
)) errcode
= NERR_Success
;
2207 case 75: /* Resume queue */
2208 if (print_queue_resume(¤t_user
, snum
, &werr
)) errcode
= NERR_Success
;
2210 case 103: /* Purge */
2211 if (print_queue_purge(¤t_user
, snum
, &werr
)) errcode
= NERR_Success
;
2215 if (!W_ERROR_IS_OK(werr
)) errcode
= W_ERROR_V(werr
);
2218 SSVAL(*rparam
,0,errcode
);
2219 SSVAL(*rparam
,2,0); /* converter word */
2225 /****************************************************************************
2226 set the property of a print job (undocumented?)
2227 ? function = 0xb -> set name of print job
2228 ? function = 0x6 -> move print job up/down
2229 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
2230 or <WWsTP> <WB21BB16B10zWWzDDz>
2231 ****************************************************************************/
2232 static int check_printjob_info(struct pack_desc
* desc
,
2233 int uLevel
, char* id
)
2235 desc
->subformat
= NULL
;
2237 case 0: desc
->format
= "W"; break;
2238 case 1: desc
->format
= "WB21BB16B10zWWzDDz"; break;
2239 case 2: desc
->format
= "WWzWWDDzz"; break;
2240 case 3: desc
->format
= "WWzWWDDzzzzzzzzzzlz"; break;
2241 case 4: desc
->format
= "WWzWWDDzzzzzDDDDDDD"; break;
2242 default: return False
;
2244 if (strcmp(desc
->format
,id
) != 0) return False
;
2248 static BOOL
api_PrintJobInfo(connection_struct
*conn
,uint16 vuid
,char *param
,char *data
,
2249 int mdrcnt
,int mprcnt
,
2250 char **rdata
,char **rparam
,
2251 int *rdata_len
,int *rparam_len
)
2253 struct pack_desc desc
;
2254 char *str1
= param
+2;
2255 char *str2
= skip_string(str1
,1);
2256 char *p
= skip_string(str2
,1);
2260 int uLevel
= SVAL(p
,2);
2261 int function
= SVAL(p
,4);
2264 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
))
2267 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
2269 if ( (snum
= lp_servicenumber(sharename
)) == -1 ) {
2270 DEBUG(0,("api_PrintJobInfo: unable to get service number from sharename [%s]\n",
2277 /* check it's a supported varient */
2278 if ((strcmp(str1
,"WWsTP")) ||
2279 (!check_printjob_info(&desc
,uLevel
,str2
)))
2282 if (!print_job_exists(sharename
, jobid
)) {
2283 errcode
=NERR_JobNotFound
;
2287 errcode
= NERR_notsupported
;
2291 /* change job place in the queue,
2292 data gives the new place */
2293 place
= SVAL(data
,0);
2294 if (print_job_set_place(snum
, jobid
, place
)) {
2295 errcode
=NERR_Success
;
2300 /* change print job name, data gives the name */
2301 if (print_job_set_name(snum
, jobid
, data
)) {
2302 errcode
=NERR_Success
;
2311 SSVALS(*rparam
,0,errcode
);
2312 SSVAL(*rparam
,2,0); /* converter word */
2318 /****************************************************************************
2319 get info about the server
2320 ****************************************************************************/
2321 static BOOL
api_RNetServerGetInfo(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
2322 int mdrcnt
,int mprcnt
,
2323 char **rdata
,char **rparam
,
2324 int *rdata_len
,int *rparam_len
)
2326 char *str1
= param
+2;
2327 char *str2
= skip_string(str1
,1);
2328 char *p
= skip_string(str2
,1);
2329 int uLevel
= SVAL(p
,0);
2333 DEBUG(4,("NetServerGetInfo level %d\n",uLevel
));
2335 /* check it's a supported varient */
2336 if (!prefix_ok(str1
,"WrLh")) return False
;
2339 if (strcmp(str2
,"B16") != 0) return False
;
2343 if (strcmp(str2
,"B16BBDz") != 0) return False
;
2347 if (strcmp(str2
,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")
2352 if (strcmp(str2
,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz")
2357 if (strcmp(str2
,"DN") != 0) return False
;
2361 if (strcmp(str2
,"B16BBDzWWzzz") != 0) return False
;
2364 default: return False
;
2367 *rdata_len
= mdrcnt
;
2368 *rdata
= SMB_REALLOC_LIMIT(*rdata
,*rdata_len
);
2371 p2
= p
+ struct_len
;
2373 srvstr_push(NULL
, p
,get_local_machine_name(),16,
2374 STR_ASCII
|STR_UPPER
|STR_TERMINATE
);
2379 struct srv_info_struct
*servers
=NULL
;
2382 uint32 servertype
= lp_default_server_announce();
2384 push_ascii(comment
,lp_serverstring(), MAX_SERVER_STRING_LENGTH
,STR_TERMINATE
);
2386 if ((count
=get_server_info(SV_TYPE_ALL
,&servers
,lp_workgroup()))>0) {
2387 for (i
=0;i
<count
;i
++) {
2388 if (strequal(servers
[i
].name
,get_local_machine_name())) {
2389 servertype
= servers
[i
].type
;
2390 push_ascii(comment
,servers
[i
].comment
,sizeof(pstring
),STR_TERMINATE
);
2396 SCVAL(p
,0,lp_major_announce_version());
2397 SCVAL(p
,1,lp_minor_announce_version());
2398 SIVAL(p
,2,servertype
);
2400 if (mdrcnt
== struct_len
) {
2403 SIVAL(p
,6,PTR_DIFF(p2
,*rdata
));
2404 standard_sub_conn(conn
,comment
,sizeof(comment
));
2405 StrnCpy(p2
,comment
,MAX(mdrcnt
- struct_len
,0));
2406 p2
= skip_string(p2
,1);
2411 return False
; /* not yet implemented */
2414 *rdata_len
= PTR_DIFF(p2
,*rdata
);
2417 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
2418 SSVAL(*rparam
,0,NERR_Success
);
2419 SSVAL(*rparam
,2,0); /* converter word */
2420 SSVAL(*rparam
,4,*rdata_len
);
2426 /****************************************************************************
2427 get info about the server
2428 ****************************************************************************/
2429 static BOOL
api_NetWkstaGetInfo(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
2430 int mdrcnt
,int mprcnt
,
2431 char **rdata
,char **rparam
,
2432 int *rdata_len
,int *rparam_len
)
2434 char *str1
= param
+2;
2435 char *str2
= skip_string(str1
,1);
2436 char *p
= skip_string(str2
,1);
2438 extern userdom_struct current_user_info
;
2439 int level
= SVAL(p
,0);
2441 DEBUG(4,("NetWkstaGetInfo level %d\n",level
));
2444 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
2446 /* check it's a supported varient */
2447 if (!(level
==10 && strcsequal(str1
,"WrLh") && strcsequal(str2
,"zzzBBzz")))
2450 *rdata_len
= mdrcnt
+ 1024;
2451 *rdata
= SMB_REALLOC_LIMIT(*rdata
,*rdata_len
);
2453 SSVAL(*rparam
,0,NERR_Success
);
2454 SSVAL(*rparam
,2,0); /* converter word */
2460 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* host name */
2461 pstrcpy(p2
,get_local_machine_name());
2463 p2
= skip_string(p2
,1);
2466 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
));
2467 pstrcpy(p2
,current_user_info
.smb_name
);
2468 p2
= skip_string(p2
,1);
2471 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* login domain */
2472 pstrcpy(p2
,lp_workgroup());
2474 p2
= skip_string(p2
,1);
2477 SCVAL(p
,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
2478 SCVAL(p
,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
2481 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
));
2482 pstrcpy(p2
,lp_workgroup()); /* don't know. login domain?? */
2483 p2
= skip_string(p2
,1);
2486 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* don't know */
2488 p2
= skip_string(p2
,1);
2491 *rdata_len
= PTR_DIFF(p2
,*rdata
);
2493 SSVAL(*rparam
,4,*rdata_len
);
2498 /****************************************************************************
2499 get info about a user
2501 struct user_info_11 {
2502 char usri11_name[21]; 0-20
2504 char *usri11_comment; 22-25
2505 char *usri11_usr_comment; 26-29
2506 unsigned short usri11_priv; 30-31
2507 unsigned long usri11_auth_flags; 32-35
2508 long usri11_password_age; 36-39
2509 char *usri11_homedir; 40-43
2510 char *usri11_parms; 44-47
2511 long usri11_last_logon; 48-51
2512 long usri11_last_logoff; 52-55
2513 unsigned short usri11_bad_pw_count; 56-57
2514 unsigned short usri11_num_logons; 58-59
2515 char *usri11_logon_server; 60-63
2516 unsigned short usri11_country_code; 64-65
2517 char *usri11_workstations; 66-69
2518 unsigned long usri11_max_storage; 70-73
2519 unsigned short usri11_units_per_week; 74-75
2520 unsigned char *usri11_logon_hours; 76-79
2521 unsigned short usri11_code_page; 80-81
2526 usri11_name specifies the user name for which information is retireved
2528 usri11_pad aligns the next data structure element to a word boundary
2530 usri11_comment is a null terminated ASCII comment
2532 usri11_user_comment is a null terminated ASCII comment about the user
2534 usri11_priv specifies the level of the privilege assigned to the user.
2535 The possible values are:
2537 Name Value Description
2538 USER_PRIV_GUEST 0 Guest privilege
2539 USER_PRIV_USER 1 User privilege
2540 USER_PRV_ADMIN 2 Administrator privilege
2542 usri11_auth_flags specifies the account operator privileges. The
2543 possible values are:
2545 Name Value Description
2546 AF_OP_PRINT 0 Print operator
2549 Leach, Naik [Page 28]
2553 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2556 AF_OP_COMM 1 Communications operator
2557 AF_OP_SERVER 2 Server operator
2558 AF_OP_ACCOUNTS 3 Accounts operator
2561 usri11_password_age specifies how many seconds have elapsed since the
2562 password was last changed.
2564 usri11_home_dir points to a null terminated ASCII string that contains
2565 the path name of the user's home directory.
2567 usri11_parms points to a null terminated ASCII string that is set
2568 aside for use by applications.
2570 usri11_last_logon specifies the time when the user last logged on.
2571 This value is stored as the number of seconds elapsed since
2572 00:00:00, January 1, 1970.
2574 usri11_last_logoff specifies the time when the user last logged off.
2575 This value is stored as the number of seconds elapsed since
2576 00:00:00, January 1, 1970. A value of 0 means the last logoff
2579 usri11_bad_pw_count specifies the number of incorrect passwords
2580 entered since the last successful logon.
2582 usri11_log1_num_logons specifies the number of times this user has
2583 logged on. A value of -1 means the number of logons is unknown.
2585 usri11_logon_server points to a null terminated ASCII string that
2586 contains the name of the server to which logon requests are sent.
2587 A null string indicates logon requests should be sent to the
2590 usri11_country_code specifies the country code for the user's language
2593 usri11_workstations points to a null terminated ASCII string that
2594 contains the names of workstations the user may log on from.
2595 There may be up to 8 workstations, with the names separated by
2596 commas. A null strings indicates there are no restrictions.
2598 usri11_max_storage specifies the maximum amount of disk space the user
2599 can occupy. A value of 0xffffffff indicates there are no
2602 usri11_units_per_week specifies the equal number of time units into
2603 which a week is divided. This value must be equal to 168.
2605 usri11_logon_hours points to a 21 byte (168 bits) string that
2606 specifies the time during which the user can log on. Each bit
2607 represents one unique hour in a week. The first bit (bit 0, word
2608 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
2612 Leach, Naik [Page 29]
2616 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2619 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
2620 are no restrictions.
2622 usri11_code_page specifies the code page for the user's language of
2625 All of the pointers in this data structure need to be treated
2626 specially. The pointer is a 32 bit pointer. The higher 16 bits need
2627 to be ignored. The converter word returned in the parameters section
2628 needs to be subtracted from the lower 16 bits to calculate an offset
2629 into the return buffer where this ASCII string resides.
2631 There is no auxiliary data in the response.
2633 ****************************************************************************/
2635 #define usri11_name 0
2636 #define usri11_pad 21
2637 #define usri11_comment 22
2638 #define usri11_usr_comment 26
2639 #define usri11_full_name 30
2640 #define usri11_priv 34
2641 #define usri11_auth_flags 36
2642 #define usri11_password_age 40
2643 #define usri11_homedir 44
2644 #define usri11_parms 48
2645 #define usri11_last_logon 52
2646 #define usri11_last_logoff 56
2647 #define usri11_bad_pw_count 60
2648 #define usri11_num_logons 62
2649 #define usri11_logon_server 64
2650 #define usri11_country_code 68
2651 #define usri11_workstations 70
2652 #define usri11_max_storage 74
2653 #define usri11_units_per_week 78
2654 #define usri11_logon_hours 80
2655 #define usri11_code_page 84
2656 #define usri11_end 86
2658 #define USER_PRIV_GUEST 0
2659 #define USER_PRIV_USER 1
2660 #define USER_PRIV_ADMIN 2
2662 #define AF_OP_PRINT 0
2663 #define AF_OP_COMM 1
2664 #define AF_OP_SERVER 2
2665 #define AF_OP_ACCOUNTS 3
2668 static BOOL
api_RNetUserGetInfo(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
2669 int mdrcnt
,int mprcnt
,
2670 char **rdata
,char **rparam
,
2671 int *rdata_len
,int *rparam_len
)
2673 char *str1
= param
+2;
2674 char *str2
= skip_string(str1
,1);
2675 char *UserName
= skip_string(str2
,1);
2676 char *p
= skip_string(UserName
,1);
2677 int uLevel
= SVAL(p
,0);
2679 const char *level_string
;
2681 /* get NIS home of a previously validated user - simeon */
2682 /* With share level security vuid will always be zero.
2683 Don't depend on vuser being non-null !!. JRA */
2684 user_struct
*vuser
= get_valid_user_struct(vuid
);
2686 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser
->uid
,
2687 vuser
->user
.unix_name
));
2690 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
2692 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel
));
2694 /* check it's a supported variant */
2695 if (strcmp(str1
,"zWrLh") != 0) return False
;
2698 case 0: level_string
= "B21"; break;
2699 case 1: level_string
= "B21BB16DWzzWz"; break;
2700 case 2: level_string
= "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
2701 case 10: level_string
= "B21Bzzz"; break;
2702 case 11: level_string
= "B21BzzzWDDzzDDWWzWzDWb21W"; break;
2703 default: return False
;
2706 if (strcmp(level_string
,str2
) != 0) return False
;
2708 *rdata_len
= mdrcnt
+ 1024;
2709 *rdata
= SMB_REALLOC_LIMIT(*rdata
,*rdata_len
);
2711 SSVAL(*rparam
,0,NERR_Success
);
2712 SSVAL(*rparam
,2,0); /* converter word */
2715 p2
= p
+ usri11_end
;
2718 fstrcpy(p
+usri11_name
,UserName
); /* 21 bytes - user name */
2722 SCVAL(p
,usri11_pad
,0); /* padding - 1 byte */
2727 SIVAL(p
,usri11_comment
,PTR_DIFF(p2
,p
)); /* comment */
2728 pstrcpy(p2
,"Comment");
2729 p2
= skip_string(p2
,1);
2731 SIVAL(p
,usri11_usr_comment
,PTR_DIFF(p2
,p
)); /* user_comment */
2732 pstrcpy(p2
,"UserComment");
2733 p2
= skip_string(p2
,1);
2735 /* EEK! the cifsrap.txt doesn't have this in!!!! */
2736 SIVAL(p
,usri11_full_name
,PTR_DIFF(p2
,p
)); /* full name */
2737 pstrcpy(p2
,((vuser
!= NULL
) ? vuser
->user
.full_name
: UserName
));
2738 p2
= skip_string(p2
,1);
2741 if (uLevel
== 11) /* modelled after NTAS 3.51 reply */
2743 SSVAL(p
,usri11_priv
,conn
->admin_user
?USER_PRIV_ADMIN
:USER_PRIV_USER
);
2744 SIVAL(p
,usri11_auth_flags
,AF_OP_PRINT
); /* auth flags */
2745 SIVALS(p
,usri11_password_age
,-1); /* password age */
2746 SIVAL(p
,usri11_homedir
,PTR_DIFF(p2
,p
)); /* home dir */
2747 pstrcpy(p2
, vuser
&& vuser
->homedir
? vuser
->homedir
: "");
2748 p2
= skip_string(p2
,1);
2749 SIVAL(p
,usri11_parms
,PTR_DIFF(p2
,p
)); /* parms */
2751 p2
= skip_string(p2
,1);
2752 SIVAL(p
,usri11_last_logon
,0); /* last logon */
2753 SIVAL(p
,usri11_last_logoff
,0); /* last logoff */
2754 SSVALS(p
,usri11_bad_pw_count
,-1); /* bad pw counts */
2755 SSVALS(p
,usri11_num_logons
,-1); /* num logons */
2756 SIVAL(p
,usri11_logon_server
,PTR_DIFF(p2
,p
)); /* logon server */
2757 pstrcpy(p2
,"\\\\*");
2758 p2
= skip_string(p2
,1);
2759 SSVAL(p
,usri11_country_code
,0); /* country code */
2761 SIVAL(p
,usri11_workstations
,PTR_DIFF(p2
,p
)); /* workstations */
2763 p2
= skip_string(p2
,1);
2765 SIVALS(p
,usri11_max_storage
,-1); /* max storage */
2766 SSVAL(p
,usri11_units_per_week
,168); /* units per week */
2767 SIVAL(p
,usri11_logon_hours
,PTR_DIFF(p2
,p
)); /* logon hours */
2769 /* a simple way to get logon hours at all times. */
2771 SCVAL(p2
,21,0); /* fix zero termination */
2772 p2
= skip_string(p2
,1);
2774 SSVAL(p
,usri11_code_page
,0); /* code page */
2776 if (uLevel
== 1 || uLevel
== 2)
2778 memset(p
+22,' ',16); /* password */
2779 SIVALS(p
,38,-1); /* password age */
2781 conn
->admin_user
?USER_PRIV_ADMIN
:USER_PRIV_USER
);
2782 SIVAL(p
,44,PTR_DIFF(p2
,*rdata
)); /* home dir */
2783 pstrcpy(p2
, vuser
&& vuser
->homedir
? vuser
->homedir
: "");
2784 p2
= skip_string(p2
,1);
2785 SIVAL(p
,48,PTR_DIFF(p2
,*rdata
)); /* comment */
2787 SSVAL(p
,52,0); /* flags */
2788 SIVAL(p
,54,PTR_DIFF(p2
,*rdata
)); /* script_path */
2789 pstrcpy(p2
,vuser
&& vuser
->logon_script
? vuser
->logon_script
: "");
2790 p2
= skip_string(p2
,1);
2793 SIVAL(p
,60,0); /* auth_flags */
2794 SIVAL(p
,64,PTR_DIFF(p2
,*rdata
)); /* full_name */
2795 pstrcpy(p2
,((vuser
!= NULL
) ? vuser
->user
.full_name
: UserName
));
2796 p2
= skip_string(p2
,1);
2797 SIVAL(p
,68,0); /* urs_comment */
2798 SIVAL(p
,72,PTR_DIFF(p2
,*rdata
)); /* parms */
2800 p2
= skip_string(p2
,1);
2801 SIVAL(p
,76,0); /* workstations */
2802 SIVAL(p
,80,0); /* last_logon */
2803 SIVAL(p
,84,0); /* last_logoff */
2804 SIVALS(p
,88,-1); /* acct_expires */
2805 SIVALS(p
,92,-1); /* max_storage */
2806 SSVAL(p
,96,168); /* units_per_week */
2807 SIVAL(p
,98,PTR_DIFF(p2
,*rdata
)); /* logon_hours */
2810 SSVALS(p
,102,-1); /* bad_pw_count */
2811 SSVALS(p
,104,-1); /* num_logons */
2812 SIVAL(p
,106,PTR_DIFF(p2
,*rdata
)); /* logon_server */
2813 pstrcpy(p2
,"\\\\%L");
2814 standard_sub_conn(conn
, p2
,0);
2815 p2
= skip_string(p2
,1);
2816 SSVAL(p
,110,49); /* country_code */
2817 SSVAL(p
,112,860); /* code page */
2821 *rdata_len
= PTR_DIFF(p2
,*rdata
);
2823 SSVAL(*rparam
,4,*rdata_len
); /* is this right?? */
2828 static BOOL
api_WWkstaUserLogon(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
2829 int mdrcnt
,int mprcnt
,
2830 char **rdata
,char **rparam
,
2831 int *rdata_len
,int *rparam_len
)
2833 char *str1
= param
+2;
2834 char *str2
= skip_string(str1
,1);
2835 char *p
= skip_string(str2
,1);
2837 struct pack_desc desc
;
2839 /* With share level security vuid will always be zero.
2840 Don't depend on vuser being non-null !!. JRA */
2841 user_struct
*vuser
= get_valid_user_struct(vuid
);
2843 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser
->uid
,
2844 vuser
->user
.unix_name
));
2849 memset((char *)&desc
,'\0',sizeof(desc
));
2851 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel
,name
));
2853 /* check it's a supported varient */
2854 if (strcmp(str1
,"OOWb54WrLh") != 0) return False
;
2855 if (uLevel
!= 1 || strcmp(str2
,"WB21BWDWWDDDDDDDzzzD") != 0) return False
;
2856 if (mdrcnt
> 0) *rdata
= SMB_REALLOC_LIMIT(*rdata
,mdrcnt
);
2858 desc
.buflen
= mdrcnt
;
2859 desc
.subformat
= NULL
;
2862 if (init_package(&desc
,1,0))
2864 PACKI(&desc
,"W",0); /* code */
2865 PACKS(&desc
,"B21",name
); /* eff. name */
2866 PACKS(&desc
,"B",""); /* pad */
2868 conn
->admin_user
?USER_PRIV_ADMIN
:USER_PRIV_USER
);
2869 PACKI(&desc
,"D",0); /* auth flags XXX */
2870 PACKI(&desc
,"W",0); /* num logons */
2871 PACKI(&desc
,"W",0); /* bad pw count */
2872 PACKI(&desc
,"D",0); /* last logon */
2873 PACKI(&desc
,"D",-1); /* last logoff */
2874 PACKI(&desc
,"D",-1); /* logoff time */
2875 PACKI(&desc
,"D",-1); /* kickoff time */
2876 PACKI(&desc
,"D",0); /* password age */
2877 PACKI(&desc
,"D",0); /* password can change */
2878 PACKI(&desc
,"D",-1); /* password must change */
2881 fstrcpy(mypath
,"\\\\");
2882 fstrcat(mypath
,get_local_machine_name());
2884 PACKS(&desc
,"z",mypath
); /* computer */
2886 PACKS(&desc
,"z",lp_workgroup());/* domain */
2888 PACKS(&desc
,"z", vuser
&& vuser
->logon_script
? vuser
->logon_script
:""); /* script path */
2890 PACKI(&desc
,"D",0x00000000); /* reserved */
2893 *rdata_len
= desc
.usedlen
;
2895 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
2896 SSVALS(*rparam
,0,desc
.errcode
);
2898 SSVAL(*rparam
,4,desc
.neededlen
);
2900 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc
.errcode
));
2905 /****************************************************************************
2906 api_WAccessGetUserPerms
2907 ****************************************************************************/
2908 static BOOL
api_WAccessGetUserPerms(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
2909 int mdrcnt
,int mprcnt
,
2910 char **rdata
,char **rparam
,
2911 int *rdata_len
,int *rparam_len
)
2913 char *str1
= param
+2;
2914 char *str2
= skip_string(str1
,1);
2915 char *user
= skip_string(str2
,1);
2916 char *resource
= skip_string(user
,1);
2918 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user
,resource
));
2920 /* check it's a supported varient */
2921 if (strcmp(str1
,"zzh") != 0) return False
;
2922 if (strcmp(str2
,"") != 0) return False
;
2925 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
2926 SSVALS(*rparam
,0,0); /* errorcode */
2927 SSVAL(*rparam
,2,0); /* converter word */
2928 SSVAL(*rparam
,4,0x7f); /* permission flags */
2933 /****************************************************************************
2934 api_WPrintJobEnumerate
2935 ****************************************************************************/
2936 static BOOL
api_WPrintJobGetInfo(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
2937 int mdrcnt
,int mprcnt
,
2938 char **rdata
,char **rparam
,
2939 int *rdata_len
,int *rparam_len
)
2941 char *str1
= param
+2;
2942 char *str2
= skip_string(str1
,1);
2943 char *p
= skip_string(str2
,1);
2950 struct pack_desc desc
;
2951 print_queue_struct
*queue
=NULL
;
2952 print_status_struct status
;
2957 memset((char *)&desc
,'\0',sizeof(desc
));
2958 memset((char *)&status
,'\0',sizeof(status
));
2960 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel
,SVAL(p
,0)));
2962 /* check it's a supported varient */
2963 if (strcmp(str1
,"WWrLh") != 0) return False
;
2964 if (!check_printjob_info(&desc
,uLevel
,str2
)) return False
;
2966 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
))
2969 snum
= lp_servicenumber( sharename
);
2970 if (snum
< 0 || !VALID_SNUM(snum
)) return(False
);
2972 count
= print_queue_status(snum
,&queue
,&status
);
2973 for (i
= 0; i
< count
; i
++) {
2974 if (queue
[i
].job
== jobid
) break;
2978 *rdata
= SMB_REALLOC_LIMIT(*rdata
,mdrcnt
);
2980 desc
.buflen
= mdrcnt
;
2983 * Don't return data but need to get correct length
2984 * init_package will return wrong size if buflen=0
2986 desc
.buflen
= getlen(desc
.format
);
2987 desc
.base
= tmpdata
= (char *)SMB_MALLOC( desc
.buflen
);
2990 if (init_package(&desc
,1,0)) {
2992 fill_printjob_info(conn
,snum
,uLevel
,&desc
,&queue
[i
],i
);
2993 *rdata_len
= desc
.usedlen
;
2996 desc
.errcode
= NERR_JobNotFound
;
3002 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
3003 SSVALS(*rparam
,0,desc
.errcode
);
3005 SSVAL(*rparam
,4,desc
.neededlen
);
3010 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc
.errcode
));
3014 static BOOL
api_WPrintJobEnumerate(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
3015 int mdrcnt
,int mprcnt
,
3016 char **rdata
,char **rparam
,
3017 int *rdata_len
,int *rparam_len
)
3019 char *str1
= param
+2;
3020 char *str2
= skip_string(str1
,1);
3021 char *p
= skip_string(str2
,1);
3027 struct pack_desc desc
;
3028 print_queue_struct
*queue
=NULL
;
3029 print_status_struct status
;
3031 memset((char *)&desc
,'\0',sizeof(desc
));
3032 memset((char *)&status
,'\0',sizeof(status
));
3034 p
= skip_string(p
,1);
3037 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel
,name
));
3039 /* check it's a supported variant */
3040 if (strcmp(str1
,"zWrLeh") != 0)
3044 return False
; /* defined only for uLevel 0,1,2 */
3046 if (!check_printjob_info(&desc
,uLevel
,str2
))
3049 snum
= find_service(name
);
3050 if ( !(lp_snum_ok(snum
) && lp_print_ok(snum
)) )
3053 count
= print_queue_status(snum
,&queue
,&status
);
3054 if (mdrcnt
> 0) *rdata
= SMB_REALLOC_LIMIT(*rdata
,mdrcnt
);
3056 desc
.buflen
= mdrcnt
;
3058 if (init_package(&desc
,count
,0)) {
3060 for (i
= 0; i
< count
; i
++) {
3061 fill_printjob_info(conn
,snum
,uLevel
,&desc
,&queue
[i
],i
);
3062 if (desc
.errcode
== NERR_Success
) succnt
= i
+1;
3066 *rdata_len
= desc
.usedlen
;
3069 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
3070 SSVALS(*rparam
,0,desc
.errcode
);
3072 SSVAL(*rparam
,4,succnt
);
3073 SSVAL(*rparam
,6,count
);
3077 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc
.errcode
));
3081 static int check_printdest_info(struct pack_desc
* desc
,
3082 int uLevel
, char* id
)
3084 desc
->subformat
= NULL
;
3086 case 0: desc
->format
= "B9"; break;
3087 case 1: desc
->format
= "B9B21WWzW"; break;
3088 case 2: desc
->format
= "z"; break;
3089 case 3: desc
->format
= "zzzWWzzzWW"; break;
3090 default: return False
;
3092 if (strcmp(desc
->format
,id
) != 0) return False
;
3096 static void fill_printdest_info(connection_struct
*conn
, int snum
, int uLevel
,
3097 struct pack_desc
* desc
)
3100 strncpy(buf
,SERVICE(snum
),sizeof(buf
)-1);
3101 buf
[sizeof(buf
)-1] = 0;
3104 PACKS(desc
,"B9",buf
); /* szName */
3106 PACKS(desc
,"B21",""); /* szUserName */
3107 PACKI(desc
,"W",0); /* uJobId */
3108 PACKI(desc
,"W",0); /* fsStatus */
3109 PACKS(desc
,"z",""); /* pszStatus */
3110 PACKI(desc
,"W",0); /* time */
3113 if (uLevel
== 2 || uLevel
== 3) {
3114 PACKS(desc
,"z",buf
); /* pszPrinterName */
3116 PACKS(desc
,"z",""); /* pszUserName */
3117 PACKS(desc
,"z",""); /* pszLogAddr */
3118 PACKI(desc
,"W",0); /* uJobId */
3119 PACKI(desc
,"W",0); /* fsStatus */
3120 PACKS(desc
,"z",""); /* pszStatus */
3121 PACKS(desc
,"z",""); /* pszComment */
3122 PACKS(desc
,"z","NULL"); /* pszDrivers */
3123 PACKI(desc
,"W",0); /* time */
3124 PACKI(desc
,"W",0); /* pad1 */
3129 static BOOL
api_WPrintDestGetInfo(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
3130 int mdrcnt
,int mprcnt
,
3131 char **rdata
,char **rparam
,
3132 int *rdata_len
,int *rparam_len
)
3134 char *str1
= param
+2;
3135 char *str2
= skip_string(str1
,1);
3136 char *p
= skip_string(str2
,1);
3137 char* PrinterName
= p
;
3139 struct pack_desc desc
;
3143 memset((char *)&desc
,'\0',sizeof(desc
));
3145 p
= skip_string(p
,1);
3148 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel
,PrinterName
));
3150 /* check it's a supported varient */
3151 if (strcmp(str1
,"zWrLh") != 0) return False
;
3152 if (!check_printdest_info(&desc
,uLevel
,str2
)) return False
;
3154 snum
= find_service(PrinterName
);
3155 if ( !(lp_snum_ok(snum
) && lp_print_ok(snum
)) ) {
3157 desc
.errcode
= NERR_DestNotFound
;
3162 *rdata
= SMB_REALLOC_LIMIT(*rdata
,mdrcnt
);
3164 desc
.buflen
= mdrcnt
;
3167 * Don't return data but need to get correct length
3168 * init_package will return wrong size if buflen=0
3170 desc
.buflen
= getlen(desc
.format
);
3171 desc
.base
= tmpdata
= (char *)SMB_MALLOC( desc
.buflen
);
3173 if (init_package(&desc
,1,0)) {
3174 fill_printdest_info(conn
,snum
,uLevel
,&desc
);
3176 *rdata_len
= desc
.usedlen
;
3180 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
3181 SSVALS(*rparam
,0,desc
.errcode
);
3183 SSVAL(*rparam
,4,desc
.neededlen
);
3185 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc
.errcode
));
3190 static BOOL
api_WPrintDestEnum(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
3191 int mdrcnt
,int mprcnt
,
3192 char **rdata
,char **rparam
,
3193 int *rdata_len
,int *rparam_len
)
3195 char *str1
= param
+2;
3196 char *str2
= skip_string(str1
,1);
3197 char *p
= skip_string(str2
,1);
3201 struct pack_desc desc
;
3202 int services
= lp_numservices();
3204 memset((char *)&desc
,'\0',sizeof(desc
));
3208 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel
));
3210 /* check it's a supported varient */
3211 if (strcmp(str1
,"WrLeh") != 0) return False
;
3212 if (!check_printdest_info(&desc
,uLevel
,str2
)) return False
;
3215 for (i
= 0; i
< services
; i
++)
3216 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
))
3219 if (mdrcnt
> 0) *rdata
= SMB_REALLOC_LIMIT(*rdata
,mdrcnt
);
3221 desc
.buflen
= mdrcnt
;
3222 if (init_package(&desc
,queuecnt
,0)) {
3225 for (i
= 0; i
< services
; i
++) {
3226 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
)) {
3227 fill_printdest_info(conn
,i
,uLevel
,&desc
);
3229 if (desc
.errcode
== NERR_Success
) succnt
= n
;
3234 *rdata_len
= desc
.usedlen
;
3237 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
3238 SSVALS(*rparam
,0,desc
.errcode
);
3240 SSVAL(*rparam
,4,succnt
);
3241 SSVAL(*rparam
,6,queuecnt
);
3243 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc
.errcode
));
3247 static BOOL
api_WPrintDriverEnum(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
3248 int mdrcnt
,int mprcnt
,
3249 char **rdata
,char **rparam
,
3250 int *rdata_len
,int *rparam_len
)
3252 char *str1
= param
+2;
3253 char *str2
= skip_string(str1
,1);
3254 char *p
= skip_string(str2
,1);
3257 struct pack_desc desc
;
3259 memset((char *)&desc
,'\0',sizeof(desc
));
3263 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel
));
3265 /* check it's a supported varient */
3266 if (strcmp(str1
,"WrLeh") != 0) return False
;
3267 if (uLevel
!= 0 || strcmp(str2
,"B41") != 0) return False
;
3269 if (mdrcnt
> 0) *rdata
= SMB_REALLOC_LIMIT(*rdata
,mdrcnt
);
3271 desc
.buflen
= mdrcnt
;
3272 if (init_package(&desc
,1,0)) {
3273 PACKS(&desc
,"B41","NULL");
3276 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
3278 *rdata_len
= desc
.usedlen
;
3281 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
3282 SSVALS(*rparam
,0,desc
.errcode
);
3284 SSVAL(*rparam
,4,succnt
);
3287 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc
.errcode
));
3291 static BOOL
api_WPrintQProcEnum(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
3292 int mdrcnt
,int mprcnt
,
3293 char **rdata
,char **rparam
,
3294 int *rdata_len
,int *rparam_len
)
3296 char *str1
= param
+2;
3297 char *str2
= skip_string(str1
,1);
3298 char *p
= skip_string(str2
,1);
3301 struct pack_desc desc
;
3303 memset((char *)&desc
,'\0',sizeof(desc
));
3307 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel
));
3309 /* check it's a supported varient */
3310 if (strcmp(str1
,"WrLeh") != 0) return False
;
3311 if (uLevel
!= 0 || strcmp(str2
,"B13") != 0) return False
;
3313 if (mdrcnt
> 0) *rdata
= SMB_REALLOC_LIMIT(*rdata
,mdrcnt
);
3315 desc
.buflen
= mdrcnt
;
3317 if (init_package(&desc
,1,0)) {
3318 PACKS(&desc
,"B13","lpd");
3321 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
3323 *rdata_len
= desc
.usedlen
;
3326 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
3327 SSVALS(*rparam
,0,desc
.errcode
);
3329 SSVAL(*rparam
,4,succnt
);
3332 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc
.errcode
));
3336 static BOOL
api_WPrintPortEnum(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
3337 int mdrcnt
,int mprcnt
,
3338 char **rdata
,char **rparam
,
3339 int *rdata_len
,int *rparam_len
)
3341 char *str1
= param
+2;
3342 char *str2
= skip_string(str1
,1);
3343 char *p
= skip_string(str2
,1);
3346 struct pack_desc desc
;
3348 memset((char *)&desc
,'\0',sizeof(desc
));
3352 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel
));
3354 /* check it's a supported varient */
3355 if (strcmp(str1
,"WrLeh") != 0) return False
;
3356 if (uLevel
!= 0 || strcmp(str2
,"B9") != 0) return False
;
3358 if (mdrcnt
> 0) *rdata
= SMB_REALLOC_LIMIT(*rdata
,mdrcnt
);
3359 memset((char *)&desc
,'\0',sizeof(desc
));
3361 desc
.buflen
= mdrcnt
;
3363 if (init_package(&desc
,1,0)) {
3364 PACKS(&desc
,"B13","lp0");
3367 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
3369 *rdata_len
= desc
.usedlen
;
3372 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
3373 SSVALS(*rparam
,0,desc
.errcode
);
3375 SSVAL(*rparam
,4,succnt
);
3378 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc
.errcode
));
3383 /****************************************************************************
3385 ****************************************************************************/
3386 static BOOL
api_RNetSessionEnum(connection_struct
*conn
,uint16 vuid
, char *param
, char *data
,
3387 int mdrcnt
,int mprcnt
,
3388 char **rdata
,char **rparam
,
3389 int *rdata_len
,int *rparam_len
)
3392 char *str1
= param
+2;
3393 char *str2
= skip_string(str1
,1);
3394 char *p
= skip_string(str2
,1);
3396 struct pack_desc desc
;
3397 struct sessionid
*session_list
;
3398 int i
, num_sessions
;
3400 memset((char *)&desc
,'\0',sizeof(desc
));
3404 DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel
));
3405 DEBUG(7,("RNetSessionEnum req string=%s\n",str1
));
3406 DEBUG(7,("RNetSessionEnum ret string=%s\n",str2
));
3408 /* check it's a supported varient */
3409 if (strcmp(str1
,RAP_NetSessionEnum_REQ
) != 0) return False
;
3410 if (uLevel
!= 2 || strcmp(str2
,RAP_SESSION_INFO_L2
) != 0) return False
;
3412 num_sessions
= list_sessions(&session_list
);
3414 if (mdrcnt
> 0) *rdata
= SMB_REALLOC_LIMIT(*rdata
,mdrcnt
);
3415 memset((char *)&desc
,'\0',sizeof(desc
));
3417 desc
.buflen
= mdrcnt
;
3419 if (!init_package(&desc
,num_sessions
,0)) {
3423 for(i
=0; i
<num_sessions
; i
++) {
3424 PACKS(&desc
, "z", session_list
[i
].remote_machine
);
3425 PACKS(&desc
, "z", session_list
[i
].username
);
3426 PACKI(&desc
, "W", 1); /* num conns */
3427 PACKI(&desc
, "W", 0); /* num opens */
3428 PACKI(&desc
, "W", 1); /* num users */
3429 PACKI(&desc
, "D", 0); /* session time */
3430 PACKI(&desc
, "D", 0); /* idle time */
3431 PACKI(&desc
, "D", 0); /* flags */
3432 PACKS(&desc
, "z", "Unknown Client"); /* client type string */
3435 *rdata_len
= desc
.usedlen
;
3438 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
3439 SSVALS(*rparam
,0,desc
.errcode
);
3440 SSVAL(*rparam
,2,0); /* converter */
3441 SSVAL(*rparam
,4,num_sessions
); /* count */
3443 DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc
.errcode
));
3448 /****************************************************************************
3449 The buffer was too small
3450 ****************************************************************************/
3452 static BOOL
api_TooSmall(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
3453 int mdrcnt
,int mprcnt
,
3454 char **rdata
,char **rparam
,
3455 int *rdata_len
,int *rparam_len
)
3457 *rparam_len
= MIN(*rparam_len
,mprcnt
);
3458 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
3462 SSVAL(*rparam
,0,NERR_BufTooSmall
);
3464 DEBUG(3,("Supplied buffer too small in API command\n"));
3470 /****************************************************************************
3471 The request is not supported
3472 ****************************************************************************/
3474 static BOOL
api_Unsupported(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
3475 int mdrcnt
,int mprcnt
,
3476 char **rdata
,char **rparam
,
3477 int *rdata_len
,int *rparam_len
)
3480 *rparam
= SMB_REALLOC_LIMIT(*rparam
,*rparam_len
);
3484 SSVAL(*rparam
,0,NERR_notsupported
);
3485 SSVAL(*rparam
,2,0); /* converter word */
3487 DEBUG(3,("Unsupported API command\n"));
3499 BOOL (*fn
)(connection_struct
*,uint16
,char *,char *,
3500 int,int,char **,char **,int *,int *);
3501 BOOL auth_user
; /* Deny anonymous access? */
3502 } api_commands
[] = {
3503 {"RNetShareEnum", RAP_WshareEnum
, api_RNetShareEnum
, True
},
3504 {"RNetShareGetInfo", RAP_WshareGetInfo
, api_RNetShareGetInfo
},
3505 {"RNetShareAdd", RAP_WshareAdd
, api_RNetShareAdd
},
3506 {"RNetSessionEnum", RAP_WsessionEnum
, api_RNetSessionEnum
, True
},
3507 {"RNetServerGetInfo", RAP_WserverGetInfo
, api_RNetServerGetInfo
},
3508 {"RNetGroupEnum", RAP_WGroupEnum
, api_RNetGroupEnum
, True
},
3509 {"RNetGroupGetUsers", RAP_WGroupGetUsers
, api_RNetGroupGetUsers
, True
},
3510 {"RNetUserEnum", RAP_WUserEnum
, api_RNetUserEnum
, True
},
3511 {"RNetUserGetInfo", RAP_WUserGetInfo
, api_RNetUserGetInfo
},
3512 {"NetUserGetGroups", RAP_WUserGetGroups
, api_NetUserGetGroups
},
3513 {"NetWkstaGetInfo", RAP_WWkstaGetInfo
, api_NetWkstaGetInfo
},
3514 {"DosPrintQEnum", RAP_WPrintQEnum
, api_DosPrintQEnum
, True
},
3515 {"DosPrintQGetInfo", RAP_WPrintQGetInfo
, api_DosPrintQGetInfo
},
3516 {"WPrintQueuePause", RAP_WPrintQPause
, api_WPrintQueueCtrl
},
3517 {"WPrintQueueResume", RAP_WPrintQContinue
, api_WPrintQueueCtrl
},
3518 {"WPrintJobEnumerate",RAP_WPrintJobEnum
, api_WPrintJobEnumerate
},
3519 {"WPrintJobGetInfo", RAP_WPrintJobGetInfo
, api_WPrintJobGetInfo
},
3520 {"RDosPrintJobDel", RAP_WPrintJobDel
, api_RDosPrintJobDel
},
3521 {"RDosPrintJobPause", RAP_WPrintJobPause
, api_RDosPrintJobDel
},
3522 {"RDosPrintJobResume",RAP_WPrintJobContinue
, api_RDosPrintJobDel
},
3523 {"WPrintDestEnum", RAP_WPrintDestEnum
, api_WPrintDestEnum
},
3524 {"WPrintDestGetInfo", RAP_WPrintDestGetInfo
, api_WPrintDestGetInfo
},
3525 {"NetRemoteTOD", RAP_NetRemoteTOD
, api_NetRemoteTOD
},
3526 {"WPrintQueuePurge", RAP_WPrintQPurge
, api_WPrintQueueCtrl
},
3527 {"NetServerEnum", RAP_NetServerEnum2
, api_RNetServerEnum
}, /* anon OK */
3528 {"WAccessGetUserPerms",RAP_WAccessGetUserPerms
,api_WAccessGetUserPerms
},
3529 {"SetUserPassword", RAP_WUserPasswordSet2
, api_SetUserPassword
},
3530 {"WWkstaUserLogon", RAP_WWkstaUserLogon
, api_WWkstaUserLogon
},
3531 {"PrintJobInfo", RAP_WPrintJobSetInfo
, api_PrintJobInfo
},
3532 {"WPrintDriverEnum", RAP_WPrintDriverEnum
, api_WPrintDriverEnum
},
3533 {"WPrintQProcEnum", RAP_WPrintQProcessorEnum
,api_WPrintQProcEnum
},
3534 {"WPrintPortEnum", RAP_WPrintPortEnum
, api_WPrintPortEnum
},
3535 {"SamOEMChangePassword",RAP_SamOEMChgPasswordUser2_P
,api_SamOEMChangePassword
}, /* anon OK */
3536 {NULL
, -1, api_Unsupported
}};
3538 /* The following RAP calls are not implemented by Samba:
3540 RAP_WFileEnum2 - anon not OK
3543 /****************************************************************************
3544 Handle remote api calls
3545 ****************************************************************************/
3547 int api_reply(connection_struct
*conn
,uint16 vuid
,char *outbuf
,char *data
,char *params
,
3548 int tdscnt
,int tpscnt
,int mdrcnt
,int mprcnt
)
3552 char *rparam
= NULL
;
3559 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
3563 api_command
= SVAL(params
,0);
3565 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
3568 skip_string(params
+2,1),
3569 tdscnt
,tpscnt
,mdrcnt
,mprcnt
));
3571 for (i
=0;api_commands
[i
].name
;i
++) {
3572 if (api_commands
[i
].id
== api_command
&& api_commands
[i
].fn
) {
3573 DEBUG(3,("Doing %s\n",api_commands
[i
].name
));
3578 /* Check whether this api call can be done anonymously */
3580 if (api_commands
[i
].auth_user
&& lp_restrict_anonymous()) {
3581 user_struct
*user
= get_valid_user_struct(vuid
);
3583 if (!user
|| user
->guest
)
3584 return ERROR_NT(NT_STATUS_ACCESS_DENIED
);
3587 rdata
= (char *)SMB_MALLOC(1024);
3589 memset(rdata
,'\0',1024);
3591 rparam
= (char *)SMB_MALLOC(1024);
3593 memset(rparam
,'\0',1024);
3595 if(!rdata
|| !rparam
) {
3596 DEBUG(0,("api_reply: malloc fail !\n"));
3600 reply
= api_commands
[i
].fn(conn
,vuid
,params
,data
,mdrcnt
,mprcnt
,
3601 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
3604 if (rdata_len
> mdrcnt
||
3605 rparam_len
> mprcnt
) {
3606 reply
= api_TooSmall(conn
,vuid
,params
,data
,mdrcnt
,mprcnt
,
3607 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
3610 /* if we get False back then it's actually unsupported */
3612 api_Unsupported(conn
,vuid
,params
,data
,mdrcnt
,mprcnt
,
3613 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
3615 send_trans_reply(outbuf
, rparam
, rparam_len
, rdata
, rdata_len
, False
);