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(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
, "\\\\");
552 fstrcat(location
, get_called_name());
553 fstrcat(location
, "\\print$\\WIN40\\0");
554 PACKS(desc
,"z", location
); /* share to retrieve files */
556 PACKS(desc
,"z", driver
.info_3
->defaultdatatype
); /* default data type */
557 PACKS(desc
,"z", driver
.info_3
->helpfile
); /* helpfile name */
558 PACKS(desc
,"z", driver
.info_3
->driverpath
); /* driver name */
560 DEBUG(3,("Printer Driver Name: %s:\n",driver
.info_3
->name
));
561 DEBUG(3,("Driver: %s:\n",driver
.info_3
->driverpath
));
562 DEBUG(3,("Data File: %s:\n",driver
.info_3
->datafile
));
563 DEBUG(3,("Language Monitor: %s:\n",driver
.info_3
->monitorname
));
564 DEBUG(3,("Driver Location: %s:\n",location
));
565 DEBUG(3,("Data Type: %s:\n",driver
.info_3
->defaultdatatype
));
566 DEBUG(3,("Help File: %s:\n",driver
.info_3
->helpfile
));
567 PACKI(desc
,"N",count
); /* number of files to copy */
569 for ( i
=0; i
<count
&& driver
.info_3
->dependentfiles
&& *driver
.info_3
->dependentfiles
[i
]; i
++)
571 trim_string(driver
.info_3
->dependentfiles
[i
], "\\print$\\WIN40\\0\\", 0);
572 PACKS(desc
,"z",driver
.info_3
->dependentfiles
[i
]); /* driver files to copy */
573 DEBUG(3,("Dependent File: %s:\n",driver
.info_3
->dependentfiles
[i
]));
578 DEBUG(3,("fill_printq_info_52: file count specified by client [%d] != number of dependent files [%i]\n",
581 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n", SERVICE(snum
),i
));
583 desc
->errcode
=NERR_Success
;
587 DEBUG(3,("fill_printq_info: Can't supply driver files\n"));
588 desc
->errcode
=NERR_notsupported
;
592 free_a_printer( &printer
, 2 );
595 free_a_printer_driver( driver
, 3 );
599 static void fill_printq_info(connection_struct
*conn
, int snum
, int uLevel
,
600 struct pack_desc
* desc
,
601 int count
, print_queue_struct
* queue
,
602 print_status_struct
* status
)
607 PACKS(desc
,"B13",SERVICE(snum
));
612 PACKS(desc
,"z",Expand(conn
,snum
,SERVICE(snum
)));
615 PACKI(desc
,"K",printq_status(status
->status
));
619 if (uLevel
== 1 || uLevel
== 2) {
620 PACKS(desc
,"B",""); /* alignment */
621 PACKI(desc
,"W",5); /* priority */
622 PACKI(desc
,"W",0); /* start time */
623 PACKI(desc
,"W",0); /* until time */
624 PACKS(desc
,"z",""); /* pSepFile */
625 PACKS(desc
,"z","lpd"); /* pPrProc */
626 PACKS(desc
,"z",SERVICE(snum
)); /* pDestinations */
627 PACKS(desc
,"z",""); /* pParms */
629 PACKS(desc
,"z","UNKNOWN PRINTER");
630 PACKI(desc
,"W",LPSTAT_ERROR
);
632 else if (!status
|| !status
->message
[0]) {
633 PACKS(desc
,"z",Expand(conn
,snum
,lp_comment(snum
)));
634 PACKI(desc
,"W",LPSTAT_OK
); /* status */
636 PACKS(desc
,"z",status
->message
);
637 PACKI(desc
,"W",printq_status(status
->status
)); /* status */
639 PACKI(desc
,(uLevel
== 1 ? "W" : "N"),count
);
642 if (uLevel
== 3 || uLevel
== 4) {
645 PACKI(desc
,"W",5); /* uPriority */
646 PACKI(desc
,"W",0); /* uStarttime */
647 PACKI(desc
,"W",0); /* uUntiltime */
648 PACKI(desc
,"W",5); /* pad1 */
649 PACKS(desc
,"z",""); /* pszSepFile */
650 PACKS(desc
,"z","WinPrint"); /* pszPrProc */
651 PACKS(desc
,"z",NULL
); /* pszParms */
652 PACKS(desc
,"z",NULL
); /* pszComment - don't ask.... JRA */
653 /* "don't ask" that it's done this way to fix corrupted
654 Win9X/ME printer comments. */
656 PACKI(desc
,"W",LPSTAT_OK
); /* fsStatus */
658 PACKI(desc
,"W",printq_status(status
->status
)); /* fsStatus */
660 PACKI(desc
,(uLevel
== 3 ? "W" : "N"),count
); /* cJobs */
661 PACKS(desc
,"z",SERVICE(snum
)); /* pszPrinters */
662 get_driver_name(snum
,drivername
);
663 PACKS(desc
,"z",drivername
); /* pszDriverName */
664 PackDriverData(desc
); /* pDriverData */
667 if (uLevel
== 2 || uLevel
== 4) {
669 for (i
=0;i
<count
;i
++)
670 fill_printjob_info(conn
,snum
,uLevel
== 2 ? 1 : 2,desc
,&queue
[i
],i
);
674 fill_printq_info_52( conn
, snum
, desc
, count
);
677 /* This function returns the number of files for a given driver */
678 static int get_printerdrivernumber(int snum
)
681 NT_PRINTER_DRIVER_INFO_LEVEL driver
;
682 NT_PRINTER_INFO_LEVEL
*printer
= NULL
;
686 if ( !W_ERROR_IS_OK(get_a_printer( NULL
, &printer
, 2, lp_servicename(snum
))) ) {
687 DEBUG(3,("get_printerdrivernumber: Failed to lookup printer [%s]\n",
688 lp_servicename(snum
)));
692 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver
, 3, printer
->info_2
->drivername
,
695 DEBUG(3,("get_printerdrivernumber: Failed to lookup driver [%s]\n",
696 printer
->info_2
->drivername
));
700 /* count the number of files */
701 while ( driver
.info_3
->dependentfiles
&& *driver
.info_3
->dependentfiles
[result
] )
706 free_a_printer( &printer
, 2 );
709 free_a_printer_driver( driver
, 3 );
714 static BOOL
api_DosPrintQGetInfo(connection_struct
*conn
,
715 uint16 vuid
, char *param
,char *data
,
716 int mdrcnt
,int mprcnt
,
717 char **rdata
,char **rparam
,
718 int *rdata_len
,int *rparam_len
)
720 char *str1
= param
+2;
721 char *str2
= skip_string(str1
,1);
722 char *p
= skip_string(str2
,1);
728 struct pack_desc desc
;
729 print_queue_struct
*queue
=NULL
;
730 print_status_struct status
;
733 memset((char *)&status
,'\0',sizeof(status
));
734 memset((char *)&desc
,'\0',sizeof(desc
));
736 p
= skip_string(p
,1);
740 /* remove any trailing username */
741 if ((p
= strchr_m(QueueName
,'%')))
744 DEBUG(3,("api_DosPrintQGetInfo uLevel=%d name=%s\n",uLevel
,QueueName
));
746 /* check it's a supported varient */
747 if (!prefix_ok(str1
,"zWrLh"))
749 if (!check_printq_info(&desc
,uLevel
,str2
,str3
)) {
751 * Patch from Scott Moomaw <scott@bridgewater.edu>
752 * to return the 'invalid info level' error if an
753 * unknown level was requested.
757 *rparam
= REALLOC(*rparam
,*rparam_len
);
758 SSVALS(*rparam
,0,ERRunknownlevel
);
764 snum
= lp_servicenumber(QueueName
);
765 if (snum
< 0 && pcap_printername_ok(QueueName
,NULL
)) {
766 int pnum
= lp_servicenumber(PRINTERS_NAME
);
768 lp_add_printer(QueueName
,pnum
);
769 snum
= lp_servicenumber(QueueName
);
773 if (snum
< 0 || !VALID_SNUM(snum
))
777 count
= get_printerdrivernumber(snum
);
778 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count
));
780 count
= print_queue_status(snum
, &queue
,&status
);
784 *rdata
= REALLOC(*rdata
,mdrcnt
);
786 desc
.buflen
= mdrcnt
;
789 * Don't return data but need to get correct length
790 * init_package will return wrong size if buflen=0
792 desc
.buflen
= getlen(desc
.format
);
793 desc
.base
= tmpdata
= (char *) malloc (desc
.buflen
);
796 if (init_package(&desc
,1,count
)) {
797 desc
.subcount
= count
;
798 fill_printq_info(conn
,snum
,uLevel
,&desc
,count
,queue
,&status
);
801 *rdata_len
= desc
.usedlen
;
804 * We must set the return code to ERRbuftoosmall
805 * in order to support lanman style printing with Win NT/2k
808 if (!mdrcnt
&& lp_disable_spoolss())
809 desc
.errcode
= ERRbuftoosmall
;
811 *rdata_len
= desc
.usedlen
;
813 *rparam
= REALLOC(*rparam
,*rparam_len
);
814 SSVALS(*rparam
,0,desc
.errcode
);
816 SSVAL(*rparam
,4,desc
.neededlen
);
818 DEBUG(4,("printqgetinfo: errorcode %d\n",desc
.errcode
));
826 /****************************************************************************
827 View list of all print jobs on all queues.
828 ****************************************************************************/
830 static BOOL
api_DosPrintQEnum(connection_struct
*conn
, uint16 vuid
, char* param
, char* data
,
831 int mdrcnt
, int mprcnt
,
832 char **rdata
, char** rparam
,
833 int *rdata_len
, int *rparam_len
)
835 char *param_format
= param
+2;
836 char *output_format1
= skip_string(param_format
,1);
837 char *p
= skip_string(output_format1
,1);
838 int uLevel
= SVAL(p
,0);
839 char *output_format2
= p
+ 4;
840 int services
= lp_numservices();
842 struct pack_desc desc
;
843 print_queue_struct
**queue
= NULL
;
844 print_status_struct
*status
= NULL
;
845 int* subcntarr
= NULL
;
846 int queuecnt
, subcnt
=0, succnt
=0;
848 memset((char *)&desc
,'\0',sizeof(desc
));
850 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel
));
852 if (!prefix_ok(param_format
,"WrLeh")) return False
;
853 if (!check_printq_info(&desc
,uLevel
,output_format1
,output_format2
)) {
855 * Patch from Scott Moomaw <scott@bridgewater.edu>
856 * to return the 'invalid info level' error if an
857 * unknown level was requested.
861 *rparam
= REALLOC(*rparam
,*rparam_len
);
862 SSVALS(*rparam
,0,ERRunknownlevel
);
869 for (i
= 0; i
< services
; i
++)
870 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
))
873 if((queue
= (print_queue_struct
**)malloc(queuecnt
*sizeof(print_queue_struct
*))) == NULL
) {
874 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
877 memset(queue
,0,queuecnt
*sizeof(print_queue_struct
*));
878 if((status
= (print_status_struct
*)malloc(queuecnt
*sizeof(print_status_struct
))) == NULL
) {
879 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
882 memset(status
,0,queuecnt
*sizeof(print_status_struct
));
883 if((subcntarr
= (int*)malloc(queuecnt
*sizeof(int))) == NULL
) {
884 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
889 for (i
= 0; i
< services
; i
++)
890 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
)) {
891 subcntarr
[n
] = print_queue_status(i
, &queue
[n
],&status
[n
]);
892 subcnt
+= subcntarr
[n
];
896 if (mdrcnt
> 0) *rdata
= REALLOC(*rdata
,mdrcnt
);
898 desc
.buflen
= mdrcnt
;
900 if (init_package(&desc
,queuecnt
,subcnt
)) {
903 for (i
= 0; i
< services
; i
++)
904 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
)) {
905 fill_printq_info(conn
,i
,uLevel
,&desc
,subcntarr
[n
],queue
[n
],&status
[n
]);
907 if (desc
.errcode
== NERR_Success
) succnt
= n
;
911 SAFE_FREE(subcntarr
);
913 *rdata_len
= desc
.usedlen
;
915 *rparam
= REALLOC(*rparam
,*rparam_len
);
916 SSVALS(*rparam
,0,desc
.errcode
);
918 SSVAL(*rparam
,4,succnt
);
919 SSVAL(*rparam
,6,queuecnt
);
921 for (i
= 0; i
< queuecnt
; i
++) {
922 if (queue
) SAFE_FREE(queue
[i
]);
931 /****************************************************************************
932 get info level for a server list query
933 ****************************************************************************/
934 static BOOL
check_server_info(int uLevel
, char* id
)
938 if (strcmp(id
,"B16") != 0) return False
;
941 if (strcmp(id
,"B16BBDz") != 0) return False
;
949 struct srv_info_struct
959 /*******************************************************************
960 get server info lists from the files saved by nmbd. Return the
962 ******************************************************************/
963 static int get_server_info(uint32 servertype
,
964 struct srv_info_struct
**servers
,
970 BOOL local_list_only
;
973 lines
= file_lines_load(lock_path(SERVER_LIST
), NULL
);
975 DEBUG(4,("Can't open %s - %s\n",lock_path(SERVER_LIST
),strerror(errno
)));
979 /* request for everything is code for request all servers */
980 if (servertype
== SV_TYPE_ALL
)
981 servertype
&= ~(SV_TYPE_DOMAIN_ENUM
|SV_TYPE_LOCAL_LIST_ONLY
);
983 local_list_only
= (servertype
& SV_TYPE_LOCAL_LIST_ONLY
);
985 DEBUG(4,("Servertype search: %8x\n",servertype
));
987 for (i
=0;lines
[i
];i
++) {
989 struct srv_info_struct
*s
;
990 const char *ptr
= lines
[i
];
995 if (count
== alloced
) {
996 struct srv_info_struct
*ts
;
999 ts
= (struct srv_info_struct
*)
1000 Realloc(*servers
,sizeof(**servers
)*alloced
);
1002 DEBUG(0,("get_server_info: failed to enlarge servers info struct!\n"));
1006 memset((char *)((*servers
)+count
),'\0',sizeof(**servers
)*(alloced
-count
));
1008 s
= &(*servers
)[count
];
1010 if (!next_token(&ptr
,s
->name
, NULL
, sizeof(s
->name
))) continue;
1011 if (!next_token(&ptr
,stype
, NULL
, sizeof(stype
))) continue;
1012 if (!next_token(&ptr
,s
->comment
, NULL
, sizeof(s
->comment
))) continue;
1013 if (!next_token(&ptr
,s
->domain
, NULL
, sizeof(s
->domain
))) {
1014 /* this allows us to cope with an old nmbd */
1015 fstrcpy(s
->domain
,lp_workgroup());
1018 if (sscanf(stype
,"%X",&s
->type
) != 1) {
1019 DEBUG(4,("r:host file "));
1023 /* Filter the servers/domains we return based on what was asked for. */
1025 /* Check to see if we are being asked for a local list only. */
1026 if(local_list_only
&& ((s
->type
& SV_TYPE_LOCAL_LIST_ONLY
) == 0)) {
1027 DEBUG(4,("r: local list only"));
1031 /* doesn't match up: don't want it */
1032 if (!(servertype
& s
->type
)) {
1033 DEBUG(4,("r:serv type "));
1037 if ((servertype
& SV_TYPE_DOMAIN_ENUM
) !=
1038 (s
->type
& SV_TYPE_DOMAIN_ENUM
))
1040 DEBUG(4,("s: dom mismatch "));
1044 if (!strequal(domain
, s
->domain
) && !(servertype
& SV_TYPE_DOMAIN_ENUM
))
1049 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1050 s
->type
&= ~SV_TYPE_LOCAL_LIST_ONLY
;
1054 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1055 s
->name
, s
->type
, s
->comment
, s
->domain
));
1057 s
->server_added
= True
;
1062 DEBUG(4,("%20s %8x %25s %15s\n",
1063 s
->name
, s
->type
, s
->comment
, s
->domain
));
1067 file_lines_free(lines
);
1072 /*******************************************************************
1073 fill in a server info structure
1074 ******************************************************************/
1075 static int fill_srv_info(struct srv_info_struct
*service
,
1076 int uLevel
, char **buf
, int *buflen
,
1077 char **stringbuf
, int *stringspace
, char *baseaddr
)
1086 case 0: struct_len
= 16; break;
1087 case 1: struct_len
= 26; break;
1097 len
= strlen(service
->comment
)+1;
1101 if (buflen
) *buflen
= struct_len
;
1102 if (stringspace
) *stringspace
= len
;
1103 return struct_len
+ len
;
1108 if (*buflen
< struct_len
) return -1;
1116 p2
= p
+ struct_len
;
1117 l2
= *buflen
- struct_len
;
1119 if (!baseaddr
) baseaddr
= p
;
1124 push_ascii(p
,service
->name
, 15, STR_TERMINATE
);
1128 push_ascii(p
,service
->name
,15, STR_TERMINATE
);
1129 SIVAL(p
,18,service
->type
);
1130 SIVAL(p
,22,PTR_DIFF(p2
,baseaddr
));
1131 len
+= CopyAndAdvance(&p2
,service
->comment
,&l2
);
1137 *buf
= p
+ struct_len
;
1138 *buflen
-= struct_len
;
1151 static BOOL
srv_comp(struct srv_info_struct
*s1
,struct srv_info_struct
*s2
)
1153 return(strcmp(s1
->name
,s2
->name
));
1156 /****************************************************************************
1157 view list of servers available (or possibly domains). The info is
1158 extracted from lists saved by nmbd on the local host
1159 ****************************************************************************/
1160 static BOOL
api_RNetServerEnum(connection_struct
*conn
, uint16 vuid
, char *param
, char *data
,
1161 int mdrcnt
, int mprcnt
, char **rdata
,
1162 char **rparam
, int *rdata_len
, int *rparam_len
)
1164 char *str1
= param
+2;
1165 char *str2
= skip_string(str1
,1);
1166 char *p
= skip_string(str2
,1);
1167 int uLevel
= SVAL(p
,0);
1168 int buf_len
= SVAL(p
,2);
1169 uint32 servertype
= IVAL(p
,4);
1171 int data_len
, fixed_len
, string_len
;
1172 int f_len
= 0, s_len
= 0;
1173 struct srv_info_struct
*servers
=NULL
;
1174 int counted
=0,total
=0;
1177 BOOL domain_request
;
1180 /* If someone sets all the bits they don't really mean to set
1181 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1184 if (servertype
== SV_TYPE_ALL
)
1185 servertype
&= ~(SV_TYPE_DOMAIN_ENUM
|SV_TYPE_LOCAL_LIST_ONLY
);
1187 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1188 any other bit (they may just set this bit on it's own) they
1189 want all the locally seen servers. However this bit can be
1190 set on its own so set the requested servers to be
1191 ALL - DOMAIN_ENUM. */
1193 if ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) && !(servertype
& SV_TYPE_DOMAIN_ENUM
))
1194 servertype
= SV_TYPE_ALL
& ~(SV_TYPE_DOMAIN_ENUM
);
1196 domain_request
= ((servertype
& SV_TYPE_DOMAIN_ENUM
) != 0);
1197 local_request
= ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) != 0);
1201 if (!prefix_ok(str1
,"WrLehD")) return False
;
1202 if (!check_server_info(uLevel
,str2
)) return False
;
1204 DEBUG(4, ("server request level: %s %8x ", str2
, servertype
));
1205 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request
)));
1206 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request
)));
1208 if (strcmp(str1
, "WrLehDz") == 0) {
1209 pull_ascii_fstring(domain
, p
);
1211 fstrcpy(domain
, lp_workgroup());
1214 if (lp_browse_list())
1215 total
= get_server_info(servertype
,&servers
,domain
);
1217 data_len
= fixed_len
= string_len
= 0;
1221 qsort(servers
,total
,sizeof(servers
[0]),QSORT_CAST srv_comp
);
1224 char *lastname
=NULL
;
1226 for (i
=0;i
<total
;i
++)
1228 struct srv_info_struct
*s
= &servers
[i
];
1229 if (lastname
&& strequal(lastname
,s
->name
)) continue;
1231 data_len
+= fill_srv_info(s
,uLevel
,0,&f_len
,0,&s_len
,0);
1232 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1233 s
->name
, s
->type
, s
->comment
, s
->domain
));
1235 if (data_len
<= buf_len
) {
1238 string_len
+= s_len
;
1245 *rdata_len
= fixed_len
+ string_len
;
1246 *rdata
= REALLOC(*rdata
,*rdata_len
);
1247 memset(*rdata
,'\0',*rdata_len
);
1249 p2
= (*rdata
) + fixed_len
; /* auxilliary data (strings) will go here */
1255 char *lastname
=NULL
;
1256 int count2
= counted
;
1257 for (i
= 0; i
< total
&& count2
;i
++)
1259 struct srv_info_struct
*s
= &servers
[i
];
1260 if (lastname
&& strequal(lastname
,s
->name
)) continue;
1262 fill_srv_info(s
,uLevel
,&p
,&f_len
,&p2
,&s_len
,*rdata
);
1263 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1264 s
->name
, s
->type
, s
->comment
, s
->domain
));
1270 *rparam
= REALLOC(*rparam
,*rparam_len
);
1271 SSVAL(*rparam
,0,(missed
== 0 ? NERR_Success
: ERRmoredata
));
1273 SSVAL(*rparam
,4,counted
);
1274 SSVAL(*rparam
,6,counted
+missed
);
1278 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1279 domain
,uLevel
,counted
,counted
+missed
));
1284 /****************************************************************************
1285 command 0x34 - suspected of being a "Lookup Names" stub api
1286 ****************************************************************************/
1287 static BOOL
api_RNetGroupGetUsers(connection_struct
*conn
, uint16 vuid
, char *param
, char *data
,
1288 int mdrcnt
, int mprcnt
, char **rdata
,
1289 char **rparam
, int *rdata_len
, int *rparam_len
)
1291 char *str1
= param
+2;
1292 char *str2
= skip_string(str1
,1);
1293 char *p
= skip_string(str2
,1);
1294 int uLevel
= SVAL(p
,0);
1295 int buf_len
= SVAL(p
,2);
1299 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1300 str1
, str2
, p
, uLevel
, buf_len
));
1302 if (!prefix_ok(str1
,"zWrLeh")) return False
;
1307 *rparam
= REALLOC(*rparam
,*rparam_len
);
1309 SSVAL(*rparam
,0,0x08AC); /* informational warning message */
1311 SSVAL(*rparam
,4,counted
);
1312 SSVAL(*rparam
,6,counted
+missed
);
1317 /****************************************************************************
1318 get info about a share
1319 ****************************************************************************/
1320 static BOOL
check_share_info(int uLevel
, char* id
)
1324 if (strcmp(id
,"B13") != 0) return False
;
1327 if (strcmp(id
,"B13BWz") != 0) return False
;
1330 if (strcmp(id
,"B13BWzWWWzB9B") != 0) return False
;
1333 if (strcmp(id
,"B13BWzWWWzB9BB9BWzWWzWW") != 0) return False
;
1335 default: return False
;
1340 static int fill_share_info(connection_struct
*conn
, int snum
, int uLevel
,
1341 char** buf
, int* buflen
,
1342 char** stringbuf
, int* stringspace
, char* baseaddr
)
1351 case 0: struct_len
= 13; break;
1352 case 1: struct_len
= 20; break;
1353 case 2: struct_len
= 40; break;
1354 case 91: struct_len
= 68; break;
1362 if (uLevel
> 0) len
+= StrlenExpanded(conn
,snum
,lp_comment(snum
));
1363 if (uLevel
> 1) len
+= strlen(lp_pathname(snum
)) + 1;
1364 if (buflen
) *buflen
= struct_len
;
1365 if (stringspace
) *stringspace
= len
;
1366 return struct_len
+ len
;
1371 if ((*buflen
) < struct_len
) return -1;
1379 p2
= p
+ struct_len
;
1380 l2
= (*buflen
) - struct_len
;
1382 if (!baseaddr
) baseaddr
= p
;
1384 push_ascii(p
,lp_servicename(snum
),13, STR_TERMINATE
);
1390 type
= STYPE_DISKTREE
;
1391 if (lp_print_ok(snum
)) type
= STYPE_PRINTQ
;
1392 if (strequal("IPC",lp_fstype(snum
))) type
= STYPE_IPC
;
1393 SSVAL(p
,14,type
); /* device type */
1394 SIVAL(p
,16,PTR_DIFF(p2
,baseaddr
));
1395 len
+= CopyExpanded(conn
,snum
,&p2
,lp_comment(snum
),&l2
);
1400 SSVAL(p
,20,ACCESS_READ
|ACCESS_WRITE
|ACCESS_CREATE
); /* permissions */
1401 SSVALS(p
,22,-1); /* max uses */
1402 SSVAL(p
,24,1); /* current uses */
1403 SIVAL(p
,26,PTR_DIFF(p2
,baseaddr
)); /* local pathname */
1404 len
+= CopyAndAdvance(&p2
,lp_pathname(snum
),&l2
);
1405 memset(p
+30,0,SHPWLEN
+2); /* passwd (reserved), pad field */
1410 memset(p
+40,0,SHPWLEN
+2);
1422 (*buf
) = p
+ struct_len
;
1423 (*buflen
) -= struct_len
;
1425 (*stringspace
) = l2
;
1435 static BOOL
api_RNetShareGetInfo(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
1436 int mdrcnt
,int mprcnt
,
1437 char **rdata
,char **rparam
,
1438 int *rdata_len
,int *rparam_len
)
1440 char *str1
= param
+2;
1441 char *str2
= skip_string(str1
,1);
1442 char *netname
= skip_string(str2
,1);
1443 char *p
= skip_string(netname
,1);
1444 int uLevel
= SVAL(p
,0);
1445 int snum
= find_service(netname
);
1447 if (snum
< 0) return False
;
1449 /* check it's a supported varient */
1450 if (!prefix_ok(str1
,"zWrLh")) return False
;
1451 if (!check_share_info(uLevel
,str2
)) return False
;
1453 *rdata
= REALLOC(*rdata
,mdrcnt
);
1455 *rdata_len
= fill_share_info(conn
,snum
,uLevel
,&p
,&mdrcnt
,0,0,0);
1456 if (*rdata_len
< 0) return False
;
1459 *rparam
= REALLOC(*rparam
,*rparam_len
);
1460 SSVAL(*rparam
,0,NERR_Success
);
1461 SSVAL(*rparam
,2,0); /* converter word */
1462 SSVAL(*rparam
,4,*rdata_len
);
1467 /****************************************************************************
1468 view list of shares available
1469 ****************************************************************************/
1470 static BOOL
api_RNetShareEnum(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
1471 int mdrcnt
,int mprcnt
,
1472 char **rdata
,char **rparam
,
1473 int *rdata_len
,int *rparam_len
)
1475 char *str1
= param
+2;
1476 char *str2
= skip_string(str1
,1);
1477 char *p
= skip_string(str2
,1);
1478 int uLevel
= SVAL(p
,0);
1479 int buf_len
= SVAL(p
,2);
1481 int count
=lp_numservices();
1482 int total
=0,counted
=0;
1483 BOOL missed
= False
;
1485 int data_len
, fixed_len
, string_len
;
1486 int f_len
= 0, s_len
= 0;
1488 if (!prefix_ok(str1
,"WrLeh")) return False
;
1489 if (!check_share_info(uLevel
,str2
)) return False
;
1491 data_len
= fixed_len
= string_len
= 0;
1492 for (i
=0;i
<count
;i
++)
1493 if (lp_browseable(i
) && lp_snum_ok(i
))
1496 data_len
+= fill_share_info(conn
,i
,uLevel
,0,&f_len
,0,&s_len
,0);
1497 if (data_len
<= buf_len
)
1501 string_len
+= s_len
;
1506 *rdata_len
= fixed_len
+ string_len
;
1507 *rdata
= REALLOC(*rdata
,*rdata_len
);
1508 memset(*rdata
,0,*rdata_len
);
1510 p2
= (*rdata
) + fixed_len
; /* auxiliary data (strings) will go here */
1514 for (i
= 0; i
< count
;i
++)
1515 if (lp_browseable(i
) && lp_snum_ok(i
))
1516 if (fill_share_info(conn
,i
,uLevel
,&p
,&f_len
,&p2
,&s_len
,*rdata
) < 0)
1520 *rparam
= REALLOC(*rparam
,*rparam_len
);
1521 SSVAL(*rparam
,0,missed
? ERRmoredata
: NERR_Success
);
1523 SSVAL(*rparam
,4,counted
);
1524 SSVAL(*rparam
,6,total
);
1526 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1527 counted
,total
,uLevel
,
1528 buf_len
,*rdata_len
,mdrcnt
));
1532 /****************************************************************************
1534 ****************************************************************************/
1535 static BOOL
api_RNetShareAdd(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
1536 int mdrcnt
,int mprcnt
,
1537 char **rdata
,char **rparam
,
1538 int *rdata_len
,int *rparam_len
)
1540 char *str1
= param
+2;
1541 char *str2
= skip_string(str1
,1);
1542 char *p
= skip_string(str2
,1);
1543 int uLevel
= SVAL(p
,0);
1547 char *command
, *cmdname
;
1548 unsigned int offset
;
1552 /* check it's a supported varient */
1553 if (!prefix_ok(str1
,RAP_WShareAdd_REQ
)) return False
;
1554 if (!check_share_info(uLevel
,str2
)) return False
;
1555 if (uLevel
!= 2) return False
;
1557 pull_ascii_fstring(sharename
,data
);
1558 snum
= find_service(sharename
);
1559 if (snum
>= 0) { /* already exists */
1564 /* only support disk share adds */
1565 if (SVAL(data
,14)!=STYPE_DISKTREE
) return False
;
1567 offset
= IVAL(data
, 16);
1568 if (offset
>= mdrcnt
) {
1569 res
= ERRinvalidparam
;
1572 pull_ascii_fstring(comment
, offset
? (data
+offset
) : "");
1574 offset
= IVAL(data
, 26);
1575 if (offset
>= mdrcnt
) {
1576 res
= ERRinvalidparam
;
1579 pull_ascii_pstring(pathname
, offset
? (data
+offset
) : "");
1581 string_replace(sharename
, '"', ' ');
1582 string_replace(pathname
, '"', ' ');
1583 string_replace(comment
, '"', ' ');
1585 cmdname
= lp_add_share_cmd();
1587 if (!cmdname
|| *cmdname
== '\0') return False
;
1589 asprintf(&command
, "%s \"%s\" \"%s\" \"%s\" \"%s\"",
1590 lp_add_share_cmd(), dyn_CONFIGFILE
, sharename
, pathname
, comment
);
1593 DEBUG(10,("api_RNetShareAdd: Running [%s]\n", command
));
1594 if ((res
= smbrun(command
, NULL
)) != 0) {
1595 DEBUG(1,("api_RNetShareAdd: Running [%s] returned (%d)\n", command
, res
));
1601 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED
, NULL
, 0, False
, NULL
);
1603 } else return False
;
1606 *rparam
= REALLOC(*rparam
,*rparam_len
);
1607 SSVAL(*rparam
,0,NERR_Success
);
1608 SSVAL(*rparam
,2,0); /* converter word */
1609 SSVAL(*rparam
,4,*rdata_len
);
1616 *rparam
= REALLOC(*rparam
,*rparam_len
);
1618 SSVAL(*rparam
,0,res
);
1624 /****************************************************************************
1625 view list of groups available
1626 ****************************************************************************/
1627 static BOOL
api_RNetGroupEnum(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
1628 int mdrcnt
,int mprcnt
,
1629 char **rdata
,char **rparam
,
1630 int *rdata_len
,int *rparam_len
)
1634 int resume_context
, cli_buf_size
;
1635 char *str1
= param
+2;
1636 char *str2
= skip_string(str1
,1);
1637 char *p
= skip_string(str2
,1);
1639 GROUP_MAP
*group_list
;
1642 if (strcmp(str1
,"WrLeh") != 0)
1646 * W-> resume context (number of users to skip)
1647 * r -> return parameter pointer to receive buffer
1648 * L -> length of receive buffer
1649 * e -> return parameter number of entries
1650 * h -> return parameter total number of users
1652 if (strcmp("B21",str2
) != 0)
1655 /* get list of domain groups SID_DOMAIN_GRP=2 */
1656 if(!pdb_enum_group_mapping(SID_NAME_DOM_GRP
, &group_list
, &num_entries
, False
)) {
1657 DEBUG(3,("api_RNetGroupEnum:failed to get group list"));
1661 resume_context
= SVAL(p
,0);
1662 cli_buf_size
=SVAL(p
+2,0);
1663 DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: %d\n", resume_context
, cli_buf_size
));
1665 *rdata_len
= cli_buf_size
;
1666 *rdata
= REALLOC(*rdata
,*rdata_len
);
1670 for(i
=resume_context
; i
<num_entries
; i
++) {
1671 char* name
=group_list
[i
].nt_name
;
1672 if( ((PTR_DIFF(p
,*rdata
)+21) <= *rdata_len
) ) {
1673 /* truncate the name at 21 chars. */
1674 memcpy(p
, name
, 21);
1675 DEBUG(10,("adding entry %d group %s\n", i
, p
));
1678 /* set overflow error */
1679 DEBUG(3,("overflow on entry %d group %s\n", i
, name
));
1685 *rdata_len
= PTR_DIFF(p
,*rdata
);
1688 *rparam
= REALLOC(*rparam
,*rparam_len
);
1690 SSVAL(*rparam
, 0, errflags
);
1691 SSVAL(*rparam
, 2, 0); /* converter word */
1692 SSVAL(*rparam
, 4, i
-resume_context
); /* is this right?? */
1693 SSVAL(*rparam
, 6, num_entries
); /* is this right?? */
1698 /*******************************************************************
1699 get groups that a user is a member of
1700 ******************************************************************/
1701 static BOOL
api_NetUserGetGroups(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
1702 int mdrcnt
,int mprcnt
,
1703 char **rdata
,char **rparam
,
1704 int *rdata_len
,int *rparam_len
)
1706 char *str1
= param
+2;
1707 char *str2
= skip_string(str1
,1);
1708 char *UserName
= skip_string(str2
,1);
1709 char *p
= skip_string(UserName
,1);
1710 int uLevel
= SVAL(p
,0);
1711 const char *level_string
;
1713 SAM_ACCOUNT
*sampw
= NULL
;
1715 DOM_GID
*gids
= NULL
;
1720 enum SID_NAME_USE grp_type
;
1721 DOM_SID sid
, dom_sid
;
1724 *rparam
= REALLOC(*rparam
,*rparam_len
);
1726 /* check it's a supported varient */
1728 if ( strcmp(str1
,"zWrLeh") != 0 )
1733 level_string
= "B21";
1739 if (strcmp(level_string
,str2
) != 0)
1742 *rdata_len
= mdrcnt
+ 1024;
1743 *rdata
= REALLOC(*rdata
,*rdata_len
);
1745 SSVAL(*rparam
,0,NERR_Success
);
1746 SSVAL(*rparam
,2,0); /* converter word */
1750 /* Lookup the user information; This should only be one of
1751 our accounts (not remote domains) */
1753 pdb_init_sam( &sampw
);
1755 become_root(); /* ROOT BLOCK */
1757 if ( !pdb_getsampwnam(sampw
, UserName
) )
1760 /* this next set of code is horribly inefficient, but since
1761 it is rarely called, I'm going to leave it like this since
1762 it easier to follow --jerry */
1764 /* get the list of group SIDs */
1766 if ( !get_domain_user_groups(conn
->mem_ctx
, &num_groups
, &gids
, sampw
) ) {
1767 DEBUG(1,("api_NetUserGetGroups: get_domain_user_groups() failed!\n"));
1771 /* convert to names (we don't support universal groups so the domain
1772 can only be ours) */
1774 sid_copy( &dom_sid
, get_global_sam_sid() );
1775 for (i
=0; i
<num_groups
; i
++) {
1777 /* make the DOM_GID into a DOM_SID and then lookup
1780 sid_copy( &sid
, &dom_sid
);
1781 sid_append_rid( &sid
, gids
[i
].g_rid
);
1783 if ( lookup_sid(&sid
, grp_domain
, grp_name
, &grp_type
) ) {
1784 pstrcpy(p
, grp_name
);
1790 *rdata_len
= PTR_DIFF(p
,*rdata
);
1792 SSVAL(*rparam
,4,count
); /* is this right?? */
1793 SSVAL(*rparam
,6,count
); /* is this right?? */
1798 unbecome_root(); /* END ROOT BLOCK */
1800 pdb_free_sam( &sampw
);
1805 /*******************************************************************
1807 ******************************************************************/
1808 static BOOL
api_RNetUserEnum(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
1809 int mdrcnt
,int mprcnt
,
1810 char **rdata
,char **rparam
,
1811 int *rdata_len
,int *rparam_len
)
1813 SAM_ACCOUNT
*pwd
=NULL
;
1817 int resume_context
, cli_buf_size
;
1819 char *str1
= param
+2;
1820 char *str2
= skip_string(str1
,1);
1821 char *p
= skip_string(str2
,1);
1823 if (strcmp(str1
,"WrLeh") != 0)
1826 * W-> resume context (number of users to skip)
1827 * r -> return parameter pointer to receive buffer
1828 * L -> length of receive buffer
1829 * e -> return parameter number of entries
1830 * h -> return parameter total number of users
1833 resume_context
= SVAL(p
,0);
1834 cli_buf_size
=SVAL(p
+2,0);
1835 DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n", resume_context
, cli_buf_size
));
1838 *rparam
= REALLOC(*rparam
,*rparam_len
);
1840 /* check it's a supported varient */
1841 if (strcmp("B21",str2
) != 0)
1844 *rdata_len
= cli_buf_size
;
1845 *rdata
= REALLOC(*rdata
,*rdata_len
);
1849 /* to get user list enumerations for NetUserEnum in B21 format */
1852 /* Open the passgrp file - not for update. */
1854 if(!pdb_setsampwent(False
)) {
1855 DEBUG(0, ("api_RNetUserEnum:unable to open sam database.\n"));
1859 errflags
=NERR_Success
;
1861 while ( pdb_getsampwent(pwd
) ) {
1862 const char *name
=pdb_get_username(pwd
);
1863 if ((name
) && (*(name
+strlen(name
)-1)!='$')) {
1865 if(count_total
>=resume_context
) {
1866 if( ((PTR_DIFF(p
,*rdata
)+21)<=*rdata_len
)&&(strlen(name
)<=21) ) {
1868 DEBUG(10,("api_RNetUserEnum:adding entry %d username %s\n",count_sent
,p
));
1872 /* set overflow error */
1873 DEBUG(10,("api_RNetUserEnum:overflow on entry %d username %s\n",count_sent
,name
));
1886 *rdata_len
= PTR_DIFF(p
,*rdata
);
1888 SSVAL(*rparam
,0,errflags
);
1889 SSVAL(*rparam
,2,0); /* converter word */
1890 SSVAL(*rparam
,4,count_sent
); /* is this right?? */
1891 SSVAL(*rparam
,6,count_total
); /* is this right?? */
1898 /****************************************************************************
1899 get the time of day info
1900 ****************************************************************************/
1901 static BOOL
api_NetRemoteTOD(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
1902 int mdrcnt
,int mprcnt
,
1903 char **rdata
,char **rparam
,
1904 int *rdata_len
,int *rparam_len
)
1908 *rparam
= REALLOC(*rparam
,*rparam_len
);
1911 *rdata
= REALLOC(*rdata
,*rdata_len
);
1913 SSVAL(*rparam
,0,NERR_Success
);
1914 SSVAL(*rparam
,2,0); /* converter word */
1920 time_t unixdate
= time(NULL
);
1922 put_dos_date3(p
,0,unixdate
); /* this is the time that is looked at
1923 by NT in a "net time" operation,
1924 it seems to ignore the one below */
1926 /* the client expects to get localtime, not GMT, in this bit
1927 (I think, this needs testing) */
1928 t
= LocalTime(&unixdate
);
1930 SIVAL(p
,4,0); /* msecs ? */
1931 SCVAL(p
,8,t
->tm_hour
);
1932 SCVAL(p
,9,t
->tm_min
);
1933 SCVAL(p
,10,t
->tm_sec
);
1934 SCVAL(p
,11,0); /* hundredths of seconds */
1935 SSVALS(p
,12,TimeDiff(unixdate
)/60); /* timezone in minutes from GMT */
1936 SSVAL(p
,14,10000); /* timer interval in 0.0001 of sec */
1937 SCVAL(p
,16,t
->tm_mday
);
1938 SCVAL(p
,17,t
->tm_mon
+ 1);
1939 SSVAL(p
,18,1900+t
->tm_year
);
1940 SCVAL(p
,20,t
->tm_wday
);
1947 /****************************************************************************
1948 Set the user password.
1949 *****************************************************************************/
1951 static BOOL
api_SetUserPassword(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
1952 int mdrcnt
,int mprcnt
,
1953 char **rdata
,char **rparam
,
1954 int *rdata_len
,int *rparam_len
)
1956 char *p
= skip_string(param
+2,2);
1958 fstring pass1
,pass2
;
1960 pull_ascii_fstring(user
,p
);
1962 p
= skip_string(p
,1);
1964 memset(pass1
,'\0',sizeof(pass1
));
1965 memset(pass2
,'\0',sizeof(pass2
));
1967 memcpy(pass2
,p
+16,16);
1970 *rparam
= REALLOC(*rparam
,*rparam_len
);
1974 SSVAL(*rparam
,0,NERR_badpass
);
1975 SSVAL(*rparam
,2,0); /* converter word */
1977 DEBUG(3,("Set password for <%s>\n",user
));
1980 * Attempt to verify the old password against smbpasswd entries
1981 * Win98 clients send old and new password in plaintext for this call.
1985 auth_serversupplied_info
*server_info
= NULL
;
1986 DATA_BLOB password
= data_blob(pass1
, strlen(pass1
)+1);
1988 if (NT_STATUS_IS_OK(check_plaintext_password(user
,password
,&server_info
))) {
1991 if (NT_STATUS_IS_OK(change_oem_password(server_info
->sam_account
, pass1
, pass2
, False
))) {
1992 SSVAL(*rparam
,0,NERR_Success
);
1996 free_server_info(&server_info
);
1998 data_blob_clear_free(&password
);
2002 * If the plaintext change failed, attempt
2003 * the old encrypted method. NT will generate this
2004 * after trying the samr method. Note that this
2005 * method is done as a last resort as this
2006 * password change method loses the NT password hash
2007 * and cannot change the UNIX password as no plaintext
2011 if(SVAL(*rparam
,0) != NERR_Success
) {
2012 SAM_ACCOUNT
*hnd
= NULL
;
2014 if (check_lanman_password(user
,(unsigned char *)pass1
,(unsigned char *)pass2
, &hnd
)) {
2016 if (change_lanman_password(hnd
,(uchar
*)pass2
)) {
2017 SSVAL(*rparam
,0,NERR_Success
);
2024 memset((char *)pass1
,'\0',sizeof(fstring
));
2025 memset((char *)pass2
,'\0',sizeof(fstring
));
2030 /****************************************************************************
2031 Set the user password (SamOEM version - gets plaintext).
2032 ****************************************************************************/
2034 static BOOL
api_SamOEMChangePassword(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
2035 int mdrcnt
,int mprcnt
,
2036 char **rdata
,char **rparam
,
2037 int *rdata_len
,int *rparam_len
)
2040 char *p
= param
+ 2;
2042 *rparam
= REALLOC(*rparam
,*rparam_len
);
2046 SSVAL(*rparam
,0,NERR_badpass
);
2049 * Check the parameter definition is correct.
2052 if(!strequal(param
+ 2, "zsT")) {
2053 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", param
+ 2));
2056 p
= skip_string(p
, 1);
2058 if(!strequal(p
, "B516B16")) {
2059 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p
));
2062 p
= skip_string(p
,1);
2063 p
+= pull_ascii_fstring(user
,p
);
2065 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user
));
2068 * Pass the user through the NT -> unix user mapping
2072 (void)map_username(user
);
2074 if (NT_STATUS_IS_OK(pass_oem_change(user
, (uchar
*) data
, (uchar
*)&data
[516], NULL
, NULL
))) {
2075 SSVAL(*rparam
,0,NERR_Success
);
2081 /****************************************************************************
2084 ****************************************************************************/
2085 static BOOL
api_RDosPrintJobDel(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
2086 int mdrcnt
,int mprcnt
,
2087 char **rdata
,char **rparam
,
2088 int *rdata_len
,int *rparam_len
)
2090 int function
= SVAL(param
,0);
2091 char *str1
= param
+2;
2092 char *str2
= skip_string(str1
,1);
2093 char *p
= skip_string(str2
,1);
2097 extern struct current_user current_user
;
2098 WERROR werr
= WERR_OK
;
2100 if(!rap_to_pjobid(SVAL(p
,0),&snum
,&jobid
))
2103 /* check it's a supported varient */
2104 if (!(strcsequal(str1
,"W") && strcsequal(str2
,"")))
2108 *rparam
= REALLOC(*rparam
,*rparam_len
);
2111 if (!print_job_exists(snum
, jobid
)) {
2112 errcode
= NERR_JobNotFound
;
2116 errcode
= NERR_notsupported
;
2119 case 81: /* delete */
2120 if (print_job_delete(¤t_user
, snum
, jobid
, &werr
))
2121 errcode
= NERR_Success
;
2123 case 82: /* pause */
2124 if (print_job_pause(¤t_user
, snum
, jobid
, &werr
))
2125 errcode
= NERR_Success
;
2127 case 83: /* resume */
2128 if (print_job_resume(¤t_user
, snum
, jobid
, &werr
))
2129 errcode
= NERR_Success
;
2133 if (!W_ERROR_IS_OK(werr
))
2134 errcode
= W_ERROR_V(werr
);
2137 SSVAL(*rparam
,0,errcode
);
2138 SSVAL(*rparam
,2,0); /* converter word */
2143 /****************************************************************************
2144 Purge a print queue - or pause or resume it.
2145 ****************************************************************************/
2146 static BOOL
api_WPrintQueueCtrl(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
2147 int mdrcnt
,int mprcnt
,
2148 char **rdata
,char **rparam
,
2149 int *rdata_len
,int *rparam_len
)
2151 int function
= SVAL(param
,0);
2152 char *str1
= param
+2;
2153 char *str2
= skip_string(str1
,1);
2154 char *QueueName
= skip_string(str2
,1);
2155 int errcode
= NERR_notsupported
;
2157 WERROR werr
= WERR_OK
;
2158 extern struct current_user current_user
;
2160 /* check it's a supported varient */
2161 if (!(strcsequal(str1
,"z") && strcsequal(str2
,"")))
2165 *rparam
= REALLOC(*rparam
,*rparam_len
);
2168 snum
= print_queue_snum(QueueName
);
2171 errcode
= NERR_JobNotFound
;
2176 case 74: /* Pause queue */
2177 if (print_queue_pause(¤t_user
, snum
, &werr
)) errcode
= NERR_Success
;
2179 case 75: /* Resume queue */
2180 if (print_queue_resume(¤t_user
, snum
, &werr
)) errcode
= NERR_Success
;
2182 case 103: /* Purge */
2183 if (print_queue_purge(¤t_user
, snum
, &werr
)) errcode
= NERR_Success
;
2187 if (!W_ERROR_IS_OK(werr
)) errcode
= W_ERROR_V(werr
);
2190 SSVAL(*rparam
,0,errcode
);
2191 SSVAL(*rparam
,2,0); /* converter word */
2197 /****************************************************************************
2198 set the property of a print job (undocumented?)
2199 ? function = 0xb -> set name of print job
2200 ? function = 0x6 -> move print job up/down
2201 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
2202 or <WWsTP> <WB21BB16B10zWWzDDz>
2203 ****************************************************************************/
2204 static int check_printjob_info(struct pack_desc
* desc
,
2205 int uLevel
, char* id
)
2207 desc
->subformat
= NULL
;
2209 case 0: desc
->format
= "W"; break;
2210 case 1: desc
->format
= "WB21BB16B10zWWzDDz"; break;
2211 case 2: desc
->format
= "WWzWWDDzz"; break;
2212 case 3: desc
->format
= "WWzWWDDzzzzzzzzzzlz"; break;
2213 case 4: desc
->format
= "WWzWWDDzzzzzDDDDDDD"; break;
2214 default: return False
;
2216 if (strcmp(desc
->format
,id
) != 0) return False
;
2220 static BOOL
api_PrintJobInfo(connection_struct
*conn
,uint16 vuid
,char *param
,char *data
,
2221 int mdrcnt
,int mprcnt
,
2222 char **rdata
,char **rparam
,
2223 int *rdata_len
,int *rparam_len
)
2225 struct pack_desc desc
;
2226 char *str1
= param
+2;
2227 char *str2
= skip_string(str1
,1);
2228 char *p
= skip_string(str2
,1);
2231 int uLevel
= SVAL(p
,2);
2232 int function
= SVAL(p
,4);
2235 if(!rap_to_pjobid(SVAL(p
,0),&snum
,&jobid
))
2238 *rparam
= REALLOC(*rparam
,*rparam_len
);
2242 /* check it's a supported varient */
2243 if ((strcmp(str1
,"WWsTP")) ||
2244 (!check_printjob_info(&desc
,uLevel
,str2
)))
2247 if (!print_job_exists(snum
, jobid
)) {
2248 errcode
=NERR_JobNotFound
;
2252 errcode
= NERR_notsupported
;
2256 /* change job place in the queue,
2257 data gives the new place */
2258 place
= SVAL(data
,0);
2259 if (print_job_set_place(snum
, jobid
, place
)) {
2260 errcode
=NERR_Success
;
2265 /* change print job name, data gives the name */
2266 if (print_job_set_name(snum
, jobid
, data
)) {
2267 errcode
=NERR_Success
;
2276 SSVALS(*rparam
,0,errcode
);
2277 SSVAL(*rparam
,2,0); /* converter word */
2283 /****************************************************************************
2284 get info about the server
2285 ****************************************************************************/
2286 static BOOL
api_RNetServerGetInfo(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
2287 int mdrcnt
,int mprcnt
,
2288 char **rdata
,char **rparam
,
2289 int *rdata_len
,int *rparam_len
)
2291 char *str1
= param
+2;
2292 char *str2
= skip_string(str1
,1);
2293 char *p
= skip_string(str2
,1);
2294 int uLevel
= SVAL(p
,0);
2298 DEBUG(4,("NetServerGetInfo level %d\n",uLevel
));
2300 /* check it's a supported varient */
2301 if (!prefix_ok(str1
,"WrLh")) return False
;
2304 if (strcmp(str2
,"B16") != 0) return False
;
2308 if (strcmp(str2
,"B16BBDz") != 0) return False
;
2312 if (strcmp(str2
,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")
2317 if (strcmp(str2
,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz")
2322 if (strcmp(str2
,"DN") != 0) return False
;
2326 if (strcmp(str2
,"B16BBDzWWzzz") != 0) return False
;
2329 default: return False
;
2332 *rdata_len
= mdrcnt
;
2333 *rdata
= REALLOC(*rdata
,*rdata_len
);
2336 p2
= p
+ struct_len
;
2338 srvstr_push(NULL
, p
,local_machine
,16,
2339 STR_ASCII
|STR_UPPER
|STR_TERMINATE
);
2344 struct srv_info_struct
*servers
=NULL
;
2347 uint32 servertype
= lp_default_server_announce();
2349 push_ascii(comment
,lp_serverstring(), MAX_SERVER_STRING_LENGTH
,STR_TERMINATE
);
2351 if ((count
=get_server_info(SV_TYPE_ALL
,&servers
,lp_workgroup()))>0) {
2352 for (i
=0;i
<count
;i
++) {
2353 if (strequal(servers
[i
].name
,local_machine
)) {
2354 servertype
= servers
[i
].type
;
2355 push_ascii(comment
,servers
[i
].comment
,sizeof(pstring
),STR_TERMINATE
);
2361 SCVAL(p
,0,lp_major_announce_version());
2362 SCVAL(p
,1,lp_minor_announce_version());
2363 SIVAL(p
,2,servertype
);
2365 if (mdrcnt
== struct_len
) {
2368 SIVAL(p
,6,PTR_DIFF(p2
,*rdata
));
2369 standard_sub_conn(conn
,comment
,sizeof(comment
));
2370 StrnCpy(p2
,comment
,MAX(mdrcnt
- struct_len
,0));
2371 p2
= skip_string(p2
,1);
2376 return False
; /* not yet implemented */
2379 *rdata_len
= PTR_DIFF(p2
,*rdata
);
2382 *rparam
= REALLOC(*rparam
,*rparam_len
);
2383 SSVAL(*rparam
,0,NERR_Success
);
2384 SSVAL(*rparam
,2,0); /* converter word */
2385 SSVAL(*rparam
,4,*rdata_len
);
2391 /****************************************************************************
2392 get info about the server
2393 ****************************************************************************/
2394 static BOOL
api_NetWkstaGetInfo(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
2395 int mdrcnt
,int mprcnt
,
2396 char **rdata
,char **rparam
,
2397 int *rdata_len
,int *rparam_len
)
2399 char *str1
= param
+2;
2400 char *str2
= skip_string(str1
,1);
2401 char *p
= skip_string(str2
,1);
2403 extern userdom_struct current_user_info
;
2404 int level
= SVAL(p
,0);
2406 DEBUG(4,("NetWkstaGetInfo level %d\n",level
));
2409 *rparam
= REALLOC(*rparam
,*rparam_len
);
2411 /* check it's a supported varient */
2412 if (!(level
==10 && strcsequal(str1
,"WrLh") && strcsequal(str2
,"zzzBBzz")))
2415 *rdata_len
= mdrcnt
+ 1024;
2416 *rdata
= REALLOC(*rdata
,*rdata_len
);
2418 SSVAL(*rparam
,0,NERR_Success
);
2419 SSVAL(*rparam
,2,0); /* converter word */
2425 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* host name */
2426 pstrcpy(p2
,local_machine
);
2428 p2
= skip_string(p2
,1);
2431 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
));
2432 pstrcpy(p2
,current_user_info
.smb_name
);
2433 p2
= skip_string(p2
,1);
2436 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* login domain */
2437 pstrcpy(p2
,lp_workgroup());
2439 p2
= skip_string(p2
,1);
2442 SCVAL(p
,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
2443 SCVAL(p
,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
2446 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
));
2447 pstrcpy(p2
,lp_workgroup()); /* don't know. login domain?? */
2448 p2
= skip_string(p2
,1);
2451 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* don't know */
2453 p2
= skip_string(p2
,1);
2456 *rdata_len
= PTR_DIFF(p2
,*rdata
);
2458 SSVAL(*rparam
,4,*rdata_len
);
2463 /****************************************************************************
2464 get info about a user
2466 struct user_info_11 {
2467 char usri11_name[21]; 0-20
2469 char *usri11_comment; 22-25
2470 char *usri11_usr_comment; 26-29
2471 unsigned short usri11_priv; 30-31
2472 unsigned long usri11_auth_flags; 32-35
2473 long usri11_password_age; 36-39
2474 char *usri11_homedir; 40-43
2475 char *usri11_parms; 44-47
2476 long usri11_last_logon; 48-51
2477 long usri11_last_logoff; 52-55
2478 unsigned short usri11_bad_pw_count; 56-57
2479 unsigned short usri11_num_logons; 58-59
2480 char *usri11_logon_server; 60-63
2481 unsigned short usri11_country_code; 64-65
2482 char *usri11_workstations; 66-69
2483 unsigned long usri11_max_storage; 70-73
2484 unsigned short usri11_units_per_week; 74-75
2485 unsigned char *usri11_logon_hours; 76-79
2486 unsigned short usri11_code_page; 80-81
2491 usri11_name specifies the user name for which information is retireved
2493 usri11_pad aligns the next data structure element to a word boundary
2495 usri11_comment is a null terminated ASCII comment
2497 usri11_user_comment is a null terminated ASCII comment about the user
2499 usri11_priv specifies the level of the privilege assigned to the user.
2500 The possible values are:
2502 Name Value Description
2503 USER_PRIV_GUEST 0 Guest privilege
2504 USER_PRIV_USER 1 User privilege
2505 USER_PRV_ADMIN 2 Administrator privilege
2507 usri11_auth_flags specifies the account operator privileges. The
2508 possible values are:
2510 Name Value Description
2511 AF_OP_PRINT 0 Print operator
2514 Leach, Naik [Page 28]
2518 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2521 AF_OP_COMM 1 Communications operator
2522 AF_OP_SERVER 2 Server operator
2523 AF_OP_ACCOUNTS 3 Accounts operator
2526 usri11_password_age specifies how many seconds have elapsed since the
2527 password was last changed.
2529 usri11_home_dir points to a null terminated ASCII string that contains
2530 the path name of the user's home directory.
2532 usri11_parms points to a null terminated ASCII string that is set
2533 aside for use by applications.
2535 usri11_last_logon specifies the time when the user last logged on.
2536 This value is stored as the number of seconds elapsed since
2537 00:00:00, January 1, 1970.
2539 usri11_last_logoff specifies the time when the user last logged off.
2540 This value is stored as the number of seconds elapsed since
2541 00:00:00, January 1, 1970. A value of 0 means the last logoff
2544 usri11_bad_pw_count specifies the number of incorrect passwords
2545 entered since the last successful logon.
2547 usri11_log1_num_logons specifies the number of times this user has
2548 logged on. A value of -1 means the number of logons is unknown.
2550 usri11_logon_server points to a null terminated ASCII string that
2551 contains the name of the server to which logon requests are sent.
2552 A null string indicates logon requests should be sent to the
2555 usri11_country_code specifies the country code for the user's language
2558 usri11_workstations points to a null terminated ASCII string that
2559 contains the names of workstations the user may log on from.
2560 There may be up to 8 workstations, with the names separated by
2561 commas. A null strings indicates there are no restrictions.
2563 usri11_max_storage specifies the maximum amount of disk space the user
2564 can occupy. A value of 0xffffffff indicates there are no
2567 usri11_units_per_week specifies the equal number of time units into
2568 which a week is divided. This value must be equal to 168.
2570 usri11_logon_hours points to a 21 byte (168 bits) string that
2571 specifies the time during which the user can log on. Each bit
2572 represents one unique hour in a week. The first bit (bit 0, word
2573 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
2577 Leach, Naik [Page 29]
2581 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2584 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
2585 are no restrictions.
2587 usri11_code_page specifies the code page for the user's language of
2590 All of the pointers in this data structure need to be treated
2591 specially. The pointer is a 32 bit pointer. The higher 16 bits need
2592 to be ignored. The converter word returned in the parameters section
2593 needs to be subtracted from the lower 16 bits to calculate an offset
2594 into the return buffer where this ASCII string resides.
2596 There is no auxiliary data in the response.
2598 ****************************************************************************/
2600 #define usri11_name 0
2601 #define usri11_pad 21
2602 #define usri11_comment 22
2603 #define usri11_usr_comment 26
2604 #define usri11_full_name 30
2605 #define usri11_priv 34
2606 #define usri11_auth_flags 36
2607 #define usri11_password_age 40
2608 #define usri11_homedir 44
2609 #define usri11_parms 48
2610 #define usri11_last_logon 52
2611 #define usri11_last_logoff 56
2612 #define usri11_bad_pw_count 60
2613 #define usri11_num_logons 62
2614 #define usri11_logon_server 64
2615 #define usri11_country_code 68
2616 #define usri11_workstations 70
2617 #define usri11_max_storage 74
2618 #define usri11_units_per_week 78
2619 #define usri11_logon_hours 80
2620 #define usri11_code_page 84
2621 #define usri11_end 86
2623 #define USER_PRIV_GUEST 0
2624 #define USER_PRIV_USER 1
2625 #define USER_PRIV_ADMIN 2
2627 #define AF_OP_PRINT 0
2628 #define AF_OP_COMM 1
2629 #define AF_OP_SERVER 2
2630 #define AF_OP_ACCOUNTS 3
2633 static BOOL
api_RNetUserGetInfo(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
2634 int mdrcnt
,int mprcnt
,
2635 char **rdata
,char **rparam
,
2636 int *rdata_len
,int *rparam_len
)
2638 char *str1
= param
+2;
2639 char *str2
= skip_string(str1
,1);
2640 char *UserName
= skip_string(str2
,1);
2641 char *p
= skip_string(UserName
,1);
2642 int uLevel
= SVAL(p
,0);
2644 const char *level_string
;
2646 /* get NIS home of a previously validated user - simeon */
2647 /* With share level security vuid will always be zero.
2648 Don't depend on vuser being non-null !!. JRA */
2649 user_struct
*vuser
= get_valid_user_struct(vuid
);
2651 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser
->uid
,
2652 vuser
->user
.unix_name
));
2655 *rparam
= REALLOC(*rparam
,*rparam_len
);
2657 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel
));
2659 /* check it's a supported variant */
2660 if (strcmp(str1
,"zWrLh") != 0) return False
;
2663 case 0: level_string
= "B21"; break;
2664 case 1: level_string
= "B21BB16DWzzWz"; break;
2665 case 2: level_string
= "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
2666 case 10: level_string
= "B21Bzzz"; break;
2667 case 11: level_string
= "B21BzzzWDDzzDDWWzWzDWb21W"; break;
2668 default: return False
;
2671 if (strcmp(level_string
,str2
) != 0) return False
;
2673 *rdata_len
= mdrcnt
+ 1024;
2674 *rdata
= REALLOC(*rdata
,*rdata_len
);
2676 SSVAL(*rparam
,0,NERR_Success
);
2677 SSVAL(*rparam
,2,0); /* converter word */
2680 p2
= p
+ usri11_end
;
2683 fstrcpy(p
+usri11_name
,UserName
); /* 21 bytes - user name */
2687 SCVAL(p
,usri11_pad
,0); /* padding - 1 byte */
2692 SIVAL(p
,usri11_comment
,PTR_DIFF(p2
,p
)); /* comment */
2693 pstrcpy(p2
,"Comment");
2694 p2
= skip_string(p2
,1);
2696 SIVAL(p
,usri11_usr_comment
,PTR_DIFF(p2
,p
)); /* user_comment */
2697 pstrcpy(p2
,"UserComment");
2698 p2
= skip_string(p2
,1);
2700 /* EEK! the cifsrap.txt doesn't have this in!!!! */
2701 SIVAL(p
,usri11_full_name
,PTR_DIFF(p2
,p
)); /* full name */
2702 pstrcpy(p2
,((vuser
!= NULL
) ? vuser
->user
.full_name
: UserName
));
2703 p2
= skip_string(p2
,1);
2706 if (uLevel
== 11) /* modelled after NTAS 3.51 reply */
2708 SSVAL(p
,usri11_priv
,conn
->admin_user
?USER_PRIV_ADMIN
:USER_PRIV_USER
);
2709 SIVAL(p
,usri11_auth_flags
,AF_OP_PRINT
); /* auth flags */
2710 SIVALS(p
,usri11_password_age
,-1); /* password age */
2711 SIVAL(p
,usri11_homedir
,PTR_DIFF(p2
,p
)); /* home dir */
2712 pstrcpy(p2
, vuser
&& vuser
->homedir
? vuser
->homedir
: "");
2713 p2
= skip_string(p2
,1);
2714 SIVAL(p
,usri11_parms
,PTR_DIFF(p2
,p
)); /* parms */
2716 p2
= skip_string(p2
,1);
2717 SIVAL(p
,usri11_last_logon
,0); /* last logon */
2718 SIVAL(p
,usri11_last_logoff
,0); /* last logoff */
2719 SSVALS(p
,usri11_bad_pw_count
,-1); /* bad pw counts */
2720 SSVALS(p
,usri11_num_logons
,-1); /* num logons */
2721 SIVAL(p
,usri11_logon_server
,PTR_DIFF(p2
,p
)); /* logon server */
2722 pstrcpy(p2
,"\\\\*");
2723 p2
= skip_string(p2
,1);
2724 SSVAL(p
,usri11_country_code
,0); /* country code */
2726 SIVAL(p
,usri11_workstations
,PTR_DIFF(p2
,p
)); /* workstations */
2728 p2
= skip_string(p2
,1);
2730 SIVALS(p
,usri11_max_storage
,-1); /* max storage */
2731 SSVAL(p
,usri11_units_per_week
,168); /* units per week */
2732 SIVAL(p
,usri11_logon_hours
,PTR_DIFF(p2
,p
)); /* logon hours */
2734 /* a simple way to get logon hours at all times. */
2736 SCVAL(p2
,21,0); /* fix zero termination */
2737 p2
= skip_string(p2
,1);
2739 SSVAL(p
,usri11_code_page
,0); /* code page */
2741 if (uLevel
== 1 || uLevel
== 2)
2743 memset(p
+22,' ',16); /* password */
2744 SIVALS(p
,38,-1); /* password age */
2746 conn
->admin_user
?USER_PRIV_ADMIN
:USER_PRIV_USER
);
2747 SIVAL(p
,44,PTR_DIFF(p2
,*rdata
)); /* home dir */
2748 pstrcpy(p2
, vuser
&& vuser
->homedir
? vuser
->homedir
: "");
2749 p2
= skip_string(p2
,1);
2750 SIVAL(p
,48,PTR_DIFF(p2
,*rdata
)); /* comment */
2752 SSVAL(p
,52,0); /* flags */
2753 SIVAL(p
,54,PTR_DIFF(p2
,*rdata
)); /* script_path */
2754 pstrcpy(p2
,vuser
&& vuser
->logon_script
? vuser
->logon_script
: "");
2755 p2
= skip_string(p2
,1);
2758 SIVAL(p
,60,0); /* auth_flags */
2759 SIVAL(p
,64,PTR_DIFF(p2
,*rdata
)); /* full_name */
2760 pstrcpy(p2
,((vuser
!= NULL
) ? vuser
->user
.full_name
: UserName
));
2761 p2
= skip_string(p2
,1);
2762 SIVAL(p
,68,0); /* urs_comment */
2763 SIVAL(p
,72,PTR_DIFF(p2
,*rdata
)); /* parms */
2765 p2
= skip_string(p2
,1);
2766 SIVAL(p
,76,0); /* workstations */
2767 SIVAL(p
,80,0); /* last_logon */
2768 SIVAL(p
,84,0); /* last_logoff */
2769 SIVALS(p
,88,-1); /* acct_expires */
2770 SIVALS(p
,92,-1); /* max_storage */
2771 SSVAL(p
,96,168); /* units_per_week */
2772 SIVAL(p
,98,PTR_DIFF(p2
,*rdata
)); /* logon_hours */
2775 SSVALS(p
,102,-1); /* bad_pw_count */
2776 SSVALS(p
,104,-1); /* num_logons */
2777 SIVAL(p
,106,PTR_DIFF(p2
,*rdata
)); /* logon_server */
2778 pstrcpy(p2
,"\\\\%L");
2779 standard_sub_conn(conn
, p2
,0);
2780 p2
= skip_string(p2
,1);
2781 SSVAL(p
,110,49); /* country_code */
2782 SSVAL(p
,112,860); /* code page */
2786 *rdata_len
= PTR_DIFF(p2
,*rdata
);
2788 SSVAL(*rparam
,4,*rdata_len
); /* is this right?? */
2793 static BOOL
api_WWkstaUserLogon(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
2794 int mdrcnt
,int mprcnt
,
2795 char **rdata
,char **rparam
,
2796 int *rdata_len
,int *rparam_len
)
2798 char *str1
= param
+2;
2799 char *str2
= skip_string(str1
,1);
2800 char *p
= skip_string(str2
,1);
2802 struct pack_desc desc
;
2804 /* With share level security vuid will always be zero.
2805 Don't depend on vuser being non-null !!. JRA */
2806 user_struct
*vuser
= get_valid_user_struct(vuid
);
2808 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser
->uid
,
2809 vuser
->user
.unix_name
));
2814 memset((char *)&desc
,'\0',sizeof(desc
));
2816 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel
,name
));
2818 /* check it's a supported varient */
2819 if (strcmp(str1
,"OOWb54WrLh") != 0) return False
;
2820 if (uLevel
!= 1 || strcmp(str2
,"WB21BWDWWDDDDDDDzzzD") != 0) return False
;
2821 if (mdrcnt
> 0) *rdata
= REALLOC(*rdata
,mdrcnt
);
2823 desc
.buflen
= mdrcnt
;
2824 desc
.subformat
= NULL
;
2827 if (init_package(&desc
,1,0))
2829 PACKI(&desc
,"W",0); /* code */
2830 PACKS(&desc
,"B21",name
); /* eff. name */
2831 PACKS(&desc
,"B",""); /* pad */
2833 conn
->admin_user
?USER_PRIV_ADMIN
:USER_PRIV_USER
);
2834 PACKI(&desc
,"D",0); /* auth flags XXX */
2835 PACKI(&desc
,"W",0); /* num logons */
2836 PACKI(&desc
,"W",0); /* bad pw count */
2837 PACKI(&desc
,"D",0); /* last logon */
2838 PACKI(&desc
,"D",-1); /* last logoff */
2839 PACKI(&desc
,"D",-1); /* logoff time */
2840 PACKI(&desc
,"D",-1); /* kickoff time */
2841 PACKI(&desc
,"D",0); /* password age */
2842 PACKI(&desc
,"D",0); /* password can change */
2843 PACKI(&desc
,"D",-1); /* password must change */
2846 fstrcpy(mypath
,"\\\\");
2847 fstrcat(mypath
,local_machine
);
2849 PACKS(&desc
,"z",mypath
); /* computer */
2851 PACKS(&desc
,"z",lp_workgroup());/* domain */
2853 PACKS(&desc
,"z", vuser
&& vuser
->logon_script
? vuser
->logon_script
:""); /* script path */
2855 PACKI(&desc
,"D",0x00000000); /* reserved */
2858 *rdata_len
= desc
.usedlen
;
2860 *rparam
= REALLOC(*rparam
,*rparam_len
);
2861 SSVALS(*rparam
,0,desc
.errcode
);
2863 SSVAL(*rparam
,4,desc
.neededlen
);
2865 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc
.errcode
));
2870 /****************************************************************************
2871 api_WAccessGetUserPerms
2872 ****************************************************************************/
2873 static BOOL
api_WAccessGetUserPerms(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
2874 int mdrcnt
,int mprcnt
,
2875 char **rdata
,char **rparam
,
2876 int *rdata_len
,int *rparam_len
)
2878 char *str1
= param
+2;
2879 char *str2
= skip_string(str1
,1);
2880 char *user
= skip_string(str2
,1);
2881 char *resource
= skip_string(user
,1);
2883 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user
,resource
));
2885 /* check it's a supported varient */
2886 if (strcmp(str1
,"zzh") != 0) return False
;
2887 if (strcmp(str2
,"") != 0) return False
;
2890 *rparam
= REALLOC(*rparam
,*rparam_len
);
2891 SSVALS(*rparam
,0,0); /* errorcode */
2892 SSVAL(*rparam
,2,0); /* converter word */
2893 SSVAL(*rparam
,4,0x7f); /* permission flags */
2898 /****************************************************************************
2899 api_WPrintJobEnumerate
2900 ****************************************************************************/
2901 static BOOL
api_WPrintJobGetInfo(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
2902 int mdrcnt
,int mprcnt
,
2903 char **rdata
,char **rparam
,
2904 int *rdata_len
,int *rparam_len
)
2906 char *str1
= param
+2;
2907 char *str2
= skip_string(str1
,1);
2908 char *p
= skip_string(str2
,1);
2914 struct pack_desc desc
;
2915 print_queue_struct
*queue
=NULL
;
2916 print_status_struct status
;
2921 memset((char *)&desc
,'\0',sizeof(desc
));
2922 memset((char *)&status
,'\0',sizeof(status
));
2924 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel
,SVAL(p
,0)));
2926 /* check it's a supported varient */
2927 if (strcmp(str1
,"WWrLh") != 0) return False
;
2928 if (!check_printjob_info(&desc
,uLevel
,str2
)) return False
;
2930 if(!rap_to_pjobid(SVAL(p
,0),&snum
,&jobid
))
2933 if (snum
< 0 || !VALID_SNUM(snum
)) return(False
);
2935 count
= print_queue_status(snum
,&queue
,&status
);
2936 for (i
= 0; i
< count
; i
++) {
2937 if (queue
[i
].job
== jobid
) break;
2941 *rdata
= REALLOC(*rdata
,mdrcnt
);
2943 desc
.buflen
= mdrcnt
;
2946 * Don't return data but need to get correct length
2947 * init_package will return wrong size if buflen=0
2949 desc
.buflen
= getlen(desc
.format
);
2950 desc
.base
= tmpdata
= (char *)malloc ( desc
.buflen
);
2953 if (init_package(&desc
,1,0)) {
2955 fill_printjob_info(conn
,snum
,uLevel
,&desc
,&queue
[i
],i
);
2956 *rdata_len
= desc
.usedlen
;
2959 desc
.errcode
= NERR_JobNotFound
;
2965 *rparam
= REALLOC(*rparam
,*rparam_len
);
2966 SSVALS(*rparam
,0,desc
.errcode
);
2968 SSVAL(*rparam
,4,desc
.neededlen
);
2973 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc
.errcode
));
2977 static BOOL
api_WPrintJobEnumerate(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
2978 int mdrcnt
,int mprcnt
,
2979 char **rdata
,char **rparam
,
2980 int *rdata_len
,int *rparam_len
)
2982 char *str1
= param
+2;
2983 char *str2
= skip_string(str1
,1);
2984 char *p
= skip_string(str2
,1);
2990 struct pack_desc desc
;
2991 print_queue_struct
*queue
=NULL
;
2992 print_status_struct status
;
2994 memset((char *)&desc
,'\0',sizeof(desc
));
2995 memset((char *)&status
,'\0',sizeof(status
));
2997 p
= skip_string(p
,1);
3000 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel
,name
));
3002 /* check it's a supported variant */
3003 if (strcmp(str1
,"zWrLeh") != 0) return False
;
3004 if (uLevel
> 2) return False
; /* defined only for uLevel 0,1,2 */
3005 if (!check_printjob_info(&desc
,uLevel
,str2
)) return False
;
3007 snum
= lp_servicenumber(name
);
3008 if (snum
< 0 && pcap_printername_ok(name
,NULL
)) {
3009 int pnum
= lp_servicenumber(PRINTERS_NAME
);
3011 lp_add_printer(name
,pnum
);
3012 snum
= lp_servicenumber(name
);
3016 if (snum
< 0 || !VALID_SNUM(snum
)) return(False
);
3018 count
= print_queue_status(snum
,&queue
,&status
);
3019 if (mdrcnt
> 0) *rdata
= REALLOC(*rdata
,mdrcnt
);
3021 desc
.buflen
= mdrcnt
;
3023 if (init_package(&desc
,count
,0)) {
3025 for (i
= 0; i
< count
; i
++) {
3026 fill_printjob_info(conn
,snum
,uLevel
,&desc
,&queue
[i
],i
);
3027 if (desc
.errcode
== NERR_Success
) succnt
= i
+1;
3031 *rdata_len
= desc
.usedlen
;
3034 *rparam
= REALLOC(*rparam
,*rparam_len
);
3035 SSVALS(*rparam
,0,desc
.errcode
);
3037 SSVAL(*rparam
,4,succnt
);
3038 SSVAL(*rparam
,6,count
);
3042 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc
.errcode
));
3046 static int check_printdest_info(struct pack_desc
* desc
,
3047 int uLevel
, char* id
)
3049 desc
->subformat
= NULL
;
3051 case 0: desc
->format
= "B9"; break;
3052 case 1: desc
->format
= "B9B21WWzW"; break;
3053 case 2: desc
->format
= "z"; break;
3054 case 3: desc
->format
= "zzzWWzzzWW"; break;
3055 default: return False
;
3057 if (strcmp(desc
->format
,id
) != 0) return False
;
3061 static void fill_printdest_info(connection_struct
*conn
, int snum
, int uLevel
,
3062 struct pack_desc
* desc
)
3065 strncpy(buf
,SERVICE(snum
),sizeof(buf
)-1);
3066 buf
[sizeof(buf
)-1] = 0;
3069 PACKS(desc
,"B9",buf
); /* szName */
3071 PACKS(desc
,"B21",""); /* szUserName */
3072 PACKI(desc
,"W",0); /* uJobId */
3073 PACKI(desc
,"W",0); /* fsStatus */
3074 PACKS(desc
,"z",""); /* pszStatus */
3075 PACKI(desc
,"W",0); /* time */
3078 if (uLevel
== 2 || uLevel
== 3) {
3079 PACKS(desc
,"z",buf
); /* pszPrinterName */
3081 PACKS(desc
,"z",""); /* pszUserName */
3082 PACKS(desc
,"z",""); /* pszLogAddr */
3083 PACKI(desc
,"W",0); /* uJobId */
3084 PACKI(desc
,"W",0); /* fsStatus */
3085 PACKS(desc
,"z",""); /* pszStatus */
3086 PACKS(desc
,"z",""); /* pszComment */
3087 PACKS(desc
,"z","NULL"); /* pszDrivers */
3088 PACKI(desc
,"W",0); /* time */
3089 PACKI(desc
,"W",0); /* pad1 */
3094 static BOOL
api_WPrintDestGetInfo(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
3095 int mdrcnt
,int mprcnt
,
3096 char **rdata
,char **rparam
,
3097 int *rdata_len
,int *rparam_len
)
3099 char *str1
= param
+2;
3100 char *str2
= skip_string(str1
,1);
3101 char *p
= skip_string(str2
,1);
3102 char* PrinterName
= p
;
3104 struct pack_desc desc
;
3108 memset((char *)&desc
,'\0',sizeof(desc
));
3110 p
= skip_string(p
,1);
3113 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel
,PrinterName
));
3115 /* check it's a supported varient */
3116 if (strcmp(str1
,"zWrLh") != 0) return False
;
3117 if (!check_printdest_info(&desc
,uLevel
,str2
)) return False
;
3119 snum
= lp_servicenumber(PrinterName
);
3120 if (snum
< 0 && pcap_printername_ok(PrinterName
,NULL
)) {
3121 int pnum
= lp_servicenumber(PRINTERS_NAME
);
3123 lp_add_printer(PrinterName
,pnum
);
3124 snum
= lp_servicenumber(PrinterName
);
3130 desc
.errcode
= NERR_DestNotFound
;
3135 *rdata
= REALLOC(*rdata
,mdrcnt
);
3137 desc
.buflen
= mdrcnt
;
3140 * Don't return data but need to get correct length
3141 * init_package will return wrong size if buflen=0
3143 desc
.buflen
= getlen(desc
.format
);
3144 desc
.base
= tmpdata
= (char *)malloc ( desc
.buflen
);
3146 if (init_package(&desc
,1,0)) {
3147 fill_printdest_info(conn
,snum
,uLevel
,&desc
);
3149 *rdata_len
= desc
.usedlen
;
3153 *rparam
= REALLOC(*rparam
,*rparam_len
);
3154 SSVALS(*rparam
,0,desc
.errcode
);
3156 SSVAL(*rparam
,4,desc
.neededlen
);
3158 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc
.errcode
));
3163 static BOOL
api_WPrintDestEnum(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
3164 int mdrcnt
,int mprcnt
,
3165 char **rdata
,char **rparam
,
3166 int *rdata_len
,int *rparam_len
)
3168 char *str1
= param
+2;
3169 char *str2
= skip_string(str1
,1);
3170 char *p
= skip_string(str2
,1);
3174 struct pack_desc desc
;
3175 int services
= lp_numservices();
3177 memset((char *)&desc
,'\0',sizeof(desc
));
3181 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel
));
3183 /* check it's a supported varient */
3184 if (strcmp(str1
,"WrLeh") != 0) return False
;
3185 if (!check_printdest_info(&desc
,uLevel
,str2
)) return False
;
3188 for (i
= 0; i
< services
; i
++)
3189 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
))
3192 if (mdrcnt
> 0) *rdata
= REALLOC(*rdata
,mdrcnt
);
3194 desc
.buflen
= mdrcnt
;
3195 if (init_package(&desc
,queuecnt
,0)) {
3198 for (i
= 0; i
< services
; i
++) {
3199 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
)) {
3200 fill_printdest_info(conn
,i
,uLevel
,&desc
);
3202 if (desc
.errcode
== NERR_Success
) succnt
= n
;
3207 *rdata_len
= desc
.usedlen
;
3210 *rparam
= REALLOC(*rparam
,*rparam_len
);
3211 SSVALS(*rparam
,0,desc
.errcode
);
3213 SSVAL(*rparam
,4,succnt
);
3214 SSVAL(*rparam
,6,queuecnt
);
3216 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc
.errcode
));
3220 static BOOL
api_WPrintDriverEnum(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
3221 int mdrcnt
,int mprcnt
,
3222 char **rdata
,char **rparam
,
3223 int *rdata_len
,int *rparam_len
)
3225 char *str1
= param
+2;
3226 char *str2
= skip_string(str1
,1);
3227 char *p
= skip_string(str2
,1);
3230 struct pack_desc desc
;
3232 memset((char *)&desc
,'\0',sizeof(desc
));
3236 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel
));
3238 /* check it's a supported varient */
3239 if (strcmp(str1
,"WrLeh") != 0) return False
;
3240 if (uLevel
!= 0 || strcmp(str2
,"B41") != 0) return False
;
3242 if (mdrcnt
> 0) *rdata
= REALLOC(*rdata
,mdrcnt
);
3244 desc
.buflen
= mdrcnt
;
3245 if (init_package(&desc
,1,0)) {
3246 PACKS(&desc
,"B41","NULL");
3249 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
3251 *rdata_len
= desc
.usedlen
;
3254 *rparam
= REALLOC(*rparam
,*rparam_len
);
3255 SSVALS(*rparam
,0,desc
.errcode
);
3257 SSVAL(*rparam
,4,succnt
);
3260 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc
.errcode
));
3264 static BOOL
api_WPrintQProcEnum(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
3265 int mdrcnt
,int mprcnt
,
3266 char **rdata
,char **rparam
,
3267 int *rdata_len
,int *rparam_len
)
3269 char *str1
= param
+2;
3270 char *str2
= skip_string(str1
,1);
3271 char *p
= skip_string(str2
,1);
3274 struct pack_desc desc
;
3276 memset((char *)&desc
,'\0',sizeof(desc
));
3280 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel
));
3282 /* check it's a supported varient */
3283 if (strcmp(str1
,"WrLeh") != 0) return False
;
3284 if (uLevel
!= 0 || strcmp(str2
,"B13") != 0) return False
;
3286 if (mdrcnt
> 0) *rdata
= REALLOC(*rdata
,mdrcnt
);
3288 desc
.buflen
= mdrcnt
;
3290 if (init_package(&desc
,1,0)) {
3291 PACKS(&desc
,"B13","lpd");
3294 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
3296 *rdata_len
= desc
.usedlen
;
3299 *rparam
= REALLOC(*rparam
,*rparam_len
);
3300 SSVALS(*rparam
,0,desc
.errcode
);
3302 SSVAL(*rparam
,4,succnt
);
3305 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc
.errcode
));
3309 static BOOL
api_WPrintPortEnum(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
3310 int mdrcnt
,int mprcnt
,
3311 char **rdata
,char **rparam
,
3312 int *rdata_len
,int *rparam_len
)
3314 char *str1
= param
+2;
3315 char *str2
= skip_string(str1
,1);
3316 char *p
= skip_string(str2
,1);
3319 struct pack_desc desc
;
3321 memset((char *)&desc
,'\0',sizeof(desc
));
3325 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel
));
3327 /* check it's a supported varient */
3328 if (strcmp(str1
,"WrLeh") != 0) return False
;
3329 if (uLevel
!= 0 || strcmp(str2
,"B9") != 0) return False
;
3331 if (mdrcnt
> 0) *rdata
= REALLOC(*rdata
,mdrcnt
);
3332 memset((char *)&desc
,'\0',sizeof(desc
));
3334 desc
.buflen
= mdrcnt
;
3336 if (init_package(&desc
,1,0)) {
3337 PACKS(&desc
,"B13","lp0");
3340 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
3342 *rdata_len
= desc
.usedlen
;
3345 *rparam
= REALLOC(*rparam
,*rparam_len
);
3346 SSVALS(*rparam
,0,desc
.errcode
);
3348 SSVAL(*rparam
,4,succnt
);
3351 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc
.errcode
));
3356 /****************************************************************************
3358 ****************************************************************************/
3359 static BOOL
api_RNetSessionEnum(connection_struct
*conn
,uint16 vuid
, char *param
, char *data
,
3360 int mdrcnt
,int mprcnt
,
3361 char **rdata
,char **rparam
,
3362 int *rdata_len
,int *rparam_len
)
3365 char *str1
= param
+2;
3366 char *str2
= skip_string(str1
,1);
3367 char *p
= skip_string(str2
,1);
3369 struct pack_desc desc
;
3370 struct sessionid
*session_list
;
3371 int i
, num_sessions
;
3373 memset((char *)&desc
,'\0',sizeof(desc
));
3377 DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel
));
3378 DEBUG(7,("RNetSessionEnum req string=%s\n",str1
));
3379 DEBUG(7,("RNetSessionEnum ret string=%s\n",str2
));
3381 /* check it's a supported varient */
3382 if (strcmp(str1
,RAP_NetSessionEnum_REQ
) != 0) return False
;
3383 if (uLevel
!= 2 || strcmp(str2
,RAP_SESSION_INFO_L2
) != 0) return False
;
3385 num_sessions
= list_sessions(&session_list
);
3387 if (mdrcnt
> 0) *rdata
= REALLOC(*rdata
,mdrcnt
);
3388 memset((char *)&desc
,'\0',sizeof(desc
));
3390 desc
.buflen
= mdrcnt
;
3392 if (!init_package(&desc
,num_sessions
,0)) {
3396 for(i
=0; i
<num_sessions
; i
++) {
3397 PACKS(&desc
, "z", session_list
[i
].remote_machine
);
3398 PACKS(&desc
, "z", session_list
[i
].username
);
3399 PACKI(&desc
, "W", 1); /* num conns */
3400 PACKI(&desc
, "W", 0); /* num opens */
3401 PACKI(&desc
, "W", 1); /* num users */
3402 PACKI(&desc
, "D", 0); /* session time */
3403 PACKI(&desc
, "D", 0); /* idle time */
3404 PACKI(&desc
, "D", 0); /* flags */
3405 PACKS(&desc
, "z", "Unknown Client"); /* client type string */
3408 *rdata_len
= desc
.usedlen
;
3411 *rparam
= REALLOC(*rparam
,*rparam_len
);
3412 SSVALS(*rparam
,0,desc
.errcode
);
3413 SSVAL(*rparam
,2,0); /* converter */
3414 SSVAL(*rparam
,4,num_sessions
); /* count */
3416 DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc
.errcode
));
3421 /****************************************************************************
3422 The buffer was too small
3423 ****************************************************************************/
3425 static BOOL
api_TooSmall(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
3426 int mdrcnt
,int mprcnt
,
3427 char **rdata
,char **rparam
,
3428 int *rdata_len
,int *rparam_len
)
3430 *rparam_len
= MIN(*rparam_len
,mprcnt
);
3431 *rparam
= REALLOC(*rparam
,*rparam_len
);
3435 SSVAL(*rparam
,0,NERR_BufTooSmall
);
3437 DEBUG(3,("Supplied buffer too small in API command\n"));
3443 /****************************************************************************
3444 The request is not supported
3445 ****************************************************************************/
3447 static BOOL
api_Unsupported(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
3448 int mdrcnt
,int mprcnt
,
3449 char **rdata
,char **rparam
,
3450 int *rdata_len
,int *rparam_len
)
3453 *rparam
= REALLOC(*rparam
,*rparam_len
);
3457 SSVAL(*rparam
,0,NERR_notsupported
);
3458 SSVAL(*rparam
,2,0); /* converter word */
3460 DEBUG(3,("Unsupported API command\n"));
3472 BOOL (*fn
)(connection_struct
*,uint16
,char *,char *,
3473 int,int,char **,char **,int *,int *);
3474 BOOL auth_user
; /* Deny anonymous access? */
3475 } api_commands
[] = {
3476 {"RNetShareEnum", RAP_WshareEnum
, api_RNetShareEnum
, True
},
3477 {"RNetShareGetInfo", RAP_WshareGetInfo
, api_RNetShareGetInfo
},
3478 {"RNetShareAdd", RAP_WshareAdd
, api_RNetShareAdd
},
3479 {"RNetSessionEnum", RAP_WsessionEnum
, api_RNetSessionEnum
, True
},
3480 {"RNetServerGetInfo", RAP_WserverGetInfo
, api_RNetServerGetInfo
},
3481 {"RNetGroupEnum", RAP_WGroupEnum
, api_RNetGroupEnum
, True
},
3482 {"RNetGroupGetUsers", RAP_WGroupGetUsers
, api_RNetGroupGetUsers
, True
},
3483 {"RNetUserEnum", RAP_WUserEnum
, api_RNetUserEnum
, True
},
3484 {"RNetUserGetInfo", RAP_WUserGetInfo
, api_RNetUserGetInfo
},
3485 {"NetUserGetGroups", RAP_WUserGetGroups
, api_NetUserGetGroups
},
3486 {"NetWkstaGetInfo", RAP_WWkstaGetInfo
, api_NetWkstaGetInfo
},
3487 {"DosPrintQEnum", RAP_WPrintQEnum
, api_DosPrintQEnum
, True
},
3488 {"DosPrintQGetInfo", RAP_WPrintQGetInfo
, api_DosPrintQGetInfo
},
3489 {"WPrintQueuePause", RAP_WPrintQPause
, api_WPrintQueueCtrl
},
3490 {"WPrintQueueResume", RAP_WPrintQContinue
, api_WPrintQueueCtrl
},
3491 {"WPrintJobEnumerate",RAP_WPrintJobEnum
, api_WPrintJobEnumerate
},
3492 {"WPrintJobGetInfo", RAP_WPrintJobGetInfo
, api_WPrintJobGetInfo
},
3493 {"RDosPrintJobDel", RAP_WPrintJobDel
, api_RDosPrintJobDel
},
3494 {"RDosPrintJobPause", RAP_WPrintJobPause
, api_RDosPrintJobDel
},
3495 {"RDosPrintJobResume",RAP_WPrintJobContinue
, api_RDosPrintJobDel
},
3496 {"WPrintDestEnum", RAP_WPrintDestEnum
, api_WPrintDestEnum
},
3497 {"WPrintDestGetInfo", RAP_WPrintDestGetInfo
, api_WPrintDestGetInfo
},
3498 {"NetRemoteTOD", RAP_NetRemoteTOD
, api_NetRemoteTOD
},
3499 {"WPrintQueuePurge", RAP_WPrintQPurge
, api_WPrintQueueCtrl
},
3500 {"NetServerEnum", RAP_NetServerEnum2
, api_RNetServerEnum
}, /* anon OK */
3501 {"WAccessGetUserPerms",RAP_WAccessGetUserPerms
,api_WAccessGetUserPerms
},
3502 {"SetUserPassword", RAP_WUserPasswordSet2
, api_SetUserPassword
},
3503 {"WWkstaUserLogon", RAP_WWkstaUserLogon
, api_WWkstaUserLogon
},
3504 {"PrintJobInfo", RAP_WPrintJobSetInfo
, api_PrintJobInfo
},
3505 {"WPrintDriverEnum", RAP_WPrintDriverEnum
, api_WPrintDriverEnum
},
3506 {"WPrintQProcEnum", RAP_WPrintQProcessorEnum
,api_WPrintQProcEnum
},
3507 {"WPrintPortEnum", RAP_WPrintPortEnum
, api_WPrintPortEnum
},
3508 {"SamOEMChangePassword",RAP_SamOEMChgPasswordUser2_P
,api_SamOEMChangePassword
}, /* anon OK */
3509 {NULL
, -1, api_Unsupported
}};
3511 /* The following RAP calls are not implemented by Samba:
3513 RAP_WFileEnum2 - anon not OK
3516 /****************************************************************************
3517 Handle remote api calls
3518 ****************************************************************************/
3520 int api_reply(connection_struct
*conn
,uint16 vuid
,char *outbuf
,char *data
,char *params
,
3521 int tdscnt
,int tpscnt
,int mdrcnt
,int mprcnt
)
3525 char *rparam
= NULL
;
3532 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
3536 api_command
= SVAL(params
,0);
3538 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
3541 skip_string(params
+2,1),
3542 tdscnt
,tpscnt
,mdrcnt
,mprcnt
));
3544 for (i
=0;api_commands
[i
].name
;i
++) {
3545 if (api_commands
[i
].id
== api_command
&& api_commands
[i
].fn
) {
3546 DEBUG(3,("Doing %s\n",api_commands
[i
].name
));
3551 /* Check whether this api call can be done anonymously */
3553 if (api_commands
[i
].auth_user
&& lp_restrict_anonymous()) {
3554 user_struct
*user
= get_valid_user_struct(vuid
);
3556 if (!user
|| user
->guest
)
3557 return ERROR_NT(NT_STATUS_ACCESS_DENIED
);
3560 rdata
= (char *)malloc(1024);
3562 memset(rdata
,'\0',1024);
3564 rparam
= (char *)malloc(1024);
3566 memset(rparam
,'\0',1024);
3568 if(!rdata
|| !rparam
) {
3569 DEBUG(0,("api_reply: malloc fail !\n"));
3573 reply
= api_commands
[i
].fn(conn
,vuid
,params
,data
,mdrcnt
,mprcnt
,
3574 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
3577 if (rdata_len
> mdrcnt
||
3578 rparam_len
> mprcnt
) {
3579 reply
= api_TooSmall(conn
,vuid
,params
,data
,mdrcnt
,mprcnt
,
3580 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
3583 /* if we get False back then it's actually unsupported */
3585 api_Unsupported(conn
,vuid
,params
,data
,mdrcnt
,mprcnt
,
3586 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
3588 send_trans_reply(outbuf
, rparam
, rparam_len
, rdata
, rdata_len
, False
);