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
= REALLOC(*rparam
,*rparam_len
);
757 SSVALS(*rparam
,0,ERRunknownlevel
);
763 snum
= lp_servicenumber(QueueName
);
764 if (snum
< 0 && pcap_printername_ok(QueueName
,NULL
)) {
765 int pnum
= lp_servicenumber(PRINTERS_NAME
);
767 lp_add_printer(QueueName
,pnum
);
768 snum
= lp_servicenumber(QueueName
);
772 if (snum
< 0 || !VALID_SNUM(snum
))
776 count
= get_printerdrivernumber(snum
);
777 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count
));
779 count
= print_queue_status(snum
, &queue
,&status
);
783 *rdata
= REALLOC(*rdata
,mdrcnt
);
785 desc
.buflen
= mdrcnt
;
788 * Don't return data but need to get correct length
789 * init_package will return wrong size if buflen=0
791 desc
.buflen
= getlen(desc
.format
);
792 desc
.base
= tmpdata
= (char *) malloc (desc
.buflen
);
795 if (init_package(&desc
,1,count
)) {
796 desc
.subcount
= count
;
797 fill_printq_info(conn
,snum
,uLevel
,&desc
,count
,queue
,&status
);
800 *rdata_len
= desc
.usedlen
;
803 * We must set the return code to ERRbuftoosmall
804 * in order to support lanman style printing with Win NT/2k
807 if (!mdrcnt
&& lp_disable_spoolss())
808 desc
.errcode
= ERRbuftoosmall
;
810 *rdata_len
= desc
.usedlen
;
812 *rparam
= REALLOC(*rparam
,*rparam_len
);
813 SSVALS(*rparam
,0,desc
.errcode
);
815 SSVAL(*rparam
,4,desc
.neededlen
);
817 DEBUG(4,("printqgetinfo: errorcode %d\n",desc
.errcode
));
825 /****************************************************************************
826 View list of all print jobs on all queues.
827 ****************************************************************************/
829 static BOOL
api_DosPrintQEnum(connection_struct
*conn
, uint16 vuid
, char* param
, char* data
,
830 int mdrcnt
, int mprcnt
,
831 char **rdata
, char** rparam
,
832 int *rdata_len
, int *rparam_len
)
834 char *param_format
= param
+2;
835 char *output_format1
= skip_string(param_format
,1);
836 char *p
= skip_string(output_format1
,1);
837 int uLevel
= SVAL(p
,0);
838 char *output_format2
= p
+ 4;
839 int services
= lp_numservices();
841 struct pack_desc desc
;
842 print_queue_struct
**queue
= NULL
;
843 print_status_struct
*status
= NULL
;
844 int* subcntarr
= NULL
;
845 int queuecnt
, subcnt
=0, succnt
=0;
847 memset((char *)&desc
,'\0',sizeof(desc
));
849 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel
));
851 if (!prefix_ok(param_format
,"WrLeh")) return False
;
852 if (!check_printq_info(&desc
,uLevel
,output_format1
,output_format2
)) {
854 * Patch from Scott Moomaw <scott@bridgewater.edu>
855 * to return the 'invalid info level' error if an
856 * unknown level was requested.
860 *rparam
= REALLOC(*rparam
,*rparam_len
);
861 SSVALS(*rparam
,0,ERRunknownlevel
);
868 for (i
= 0; i
< services
; i
++)
869 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
))
872 if((queue
= (print_queue_struct
**)malloc(queuecnt
*sizeof(print_queue_struct
*))) == NULL
) {
873 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
876 memset(queue
,0,queuecnt
*sizeof(print_queue_struct
*));
877 if((status
= (print_status_struct
*)malloc(queuecnt
*sizeof(print_status_struct
))) == NULL
) {
878 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
881 memset(status
,0,queuecnt
*sizeof(print_status_struct
));
882 if((subcntarr
= (int*)malloc(queuecnt
*sizeof(int))) == NULL
) {
883 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
888 for (i
= 0; i
< services
; i
++)
889 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
)) {
890 subcntarr
[n
] = print_queue_status(i
, &queue
[n
],&status
[n
]);
891 subcnt
+= subcntarr
[n
];
895 if (mdrcnt
> 0) *rdata
= REALLOC(*rdata
,mdrcnt
);
897 desc
.buflen
= mdrcnt
;
899 if (init_package(&desc
,queuecnt
,subcnt
)) {
902 for (i
= 0; i
< services
; i
++)
903 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
)) {
904 fill_printq_info(conn
,i
,uLevel
,&desc
,subcntarr
[n
],queue
[n
],&status
[n
]);
906 if (desc
.errcode
== NERR_Success
) succnt
= n
;
910 SAFE_FREE(subcntarr
);
912 *rdata_len
= desc
.usedlen
;
914 *rparam
= REALLOC(*rparam
,*rparam_len
);
915 SSVALS(*rparam
,0,desc
.errcode
);
917 SSVAL(*rparam
,4,succnt
);
918 SSVAL(*rparam
,6,queuecnt
);
920 for (i
= 0; i
< queuecnt
; i
++) {
921 if (queue
) SAFE_FREE(queue
[i
]);
930 /****************************************************************************
931 get info level for a server list query
932 ****************************************************************************/
933 static BOOL
check_server_info(int uLevel
, char* id
)
937 if (strcmp(id
,"B16") != 0) return False
;
940 if (strcmp(id
,"B16BBDz") != 0) return False
;
948 struct srv_info_struct
958 /*******************************************************************
959 get server info lists from the files saved by nmbd. Return the
961 ******************************************************************/
962 static int get_server_info(uint32 servertype
,
963 struct srv_info_struct
**servers
,
969 BOOL local_list_only
;
972 lines
= file_lines_load(lock_path(SERVER_LIST
), NULL
);
974 DEBUG(4,("Can't open %s - %s\n",lock_path(SERVER_LIST
),strerror(errno
)));
978 /* request for everything is code for request all servers */
979 if (servertype
== SV_TYPE_ALL
)
980 servertype
&= ~(SV_TYPE_DOMAIN_ENUM
|SV_TYPE_LOCAL_LIST_ONLY
);
982 local_list_only
= (servertype
& SV_TYPE_LOCAL_LIST_ONLY
);
984 DEBUG(4,("Servertype search: %8x\n",servertype
));
986 for (i
=0;lines
[i
];i
++) {
988 struct srv_info_struct
*s
;
989 const char *ptr
= lines
[i
];
994 if (count
== alloced
) {
995 struct srv_info_struct
*ts
;
998 ts
= (struct srv_info_struct
*)
999 Realloc(*servers
,sizeof(**servers
)*alloced
);
1001 DEBUG(0,("get_server_info: failed to enlarge servers info struct!\n"));
1005 memset((char *)((*servers
)+count
),'\0',sizeof(**servers
)*(alloced
-count
));
1007 s
= &(*servers
)[count
];
1009 if (!next_token(&ptr
,s
->name
, NULL
, sizeof(s
->name
))) continue;
1010 if (!next_token(&ptr
,stype
, NULL
, sizeof(stype
))) continue;
1011 if (!next_token(&ptr
,s
->comment
, NULL
, sizeof(s
->comment
))) continue;
1012 if (!next_token(&ptr
,s
->domain
, NULL
, sizeof(s
->domain
))) {
1013 /* this allows us to cope with an old nmbd */
1014 fstrcpy(s
->domain
,lp_workgroup());
1017 if (sscanf(stype
,"%X",&s
->type
) != 1) {
1018 DEBUG(4,("r:host file "));
1022 /* Filter the servers/domains we return based on what was asked for. */
1024 /* Check to see if we are being asked for a local list only. */
1025 if(local_list_only
&& ((s
->type
& SV_TYPE_LOCAL_LIST_ONLY
) == 0)) {
1026 DEBUG(4,("r: local list only"));
1030 /* doesn't match up: don't want it */
1031 if (!(servertype
& s
->type
)) {
1032 DEBUG(4,("r:serv type "));
1036 if ((servertype
& SV_TYPE_DOMAIN_ENUM
) !=
1037 (s
->type
& SV_TYPE_DOMAIN_ENUM
))
1039 DEBUG(4,("s: dom mismatch "));
1043 if (!strequal(domain
, s
->domain
) && !(servertype
& SV_TYPE_DOMAIN_ENUM
))
1048 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1049 s
->type
&= ~SV_TYPE_LOCAL_LIST_ONLY
;
1053 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1054 s
->name
, s
->type
, s
->comment
, s
->domain
));
1056 s
->server_added
= True
;
1061 DEBUG(4,("%20s %8x %25s %15s\n",
1062 s
->name
, s
->type
, s
->comment
, s
->domain
));
1066 file_lines_free(lines
);
1071 /*******************************************************************
1072 fill in a server info structure
1073 ******************************************************************/
1074 static int fill_srv_info(struct srv_info_struct
*service
,
1075 int uLevel
, char **buf
, int *buflen
,
1076 char **stringbuf
, int *stringspace
, char *baseaddr
)
1085 case 0: struct_len
= 16; break;
1086 case 1: struct_len
= 26; break;
1096 len
= strlen(service
->comment
)+1;
1100 if (buflen
) *buflen
= struct_len
;
1101 if (stringspace
) *stringspace
= len
;
1102 return struct_len
+ len
;
1107 if (*buflen
< struct_len
) return -1;
1115 p2
= p
+ struct_len
;
1116 l2
= *buflen
- struct_len
;
1118 if (!baseaddr
) baseaddr
= p
;
1123 push_ascii(p
,service
->name
, MAX_NETBIOSNAME_LEN
, STR_TERMINATE
);
1127 push_ascii(p
,service
->name
,MAX_NETBIOSNAME_LEN
, STR_TERMINATE
);
1128 SIVAL(p
,18,service
->type
);
1129 SIVAL(p
,22,PTR_DIFF(p2
,baseaddr
));
1130 len
+= CopyAndAdvance(&p2
,service
->comment
,&l2
);
1136 *buf
= p
+ struct_len
;
1137 *buflen
-= struct_len
;
1150 static BOOL
srv_comp(struct srv_info_struct
*s1
,struct srv_info_struct
*s2
)
1152 return(strcmp(s1
->name
,s2
->name
));
1155 /****************************************************************************
1156 view list of servers available (or possibly domains). The info is
1157 extracted from lists saved by nmbd on the local host
1158 ****************************************************************************/
1159 static BOOL
api_RNetServerEnum(connection_struct
*conn
, uint16 vuid
, char *param
, char *data
,
1160 int mdrcnt
, int mprcnt
, char **rdata
,
1161 char **rparam
, int *rdata_len
, int *rparam_len
)
1163 char *str1
= param
+2;
1164 char *str2
= skip_string(str1
,1);
1165 char *p
= skip_string(str2
,1);
1166 int uLevel
= SVAL(p
,0);
1167 int buf_len
= SVAL(p
,2);
1168 uint32 servertype
= IVAL(p
,4);
1170 int data_len
, fixed_len
, string_len
;
1171 int f_len
= 0, s_len
= 0;
1172 struct srv_info_struct
*servers
=NULL
;
1173 int counted
=0,total
=0;
1176 BOOL domain_request
;
1179 /* If someone sets all the bits they don't really mean to set
1180 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1183 if (servertype
== SV_TYPE_ALL
)
1184 servertype
&= ~(SV_TYPE_DOMAIN_ENUM
|SV_TYPE_LOCAL_LIST_ONLY
);
1186 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1187 any other bit (they may just set this bit on it's own) they
1188 want all the locally seen servers. However this bit can be
1189 set on its own so set the requested servers to be
1190 ALL - DOMAIN_ENUM. */
1192 if ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) && !(servertype
& SV_TYPE_DOMAIN_ENUM
))
1193 servertype
= SV_TYPE_ALL
& ~(SV_TYPE_DOMAIN_ENUM
);
1195 domain_request
= ((servertype
& SV_TYPE_DOMAIN_ENUM
) != 0);
1196 local_request
= ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) != 0);
1200 if (!prefix_ok(str1
,"WrLehD")) return False
;
1201 if (!check_server_info(uLevel
,str2
)) return False
;
1203 DEBUG(4, ("server request level: %s %8x ", str2
, servertype
));
1204 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request
)));
1205 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request
)));
1207 if (strcmp(str1
, "WrLehDz") == 0) {
1208 pull_ascii_fstring(domain
, p
);
1210 fstrcpy(domain
, lp_workgroup());
1213 if (lp_browse_list())
1214 total
= get_server_info(servertype
,&servers
,domain
);
1216 data_len
= fixed_len
= string_len
= 0;
1220 qsort(servers
,total
,sizeof(servers
[0]),QSORT_CAST srv_comp
);
1223 char *lastname
=NULL
;
1225 for (i
=0;i
<total
;i
++)
1227 struct srv_info_struct
*s
= &servers
[i
];
1228 if (lastname
&& strequal(lastname
,s
->name
)) continue;
1230 data_len
+= fill_srv_info(s
,uLevel
,0,&f_len
,0,&s_len
,0);
1231 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1232 s
->name
, s
->type
, s
->comment
, s
->domain
));
1234 if (data_len
<= buf_len
) {
1237 string_len
+= s_len
;
1244 *rdata_len
= fixed_len
+ string_len
;
1245 *rdata
= REALLOC(*rdata
,*rdata_len
);
1246 memset(*rdata
,'\0',*rdata_len
);
1248 p2
= (*rdata
) + fixed_len
; /* auxilliary data (strings) will go here */
1254 char *lastname
=NULL
;
1255 int count2
= counted
;
1256 for (i
= 0; i
< total
&& count2
;i
++)
1258 struct srv_info_struct
*s
= &servers
[i
];
1259 if (lastname
&& strequal(lastname
,s
->name
)) continue;
1261 fill_srv_info(s
,uLevel
,&p
,&f_len
,&p2
,&s_len
,*rdata
);
1262 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1263 s
->name
, s
->type
, s
->comment
, s
->domain
));
1269 *rparam
= REALLOC(*rparam
,*rparam_len
);
1270 SSVAL(*rparam
,0,(missed
== 0 ? NERR_Success
: ERRmoredata
));
1272 SSVAL(*rparam
,4,counted
);
1273 SSVAL(*rparam
,6,counted
+missed
);
1277 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1278 domain
,uLevel
,counted
,counted
+missed
));
1283 /****************************************************************************
1284 command 0x34 - suspected of being a "Lookup Names" stub api
1285 ****************************************************************************/
1286 static BOOL
api_RNetGroupGetUsers(connection_struct
*conn
, uint16 vuid
, char *param
, char *data
,
1287 int mdrcnt
, int mprcnt
, char **rdata
,
1288 char **rparam
, int *rdata_len
, int *rparam_len
)
1290 char *str1
= param
+2;
1291 char *str2
= skip_string(str1
,1);
1292 char *p
= skip_string(str2
,1);
1293 int uLevel
= SVAL(p
,0);
1294 int buf_len
= SVAL(p
,2);
1298 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1299 str1
, str2
, p
, uLevel
, buf_len
));
1301 if (!prefix_ok(str1
,"zWrLeh")) return False
;
1306 *rparam
= REALLOC(*rparam
,*rparam_len
);
1308 SSVAL(*rparam
,0,0x08AC); /* informational warning message */
1310 SSVAL(*rparam
,4,counted
);
1311 SSVAL(*rparam
,6,counted
+missed
);
1316 /****************************************************************************
1317 get info about a share
1318 ****************************************************************************/
1319 static BOOL
check_share_info(int uLevel
, char* id
)
1323 if (strcmp(id
,"B13") != 0) return False
;
1326 if (strcmp(id
,"B13BWz") != 0) return False
;
1329 if (strcmp(id
,"B13BWzWWWzB9B") != 0) return False
;
1332 if (strcmp(id
,"B13BWzWWWzB9BB9BWzWWzWW") != 0) return False
;
1334 default: return False
;
1339 static int fill_share_info(connection_struct
*conn
, int snum
, int uLevel
,
1340 char** buf
, int* buflen
,
1341 char** stringbuf
, int* stringspace
, char* baseaddr
)
1350 case 0: struct_len
= 13; break;
1351 case 1: struct_len
= 20; break;
1352 case 2: struct_len
= 40; break;
1353 case 91: struct_len
= 68; break;
1361 if (uLevel
> 0) len
+= StrlenExpanded(conn
,snum
,lp_comment(snum
));
1362 if (uLevel
> 1) len
+= strlen(lp_pathname(snum
)) + 1;
1363 if (buflen
) *buflen
= struct_len
;
1364 if (stringspace
) *stringspace
= len
;
1365 return struct_len
+ len
;
1370 if ((*buflen
) < struct_len
) return -1;
1378 p2
= p
+ struct_len
;
1379 l2
= (*buflen
) - struct_len
;
1381 if (!baseaddr
) baseaddr
= p
;
1383 push_ascii(p
,lp_servicename(snum
),13, STR_TERMINATE
);
1389 type
= STYPE_DISKTREE
;
1390 if (lp_print_ok(snum
)) type
= STYPE_PRINTQ
;
1391 if (strequal("IPC",lp_fstype(snum
))) type
= STYPE_IPC
;
1392 SSVAL(p
,14,type
); /* device type */
1393 SIVAL(p
,16,PTR_DIFF(p2
,baseaddr
));
1394 len
+= CopyExpanded(conn
,snum
,&p2
,lp_comment(snum
),&l2
);
1399 SSVAL(p
,20,ACCESS_READ
|ACCESS_WRITE
|ACCESS_CREATE
); /* permissions */
1400 SSVALS(p
,22,-1); /* max uses */
1401 SSVAL(p
,24,1); /* current uses */
1402 SIVAL(p
,26,PTR_DIFF(p2
,baseaddr
)); /* local pathname */
1403 len
+= CopyAndAdvance(&p2
,lp_pathname(snum
),&l2
);
1404 memset(p
+30,0,SHPWLEN
+2); /* passwd (reserved), pad field */
1409 memset(p
+40,0,SHPWLEN
+2);
1421 (*buf
) = p
+ struct_len
;
1422 (*buflen
) -= struct_len
;
1424 (*stringspace
) = l2
;
1434 static BOOL
api_RNetShareGetInfo(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
1435 int mdrcnt
,int mprcnt
,
1436 char **rdata
,char **rparam
,
1437 int *rdata_len
,int *rparam_len
)
1439 char *str1
= param
+2;
1440 char *str2
= skip_string(str1
,1);
1441 char *netname
= skip_string(str2
,1);
1442 char *p
= skip_string(netname
,1);
1443 int uLevel
= SVAL(p
,0);
1444 int snum
= find_service(netname
);
1446 if (snum
< 0) return False
;
1448 /* check it's a supported varient */
1449 if (!prefix_ok(str1
,"zWrLh")) return False
;
1450 if (!check_share_info(uLevel
,str2
)) return False
;
1452 *rdata
= REALLOC(*rdata
,mdrcnt
);
1454 *rdata_len
= fill_share_info(conn
,snum
,uLevel
,&p
,&mdrcnt
,0,0,0);
1455 if (*rdata_len
< 0) return False
;
1458 *rparam
= REALLOC(*rparam
,*rparam_len
);
1459 SSVAL(*rparam
,0,NERR_Success
);
1460 SSVAL(*rparam
,2,0); /* converter word */
1461 SSVAL(*rparam
,4,*rdata_len
);
1466 /****************************************************************************
1467 View the list of available shares.
1469 This function is the server side of the NetShareEnum() RAP call.
1470 It fills the return buffer with share names and share comments.
1471 Note that the return buffer normally (in all known cases) allows only
1472 twelve byte strings for share names (plus one for a nul terminator).
1473 Share names longer than 12 bytes must be skipped.
1474 ****************************************************************************/
1475 static BOOL
api_RNetShareEnum( connection_struct
*conn
,
1486 char *str1
= param
+2;
1487 char *str2
= skip_string(str1
,1);
1488 char *p
= skip_string(str2
,1);
1489 int uLevel
= SVAL(p
,0);
1490 int buf_len
= SVAL(p
,2);
1492 int count
=lp_numservices();
1493 int total
=0,counted
=0;
1494 BOOL missed
= False
;
1496 int data_len
, fixed_len
, string_len
;
1497 int f_len
= 0, s_len
= 0;
1499 if (!prefix_ok(str1
,"WrLeh")) return False
;
1500 if (!check_share_info(uLevel
,str2
)) return False
;
1502 data_len
= fixed_len
= string_len
= 0;
1503 for (i
=0;i
<count
;i
++) {
1504 fstring servicename_dos
;
1505 push_ascii_fstring(servicename_dos
, lp_servicename(i
));
1506 if( lp_browseable( i
)
1508 && (strlen(servicename_dos
) < 13) ) /* Maximum name length. */
1511 data_len
+= fill_share_info(conn
,i
,uLevel
,0,&f_len
,0,&s_len
,0);
1512 if (data_len
<= buf_len
)
1516 string_len
+= s_len
;
1522 *rdata_len
= fixed_len
+ string_len
;
1523 *rdata
= REALLOC(*rdata
,*rdata_len
);
1524 memset(*rdata
,0,*rdata_len
);
1526 p2
= (*rdata
) + fixed_len
; /* auxiliary data (strings) will go here */
1530 for( i
= 0; i
< count
; i
++ )
1532 fstring servicename_dos
;
1533 push_ascii_fstring(servicename_dos
, lp_servicename(i
));
1534 if( lp_browseable( i
)
1536 && (strlen(servicename_dos
) < 13) )
1538 if( fill_share_info( conn
,i
,uLevel
,&p
,&f_len
,&p2
,&s_len
,*rdata
) < 0 )
1544 *rparam
= REALLOC(*rparam
,*rparam_len
);
1545 SSVAL(*rparam
,0,missed
? ERRmoredata
: NERR_Success
);
1547 SSVAL(*rparam
,4,counted
);
1548 SSVAL(*rparam
,6,total
);
1550 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1551 counted
,total
,uLevel
,
1552 buf_len
,*rdata_len
,mdrcnt
));
1554 } /* api_RNetShareEnum */
1556 /****************************************************************************
1558 ****************************************************************************/
1559 static BOOL
api_RNetShareAdd(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
1560 int mdrcnt
,int mprcnt
,
1561 char **rdata
,char **rparam
,
1562 int *rdata_len
,int *rparam_len
)
1564 char *str1
= param
+2;
1565 char *str2
= skip_string(str1
,1);
1566 char *p
= skip_string(str2
,1);
1567 int uLevel
= SVAL(p
,0);
1571 char *command
, *cmdname
;
1572 unsigned int offset
;
1576 /* check it's a supported varient */
1577 if (!prefix_ok(str1
,RAP_WShareAdd_REQ
)) return False
;
1578 if (!check_share_info(uLevel
,str2
)) return False
;
1579 if (uLevel
!= 2) return False
;
1581 pull_ascii_fstring(sharename
,data
);
1582 snum
= find_service(sharename
);
1583 if (snum
>= 0) { /* already exists */
1588 /* only support disk share adds */
1589 if (SVAL(data
,14)!=STYPE_DISKTREE
) return False
;
1591 offset
= IVAL(data
, 16);
1592 if (offset
>= mdrcnt
) {
1593 res
= ERRinvalidparam
;
1596 pull_ascii_fstring(comment
, offset
? (data
+offset
) : "");
1598 offset
= IVAL(data
, 26);
1599 if (offset
>= mdrcnt
) {
1600 res
= ERRinvalidparam
;
1603 pull_ascii_pstring(pathname
, offset
? (data
+offset
) : "");
1605 string_replace(sharename
, '"', ' ');
1606 string_replace(pathname
, '"', ' ');
1607 string_replace(comment
, '"', ' ');
1609 cmdname
= lp_add_share_cmd();
1611 if (!cmdname
|| *cmdname
== '\0') return False
;
1613 asprintf(&command
, "%s \"%s\" \"%s\" \"%s\" \"%s\"",
1614 lp_add_share_cmd(), dyn_CONFIGFILE
, sharename
, pathname
, comment
);
1617 DEBUG(10,("api_RNetShareAdd: Running [%s]\n", command
));
1618 if ((res
= smbrun(command
, NULL
)) != 0) {
1619 DEBUG(1,("api_RNetShareAdd: Running [%s] returned (%d)\n", command
, res
));
1625 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED
, NULL
, 0, False
, NULL
);
1627 } else return False
;
1630 *rparam
= REALLOC(*rparam
,*rparam_len
);
1631 SSVAL(*rparam
,0,NERR_Success
);
1632 SSVAL(*rparam
,2,0); /* converter word */
1633 SSVAL(*rparam
,4,*rdata_len
);
1640 *rparam
= REALLOC(*rparam
,*rparam_len
);
1642 SSVAL(*rparam
,0,res
);
1648 /****************************************************************************
1649 view list of groups available
1650 ****************************************************************************/
1651 static BOOL
api_RNetGroupEnum(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
1652 int mdrcnt
,int mprcnt
,
1653 char **rdata
,char **rparam
,
1654 int *rdata_len
,int *rparam_len
)
1658 int resume_context
, cli_buf_size
;
1659 char *str1
= param
+2;
1660 char *str2
= skip_string(str1
,1);
1661 char *p
= skip_string(str2
,1);
1664 GROUP_MAP
*group_list
;
1667 if (strcmp(str1
,"WrLeh") != 0)
1671 * W-> resume context (number of users to skip)
1672 * r -> return parameter pointer to receive buffer
1673 * L -> length of receive buffer
1674 * e -> return parameter number of entries
1675 * h -> return parameter total number of users
1677 if (strcmp("B21",str2
) != 0)
1680 /* get list of domain groups SID_DOMAIN_GRP=2 */
1682 ret
= pdb_enum_group_mapping(SID_NAME_DOM_GRP
, &group_list
, &num_entries
, False
);
1686 DEBUG(3,("api_RNetGroupEnum:failed to get group list"));
1690 resume_context
= SVAL(p
,0);
1691 cli_buf_size
=SVAL(p
+2,0);
1692 DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: %d\n", resume_context
, cli_buf_size
));
1694 *rdata_len
= cli_buf_size
;
1695 *rdata
= REALLOC(*rdata
,*rdata_len
);
1699 for(i
=resume_context
; i
<num_entries
; i
++) {
1700 char* name
=group_list
[i
].nt_name
;
1701 if( ((PTR_DIFF(p
,*rdata
)+21) <= *rdata_len
) ) {
1702 /* truncate the name at 21 chars. */
1703 memcpy(p
, name
, 21);
1704 DEBUG(10,("adding entry %d group %s\n", i
, p
));
1707 /* set overflow error */
1708 DEBUG(3,("overflow on entry %d group %s\n", i
, name
));
1714 *rdata_len
= PTR_DIFF(p
,*rdata
);
1717 *rparam
= REALLOC(*rparam
,*rparam_len
);
1719 SSVAL(*rparam
, 0, errflags
);
1720 SSVAL(*rparam
, 2, 0); /* converter word */
1721 SSVAL(*rparam
, 4, i
-resume_context
); /* is this right?? */
1722 SSVAL(*rparam
, 6, num_entries
); /* is this right?? */
1727 /*******************************************************************
1728 get groups that a user is a member of
1729 ******************************************************************/
1730 static BOOL
api_NetUserGetGroups(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
1731 int mdrcnt
,int mprcnt
,
1732 char **rdata
,char **rparam
,
1733 int *rdata_len
,int *rparam_len
)
1735 char *str1
= param
+2;
1736 char *str2
= skip_string(str1
,1);
1737 char *UserName
= skip_string(str2
,1);
1738 char *p
= skip_string(UserName
,1);
1739 int uLevel
= SVAL(p
,0);
1740 const char *level_string
;
1742 SAM_ACCOUNT
*sampw
= NULL
;
1744 DOM_GID
*gids
= NULL
;
1749 enum SID_NAME_USE grp_type
;
1750 DOM_SID sid
, dom_sid
;
1753 *rparam
= REALLOC(*rparam
,*rparam_len
);
1755 /* check it's a supported varient */
1757 if ( strcmp(str1
,"zWrLeh") != 0 )
1762 level_string
= "B21";
1768 if (strcmp(level_string
,str2
) != 0)
1771 *rdata_len
= mdrcnt
+ 1024;
1772 *rdata
= REALLOC(*rdata
,*rdata_len
);
1774 SSVAL(*rparam
,0,NERR_Success
);
1775 SSVAL(*rparam
,2,0); /* converter word */
1779 /* Lookup the user information; This should only be one of
1780 our accounts (not remote domains) */
1782 pdb_init_sam( &sampw
);
1784 become_root(); /* ROOT BLOCK */
1786 if ( !pdb_getsampwnam(sampw
, UserName
) )
1789 /* this next set of code is horribly inefficient, but since
1790 it is rarely called, I'm going to leave it like this since
1791 it easier to follow --jerry */
1793 /* get the list of group SIDs */
1795 if ( !get_domain_user_groups(conn
->mem_ctx
, &num_groups
, &gids
, sampw
) ) {
1796 DEBUG(1,("api_NetUserGetGroups: get_domain_user_groups() failed!\n"));
1800 /* convert to names (we don't support universal groups so the domain
1801 can only be ours) */
1803 sid_copy( &dom_sid
, get_global_sam_sid() );
1804 for (i
=0; i
<num_groups
; i
++) {
1806 /* make the DOM_GID into a DOM_SID and then lookup
1809 sid_copy( &sid
, &dom_sid
);
1810 sid_append_rid( &sid
, gids
[i
].g_rid
);
1812 if ( lookup_sid(&sid
, grp_domain
, grp_name
, &grp_type
) ) {
1813 pstrcpy(p
, grp_name
);
1819 *rdata_len
= PTR_DIFF(p
,*rdata
);
1821 SSVAL(*rparam
,4,count
); /* is this right?? */
1822 SSVAL(*rparam
,6,count
); /* is this right?? */
1827 unbecome_root(); /* END ROOT BLOCK */
1829 pdb_free_sam( &sampw
);
1834 /*******************************************************************
1836 ******************************************************************/
1837 static BOOL
api_RNetUserEnum(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
1838 int mdrcnt
,int mprcnt
,
1839 char **rdata
,char **rparam
,
1840 int *rdata_len
,int *rparam_len
)
1842 SAM_ACCOUNT
*pwd
=NULL
;
1846 int resume_context
, cli_buf_size
;
1848 char *str1
= param
+2;
1849 char *str2
= skip_string(str1
,1);
1850 char *p
= skip_string(str2
,1);
1852 if (strcmp(str1
,"WrLeh") != 0)
1855 * W-> resume context (number of users to skip)
1856 * r -> return parameter pointer to receive buffer
1857 * L -> length of receive buffer
1858 * e -> return parameter number of entries
1859 * h -> return parameter total number of users
1862 resume_context
= SVAL(p
,0);
1863 cli_buf_size
=SVAL(p
+2,0);
1864 DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n", resume_context
, cli_buf_size
));
1867 *rparam
= REALLOC(*rparam
,*rparam_len
);
1869 /* check it's a supported varient */
1870 if (strcmp("B21",str2
) != 0)
1873 *rdata_len
= cli_buf_size
;
1874 *rdata
= REALLOC(*rdata
,*rdata_len
);
1878 /* to get user list enumerations for NetUserEnum in B21 format */
1881 /* Open the passgrp file - not for update. */
1883 if(!pdb_setsampwent(False
)) {
1884 DEBUG(0, ("api_RNetUserEnum:unable to open sam database.\n"));
1888 errflags
=NERR_Success
;
1890 while ( pdb_getsampwent(pwd
) ) {
1891 const char *name
=pdb_get_username(pwd
);
1892 if ((name
) && (*(name
+strlen(name
)-1)!='$')) {
1894 if(count_total
>=resume_context
) {
1895 if( ((PTR_DIFF(p
,*rdata
)+21)<=*rdata_len
)&&(strlen(name
)<=21) ) {
1897 DEBUG(10,("api_RNetUserEnum:adding entry %d username %s\n",count_sent
,p
));
1901 /* set overflow error */
1902 DEBUG(10,("api_RNetUserEnum:overflow on entry %d username %s\n",count_sent
,name
));
1915 *rdata_len
= PTR_DIFF(p
,*rdata
);
1917 SSVAL(*rparam
,0,errflags
);
1918 SSVAL(*rparam
,2,0); /* converter word */
1919 SSVAL(*rparam
,4,count_sent
); /* is this right?? */
1920 SSVAL(*rparam
,6,count_total
); /* is this right?? */
1927 /****************************************************************************
1928 get the time of day info
1929 ****************************************************************************/
1930 static BOOL
api_NetRemoteTOD(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
1931 int mdrcnt
,int mprcnt
,
1932 char **rdata
,char **rparam
,
1933 int *rdata_len
,int *rparam_len
)
1937 *rparam
= REALLOC(*rparam
,*rparam_len
);
1940 *rdata
= REALLOC(*rdata
,*rdata_len
);
1942 SSVAL(*rparam
,0,NERR_Success
);
1943 SSVAL(*rparam
,2,0); /* converter word */
1949 time_t unixdate
= time(NULL
);
1951 put_dos_date3(p
,0,unixdate
); /* this is the time that is looked at
1952 by NT in a "net time" operation,
1953 it seems to ignore the one below */
1955 /* the client expects to get localtime, not GMT, in this bit
1956 (I think, this needs testing) */
1957 t
= LocalTime(&unixdate
);
1959 SIVAL(p
,4,0); /* msecs ? */
1960 SCVAL(p
,8,t
->tm_hour
);
1961 SCVAL(p
,9,t
->tm_min
);
1962 SCVAL(p
,10,t
->tm_sec
);
1963 SCVAL(p
,11,0); /* hundredths of seconds */
1964 SSVALS(p
,12,TimeDiff(unixdate
)/60); /* timezone in minutes from GMT */
1965 SSVAL(p
,14,10000); /* timer interval in 0.0001 of sec */
1966 SCVAL(p
,16,t
->tm_mday
);
1967 SCVAL(p
,17,t
->tm_mon
+ 1);
1968 SSVAL(p
,18,1900+t
->tm_year
);
1969 SCVAL(p
,20,t
->tm_wday
);
1976 /****************************************************************************
1977 Set the user password.
1978 *****************************************************************************/
1980 static BOOL
api_SetUserPassword(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
1981 int mdrcnt
,int mprcnt
,
1982 char **rdata
,char **rparam
,
1983 int *rdata_len
,int *rparam_len
)
1985 char *p
= skip_string(param
+2,2);
1987 fstring pass1
,pass2
;
1989 pull_ascii_fstring(user
,p
);
1991 p
= skip_string(p
,1);
1993 memset(pass1
,'\0',sizeof(pass1
));
1994 memset(pass2
,'\0',sizeof(pass2
));
1996 memcpy(pass2
,p
+16,16);
1999 *rparam
= REALLOC(*rparam
,*rparam_len
);
2003 SSVAL(*rparam
,0,NERR_badpass
);
2004 SSVAL(*rparam
,2,0); /* converter word */
2006 DEBUG(3,("Set password for <%s>\n",user
));
2009 * Attempt to verify the old password against smbpasswd entries
2010 * Win98 clients send old and new password in plaintext for this call.
2014 auth_serversupplied_info
*server_info
= NULL
;
2015 DATA_BLOB password
= data_blob(pass1
, strlen(pass1
)+1);
2017 if (NT_STATUS_IS_OK(check_plaintext_password(user
,password
,&server_info
))) {
2020 if (NT_STATUS_IS_OK(change_oem_password(server_info
->sam_account
, pass1
, pass2
, False
))) {
2021 SSVAL(*rparam
,0,NERR_Success
);
2025 free_server_info(&server_info
);
2027 data_blob_clear_free(&password
);
2031 * If the plaintext change failed, attempt
2032 * the old encrypted method. NT will generate this
2033 * after trying the samr method. Note that this
2034 * method is done as a last resort as this
2035 * password change method loses the NT password hash
2036 * and cannot change the UNIX password as no plaintext
2040 if(SVAL(*rparam
,0) != NERR_Success
) {
2041 SAM_ACCOUNT
*hnd
= NULL
;
2043 if (check_lanman_password(user
,(unsigned char *)pass1
,(unsigned char *)pass2
, &hnd
)) {
2045 if (change_lanman_password(hnd
,(uchar
*)pass2
)) {
2046 SSVAL(*rparam
,0,NERR_Success
);
2053 memset((char *)pass1
,'\0',sizeof(fstring
));
2054 memset((char *)pass2
,'\0',sizeof(fstring
));
2059 /****************************************************************************
2060 Set the user password (SamOEM version - gets plaintext).
2061 ****************************************************************************/
2063 static BOOL
api_SamOEMChangePassword(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
2064 int mdrcnt
,int mprcnt
,
2065 char **rdata
,char **rparam
,
2066 int *rdata_len
,int *rparam_len
)
2069 char *p
= param
+ 2;
2071 *rparam
= REALLOC(*rparam
,*rparam_len
);
2075 SSVAL(*rparam
,0,NERR_badpass
);
2078 * Check the parameter definition is correct.
2081 if(!strequal(param
+ 2, "zsT")) {
2082 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", param
+ 2));
2085 p
= skip_string(p
, 1);
2087 if(!strequal(p
, "B516B16")) {
2088 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p
));
2091 p
= skip_string(p
,1);
2092 p
+= pull_ascii_fstring(user
,p
);
2094 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user
));
2097 * Pass the user through the NT -> unix user mapping
2101 (void)map_username(user
);
2103 if (NT_STATUS_IS_OK(pass_oem_change(user
, (uchar
*) data
, (uchar
*)&data
[516], NULL
, NULL
))) {
2104 SSVAL(*rparam
,0,NERR_Success
);
2110 /****************************************************************************
2113 ****************************************************************************/
2114 static BOOL
api_RDosPrintJobDel(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
2115 int mdrcnt
,int mprcnt
,
2116 char **rdata
,char **rparam
,
2117 int *rdata_len
,int *rparam_len
)
2119 int function
= SVAL(param
,0);
2120 char *str1
= param
+2;
2121 char *str2
= skip_string(str1
,1);
2122 char *p
= skip_string(str2
,1);
2127 extern struct current_user current_user
;
2128 WERROR werr
= WERR_OK
;
2130 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
))
2133 /* check it's a supported varient */
2134 if (!(strcsequal(str1
,"W") && strcsequal(str2
,"")))
2138 *rparam
= REALLOC(*rparam
,*rparam_len
);
2141 if (!print_job_exists(sharename
, jobid
)) {
2142 errcode
= NERR_JobNotFound
;
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
= REALLOC(*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
= REALLOC(*rparam
,*rparam_len
);
2273 /* check it's a supported varient */
2274 if ((strcmp(str1
,"WWsTP")) ||
2275 (!check_printjob_info(&desc
,uLevel
,str2
)))
2278 if (!print_job_exists(sharename
, jobid
)) {
2279 errcode
=NERR_JobNotFound
;
2283 errcode
= NERR_notsupported
;
2287 /* change job place in the queue,
2288 data gives the new place */
2289 place
= SVAL(data
,0);
2290 if (print_job_set_place(snum
, jobid
, place
)) {
2291 errcode
=NERR_Success
;
2296 /* change print job name, data gives the name */
2297 if (print_job_set_name(snum
, jobid
, data
)) {
2298 errcode
=NERR_Success
;
2307 SSVALS(*rparam
,0,errcode
);
2308 SSVAL(*rparam
,2,0); /* converter word */
2314 /****************************************************************************
2315 get info about the server
2316 ****************************************************************************/
2317 static BOOL
api_RNetServerGetInfo(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
2318 int mdrcnt
,int mprcnt
,
2319 char **rdata
,char **rparam
,
2320 int *rdata_len
,int *rparam_len
)
2322 char *str1
= param
+2;
2323 char *str2
= skip_string(str1
,1);
2324 char *p
= skip_string(str2
,1);
2325 int uLevel
= SVAL(p
,0);
2329 DEBUG(4,("NetServerGetInfo level %d\n",uLevel
));
2331 /* check it's a supported varient */
2332 if (!prefix_ok(str1
,"WrLh")) return False
;
2335 if (strcmp(str2
,"B16") != 0) return False
;
2339 if (strcmp(str2
,"B16BBDz") != 0) return False
;
2343 if (strcmp(str2
,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")
2348 if (strcmp(str2
,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz")
2353 if (strcmp(str2
,"DN") != 0) return False
;
2357 if (strcmp(str2
,"B16BBDzWWzzz") != 0) return False
;
2360 default: return False
;
2363 *rdata_len
= mdrcnt
;
2364 *rdata
= REALLOC(*rdata
,*rdata_len
);
2367 p2
= p
+ struct_len
;
2369 srvstr_push(NULL
, p
,local_machine
,16,
2370 STR_ASCII
|STR_UPPER
|STR_TERMINATE
);
2375 struct srv_info_struct
*servers
=NULL
;
2378 uint32 servertype
= lp_default_server_announce();
2380 push_ascii(comment
,lp_serverstring(), MAX_SERVER_STRING_LENGTH
,STR_TERMINATE
);
2382 if ((count
=get_server_info(SV_TYPE_ALL
,&servers
,lp_workgroup()))>0) {
2383 for (i
=0;i
<count
;i
++) {
2384 if (strequal(servers
[i
].name
,local_machine
)) {
2385 servertype
= servers
[i
].type
;
2386 push_ascii(comment
,servers
[i
].comment
,sizeof(pstring
),STR_TERMINATE
);
2392 SCVAL(p
,0,lp_major_announce_version());
2393 SCVAL(p
,1,lp_minor_announce_version());
2394 SIVAL(p
,2,servertype
);
2396 if (mdrcnt
== struct_len
) {
2399 SIVAL(p
,6,PTR_DIFF(p2
,*rdata
));
2400 standard_sub_conn(conn
,comment
,sizeof(comment
));
2401 StrnCpy(p2
,comment
,MAX(mdrcnt
- struct_len
,0));
2402 p2
= skip_string(p2
,1);
2407 return False
; /* not yet implemented */
2410 *rdata_len
= PTR_DIFF(p2
,*rdata
);
2413 *rparam
= REALLOC(*rparam
,*rparam_len
);
2414 SSVAL(*rparam
,0,NERR_Success
);
2415 SSVAL(*rparam
,2,0); /* converter word */
2416 SSVAL(*rparam
,4,*rdata_len
);
2422 /****************************************************************************
2423 get info about the server
2424 ****************************************************************************/
2425 static BOOL
api_NetWkstaGetInfo(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
2426 int mdrcnt
,int mprcnt
,
2427 char **rdata
,char **rparam
,
2428 int *rdata_len
,int *rparam_len
)
2430 char *str1
= param
+2;
2431 char *str2
= skip_string(str1
,1);
2432 char *p
= skip_string(str2
,1);
2434 extern userdom_struct current_user_info
;
2435 int level
= SVAL(p
,0);
2437 DEBUG(4,("NetWkstaGetInfo level %d\n",level
));
2440 *rparam
= REALLOC(*rparam
,*rparam_len
);
2442 /* check it's a supported varient */
2443 if (!(level
==10 && strcsequal(str1
,"WrLh") && strcsequal(str2
,"zzzBBzz")))
2446 *rdata_len
= mdrcnt
+ 1024;
2447 *rdata
= REALLOC(*rdata
,*rdata_len
);
2449 SSVAL(*rparam
,0,NERR_Success
);
2450 SSVAL(*rparam
,2,0); /* converter word */
2456 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* host name */
2457 pstrcpy(p2
,local_machine
);
2459 p2
= skip_string(p2
,1);
2462 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
));
2463 pstrcpy(p2
,current_user_info
.smb_name
);
2464 p2
= skip_string(p2
,1);
2467 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* login domain */
2468 pstrcpy(p2
,lp_workgroup());
2470 p2
= skip_string(p2
,1);
2473 SCVAL(p
,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
2474 SCVAL(p
,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
2477 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
));
2478 pstrcpy(p2
,lp_workgroup()); /* don't know. login domain?? */
2479 p2
= skip_string(p2
,1);
2482 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* don't know */
2484 p2
= skip_string(p2
,1);
2487 *rdata_len
= PTR_DIFF(p2
,*rdata
);
2489 SSVAL(*rparam
,4,*rdata_len
);
2494 /****************************************************************************
2495 get info about a user
2497 struct user_info_11 {
2498 char usri11_name[21]; 0-20
2500 char *usri11_comment; 22-25
2501 char *usri11_usr_comment; 26-29
2502 unsigned short usri11_priv; 30-31
2503 unsigned long usri11_auth_flags; 32-35
2504 long usri11_password_age; 36-39
2505 char *usri11_homedir; 40-43
2506 char *usri11_parms; 44-47
2507 long usri11_last_logon; 48-51
2508 long usri11_last_logoff; 52-55
2509 unsigned short usri11_bad_pw_count; 56-57
2510 unsigned short usri11_num_logons; 58-59
2511 char *usri11_logon_server; 60-63
2512 unsigned short usri11_country_code; 64-65
2513 char *usri11_workstations; 66-69
2514 unsigned long usri11_max_storage; 70-73
2515 unsigned short usri11_units_per_week; 74-75
2516 unsigned char *usri11_logon_hours; 76-79
2517 unsigned short usri11_code_page; 80-81
2522 usri11_name specifies the user name for which information is retireved
2524 usri11_pad aligns the next data structure element to a word boundary
2526 usri11_comment is a null terminated ASCII comment
2528 usri11_user_comment is a null terminated ASCII comment about the user
2530 usri11_priv specifies the level of the privilege assigned to the user.
2531 The possible values are:
2533 Name Value Description
2534 USER_PRIV_GUEST 0 Guest privilege
2535 USER_PRIV_USER 1 User privilege
2536 USER_PRV_ADMIN 2 Administrator privilege
2538 usri11_auth_flags specifies the account operator privileges. The
2539 possible values are:
2541 Name Value Description
2542 AF_OP_PRINT 0 Print operator
2545 Leach, Naik [Page 28]
2549 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2552 AF_OP_COMM 1 Communications operator
2553 AF_OP_SERVER 2 Server operator
2554 AF_OP_ACCOUNTS 3 Accounts operator
2557 usri11_password_age specifies how many seconds have elapsed since the
2558 password was last changed.
2560 usri11_home_dir points to a null terminated ASCII string that contains
2561 the path name of the user's home directory.
2563 usri11_parms points to a null terminated ASCII string that is set
2564 aside for use by applications.
2566 usri11_last_logon specifies the time when the user last logged on.
2567 This value is stored as the number of seconds elapsed since
2568 00:00:00, January 1, 1970.
2570 usri11_last_logoff specifies the time when the user last logged off.
2571 This value is stored as the number of seconds elapsed since
2572 00:00:00, January 1, 1970. A value of 0 means the last logoff
2575 usri11_bad_pw_count specifies the number of incorrect passwords
2576 entered since the last successful logon.
2578 usri11_log1_num_logons specifies the number of times this user has
2579 logged on. A value of -1 means the number of logons is unknown.
2581 usri11_logon_server points to a null terminated ASCII string that
2582 contains the name of the server to which logon requests are sent.
2583 A null string indicates logon requests should be sent to the
2586 usri11_country_code specifies the country code for the user's language
2589 usri11_workstations points to a null terminated ASCII string that
2590 contains the names of workstations the user may log on from.
2591 There may be up to 8 workstations, with the names separated by
2592 commas. A null strings indicates there are no restrictions.
2594 usri11_max_storage specifies the maximum amount of disk space the user
2595 can occupy. A value of 0xffffffff indicates there are no
2598 usri11_units_per_week specifies the equal number of time units into
2599 which a week is divided. This value must be equal to 168.
2601 usri11_logon_hours points to a 21 byte (168 bits) string that
2602 specifies the time during which the user can log on. Each bit
2603 represents one unique hour in a week. The first bit (bit 0, word
2604 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
2608 Leach, Naik [Page 29]
2612 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2615 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
2616 are no restrictions.
2618 usri11_code_page specifies the code page for the user's language of
2621 All of the pointers in this data structure need to be treated
2622 specially. The pointer is a 32 bit pointer. The higher 16 bits need
2623 to be ignored. The converter word returned in the parameters section
2624 needs to be subtracted from the lower 16 bits to calculate an offset
2625 into the return buffer where this ASCII string resides.
2627 There is no auxiliary data in the response.
2629 ****************************************************************************/
2631 #define usri11_name 0
2632 #define usri11_pad 21
2633 #define usri11_comment 22
2634 #define usri11_usr_comment 26
2635 #define usri11_full_name 30
2636 #define usri11_priv 34
2637 #define usri11_auth_flags 36
2638 #define usri11_password_age 40
2639 #define usri11_homedir 44
2640 #define usri11_parms 48
2641 #define usri11_last_logon 52
2642 #define usri11_last_logoff 56
2643 #define usri11_bad_pw_count 60
2644 #define usri11_num_logons 62
2645 #define usri11_logon_server 64
2646 #define usri11_country_code 68
2647 #define usri11_workstations 70
2648 #define usri11_max_storage 74
2649 #define usri11_units_per_week 78
2650 #define usri11_logon_hours 80
2651 #define usri11_code_page 84
2652 #define usri11_end 86
2654 #define USER_PRIV_GUEST 0
2655 #define USER_PRIV_USER 1
2656 #define USER_PRIV_ADMIN 2
2658 #define AF_OP_PRINT 0
2659 #define AF_OP_COMM 1
2660 #define AF_OP_SERVER 2
2661 #define AF_OP_ACCOUNTS 3
2664 static BOOL
api_RNetUserGetInfo(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
2665 int mdrcnt
,int mprcnt
,
2666 char **rdata
,char **rparam
,
2667 int *rdata_len
,int *rparam_len
)
2669 char *str1
= param
+2;
2670 char *str2
= skip_string(str1
,1);
2671 char *UserName
= skip_string(str2
,1);
2672 char *p
= skip_string(UserName
,1);
2673 int uLevel
= SVAL(p
,0);
2675 const char *level_string
;
2677 /* get NIS home of a previously validated user - simeon */
2678 /* With share level security vuid will always be zero.
2679 Don't depend on vuser being non-null !!. JRA */
2680 user_struct
*vuser
= get_valid_user_struct(vuid
);
2682 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser
->uid
,
2683 vuser
->user
.unix_name
));
2686 *rparam
= REALLOC(*rparam
,*rparam_len
);
2688 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel
));
2690 /* check it's a supported variant */
2691 if (strcmp(str1
,"zWrLh") != 0) return False
;
2694 case 0: level_string
= "B21"; break;
2695 case 1: level_string
= "B21BB16DWzzWz"; break;
2696 case 2: level_string
= "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
2697 case 10: level_string
= "B21Bzzz"; break;
2698 case 11: level_string
= "B21BzzzWDDzzDDWWzWzDWb21W"; break;
2699 default: return False
;
2702 if (strcmp(level_string
,str2
) != 0) return False
;
2704 *rdata_len
= mdrcnt
+ 1024;
2705 *rdata
= REALLOC(*rdata
,*rdata_len
);
2707 SSVAL(*rparam
,0,NERR_Success
);
2708 SSVAL(*rparam
,2,0); /* converter word */
2711 p2
= p
+ usri11_end
;
2714 fstrcpy(p
+usri11_name
,UserName
); /* 21 bytes - user name */
2718 SCVAL(p
,usri11_pad
,0); /* padding - 1 byte */
2723 SIVAL(p
,usri11_comment
,PTR_DIFF(p2
,p
)); /* comment */
2724 pstrcpy(p2
,"Comment");
2725 p2
= skip_string(p2
,1);
2727 SIVAL(p
,usri11_usr_comment
,PTR_DIFF(p2
,p
)); /* user_comment */
2728 pstrcpy(p2
,"UserComment");
2729 p2
= skip_string(p2
,1);
2731 /* EEK! the cifsrap.txt doesn't have this in!!!! */
2732 SIVAL(p
,usri11_full_name
,PTR_DIFF(p2
,p
)); /* full name */
2733 pstrcpy(p2
,((vuser
!= NULL
) ? vuser
->user
.full_name
: UserName
));
2734 p2
= skip_string(p2
,1);
2737 if (uLevel
== 11) /* modelled after NTAS 3.51 reply */
2739 SSVAL(p
,usri11_priv
,conn
->admin_user
?USER_PRIV_ADMIN
:USER_PRIV_USER
);
2740 SIVAL(p
,usri11_auth_flags
,AF_OP_PRINT
); /* auth flags */
2741 SIVALS(p
,usri11_password_age
,-1); /* password age */
2742 SIVAL(p
,usri11_homedir
,PTR_DIFF(p2
,p
)); /* home dir */
2743 pstrcpy(p2
, vuser
&& vuser
->homedir
? vuser
->homedir
: "");
2744 p2
= skip_string(p2
,1);
2745 SIVAL(p
,usri11_parms
,PTR_DIFF(p2
,p
)); /* parms */
2747 p2
= skip_string(p2
,1);
2748 SIVAL(p
,usri11_last_logon
,0); /* last logon */
2749 SIVAL(p
,usri11_last_logoff
,0); /* last logoff */
2750 SSVALS(p
,usri11_bad_pw_count
,-1); /* bad pw counts */
2751 SSVALS(p
,usri11_num_logons
,-1); /* num logons */
2752 SIVAL(p
,usri11_logon_server
,PTR_DIFF(p2
,p
)); /* logon server */
2753 pstrcpy(p2
,"\\\\*");
2754 p2
= skip_string(p2
,1);
2755 SSVAL(p
,usri11_country_code
,0); /* country code */
2757 SIVAL(p
,usri11_workstations
,PTR_DIFF(p2
,p
)); /* workstations */
2759 p2
= skip_string(p2
,1);
2761 SIVALS(p
,usri11_max_storage
,-1); /* max storage */
2762 SSVAL(p
,usri11_units_per_week
,168); /* units per week */
2763 SIVAL(p
,usri11_logon_hours
,PTR_DIFF(p2
,p
)); /* logon hours */
2765 /* a simple way to get logon hours at all times. */
2767 SCVAL(p2
,21,0); /* fix zero termination */
2768 p2
= skip_string(p2
,1);
2770 SSVAL(p
,usri11_code_page
,0); /* code page */
2772 if (uLevel
== 1 || uLevel
== 2)
2774 memset(p
+22,' ',16); /* password */
2775 SIVALS(p
,38,-1); /* password age */
2777 conn
->admin_user
?USER_PRIV_ADMIN
:USER_PRIV_USER
);
2778 SIVAL(p
,44,PTR_DIFF(p2
,*rdata
)); /* home dir */
2779 pstrcpy(p2
, vuser
&& vuser
->homedir
? vuser
->homedir
: "");
2780 p2
= skip_string(p2
,1);
2781 SIVAL(p
,48,PTR_DIFF(p2
,*rdata
)); /* comment */
2783 SSVAL(p
,52,0); /* flags */
2784 SIVAL(p
,54,PTR_DIFF(p2
,*rdata
)); /* script_path */
2785 pstrcpy(p2
,vuser
&& vuser
->logon_script
? vuser
->logon_script
: "");
2786 p2
= skip_string(p2
,1);
2789 SIVAL(p
,60,0); /* auth_flags */
2790 SIVAL(p
,64,PTR_DIFF(p2
,*rdata
)); /* full_name */
2791 pstrcpy(p2
,((vuser
!= NULL
) ? vuser
->user
.full_name
: UserName
));
2792 p2
= skip_string(p2
,1);
2793 SIVAL(p
,68,0); /* urs_comment */
2794 SIVAL(p
,72,PTR_DIFF(p2
,*rdata
)); /* parms */
2796 p2
= skip_string(p2
,1);
2797 SIVAL(p
,76,0); /* workstations */
2798 SIVAL(p
,80,0); /* last_logon */
2799 SIVAL(p
,84,0); /* last_logoff */
2800 SIVALS(p
,88,-1); /* acct_expires */
2801 SIVALS(p
,92,-1); /* max_storage */
2802 SSVAL(p
,96,168); /* units_per_week */
2803 SIVAL(p
,98,PTR_DIFF(p2
,*rdata
)); /* logon_hours */
2806 SSVALS(p
,102,-1); /* bad_pw_count */
2807 SSVALS(p
,104,-1); /* num_logons */
2808 SIVAL(p
,106,PTR_DIFF(p2
,*rdata
)); /* logon_server */
2809 pstrcpy(p2
,"\\\\%L");
2810 standard_sub_conn(conn
, p2
,0);
2811 p2
= skip_string(p2
,1);
2812 SSVAL(p
,110,49); /* country_code */
2813 SSVAL(p
,112,860); /* code page */
2817 *rdata_len
= PTR_DIFF(p2
,*rdata
);
2819 SSVAL(*rparam
,4,*rdata_len
); /* is this right?? */
2824 static BOOL
api_WWkstaUserLogon(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
2825 int mdrcnt
,int mprcnt
,
2826 char **rdata
,char **rparam
,
2827 int *rdata_len
,int *rparam_len
)
2829 char *str1
= param
+2;
2830 char *str2
= skip_string(str1
,1);
2831 char *p
= skip_string(str2
,1);
2833 struct pack_desc desc
;
2835 /* With share level security vuid will always be zero.
2836 Don't depend on vuser being non-null !!. JRA */
2837 user_struct
*vuser
= get_valid_user_struct(vuid
);
2839 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser
->uid
,
2840 vuser
->user
.unix_name
));
2845 memset((char *)&desc
,'\0',sizeof(desc
));
2847 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel
,name
));
2849 /* check it's a supported varient */
2850 if (strcmp(str1
,"OOWb54WrLh") != 0) return False
;
2851 if (uLevel
!= 1 || strcmp(str2
,"WB21BWDWWDDDDDDDzzzD") != 0) return False
;
2852 if (mdrcnt
> 0) *rdata
= REALLOC(*rdata
,mdrcnt
);
2854 desc
.buflen
= mdrcnt
;
2855 desc
.subformat
= NULL
;
2858 if (init_package(&desc
,1,0))
2860 PACKI(&desc
,"W",0); /* code */
2861 PACKS(&desc
,"B21",name
); /* eff. name */
2862 PACKS(&desc
,"B",""); /* pad */
2864 conn
->admin_user
?USER_PRIV_ADMIN
:USER_PRIV_USER
);
2865 PACKI(&desc
,"D",0); /* auth flags XXX */
2866 PACKI(&desc
,"W",0); /* num logons */
2867 PACKI(&desc
,"W",0); /* bad pw count */
2868 PACKI(&desc
,"D",0); /* last logon */
2869 PACKI(&desc
,"D",-1); /* last logoff */
2870 PACKI(&desc
,"D",-1); /* logoff time */
2871 PACKI(&desc
,"D",-1); /* kickoff time */
2872 PACKI(&desc
,"D",0); /* password age */
2873 PACKI(&desc
,"D",0); /* password can change */
2874 PACKI(&desc
,"D",-1); /* password must change */
2877 fstrcpy(mypath
,"\\\\");
2878 fstrcat(mypath
,local_machine
);
2880 PACKS(&desc
,"z",mypath
); /* computer */
2882 PACKS(&desc
,"z",lp_workgroup());/* domain */
2884 PACKS(&desc
,"z", vuser
&& vuser
->logon_script
? vuser
->logon_script
:""); /* script path */
2886 PACKI(&desc
,"D",0x00000000); /* reserved */
2889 *rdata_len
= desc
.usedlen
;
2891 *rparam
= REALLOC(*rparam
,*rparam_len
);
2892 SSVALS(*rparam
,0,desc
.errcode
);
2894 SSVAL(*rparam
,4,desc
.neededlen
);
2896 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc
.errcode
));
2901 /****************************************************************************
2902 api_WAccessGetUserPerms
2903 ****************************************************************************/
2904 static BOOL
api_WAccessGetUserPerms(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
2905 int mdrcnt
,int mprcnt
,
2906 char **rdata
,char **rparam
,
2907 int *rdata_len
,int *rparam_len
)
2909 char *str1
= param
+2;
2910 char *str2
= skip_string(str1
,1);
2911 char *user
= skip_string(str2
,1);
2912 char *resource
= skip_string(user
,1);
2914 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user
,resource
));
2916 /* check it's a supported varient */
2917 if (strcmp(str1
,"zzh") != 0) return False
;
2918 if (strcmp(str2
,"") != 0) return False
;
2921 *rparam
= REALLOC(*rparam
,*rparam_len
);
2922 SSVALS(*rparam
,0,0); /* errorcode */
2923 SSVAL(*rparam
,2,0); /* converter word */
2924 SSVAL(*rparam
,4,0x7f); /* permission flags */
2929 /****************************************************************************
2930 api_WPrintJobEnumerate
2931 ****************************************************************************/
2932 static BOOL
api_WPrintJobGetInfo(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
2933 int mdrcnt
,int mprcnt
,
2934 char **rdata
,char **rparam
,
2935 int *rdata_len
,int *rparam_len
)
2937 char *str1
= param
+2;
2938 char *str2
= skip_string(str1
,1);
2939 char *p
= skip_string(str2
,1);
2946 struct pack_desc desc
;
2947 print_queue_struct
*queue
=NULL
;
2948 print_status_struct status
;
2953 memset((char *)&desc
,'\0',sizeof(desc
));
2954 memset((char *)&status
,'\0',sizeof(status
));
2956 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel
,SVAL(p
,0)));
2958 /* check it's a supported varient */
2959 if (strcmp(str1
,"WWrLh") != 0) return False
;
2960 if (!check_printjob_info(&desc
,uLevel
,str2
)) return False
;
2962 if(!rap_to_pjobid(SVAL(p
,0), sharename
, &jobid
))
2965 if (snum
< 0 || !VALID_SNUM(snum
)) return(False
);
2967 count
= print_queue_status(snum
,&queue
,&status
);
2968 for (i
= 0; i
< count
; i
++) {
2969 if (queue
[i
].job
== jobid
) break;
2973 *rdata
= REALLOC(*rdata
,mdrcnt
);
2975 desc
.buflen
= mdrcnt
;
2978 * Don't return data but need to get correct length
2979 * init_package will return wrong size if buflen=0
2981 desc
.buflen
= getlen(desc
.format
);
2982 desc
.base
= tmpdata
= (char *)malloc ( desc
.buflen
);
2985 if (init_package(&desc
,1,0)) {
2987 fill_printjob_info(conn
,snum
,uLevel
,&desc
,&queue
[i
],i
);
2988 *rdata_len
= desc
.usedlen
;
2991 desc
.errcode
= NERR_JobNotFound
;
2997 *rparam
= REALLOC(*rparam
,*rparam_len
);
2998 SSVALS(*rparam
,0,desc
.errcode
);
3000 SSVAL(*rparam
,4,desc
.neededlen
);
3005 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc
.errcode
));
3009 static BOOL
api_WPrintJobEnumerate(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
3010 int mdrcnt
,int mprcnt
,
3011 char **rdata
,char **rparam
,
3012 int *rdata_len
,int *rparam_len
)
3014 char *str1
= param
+2;
3015 char *str2
= skip_string(str1
,1);
3016 char *p
= skip_string(str2
,1);
3022 struct pack_desc desc
;
3023 print_queue_struct
*queue
=NULL
;
3024 print_status_struct status
;
3026 memset((char *)&desc
,'\0',sizeof(desc
));
3027 memset((char *)&status
,'\0',sizeof(status
));
3029 p
= skip_string(p
,1);
3032 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel
,name
));
3034 /* check it's a supported variant */
3035 if (strcmp(str1
,"zWrLeh") != 0) return False
;
3036 if (uLevel
> 2) return False
; /* defined only for uLevel 0,1,2 */
3037 if (!check_printjob_info(&desc
,uLevel
,str2
)) return False
;
3039 snum
= lp_servicenumber(name
);
3040 if (snum
< 0 && pcap_printername_ok(name
,NULL
)) {
3041 int pnum
= lp_servicenumber(PRINTERS_NAME
);
3043 lp_add_printer(name
,pnum
);
3044 snum
= lp_servicenumber(name
);
3048 if (snum
< 0 || !VALID_SNUM(snum
)) return(False
);
3050 count
= print_queue_status(snum
,&queue
,&status
);
3051 if (mdrcnt
> 0) *rdata
= REALLOC(*rdata
,mdrcnt
);
3053 desc
.buflen
= mdrcnt
;
3055 if (init_package(&desc
,count
,0)) {
3057 for (i
= 0; i
< count
; i
++) {
3058 fill_printjob_info(conn
,snum
,uLevel
,&desc
,&queue
[i
],i
);
3059 if (desc
.errcode
== NERR_Success
) succnt
= i
+1;
3063 *rdata_len
= desc
.usedlen
;
3066 *rparam
= REALLOC(*rparam
,*rparam_len
);
3067 SSVALS(*rparam
,0,desc
.errcode
);
3069 SSVAL(*rparam
,4,succnt
);
3070 SSVAL(*rparam
,6,count
);
3074 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc
.errcode
));
3078 static int check_printdest_info(struct pack_desc
* desc
,
3079 int uLevel
, char* id
)
3081 desc
->subformat
= NULL
;
3083 case 0: desc
->format
= "B9"; break;
3084 case 1: desc
->format
= "B9B21WWzW"; break;
3085 case 2: desc
->format
= "z"; break;
3086 case 3: desc
->format
= "zzzWWzzzWW"; break;
3087 default: return False
;
3089 if (strcmp(desc
->format
,id
) != 0) return False
;
3093 static void fill_printdest_info(connection_struct
*conn
, int snum
, int uLevel
,
3094 struct pack_desc
* desc
)
3097 strncpy(buf
,SERVICE(snum
),sizeof(buf
)-1);
3098 buf
[sizeof(buf
)-1] = 0;
3101 PACKS(desc
,"B9",buf
); /* szName */
3103 PACKS(desc
,"B21",""); /* szUserName */
3104 PACKI(desc
,"W",0); /* uJobId */
3105 PACKI(desc
,"W",0); /* fsStatus */
3106 PACKS(desc
,"z",""); /* pszStatus */
3107 PACKI(desc
,"W",0); /* time */
3110 if (uLevel
== 2 || uLevel
== 3) {
3111 PACKS(desc
,"z",buf
); /* pszPrinterName */
3113 PACKS(desc
,"z",""); /* pszUserName */
3114 PACKS(desc
,"z",""); /* pszLogAddr */
3115 PACKI(desc
,"W",0); /* uJobId */
3116 PACKI(desc
,"W",0); /* fsStatus */
3117 PACKS(desc
,"z",""); /* pszStatus */
3118 PACKS(desc
,"z",""); /* pszComment */
3119 PACKS(desc
,"z","NULL"); /* pszDrivers */
3120 PACKI(desc
,"W",0); /* time */
3121 PACKI(desc
,"W",0); /* pad1 */
3126 static BOOL
api_WPrintDestGetInfo(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
3127 int mdrcnt
,int mprcnt
,
3128 char **rdata
,char **rparam
,
3129 int *rdata_len
,int *rparam_len
)
3131 char *str1
= param
+2;
3132 char *str2
= skip_string(str1
,1);
3133 char *p
= skip_string(str2
,1);
3134 char* PrinterName
= p
;
3136 struct pack_desc desc
;
3140 memset((char *)&desc
,'\0',sizeof(desc
));
3142 p
= skip_string(p
,1);
3145 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel
,PrinterName
));
3147 /* check it's a supported varient */
3148 if (strcmp(str1
,"zWrLh") != 0) return False
;
3149 if (!check_printdest_info(&desc
,uLevel
,str2
)) return False
;
3151 snum
= lp_servicenumber(PrinterName
);
3152 if (snum
< 0 && pcap_printername_ok(PrinterName
,NULL
)) {
3153 int pnum
= lp_servicenumber(PRINTERS_NAME
);
3155 lp_add_printer(PrinterName
,pnum
);
3156 snum
= lp_servicenumber(PrinterName
);
3162 desc
.errcode
= NERR_DestNotFound
;
3167 *rdata
= REALLOC(*rdata
,mdrcnt
);
3169 desc
.buflen
= mdrcnt
;
3172 * Don't return data but need to get correct length
3173 * init_package will return wrong size if buflen=0
3175 desc
.buflen
= getlen(desc
.format
);
3176 desc
.base
= tmpdata
= (char *)malloc ( desc
.buflen
);
3178 if (init_package(&desc
,1,0)) {
3179 fill_printdest_info(conn
,snum
,uLevel
,&desc
);
3181 *rdata_len
= desc
.usedlen
;
3185 *rparam
= REALLOC(*rparam
,*rparam_len
);
3186 SSVALS(*rparam
,0,desc
.errcode
);
3188 SSVAL(*rparam
,4,desc
.neededlen
);
3190 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc
.errcode
));
3195 static BOOL
api_WPrintDestEnum(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
3196 int mdrcnt
,int mprcnt
,
3197 char **rdata
,char **rparam
,
3198 int *rdata_len
,int *rparam_len
)
3200 char *str1
= param
+2;
3201 char *str2
= skip_string(str1
,1);
3202 char *p
= skip_string(str2
,1);
3206 struct pack_desc desc
;
3207 int services
= lp_numservices();
3209 memset((char *)&desc
,'\0',sizeof(desc
));
3213 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel
));
3215 /* check it's a supported varient */
3216 if (strcmp(str1
,"WrLeh") != 0) return False
;
3217 if (!check_printdest_info(&desc
,uLevel
,str2
)) return False
;
3220 for (i
= 0; i
< services
; i
++)
3221 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
))
3224 if (mdrcnt
> 0) *rdata
= REALLOC(*rdata
,mdrcnt
);
3226 desc
.buflen
= mdrcnt
;
3227 if (init_package(&desc
,queuecnt
,0)) {
3230 for (i
= 0; i
< services
; i
++) {
3231 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
)) {
3232 fill_printdest_info(conn
,i
,uLevel
,&desc
);
3234 if (desc
.errcode
== NERR_Success
) succnt
= n
;
3239 *rdata_len
= desc
.usedlen
;
3242 *rparam
= REALLOC(*rparam
,*rparam_len
);
3243 SSVALS(*rparam
,0,desc
.errcode
);
3245 SSVAL(*rparam
,4,succnt
);
3246 SSVAL(*rparam
,6,queuecnt
);
3248 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc
.errcode
));
3252 static BOOL
api_WPrintDriverEnum(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
3253 int mdrcnt
,int mprcnt
,
3254 char **rdata
,char **rparam
,
3255 int *rdata_len
,int *rparam_len
)
3257 char *str1
= param
+2;
3258 char *str2
= skip_string(str1
,1);
3259 char *p
= skip_string(str2
,1);
3262 struct pack_desc desc
;
3264 memset((char *)&desc
,'\0',sizeof(desc
));
3268 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel
));
3270 /* check it's a supported varient */
3271 if (strcmp(str1
,"WrLeh") != 0) return False
;
3272 if (uLevel
!= 0 || strcmp(str2
,"B41") != 0) return False
;
3274 if (mdrcnt
> 0) *rdata
= REALLOC(*rdata
,mdrcnt
);
3276 desc
.buflen
= mdrcnt
;
3277 if (init_package(&desc
,1,0)) {
3278 PACKS(&desc
,"B41","NULL");
3281 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
3283 *rdata_len
= desc
.usedlen
;
3286 *rparam
= REALLOC(*rparam
,*rparam_len
);
3287 SSVALS(*rparam
,0,desc
.errcode
);
3289 SSVAL(*rparam
,4,succnt
);
3292 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc
.errcode
));
3296 static BOOL
api_WPrintQProcEnum(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
3297 int mdrcnt
,int mprcnt
,
3298 char **rdata
,char **rparam
,
3299 int *rdata_len
,int *rparam_len
)
3301 char *str1
= param
+2;
3302 char *str2
= skip_string(str1
,1);
3303 char *p
= skip_string(str2
,1);
3306 struct pack_desc desc
;
3308 memset((char *)&desc
,'\0',sizeof(desc
));
3312 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel
));
3314 /* check it's a supported varient */
3315 if (strcmp(str1
,"WrLeh") != 0) return False
;
3316 if (uLevel
!= 0 || strcmp(str2
,"B13") != 0) return False
;
3318 if (mdrcnt
> 0) *rdata
= REALLOC(*rdata
,mdrcnt
);
3320 desc
.buflen
= mdrcnt
;
3322 if (init_package(&desc
,1,0)) {
3323 PACKS(&desc
,"B13","lpd");
3326 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
3328 *rdata_len
= desc
.usedlen
;
3331 *rparam
= REALLOC(*rparam
,*rparam_len
);
3332 SSVALS(*rparam
,0,desc
.errcode
);
3334 SSVAL(*rparam
,4,succnt
);
3337 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc
.errcode
));
3341 static BOOL
api_WPrintPortEnum(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
3342 int mdrcnt
,int mprcnt
,
3343 char **rdata
,char **rparam
,
3344 int *rdata_len
,int *rparam_len
)
3346 char *str1
= param
+2;
3347 char *str2
= skip_string(str1
,1);
3348 char *p
= skip_string(str2
,1);
3351 struct pack_desc desc
;
3353 memset((char *)&desc
,'\0',sizeof(desc
));
3357 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel
));
3359 /* check it's a supported varient */
3360 if (strcmp(str1
,"WrLeh") != 0) return False
;
3361 if (uLevel
!= 0 || strcmp(str2
,"B9") != 0) return False
;
3363 if (mdrcnt
> 0) *rdata
= REALLOC(*rdata
,mdrcnt
);
3364 memset((char *)&desc
,'\0',sizeof(desc
));
3366 desc
.buflen
= mdrcnt
;
3368 if (init_package(&desc
,1,0)) {
3369 PACKS(&desc
,"B13","lp0");
3372 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
3374 *rdata_len
= desc
.usedlen
;
3377 *rparam
= REALLOC(*rparam
,*rparam_len
);
3378 SSVALS(*rparam
,0,desc
.errcode
);
3380 SSVAL(*rparam
,4,succnt
);
3383 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc
.errcode
));
3388 /****************************************************************************
3390 ****************************************************************************/
3391 static BOOL
api_RNetSessionEnum(connection_struct
*conn
,uint16 vuid
, char *param
, char *data
,
3392 int mdrcnt
,int mprcnt
,
3393 char **rdata
,char **rparam
,
3394 int *rdata_len
,int *rparam_len
)
3397 char *str1
= param
+2;
3398 char *str2
= skip_string(str1
,1);
3399 char *p
= skip_string(str2
,1);
3401 struct pack_desc desc
;
3402 struct sessionid
*session_list
;
3403 int i
, num_sessions
;
3405 memset((char *)&desc
,'\0',sizeof(desc
));
3409 DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel
));
3410 DEBUG(7,("RNetSessionEnum req string=%s\n",str1
));
3411 DEBUG(7,("RNetSessionEnum ret string=%s\n",str2
));
3413 /* check it's a supported varient */
3414 if (strcmp(str1
,RAP_NetSessionEnum_REQ
) != 0) return False
;
3415 if (uLevel
!= 2 || strcmp(str2
,RAP_SESSION_INFO_L2
) != 0) return False
;
3417 num_sessions
= list_sessions(&session_list
);
3419 if (mdrcnt
> 0) *rdata
= REALLOC(*rdata
,mdrcnt
);
3420 memset((char *)&desc
,'\0',sizeof(desc
));
3422 desc
.buflen
= mdrcnt
;
3424 if (!init_package(&desc
,num_sessions
,0)) {
3428 for(i
=0; i
<num_sessions
; i
++) {
3429 PACKS(&desc
, "z", session_list
[i
].remote_machine
);
3430 PACKS(&desc
, "z", session_list
[i
].username
);
3431 PACKI(&desc
, "W", 1); /* num conns */
3432 PACKI(&desc
, "W", 0); /* num opens */
3433 PACKI(&desc
, "W", 1); /* num users */
3434 PACKI(&desc
, "D", 0); /* session time */
3435 PACKI(&desc
, "D", 0); /* idle time */
3436 PACKI(&desc
, "D", 0); /* flags */
3437 PACKS(&desc
, "z", "Unknown Client"); /* client type string */
3440 *rdata_len
= desc
.usedlen
;
3443 *rparam
= REALLOC(*rparam
,*rparam_len
);
3444 SSVALS(*rparam
,0,desc
.errcode
);
3445 SSVAL(*rparam
,2,0); /* converter */
3446 SSVAL(*rparam
,4,num_sessions
); /* count */
3448 DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc
.errcode
));
3453 /****************************************************************************
3454 The buffer was too small
3455 ****************************************************************************/
3457 static BOOL
api_TooSmall(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
3458 int mdrcnt
,int mprcnt
,
3459 char **rdata
,char **rparam
,
3460 int *rdata_len
,int *rparam_len
)
3462 *rparam_len
= MIN(*rparam_len
,mprcnt
);
3463 *rparam
= REALLOC(*rparam
,*rparam_len
);
3467 SSVAL(*rparam
,0,NERR_BufTooSmall
);
3469 DEBUG(3,("Supplied buffer too small in API command\n"));
3475 /****************************************************************************
3476 The request is not supported
3477 ****************************************************************************/
3479 static BOOL
api_Unsupported(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
3480 int mdrcnt
,int mprcnt
,
3481 char **rdata
,char **rparam
,
3482 int *rdata_len
,int *rparam_len
)
3485 *rparam
= REALLOC(*rparam
,*rparam_len
);
3489 SSVAL(*rparam
,0,NERR_notsupported
);
3490 SSVAL(*rparam
,2,0); /* converter word */
3492 DEBUG(3,("Unsupported API command\n"));
3504 BOOL (*fn
)(connection_struct
*,uint16
,char *,char *,
3505 int,int,char **,char **,int *,int *);
3506 BOOL auth_user
; /* Deny anonymous access? */
3507 } api_commands
[] = {
3508 {"RNetShareEnum", RAP_WshareEnum
, api_RNetShareEnum
, True
},
3509 {"RNetShareGetInfo", RAP_WshareGetInfo
, api_RNetShareGetInfo
},
3510 {"RNetShareAdd", RAP_WshareAdd
, api_RNetShareAdd
},
3511 {"RNetSessionEnum", RAP_WsessionEnum
, api_RNetSessionEnum
, True
},
3512 {"RNetServerGetInfo", RAP_WserverGetInfo
, api_RNetServerGetInfo
},
3513 {"RNetGroupEnum", RAP_WGroupEnum
, api_RNetGroupEnum
, True
},
3514 {"RNetGroupGetUsers", RAP_WGroupGetUsers
, api_RNetGroupGetUsers
, True
},
3515 {"RNetUserEnum", RAP_WUserEnum
, api_RNetUserEnum
, True
},
3516 {"RNetUserGetInfo", RAP_WUserGetInfo
, api_RNetUserGetInfo
},
3517 {"NetUserGetGroups", RAP_WUserGetGroups
, api_NetUserGetGroups
},
3518 {"NetWkstaGetInfo", RAP_WWkstaGetInfo
, api_NetWkstaGetInfo
},
3519 {"DosPrintQEnum", RAP_WPrintQEnum
, api_DosPrintQEnum
, True
},
3520 {"DosPrintQGetInfo", RAP_WPrintQGetInfo
, api_DosPrintQGetInfo
},
3521 {"WPrintQueuePause", RAP_WPrintQPause
, api_WPrintQueueCtrl
},
3522 {"WPrintQueueResume", RAP_WPrintQContinue
, api_WPrintQueueCtrl
},
3523 {"WPrintJobEnumerate",RAP_WPrintJobEnum
, api_WPrintJobEnumerate
},
3524 {"WPrintJobGetInfo", RAP_WPrintJobGetInfo
, api_WPrintJobGetInfo
},
3525 {"RDosPrintJobDel", RAP_WPrintJobDel
, api_RDosPrintJobDel
},
3526 {"RDosPrintJobPause", RAP_WPrintJobPause
, api_RDosPrintJobDel
},
3527 {"RDosPrintJobResume",RAP_WPrintJobContinue
, api_RDosPrintJobDel
},
3528 {"WPrintDestEnum", RAP_WPrintDestEnum
, api_WPrintDestEnum
},
3529 {"WPrintDestGetInfo", RAP_WPrintDestGetInfo
, api_WPrintDestGetInfo
},
3530 {"NetRemoteTOD", RAP_NetRemoteTOD
, api_NetRemoteTOD
},
3531 {"WPrintQueuePurge", RAP_WPrintQPurge
, api_WPrintQueueCtrl
},
3532 {"NetServerEnum", RAP_NetServerEnum2
, api_RNetServerEnum
}, /* anon OK */
3533 {"WAccessGetUserPerms",RAP_WAccessGetUserPerms
,api_WAccessGetUserPerms
},
3534 {"SetUserPassword", RAP_WUserPasswordSet2
, api_SetUserPassword
},
3535 {"WWkstaUserLogon", RAP_WWkstaUserLogon
, api_WWkstaUserLogon
},
3536 {"PrintJobInfo", RAP_WPrintJobSetInfo
, api_PrintJobInfo
},
3537 {"WPrintDriverEnum", RAP_WPrintDriverEnum
, api_WPrintDriverEnum
},
3538 {"WPrintQProcEnum", RAP_WPrintQProcessorEnum
,api_WPrintQProcEnum
},
3539 {"WPrintPortEnum", RAP_WPrintPortEnum
, api_WPrintPortEnum
},
3540 {"SamOEMChangePassword",RAP_SamOEMChgPasswordUser2_P
,api_SamOEMChangePassword
}, /* anon OK */
3541 {NULL
, -1, api_Unsupported
}};
3543 /* The following RAP calls are not implemented by Samba:
3545 RAP_WFileEnum2 - anon not OK
3548 /****************************************************************************
3549 Handle remote api calls
3550 ****************************************************************************/
3552 int api_reply(connection_struct
*conn
,uint16 vuid
,char *outbuf
,char *data
,char *params
,
3553 int tdscnt
,int tpscnt
,int mdrcnt
,int mprcnt
)
3557 char *rparam
= NULL
;
3564 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
3568 api_command
= SVAL(params
,0);
3570 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
3573 skip_string(params
+2,1),
3574 tdscnt
,tpscnt
,mdrcnt
,mprcnt
));
3576 for (i
=0;api_commands
[i
].name
;i
++) {
3577 if (api_commands
[i
].id
== api_command
&& api_commands
[i
].fn
) {
3578 DEBUG(3,("Doing %s\n",api_commands
[i
].name
));
3583 /* Check whether this api call can be done anonymously */
3585 if (api_commands
[i
].auth_user
&& lp_restrict_anonymous()) {
3586 user_struct
*user
= get_valid_user_struct(vuid
);
3588 if (!user
|| user
->guest
)
3589 return ERROR_NT(NT_STATUS_ACCESS_DENIED
);
3592 rdata
= (char *)malloc(1024);
3594 memset(rdata
,'\0',1024);
3596 rparam
= (char *)malloc(1024);
3598 memset(rparam
,'\0',1024);
3600 if(!rdata
|| !rparam
) {
3601 DEBUG(0,("api_reply: malloc fail !\n"));
3605 reply
= api_commands
[i
].fn(conn
,vuid
,params
,data
,mdrcnt
,mprcnt
,
3606 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
3609 if (rdata_len
> mdrcnt
||
3610 rparam_len
> mprcnt
) {
3611 reply
= api_TooSmall(conn
,vuid
,params
,data
,mdrcnt
,mprcnt
,
3612 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
3615 /* if we get False back then it's actually unsupported */
3617 api_Unsupported(conn
,vuid
,params
,data
,mdrcnt
,mprcnt
,
3618 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
3620 send_trans_reply(outbuf
, rparam
, rparam_len
, rdata
, rdata_len
, False
);