2 Unix SMB/Netbios implementation.
4 Inter-process communication and named pipe handling
5 Copyright (C) Andrew Tridgell 1992-1998
8 Copyright (C) John H Terpstra 1995-1998
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 This file handles the named pipe and mailslot calls
26 in the SMBtrans protocol
37 extern int DEBUGLEVEL
;
40 extern fstring local_machine
;
41 extern fstring global_myworkgroup
;
43 #define NERR_Success 0
44 #define NERR_badpass 86
45 #define NERR_notsupported 50
47 #define NERR_BASE (2100)
48 #define NERR_BufTooSmall (NERR_BASE+23)
49 #define NERR_JobNotFound (NERR_BASE+51)
50 #define NERR_DestNotFound (NERR_BASE+52)
51 #define ERROR_INVALID_LEVEL 124
53 #define ACCESS_READ 0x01
54 #define ACCESS_WRITE 0x02
55 #define ACCESS_CREATE 0x04
57 #define SHPWLEN 8 /* share password length */
58 #define NNLEN 12 /* 8.3 net name length */
59 #define SNLEN 15 /* service name length */
60 #define QNLEN 12 /* queue name maximum length */
63 extern int smb_read_error
;
65 static BOOL
api_Unsupported(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
66 int mdrcnt
,int mprcnt
,
67 char **rdata
,char **rparam
,
68 int *rdata_len
,int *rparam_len
);
69 static BOOL
api_TooSmall(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
70 int mdrcnt
,int mprcnt
,
71 char **rdata
,char **rparam
,
72 int *rdata_len
,int *rparam_len
);
75 static int CopyExpanded(connection_struct
*conn
,
76 int snum
, char** dst
, char* src
, int* n
)
81 if (!src
|| !dst
|| !n
|| !(*dst
)) return(0);
83 StrnCpy(buf
,src
,sizeof(buf
)/2);
84 pstring_sub(buf
,"%S",lp_servicename(snum
));
85 standard_sub(conn
,buf
);
93 static int CopyAndAdvance(char** dst
, char* src
, int* n
)
96 if (!src
|| !dst
|| !n
|| !(*dst
)) return(0);
97 StrnCpy(*dst
,src
,*n
-1);
104 static int StrlenExpanded(connection_struct
*conn
, int snum
, char* s
)
108 StrnCpy(buf
,s
,sizeof(buf
)/2);
109 pstring_sub(buf
,"%S",lp_servicename(snum
));
110 standard_sub(conn
,buf
);
111 return strlen(buf
) + 1;
114 static char* Expand(connection_struct
*conn
, int snum
, char* s
)
117 if (!s
) return(NULL
);
118 StrnCpy(buf
,s
,sizeof(buf
)/2);
119 pstring_sub(buf
,"%S",lp_servicename(snum
));
120 standard_sub(conn
,buf
);
124 /*******************************************************************
125 check a API string for validity when we only need to check the prefix
126 ******************************************************************/
127 static BOOL
prefix_ok(char *str
,char *prefix
)
129 return(strncmp(str
,prefix
,strlen(prefix
)) == 0);
132 /*******************************************************************
133 copies parameters and data, as needed, into the smb buffer
135 *both* the data and params sections should be aligned. this
136 is fudged in the rpc pipes by
137 at present, only the data section is. this may be a possible
138 cause of some of the ipc problems being experienced. lkcl26dec97
140 ******************************************************************/
142 static void copy_trans_params_and_data(char *outbuf
, int align
,
143 char *rparam
, int param_offset
, int param_len
,
144 char *rdata
, int data_offset
, int data_len
)
146 char *copy_into
= smb_buf(outbuf
)+1;
154 DEBUG(5,("copy_trans_params_and_data: params[%d..%d] data[%d..%d]\n",
155 param_offset
, param_offset
+ param_len
,
156 data_offset
, data_offset
+ data_len
));
159 memcpy(copy_into
, &rparam
[param_offset
], param_len
);
161 copy_into
+= param_len
+ align
;
164 memcpy(copy_into
, &rdata
[data_offset
], data_len
);
167 /****************************************************************************
169 ****************************************************************************/
171 static void send_trans_reply(char *outbuf
,
172 char *rparam
, int rparam_len
,
173 char *rdata
, int rdata_len
,
174 BOOL buffer_too_large
)
176 int this_ldata
,this_lparam
;
177 int tot_data_sent
= 0;
178 int tot_param_sent
= 0;
181 int ldata
= rdata
? rdata_len
: 0;
182 int lparam
= rparam
? rparam_len
: 0;
184 if (buffer_too_large
)
185 DEBUG(5,("send_trans_reply: buffer %d too large\n", ldata
));
187 this_lparam
= MIN(lparam
,max_send
- 500); /* hack */
188 this_ldata
= MIN(ldata
,max_send
- (500+this_lparam
));
190 align
= ((this_lparam
)%4);
192 set_message(outbuf
,10,1+align
+this_ldata
+this_lparam
,True
);
194 if (buffer_too_large
)
196 /* issue a buffer size warning. on a DCE/RPC pipe, expect an SMBreadX... */
197 SIVAL(outbuf
, smb_flg2
, FLAGS2_32_BIT_ERROR_CODES
);
198 SIVAL(outbuf
, smb_rcls
, 0x80000000 | NT_STATUS_ACCESS_VIOLATION
);
201 copy_trans_params_and_data(outbuf
, align
,
202 rparam
, tot_param_sent
, this_lparam
,
203 rdata
, tot_data_sent
, this_ldata
);
205 SSVAL(outbuf
,smb_vwv0
,lparam
);
206 SSVAL(outbuf
,smb_vwv1
,ldata
);
207 SSVAL(outbuf
,smb_vwv3
,this_lparam
);
208 SSVAL(outbuf
,smb_vwv4
,smb_offset(smb_buf(outbuf
)+1,outbuf
));
209 SSVAL(outbuf
,smb_vwv5
,0);
210 SSVAL(outbuf
,smb_vwv6
,this_ldata
);
211 SSVAL(outbuf
,smb_vwv7
,smb_offset(smb_buf(outbuf
)+1+this_lparam
+align
,outbuf
));
212 SSVAL(outbuf
,smb_vwv8
,0);
213 SSVAL(outbuf
,smb_vwv9
,0);
216 send_smb(Client
,outbuf
);
218 tot_data_sent
= this_ldata
;
219 tot_param_sent
= this_lparam
;
221 while (tot_data_sent
< ldata
|| tot_param_sent
< lparam
)
223 this_lparam
= MIN(lparam
-tot_param_sent
, max_send
- 500); /* hack */
224 this_ldata
= MIN(ldata
-tot_data_sent
, max_send
- (500+this_lparam
));
232 align
= (this_lparam
%4);
234 set_message(outbuf
,10,1+this_ldata
+this_lparam
+align
,False
);
236 copy_trans_params_and_data(outbuf
, align
,
237 rparam
, tot_param_sent
, this_lparam
,
238 rdata
, tot_data_sent
, this_ldata
);
240 SSVAL(outbuf
,smb_vwv3
,this_lparam
);
241 SSVAL(outbuf
,smb_vwv4
,smb_offset(smb_buf(outbuf
)+1,outbuf
));
242 SSVAL(outbuf
,smb_vwv5
,tot_param_sent
);
243 SSVAL(outbuf
,smb_vwv6
,this_ldata
);
244 SSVAL(outbuf
,smb_vwv7
,smb_offset(smb_buf(outbuf
)+1+this_lparam
+align
,outbuf
));
245 SSVAL(outbuf
,smb_vwv8
,tot_data_sent
);
246 SSVAL(outbuf
,smb_vwv9
,0);
249 send_smb(Client
,outbuf
);
251 tot_data_sent
+= this_ldata
;
252 tot_param_sent
+= this_lparam
;
257 char* format
; /* formatstring for structure */
258 char* subformat
; /* subformat for structure */
259 char* base
; /* baseaddress of buffer */
260 int buflen
; /* remaining size for fixed part; on init: length of base */
261 int subcount
; /* count of substructures */
262 char* structbuf
; /* pointer into buffer for remaining fixed part */
263 int stringlen
; /* remaining size for variable part */
264 char* stringbuf
; /* pointer into buffer for remaining variable part */
265 int neededlen
; /* total needed size */
266 int usedlen
; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
267 char* curpos
; /* current position; pointer into format or subformat */
271 static int get_counter(char** p
)
274 if (!p
|| !(*p
)) return(1);
275 if (!isdigit((int)**p
)) return 1;
279 n
= 10 * n
+ (i
- '0');
286 static int getlen(char* p
)
292 case 'W': /* word (2 byte) */
295 case 'N': /* count of substructures (word) at end */
298 case 'D': /* double word (4 byte) */
299 case 'z': /* offset to zero terminated string (4 byte) */
300 case 'l': /* offset to user data (4 byte) */
303 case 'b': /* offset to data (with counter) (4 byte) */
307 case 'B': /* byte (with optional counter) */
308 n
+= get_counter(&p
);
315 static BOOL
init_package(struct pack_desc
* p
, int count
, int subcount
)
320 if (!p
->format
|| !p
->base
) return(False
);
322 i
= count
* getlen(p
->format
);
323 if (p
->subformat
) i
+= subcount
* getlen(p
->subformat
);
324 p
->structbuf
= p
->base
;
328 p
->curpos
= p
->format
;
332 p
->errcode
= ERRmoredata
;
335 p
->errcode
= NERR_Success
;
338 p
->stringbuf
= p
->base
+ i
;
340 return(p
->errcode
== NERR_Success
);
344 static int package(struct pack_desc
* p
, ...)
347 static int package(va_alist
)
353 int needed
=0, stringneeded
;
355 int is_string
=0, stringused
;
362 p
= va_arg(args
,struct pack_desc
*);
367 p
->curpos
= p
->format
;
369 p
->curpos
= p
->subformat
;
374 str
= va_arg(args
,char*);
375 SMB_ASSERT(strncmp(str
,p
->curpos
,strlen(str
)) == 0);
384 switch( *p
->curpos
++ ) {
385 case 'W': /* word (2 byte) */
387 temp
= va_arg(args
,int);
388 if (p
->buflen
>= needed
) SSVAL(p
->structbuf
,0,temp
);
390 case 'N': /* count of substructures (word) at end */
392 p
->subcount
= va_arg(args
,int);
393 if (p
->buflen
>= needed
) SSVAL(p
->structbuf
,0,p
->subcount
);
395 case 'D': /* double word (4 byte) */
397 temp
= va_arg(args
,int);
398 if (p
->buflen
>= needed
) SIVAL(p
->structbuf
,0,temp
);
400 case 'B': /* byte (with optional counter) */
401 needed
= get_counter(&p
->curpos
);
403 char *s
= va_arg(args
,char*);
404 if (p
->buflen
>= needed
) StrnCpy(p
->structbuf
,s
?s
:"",needed
-1);
407 case 'z': /* offset to zero terminated string (4 byte) */
408 str
= va_arg(args
,char*);
409 stringneeded
= (str
? strlen(str
)+1 : 0);
412 case 'l': /* offset to user data (4 byte) */
413 str
= va_arg(args
,char*);
414 stringneeded
= va_arg(args
,int);
417 case 'b': /* offset to data (with counter) (4 byte) */
418 str
= va_arg(args
,char*);
419 stringneeded
= get_counter(&p
->curpos
);
424 if (stringneeded
>= 0) {
426 if (p
->buflen
>= needed
) {
427 stringused
= stringneeded
;
428 if (stringused
> p
->stringlen
) {
429 stringused
= (is_string
? p
->stringlen
: 0);
430 if (p
->errcode
== NERR_Success
) p
->errcode
= ERRmoredata
;
433 SIVAL(p
->structbuf
,0,0);
435 SIVAL(p
->structbuf
,0,PTR_DIFF(p
->stringbuf
,p
->base
));
436 memcpy(p
->stringbuf
,str
?str
:"",stringused
);
437 if (is_string
) p
->stringbuf
[stringused
-1] = '\0';
438 p
->stringbuf
+= stringused
;
439 p
->stringlen
-= stringused
;
440 p
->usedlen
+= stringused
;
443 p
->neededlen
+= stringneeded
;
445 p
->neededlen
+= needed
;
446 if (p
->buflen
>= needed
) {
447 p
->structbuf
+= needed
;
449 p
->usedlen
+= needed
;
452 if (p
->errcode
== NERR_Success
) p
->errcode
= ERRmoredata
;
458 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
459 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
461 #define PACK(desc,t,v) package(desc,v)
462 #define PACKl(desc,t,v,l) package(desc,v,l)
465 static void PACKI(struct pack_desc
* desc
,char *t
,int v
)
470 static void PACKS(struct pack_desc
* desc
,char *t
,char *v
)
476 /****************************************************************************
478 ****************************************************************************/
480 static void PackDriverData(struct pack_desc
* desc
)
482 char drivdata
[4+4+32];
483 SIVAL(drivdata
,0,sizeof drivdata
); /* cb */
484 SIVAL(drivdata
,4,1000); /* lVersion */
485 memset(drivdata
+8,0,32); /* szDeviceName */
486 pstrcpy(drivdata
+8,"NULL");
487 PACKl(desc
,"l",drivdata
,sizeof drivdata
); /* pDriverData */
490 static int check_printq_info(struct pack_desc
* desc
,
491 int uLevel
, char *id1
, char *id2
)
493 desc
->subformat
= NULL
;
496 desc
->format
= "B13";
499 desc
->format
= "B13BWWWzzzzzWW";
502 desc
->format
= "B13BWWWzzzzzWN";
503 desc
->subformat
= "WB21BB16B10zWWzDDz";
506 desc
->format
= "zWWWWzzzzWWzzl";
509 desc
->format
= "zWWWWzzzzWNzzl";
510 desc
->subformat
= "WWzWWDDzz";
516 desc
->format
= "WzzzzzzzzN";
517 desc
->subformat
= "z";
519 default: return False
;
521 if (strcmp(desc
->format
,id1
) != 0) return False
;
522 if (desc
->subformat
&& strcmp(desc
->subformat
,id2
) != 0) return False
;
526 static void fill_printjob_info(connection_struct
*conn
, int snum
, int uLevel
,
527 struct pack_desc
* desc
,
528 print_queue_struct
* queue
, int n
)
530 time_t t
= queue
->time
;
532 /* the client expects localtime */
535 PACKI(desc
,"W",printjob_encode(snum
, queue
->job
)); /* uJobId */
537 PACKS(desc
,"B21",queue
->user
); /* szUserName */
538 PACKS(desc
,"B",""); /* pad */
539 PACKS(desc
,"B16",""); /* szNotifyName */
540 PACKS(desc
,"B10","PM_Q_RAW"); /* szDataType */
541 PACKS(desc
,"z",""); /* pszParms */
542 PACKI(desc
,"W",n
+1); /* uPosition */
543 PACKI(desc
,"W",queue
->status
); /* fsStatus */
544 PACKS(desc
,"z",""); /* pszStatus */
545 PACKI(desc
,"D",t
); /* ulSubmitted */
546 PACKI(desc
,"D",queue
->size
); /* ulSize */
547 PACKS(desc
,"z",queue
->file
); /* pszComment */
549 if (uLevel
== 2 || uLevel
== 3) {
550 PACKI(desc
,"W",queue
->priority
); /* uPriority */
551 PACKS(desc
,"z",queue
->user
); /* pszUserName */
552 PACKI(desc
,"W",n
+1); /* uPosition */
553 PACKI(desc
,"W",queue
->status
); /* fsStatus */
554 PACKI(desc
,"D",t
); /* ulSubmitted */
555 PACKI(desc
,"D",queue
->size
); /* ulSize */
556 PACKS(desc
,"z","Samba"); /* pszComment */
557 PACKS(desc
,"z",queue
->file
); /* pszDocument */
559 PACKS(desc
,"z",""); /* pszNotifyName */
560 PACKS(desc
,"z","PM_Q_RAW"); /* pszDataType */
561 PACKS(desc
,"z",""); /* pszParms */
562 PACKS(desc
,"z",""); /* pszStatus */
563 PACKS(desc
,"z",SERVICE(snum
)); /* pszQueue */
564 PACKS(desc
,"z","lpd"); /* pszQProcName */
565 PACKS(desc
,"z",""); /* pszQProcParms */
566 PACKS(desc
,"z","NULL"); /* pszDriverName */
567 PackDriverData(desc
); /* pDriverData */
568 PACKS(desc
,"z",""); /* pszPrinterName */
573 static void fill_printq_info(connection_struct
*conn
, int snum
, int uLevel
,
574 struct pack_desc
* desc
,
575 int count
, print_queue_struct
* queue
,
576 print_status_struct
* status
)
581 PACKS(desc
,"B13",SERVICE(snum
));
586 PACKS(desc
,"z",Expand(conn
,snum
,SERVICE(snum
)));
590 if (uLevel
== 1 || uLevel
== 2) {
591 PACKS(desc
,"B",""); /* alignment */
592 PACKI(desc
,"W",5); /* priority */
593 PACKI(desc
,"W",0); /* start time */
594 PACKI(desc
,"W",0); /* until time */
595 PACKS(desc
,"z",""); /* pSepFile */
596 PACKS(desc
,"z","lpd"); /* pPrProc */
597 PACKS(desc
,"z",SERVICE(snum
)); /* pDestinations */
598 PACKS(desc
,"z",""); /* pParms */
600 PACKS(desc
,"z","UNKNOWN PRINTER");
601 PACKI(desc
,"W",LPSTAT_ERROR
);
603 else if (!status
|| !status
->message
[0]) {
604 PACKS(desc
,"z",Expand(conn
,snum
,lp_comment(snum
)));
605 PACKI(desc
,"W",LPSTAT_OK
); /* status */
607 PACKS(desc
,"z",status
->message
);
608 PACKI(desc
,"W",status
->status
); /* status */
610 PACKI(desc
,(uLevel
== 1 ? "W" : "N"),count
);
612 if (uLevel
== 3 || uLevel
== 4) {
613 PACKI(desc
,"W",5); /* uPriority */
614 PACKI(desc
,"W",0); /* uStarttime */
615 PACKI(desc
,"W",0); /* uUntiltime */
616 PACKI(desc
,"W",5); /* pad1 */
617 PACKS(desc
,"z",""); /* pszSepFile */
618 PACKS(desc
,"z","WinPrint"); /* pszPrProc */
619 PACKS(desc
,"z",""); /* pszParms */
620 if (!status
|| !status
->message
[0]) {
621 PACKS(desc
,"z",Expand(conn
,snum
,lp_comment(snum
))); /* pszComment */
622 PACKI(desc
,"W",LPSTAT_OK
); /* fsStatus */
624 PACKS(desc
,"z",status
->message
); /* pszComment */
625 PACKI(desc
,"W",status
->status
); /* fsStatus */
627 PACKI(desc
,(uLevel
== 3 ? "W" : "N"),count
); /* cJobs */
628 PACKS(desc
,"z",SERVICE(snum
)); /* pszPrinters */
629 PACKS(desc
,"z",lp_printerdriver(snum
)); /* pszDriverName */
630 PackDriverData(desc
); /* pDriverData */
632 if (uLevel
== 2 || uLevel
== 4) {
634 for (i
=0;i
<count
;i
++)
635 fill_printjob_info(conn
,snum
,uLevel
== 2 ? 1 : 2,desc
,&queue
[i
],i
);
640 pstring tok
,driver
,datafile
,langmon
,helpfile
,datatype
;
645 pstrcpy(fname
,lp_driverfile());
646 f
=sys_fopen(fname
,"r");
648 DEBUG(3,("fill_printq_info: Can't open %s - %s\n",fname
,strerror(errno
)));
649 desc
->errcode
=NERR_notsupported
;
653 if((p
=(char *)malloc(8192*sizeof(char))) == NULL
) {
654 DEBUG(0,("fill_printq_info: malloc fail !\n"));
655 desc
->errcode
=NERR_notsupported
;
660 memset(p
, '\0',8192*sizeof(char));
663 /* lookup the long printer driver name in the file description */
664 while (f
&& !feof(f
) && !ok
)
666 p
= q
; /* reset string pointer */
669 if (next_token(&p
,tok
,":",sizeof(tok
)) &&
670 (strlen(lp_printerdriver(snum
)) == strlen(tok
)) &&
671 (!strncmp(tok
,lp_printerdriver(snum
),strlen(lp_printerdriver(snum
)))))
676 /* driver file name */
677 if (ok
&& !next_token(&p
,driver
,":",sizeof(driver
))) ok
= 0;
679 if (ok
&& !next_token(&p
,datafile
,":",sizeof(datafile
))) ok
= 0;
681 * for the next tokens - which may be empty - I have to check for empty
682 * tokens first because the next_token function will skip all empty
690 } else if (!next_token(&p
,helpfile
,":",sizeof(helpfile
))) ok
= 0;
694 /* language monitor */
698 } else if (!next_token(&p
,langmon
,":",sizeof(langmon
))) ok
= 0;
701 /* default data type */
702 if (ok
&& !next_token(&p
,datatype
,":",sizeof(datatype
))) ok
= 0;
705 PACKI(desc
,"W",0x0400); /* don't know */
706 PACKS(desc
,"z",lp_printerdriver(snum
)); /* long printer name */
707 PACKS(desc
,"z",driver
); /* Driverfile Name */
708 PACKS(desc
,"z",datafile
); /* Datafile name */
709 PACKS(desc
,"z",langmon
); /* language monitor */
710 PACKS(desc
,"z",lp_driverlocation(snum
)); /* share to retrieve files */
711 PACKS(desc
,"z",datatype
); /* default data type */
712 PACKS(desc
,"z",helpfile
); /* helpfile name */
713 PACKS(desc
,"z",driver
); /* driver name */
714 DEBUG(3,("Driver:%s:\n",driver
));
715 DEBUG(3,("Data File:%s:\n",datafile
));
716 DEBUG(3,("Language Monitor:%s:\n",langmon
));
717 DEBUG(3,("Data Type:%s:\n",datatype
));
718 DEBUG(3,("Help File:%s:\n",helpfile
));
719 PACKI(desc
,"N",count
); /* number of files to copy */
720 for (i
=0;i
<count
;i
++)
722 /* no need to check return value here - it was already tested in
723 * get_printerdrivernumber
725 next_token(&p
,tok
,",",sizeof(tok
));
726 PACKS(desc
,"z",tok
); /* driver files to copy */
727 DEBUG(3,("file:%s:\n",tok
));
730 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n",
731 SERVICE(snum
),count
));
733 DEBUG(3,("fill_printq_info: Can't supply driver files\n"));
734 desc
->errcode
=NERR_notsupported
;
740 /* This function returns the number of files for a given driver */
741 static int get_printerdrivernumber(int snum
)
749 pstrcpy(fname
,lp_driverfile());
751 DEBUG(4,("In get_printerdrivernumber: %s\n",fname
));
752 f
=sys_fopen(fname
,"r");
754 DEBUG(3,("get_printerdrivernumber: Can't open %s - %s\n",fname
,strerror(errno
)));
758 if((p
=(char *)malloc(8192*sizeof(char))) == NULL
) {
759 DEBUG(3,("get_printerdrivernumber: malloc fail !\n"));
764 q
=p
; /* need it to free memory because p change ! */
766 /* lookup the long printer driver name in the file description */
767 while (!feof(f
) && !ok
)
769 p
= q
; /* reset string pointer */
771 if (next_token(&p
,tok
,":",sizeof(tok
)) &&
772 (!strncmp(tok
,lp_printerdriver(snum
),strlen(lp_printerdriver(snum
)))))
781 if (*p
++ == ':') i
--;
786 /* count the number of files */
787 while (next_token(&p
,tok
,",",sizeof(tok
)))
795 static BOOL
api_DosPrintQGetInfo(connection_struct
*conn
,
796 uint16 vuid
, char *param
,char *data
,
797 int mdrcnt
,int mprcnt
,
798 char **rdata
,char **rparam
,
799 int *rdata_len
,int *rparam_len
)
801 char *str1
= param
+2;
802 char *str2
= skip_string(str1
,1);
803 char *p
= skip_string(str2
,1);
809 struct pack_desc desc
;
810 print_queue_struct
*queue
=NULL
;
811 print_status_struct status
;
813 memset((char *)&status
,'\0',sizeof(status
));
814 memset((char *)&desc
,'\0',sizeof(desc
));
816 p
= skip_string(p
,1);
820 /* remove any trailing username */
821 if ((p
= strchr(QueueName
,'%'))) *p
= 0;
823 DEBUG(3,("PrintQueue uLevel=%d name=%s\n",uLevel
,QueueName
));
825 /* check it's a supported varient */
826 if (!prefix_ok(str1
,"zWrLh")) return False
;
827 if (!check_printq_info(&desc
,uLevel
,str2
,str3
)) {
829 * Patch from Scott Moomaw <scott@bridgewater.edu>
830 * to return the 'invalid info level' error if an
831 * unknown level was requested.
835 *rparam
= REALLOC(*rparam
,*rparam_len
);
836 SSVALS(*rparam
,0,ERROR_INVALID_LEVEL
);
842 snum
= lp_servicenumber(QueueName
);
843 if (snum
< 0 && pcap_printername_ok(QueueName
,NULL
)) {
844 int pnum
= lp_servicenumber(PRINTERS_NAME
);
846 lp_add_printer(QueueName
,pnum
);
847 snum
= lp_servicenumber(QueueName
);
851 if (snum
< 0 || !VALID_SNUM(snum
)) return(False
);
854 count
= get_printerdrivernumber(snum
);
855 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count
));
857 count
= get_printqueue(snum
, conn
,&queue
,&status
);
860 if (mdrcnt
> 0) *rdata
= REALLOC(*rdata
,mdrcnt
);
862 desc
.buflen
= mdrcnt
;
863 if (init_package(&desc
,1,count
)) {
864 desc
.subcount
= count
;
865 fill_printq_info(conn
,snum
,uLevel
,&desc
,count
,queue
,&status
);
866 } else if(uLevel
== 0) {
868 * This is a *disgusting* hack.
869 * This is *so* bad that even I'm embarrassed (and I
870 * have no shame). Here's the deal :
871 * Until we get the correct SPOOLSS code into smbd
872 * then when we're running with NT SMB support then
873 * NT makes this call with a level of zero, and then
874 * immediately follows it with an open request to
875 * the \\SRVSVC pipe. If we allow that open to
876 * succeed then NT barfs when it cannot open the
877 * \\SPOOLSS pipe immediately after and continually
878 * whines saying "Printer name is invalid" forever
879 * after. If we cause *JUST THIS NEXT OPEN* of \\SRVSVC
880 * to fail, then NT downgrades to using the downlevel code
881 * and everything works as well as before. I hate
882 * myself for adding this code.... JRA.
885 fail_next_srvsvc_open();
888 *rdata_len
= desc
.usedlen
;
891 *rparam
= REALLOC(*rparam
,*rparam_len
);
892 SSVALS(*rparam
,0,desc
.errcode
);
894 SSVAL(*rparam
,4,desc
.neededlen
);
896 DEBUG(4,("printqgetinfo: errorcode %d\n",desc
.errcode
));
898 if (queue
) free(queue
);
904 /****************************************************************************
905 view list of all print jobs on all queues
906 ****************************************************************************/
907 static BOOL
api_DosPrintQEnum(connection_struct
*conn
, uint16 vuid
, char* param
, char* data
,
908 int mdrcnt
, int mprcnt
,
909 char **rdata
, char** rparam
,
910 int *rdata_len
, int *rparam_len
)
912 char *param_format
= param
+2;
913 char *output_format1
= skip_string(param_format
,1);
914 char *p
= skip_string(output_format1
,1);
915 int uLevel
= SVAL(p
,0);
916 char *output_format2
= p
+ 4;
917 int services
= lp_numservices();
919 struct pack_desc desc
;
920 print_queue_struct
**queue
= NULL
;
921 print_status_struct
*status
= NULL
;
922 int* subcntarr
= NULL
;
923 int queuecnt
, subcnt
=0, succnt
=0;
925 memset((char *)&desc
,'\0',sizeof(desc
));
927 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel
));
929 if (!prefix_ok(param_format
,"WrLeh")) return False
;
930 if (!check_printq_info(&desc
,uLevel
,output_format1
,output_format2
)) {
932 * Patch from Scott Moomaw <scott@bridgewater.edu>
933 * to return the 'invalid info level' error if an
934 * unknown level was requested.
938 *rparam
= REALLOC(*rparam
,*rparam_len
);
939 SSVALS(*rparam
,0,ERROR_INVALID_LEVEL
);
946 for (i
= 0; i
< services
; i
++)
947 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
))
950 if((queue
= (print_queue_struct
**)malloc(queuecnt
*sizeof(print_queue_struct
*))) == NULL
) {
951 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
954 memset(queue
,0,queuecnt
*sizeof(print_queue_struct
*));
955 if((status
= (print_status_struct
*)malloc(queuecnt
*sizeof(print_status_struct
))) == NULL
) {
956 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
959 memset(status
,0,queuecnt
*sizeof(print_status_struct
));
960 if((subcntarr
= (int*)malloc(queuecnt
*sizeof(int))) == NULL
) {
961 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
966 for (i
= 0; i
< services
; i
++)
967 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
)) {
968 subcntarr
[n
] = get_printqueue(i
, conn
,&queue
[n
],&status
[n
]);
969 subcnt
+= subcntarr
[n
];
973 if (mdrcnt
> 0) *rdata
= REALLOC(*rdata
,mdrcnt
);
975 desc
.buflen
= mdrcnt
;
977 if (init_package(&desc
,queuecnt
,subcnt
)) {
980 for (i
= 0; i
< services
; i
++)
981 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
)) {
982 fill_printq_info(conn
,i
,uLevel
,&desc
,subcntarr
[n
],queue
[n
],&status
[n
]);
984 if (desc
.errcode
== NERR_Success
) succnt
= n
;
988 if (subcntarr
) free(subcntarr
);
990 *rdata_len
= desc
.usedlen
;
992 *rparam
= REALLOC(*rparam
,*rparam_len
);
993 SSVALS(*rparam
,0,desc
.errcode
);
995 SSVAL(*rparam
,4,succnt
);
996 SSVAL(*rparam
,6,queuecnt
);
998 for (i
= 0; i
< queuecnt
; i
++) {
999 if (queue
&& queue
[i
]) free(queue
[i
]);
1002 if (queue
) free(queue
);
1003 if (status
) free(status
);
1008 /****************************************************************************
1009 get info level for a server list query
1010 ****************************************************************************/
1011 static BOOL
check_server_info(int uLevel
, char* id
)
1015 if (strcmp(id
,"B16") != 0) return False
;
1018 if (strcmp(id
,"B16BBDz") != 0) return False
;
1026 struct srv_info_struct
1036 /*******************************************************************
1037 get server info lists from the files saved by nmbd. Return the
1039 ******************************************************************/
1040 static int get_server_info(uint32 servertype
,
1041 struct srv_info_struct
**servers
,
1049 BOOL local_list_only
;
1051 pstrcpy(fname
,lp_lockdir());
1052 trim_string(fname
,NULL
,"/");
1054 pstrcat(fname
,SERVER_LIST
);
1056 f
= sys_fopen(fname
,"r");
1059 DEBUG(4,("Can't open %s - %s\n",fname
,strerror(errno
)));
1063 /* request for everything is code for request all servers */
1064 if (servertype
== SV_TYPE_ALL
)
1065 servertype
&= ~(SV_TYPE_DOMAIN_ENUM
|SV_TYPE_LOCAL_LIST_ONLY
);
1067 local_list_only
= (servertype
& SV_TYPE_LOCAL_LIST_ONLY
);
1069 DEBUG(4,("Servertype search: %8x\n",servertype
));
1074 struct srv_info_struct
*s
;
1079 fgets(line
,sizeof(line
)-1,f
);
1080 if (!*line
) continue;
1082 if (count
== alloced
) {
1084 (*servers
) = (struct srv_info_struct
*)
1085 Realloc(*servers
,sizeof(**servers
)*alloced
);
1086 if (!(*servers
)) return(0);
1087 memset((char *)((*servers
)+count
),'\0',sizeof(**servers
)*(alloced
-count
));
1089 s
= &(*servers
)[count
];
1091 if (!next_token(&ptr
,s
->name
, NULL
, sizeof(s
->name
))) continue;
1092 if (!next_token(&ptr
,stype
, NULL
, sizeof(stype
))) continue;
1093 if (!next_token(&ptr
,s
->comment
, NULL
, sizeof(s
->comment
))) continue;
1094 if (!next_token(&ptr
,s
->domain
, NULL
, sizeof(s
->domain
))) {
1095 /* this allows us to cope with an old nmbd */
1096 pstrcpy(s
->domain
,global_myworkgroup
);
1099 if (sscanf(stype
,"%X",&s
->type
) != 1) {
1100 DEBUG(4,("r:host file "));
1104 /* Filter the servers/domains we return based on what was asked for. */
1106 /* Check to see if we are being asked for a local list only. */
1107 if(local_list_only
&& ((s
->type
& SV_TYPE_LOCAL_LIST_ONLY
) == 0)) {
1108 DEBUG(4,("r: local list only"));
1112 /* doesn't match up: don't want it */
1113 if (!(servertype
& s
->type
)) {
1114 DEBUG(4,("r:serv type "));
1118 if ((servertype
& SV_TYPE_DOMAIN_ENUM
) !=
1119 (s
->type
& SV_TYPE_DOMAIN_ENUM
))
1121 DEBUG(4,("s: dom mismatch "));
1125 if (!strequal(domain
, s
->domain
) && !(servertype
& SV_TYPE_DOMAIN_ENUM
))
1130 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1131 s
->type
&= ~SV_TYPE_LOCAL_LIST_ONLY
;
1135 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1136 s
->name
, s
->type
, s
->comment
, s
->domain
));
1138 s
->server_added
= True
;
1143 DEBUG(4,("%20s %8x %25s %15s\n",
1144 s
->name
, s
->type
, s
->comment
, s
->domain
));
1153 /*******************************************************************
1154 fill in a server info structure
1155 ******************************************************************/
1156 static int fill_srv_info(struct srv_info_struct
*service
,
1157 int uLevel
, char **buf
, int *buflen
,
1158 char **stringbuf
, int *stringspace
, char *baseaddr
)
1167 case 0: struct_len
= 16; break;
1168 case 1: struct_len
= 26; break;
1178 len
= strlen(service
->comment
)+1;
1182 if (buflen
) *buflen
= struct_len
;
1183 if (stringspace
) *stringspace
= len
;
1184 return struct_len
+ len
;
1189 if (*buflen
< struct_len
) return -1;
1197 p2
= p
+ struct_len
;
1198 l2
= *buflen
- struct_len
;
1200 if (!baseaddr
) baseaddr
= p
;
1205 StrnCpy(p
,service
->name
,15);
1209 StrnCpy(p
,service
->name
,15);
1210 SIVAL(p
,18,service
->type
);
1211 SIVAL(p
,22,PTR_DIFF(p2
,baseaddr
));
1212 len
+= CopyAndAdvance(&p2
,service
->comment
,&l2
);
1218 *buf
= p
+ struct_len
;
1219 *buflen
-= struct_len
;
1232 static BOOL
srv_comp(struct srv_info_struct
*s1
,struct srv_info_struct
*s2
)
1234 return(strcmp(s1
->name
,s2
->name
));
1237 /****************************************************************************
1238 view list of servers available (or possibly domains). The info is
1239 extracted from lists saved by nmbd on the local host
1240 ****************************************************************************/
1241 static BOOL
api_RNetServerEnum(connection_struct
*conn
, uint16 vuid
, char *param
, char *data
,
1242 int mdrcnt
, int mprcnt
, char **rdata
,
1243 char **rparam
, int *rdata_len
, int *rparam_len
)
1245 char *str1
= param
+2;
1246 char *str2
= skip_string(str1
,1);
1247 char *p
= skip_string(str2
,1);
1248 int uLevel
= SVAL(p
,0);
1249 int buf_len
= SVAL(p
,2);
1250 uint32 servertype
= IVAL(p
,4);
1252 int data_len
, fixed_len
, string_len
;
1253 int f_len
= 0, s_len
= 0;
1254 struct srv_info_struct
*servers
=NULL
;
1255 int counted
=0,total
=0;
1258 BOOL domain_request
;
1261 /* If someone sets all the bits they don't really mean to set
1262 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1265 if (servertype
== SV_TYPE_ALL
)
1266 servertype
&= ~(SV_TYPE_DOMAIN_ENUM
|SV_TYPE_LOCAL_LIST_ONLY
);
1268 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1269 any other bit (they may just set this bit on it's own) they
1270 want all the locally seen servers. However this bit can be
1271 set on its own so set the requested servers to be
1272 ALL - DOMAIN_ENUM. */
1274 if ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) && !(servertype
& SV_TYPE_DOMAIN_ENUM
))
1275 servertype
= SV_TYPE_ALL
& ~(SV_TYPE_DOMAIN_ENUM
);
1277 domain_request
= ((servertype
& SV_TYPE_DOMAIN_ENUM
) != 0);
1278 local_request
= ((servertype
& SV_TYPE_LOCAL_LIST_ONLY
) != 0);
1282 if (!prefix_ok(str1
,"WrLehD")) return False
;
1283 if (!check_server_info(uLevel
,str2
)) return False
;
1285 DEBUG(4, ("server request level: %s %8x ", str2
, servertype
));
1286 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request
)));
1287 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request
)));
1289 if (strcmp(str1
, "WrLehDz") == 0) {
1290 StrnCpy(domain
, p
, sizeof(fstring
)-1);
1292 StrnCpy(domain
, global_myworkgroup
, sizeof(fstring
)-1);
1295 if (lp_browse_list())
1296 total
= get_server_info(servertype
,&servers
,domain
);
1298 data_len
= fixed_len
= string_len
= 0;
1301 qsort(servers
,total
,sizeof(servers
[0]),QSORT_CAST srv_comp
);
1304 char *lastname
=NULL
;
1306 for (i
=0;i
<total
;i
++)
1308 struct srv_info_struct
*s
= &servers
[i
];
1309 if (lastname
&& strequal(lastname
,s
->name
)) continue;
1311 data_len
+= fill_srv_info(s
,uLevel
,0,&f_len
,0,&s_len
,0);
1312 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1313 s
->name
, s
->type
, s
->comment
, s
->domain
));
1315 if (data_len
<= buf_len
) {
1318 string_len
+= s_len
;
1325 *rdata_len
= fixed_len
+ string_len
;
1326 *rdata
= REALLOC(*rdata
,*rdata_len
);
1327 memset(*rdata
,'\0',*rdata_len
);
1329 p2
= (*rdata
) + fixed_len
; /* auxilliary data (strings) will go here */
1335 char *lastname
=NULL
;
1336 int count2
= counted
;
1337 for (i
= 0; i
< total
&& count2
;i
++)
1339 struct srv_info_struct
*s
= &servers
[i
];
1340 if (lastname
&& strequal(lastname
,s
->name
)) continue;
1342 fill_srv_info(s
,uLevel
,&p
,&f_len
,&p2
,&s_len
,*rdata
);
1343 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1344 s
->name
, s
->type
, s
->comment
, s
->domain
));
1350 *rparam
= REALLOC(*rparam
,*rparam_len
);
1351 SSVAL(*rparam
,0,(missed
== 0 ? NERR_Success
: ERRmoredata
));
1353 SSVAL(*rparam
,4,counted
);
1354 SSVAL(*rparam
,6,counted
+missed
);
1356 if (servers
) free(servers
);
1358 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1359 domain
,uLevel
,counted
,counted
+missed
));
1364 /****************************************************************************
1365 command 0x34 - suspected of being a "Lookup Names" stub api
1366 ****************************************************************************/
1367 static BOOL
api_RNetGroupGetUsers(connection_struct
*conn
, uint16 vuid
, char *param
, char *data
,
1368 int mdrcnt
, int mprcnt
, char **rdata
,
1369 char **rparam
, int *rdata_len
, int *rparam_len
)
1371 char *str1
= param
+2;
1372 char *str2
= skip_string(str1
,1);
1373 char *p
= skip_string(str2
,1);
1374 int uLevel
= SVAL(p
,0);
1375 int buf_len
= SVAL(p
,2);
1379 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1380 str1
, str2
, p
, uLevel
, buf_len
));
1382 if (!prefix_ok(str1
,"zWrLeh")) return False
;
1387 *rparam
= REALLOC(*rparam
,*rparam_len
);
1389 SSVAL(*rparam
,0,0x08AC); /* informational warning message */
1391 SSVAL(*rparam
,4,counted
);
1392 SSVAL(*rparam
,6,counted
+missed
);
1397 /****************************************************************************
1398 get info about a share
1399 ****************************************************************************/
1400 static BOOL
check_share_info(int uLevel
, char* id
)
1404 if (strcmp(id
,"B13") != 0) return False
;
1407 if (strcmp(id
,"B13BWz") != 0) return False
;
1410 if (strcmp(id
,"B13BWzWWWzB9B") != 0) return False
;
1413 if (strcmp(id
,"B13BWzWWWzB9BB9BWzWWzWW") != 0) return False
;
1415 default: return False
;
1420 static int fill_share_info(connection_struct
*conn
, int snum
, int uLevel
,
1421 char** buf
, int* buflen
,
1422 char** stringbuf
, int* stringspace
, char* baseaddr
)
1431 case 0: struct_len
= 13; break;
1432 case 1: struct_len
= 20; break;
1433 case 2: struct_len
= 40; break;
1434 case 91: struct_len
= 68; break;
1442 if (uLevel
> 0) len
+= StrlenExpanded(conn
,snum
,lp_comment(snum
));
1443 if (uLevel
> 1) len
+= strlen(lp_pathname(snum
)) + 1;
1444 if (buflen
) *buflen
= struct_len
;
1445 if (stringspace
) *stringspace
= len
;
1446 return struct_len
+ len
;
1451 if ((*buflen
) < struct_len
) return -1;
1459 p2
= p
+ struct_len
;
1460 l2
= (*buflen
) - struct_len
;
1462 if (!baseaddr
) baseaddr
= p
;
1464 StrnCpy(p
,lp_servicename(snum
),13);
1470 type
= STYPE_DISKTREE
;
1471 if (lp_print_ok(snum
)) type
= STYPE_PRINTQ
;
1472 if (strequal("IPC$",lp_servicename(snum
))) type
= STYPE_IPC
;
1473 SSVAL(p
,14,type
); /* device type */
1474 SIVAL(p
,16,PTR_DIFF(p2
,baseaddr
));
1475 len
+= CopyExpanded(conn
,snum
,&p2
,lp_comment(snum
),&l2
);
1480 SSVAL(p
,20,ACCESS_READ
|ACCESS_WRITE
|ACCESS_CREATE
); /* permissions */
1481 SSVALS(p
,22,-1); /* max uses */
1482 SSVAL(p
,24,1); /* current uses */
1483 SIVAL(p
,26,PTR_DIFF(p2
,baseaddr
)); /* local pathname */
1484 len
+= CopyAndAdvance(&p2
,lp_pathname(snum
),&l2
);
1485 memset(p
+30,0,SHPWLEN
+2); /* passwd (reserved), pad field */
1490 memset(p
+40,0,SHPWLEN
+2);
1502 (*buf
) = p
+ struct_len
;
1503 (*buflen
) -= struct_len
;
1505 (*stringspace
) = l2
;
1515 static BOOL
api_RNetShareGetInfo(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
1516 int mdrcnt
,int mprcnt
,
1517 char **rdata
,char **rparam
,
1518 int *rdata_len
,int *rparam_len
)
1520 char *str1
= param
+2;
1521 char *str2
= skip_string(str1
,1);
1522 char *netname
= skip_string(str2
,1);
1523 char *p
= skip_string(netname
,1);
1524 int uLevel
= SVAL(p
,0);
1525 int snum
= find_service(netname
);
1527 if (snum
< 0) return False
;
1529 /* check it's a supported varient */
1530 if (!prefix_ok(str1
,"zWrLh")) return False
;
1531 if (!check_share_info(uLevel
,str2
)) return False
;
1533 *rdata
= REALLOC(*rdata
,mdrcnt
);
1535 *rdata_len
= fill_share_info(conn
,snum
,uLevel
,&p
,&mdrcnt
,0,0,0);
1536 if (*rdata_len
< 0) return False
;
1539 *rparam
= REALLOC(*rparam
,*rparam_len
);
1540 SSVAL(*rparam
,0,NERR_Success
);
1541 SSVAL(*rparam
,2,0); /* converter word */
1542 SSVAL(*rparam
,4,*rdata_len
);
1547 /****************************************************************************
1548 view list of shares available
1549 ****************************************************************************/
1550 static BOOL
api_RNetShareEnum(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
1551 int mdrcnt
,int mprcnt
,
1552 char **rdata
,char **rparam
,
1553 int *rdata_len
,int *rparam_len
)
1555 char *str1
= param
+2;
1556 char *str2
= skip_string(str1
,1);
1557 char *p
= skip_string(str2
,1);
1558 int uLevel
= SVAL(p
,0);
1559 int buf_len
= SVAL(p
,2);
1561 int count
=lp_numservices();
1562 int total
=0,counted
=0;
1563 BOOL missed
= False
;
1565 int data_len
, fixed_len
, string_len
;
1566 int f_len
= 0, s_len
= 0;
1568 if (!prefix_ok(str1
,"WrLeh")) return False
;
1569 //!! if (!check_share_info(uLevel,str2)) return False;
1571 data_len
= fixed_len
= string_len
= 0;
1572 for (i
=0;i
<count
;i
++)
1573 if (lp_browseable(i
) && lp_snum_ok(i
))
1576 data_len
+= fill_share_info(conn
,i
,uLevel
,0,&f_len
,0,&s_len
,0);
1577 if (data_len
<= buf_len
)
1581 string_len
+= s_len
;
1586 *rdata_len
= fixed_len
+ string_len
;
1587 *rdata
= REALLOC(*rdata
,*rdata_len
);
1588 memset(*rdata
,0,*rdata_len
);
1590 p2
= (*rdata
) + fixed_len
; /* auxillery data (strings) will go here */
1594 for (i
= 0; i
< count
;i
++)
1595 if (lp_browseable(i
) && lp_snum_ok(i
))
1596 if (fill_share_info(conn
,i
,uLevel
,&p
,&f_len
,&p2
,&s_len
,*rdata
) < 0)
1600 *rparam
= REALLOC(*rparam
,*rparam_len
);
1601 SSVAL(*rparam
,0,missed
? ERRmoredata
: NERR_Success
);
1603 SSVAL(*rparam
,4,counted
);
1604 SSVAL(*rparam
,6,total
);
1606 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1607 counted
,total
,uLevel
,
1608 buf_len
,*rdata_len
,mdrcnt
));
1614 /****************************************************************************
1615 get the time of day info
1616 ****************************************************************************/
1617 static BOOL
api_NetRemoteTOD(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
1618 int mdrcnt
,int mprcnt
,
1619 char **rdata
,char **rparam
,
1620 int *rdata_len
,int *rparam_len
)
1624 *rparam
= REALLOC(*rparam
,*rparam_len
);
1627 *rdata
= REALLOC(*rdata
,*rdata_len
);
1629 SSVAL(*rparam
,0,NERR_Success
);
1630 SSVAL(*rparam
,2,0); /* converter word */
1636 time_t unixdate
= time(NULL
);
1638 put_dos_date3(p
,0,unixdate
); /* this is the time that is looked at
1639 by NT in a "net time" operation,
1640 it seems to ignore the one below */
1642 /* the client expects to get localtime, not GMT, in this bit
1643 (I think, this needs testing) */
1644 t
= LocalTime(&unixdate
);
1646 SIVAL(p
,4,0); /* msecs ? */
1647 CVAL(p
,8) = t
->tm_hour
;
1648 CVAL(p
,9) = t
->tm_min
;
1649 CVAL(p
,10) = t
->tm_sec
;
1650 CVAL(p
,11) = 0; /* hundredths of seconds */
1651 SSVALS(p
,12,TimeDiff(unixdate
)/60); /* timezone in minutes from GMT */
1652 SSVAL(p
,14,10000); /* timer interval in 0.0001 of sec */
1653 CVAL(p
,16) = t
->tm_mday
;
1654 CVAL(p
,17) = t
->tm_mon
+ 1;
1655 SSVAL(p
,18,1900+t
->tm_year
);
1656 CVAL(p
,20) = t
->tm_wday
;
1663 /****************************************************************************
1664 Set the user password.
1665 *****************************************************************************/
1667 static BOOL
api_SetUserPassword(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
1668 int mdrcnt
,int mprcnt
,
1669 char **rdata
,char **rparam
,
1670 int *rdata_len
,int *rparam_len
)
1672 char *p
= skip_string(param
+2,2);
1674 fstring pass1
,pass2
;
1678 p
= skip_string(p
,1);
1680 memset(pass1
,'\0',sizeof(pass1
));
1681 memset(pass2
,'\0',sizeof(pass2
));
1683 memcpy(pass2
,p
+16,16);
1686 *rparam
= REALLOC(*rparam
,*rparam_len
);
1690 SSVAL(*rparam
,0,NERR_badpass
);
1691 SSVAL(*rparam
,2,0); /* converter word */
1693 DEBUG(3,("Set password for <%s>\n",user
));
1696 * Pass the user through the NT -> unix user mapping
1700 (void)map_username(user
);
1703 * Do any UNIX username case mangling.
1705 (void)Get_Pwnam( user
, True
);
1708 * Attempt to verify the old password against smbpasswd entries
1709 * Win98 clients send old and new password in plaintext for this call.
1713 fstring saved_pass2
;
1714 struct smb_passwd
*smbpw
= NULL
;
1717 * Save the new password as change_oem_password overwrites it
1721 fstrcpy(saved_pass2
, pass2
);
1723 if (check_plaintext_password(user
,pass1
,strlen(pass1
),&smbpw
) &&
1724 change_oem_password(smbpw
,pass2
,False
))
1726 SSVAL(*rparam
,0,NERR_Success
);
1729 * If unix password sync was requested, attempt to change
1730 * the /etc/passwd database also. Return failure if this cannot
1734 if(lp_unix_password_sync() && !chgpasswd(user
,pass1
,saved_pass2
,False
))
1735 SSVAL(*rparam
,0,NERR_badpass
);
1740 * If the above failed, attempt the plaintext password change.
1741 * This tests against the /etc/passwd database only.
1744 if(SVAL(*rparam
,0) != NERR_Success
)
1746 if (password_ok(user
, pass1
,strlen(pass1
),NULL
) &&
1747 chgpasswd(user
,pass1
,pass2
,False
))
1749 SSVAL(*rparam
,0,NERR_Success
);
1754 * If the plaintext change failed, attempt
1755 * the old encrypted method. NT will generate this
1756 * after trying the samr method. Note that this
1757 * method is done as a last resort as this
1758 * password change method loses the NT password hash
1759 * and cannot change the UNIX password as no plaintext
1763 if(SVAL(*rparam
,0) != NERR_Success
)
1765 struct smb_passwd
*sampw
= NULL
;
1767 if(check_lanman_password(user
,(unsigned char *)pass1
,(unsigned char *)pass2
, &sampw
) &&
1768 change_lanman_password(sampw
,(unsigned char *)pass1
,(unsigned char *)pass2
))
1770 SSVAL(*rparam
,0,NERR_Success
);
1774 memset((char *)pass1
,'\0',sizeof(fstring
));
1775 memset((char *)pass2
,'\0',sizeof(fstring
));
1780 /****************************************************************************
1781 Set the user password (SamOEM version - gets plaintext).
1782 ****************************************************************************/
1784 static BOOL
api_SamOEMChangePassword(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
1785 int mdrcnt
,int mprcnt
,
1786 char **rdata
,char **rparam
,
1787 int *rdata_len
,int *rparam_len
)
1790 char *p
= param
+ 2;
1792 *rparam
= REALLOC(*rparam
,*rparam_len
);
1796 SSVAL(*rparam
,0,NERR_badpass
);
1799 * Check the parameter definition is correct.
1801 if(!strequal(param
+ 2, "zsT")) {
1802 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", param
+ 2));
1805 p
= skip_string(p
, 1);
1807 if(!strequal(p
, "B516B16")) {
1808 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p
));
1811 p
= skip_string(p
,1);
1814 p
= skip_string(p
,1);
1816 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user
));
1819 * Pass the user through the NT -> unix user mapping
1823 (void)map_username(user
);
1826 * Do any UNIX username case mangling.
1828 (void)Get_Pwnam( user
, True
);
1830 if (pass_oem_change(user
, (uchar
*) data
, (uchar
*)&data
[516], NULL
, NULL
))
1832 SSVAL(*rparam
,0,NERR_Success
);
1838 /****************************************************************************
1841 ****************************************************************************/
1842 static BOOL
api_RDosPrintJobDel(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
1843 int mdrcnt
,int mprcnt
,
1844 char **rdata
,char **rparam
,
1845 int *rdata_len
,int *rparam_len
)
1847 int function
= SVAL(param
,0);
1848 char *str1
= param
+2;
1849 char *str2
= skip_string(str1
,1);
1850 char *p
= skip_string(str2
,1);
1854 printjob_decode(SVAL(p
,0), &snum
, &jobid
);
1856 /* check it's a supported varient */
1857 if (!(strcsequal(str1
,"W") && strcsequal(str2
,"")))
1861 *rparam
= REALLOC(*rparam
,*rparam_len
);
1865 SSVAL(*rparam
,0,NERR_Success
);
1867 if (snum
>= 0 && VALID_SNUM(snum
))
1869 print_queue_struct
*queue
=NULL
;
1871 count
= get_printqueue(snum
,conn
,&queue
,NULL
);
1873 for (i
=0;i
<count
;i
++)
1874 if ((queue
[i
].job
&0xFF) == jobid
)
1877 case 81: /* delete */
1878 DEBUG(3,("Deleting queue entry %d\n",queue
[i
].job
));
1879 del_printqueue(conn
,snum
,queue
[i
].job
);
1881 case 82: /* pause */
1882 case 83: /* resume */
1883 DEBUG(3,("%s queue entry %d\n",
1884 (function
==82?"pausing":"resuming"),queue
[i
].job
));
1885 status_printjob(conn
,snum
,queue
[i
].job
,
1886 (function
==82?LPQ_PAUSED
:LPQ_QUEUED
));
1893 SSVAL(*rparam
,0,NERR_JobNotFound
);
1895 if (queue
) free(queue
);
1898 SSVAL(*rparam
,2,0); /* converter word */
1903 /****************************************************************************
1904 Purge a print queue - or pause or resume it.
1905 ****************************************************************************/
1906 static BOOL
api_WPrintQueuePurge(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
1907 int mdrcnt
,int mprcnt
,
1908 char **rdata
,char **rparam
,
1909 int *rdata_len
,int *rparam_len
)
1911 int function
= SVAL(param
,0);
1912 char *str1
= param
+2;
1913 char *str2
= skip_string(str1
,1);
1914 char *QueueName
= skip_string(str2
,1);
1917 /* check it's a supported varient */
1918 if (!(strcsequal(str1
,"z") && strcsequal(str2
,"")))
1922 *rparam
= REALLOC(*rparam
,*rparam_len
);
1926 SSVAL(*rparam
,0,NERR_Success
);
1927 SSVAL(*rparam
,2,0); /* converter word */
1929 snum
= lp_servicenumber(QueueName
);
1930 if (snum
< 0 && pcap_printername_ok(QueueName
,NULL
)) {
1931 int pnum
= lp_servicenumber(PRINTERS_NAME
);
1933 lp_add_printer(QueueName
,pnum
);
1934 snum
= lp_servicenumber(QueueName
);
1938 if (snum
>= 0 && VALID_SNUM(snum
)) {
1942 case 74: /* Pause queue */
1943 case 75: /* Resume queue */
1944 status_printqueue(conn
,snum
,(function
==74?LPSTAT_STOPPED
:LPSTAT_OK
));
1945 DEBUG(3,("Print queue %s, queue=%s\n",
1946 (function
==74?"pause":"resume"),QueueName
));
1948 case 103: /* Purge */
1950 print_queue_struct
*queue
=NULL
;
1952 count
= get_printqueue(snum
,conn
,&queue
,NULL
);
1953 for (i
= 0; i
< count
; i
++)
1954 del_printqueue(conn
,snum
,queue
[i
].job
);
1956 if (queue
) free(queue
);
1957 DEBUG(3,("Print queue purge, queue=%s\n",QueueName
));
1967 /****************************************************************************
1968 set the property of a print job (undocumented?)
1969 ? function = 0xb -> set name of print job
1970 ? function = 0x6 -> move print job up/down
1971 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
1972 or <WWsTP> <WB21BB16B10zWWzDDz>
1973 ****************************************************************************/
1974 static int check_printjob_info(struct pack_desc
* desc
,
1975 int uLevel
, char* id
)
1977 desc
->subformat
= NULL
;
1979 case 0: desc
->format
= "W"; break;
1980 case 1: desc
->format
= "WB21BB16B10zWWzDDz"; break;
1981 case 2: desc
->format
= "WWzWWDDzz"; break;
1982 case 3: desc
->format
= "WWzWWDDzzzzzzzzzzlz"; break;
1983 default: return False
;
1985 if (strcmp(desc
->format
,id
) != 0) return False
;
1989 static BOOL
api_PrintJobInfo(connection_struct
*conn
,uint16 vuid
,char *param
,char *data
,
1990 int mdrcnt
,int mprcnt
,
1991 char **rdata
,char **rparam
,
1992 int *rdata_len
,int *rparam_len
)
1994 struct pack_desc desc
;
1995 char *str1
= param
+2;
1996 char *str2
= skip_string(str1
,1);
1997 char *p
= skip_string(str2
,1);
1999 int uLevel
= SVAL(p
,2);
2000 int function
= SVAL(p
,4); /* what is this ?? */
2005 printjob_decode(SVAL(p
,0), &snum
, &jobid
);
2008 *rparam
= REALLOC(*rparam
,*rparam_len
);
2012 /* check it's a supported varient */
2013 if ((strcmp(str1
,"WWsTP")) ||
2014 (!check_printjob_info(&desc
,uLevel
,str2
)))
2018 case 0x6: /* change job place in the queue,
2019 data gives the new place */
2020 if (snum
>= 0 && VALID_SNUM(snum
)) {
2021 print_queue_struct
*queue
=NULL
;
2025 count
= get_printqueue(snum
,conn
,&queue
,NULL
);
2026 for (i
=0;i
<count
;i
++) /* find job */
2027 if ((queue
[i
].job
&0xFF) == jobid
) break;
2030 desc
.errcode
=NERR_JobNotFound
;
2031 if (queue
) free(queue
);
2033 desc
.errcode
=NERR_Success
;
2037 int place
= SVAL(data
,0);
2038 /* we currently have no way of
2039 doing this. Can any unix do it? */
2040 if (i
< place
) /* move down */;
2041 else if (i
> place
) /* move up */;
2044 desc
.errcode
=NERR_notsupported
; /* not yet
2046 if (queue
) free(queue
);
2049 desc
.errcode
=NERR_JobNotFound
;
2053 case 0xb: /* change print job name, data gives the name */
2054 /* jobid, snum should be zero */
2055 if (isalpha((int)*s
)) {
2058 while (l
<64 && *s
) {
2059 if (issafe(*s
)) name
[l
++] = *s
;
2064 DEBUG(3,("Setting print name to %s\n",name
));
2066 fsp
= file_find_print();
2069 connection_struct
*fconn
= fsp
->conn
;
2072 if (!become_user(fconn
,vuid
) ||
2073 !become_service(fconn
,True
))
2076 if (dos_rename(fsp
->fsp_name
,name
) == 0) {
2077 string_set(&fsp
->fsp_name
,name
);
2082 desc
.errcode
=NERR_Success
;
2085 default: /* not implemented */
2089 SSVALS(*rparam
,0,desc
.errcode
);
2090 SSVAL(*rparam
,2,0); /* converter word */
2096 /****************************************************************************
2097 get info about the server
2098 ****************************************************************************/
2099 static BOOL
api_RNetServerGetInfo(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
2100 int mdrcnt
,int mprcnt
,
2101 char **rdata
,char **rparam
,
2102 int *rdata_len
,int *rparam_len
)
2104 char *str1
= param
+2;
2105 char *str2
= skip_string(str1
,1);
2106 char *p
= skip_string(str2
,1);
2107 int uLevel
= SVAL(p
,0);
2111 DEBUG(4,("NetServerGetInfo level %d\n",uLevel
));
2113 /* check it's a supported varient */
2114 if (!prefix_ok(str1
,"WrLh")) return False
;
2117 if (strcmp(str2
,"B16") != 0) return False
;
2121 if (strcmp(str2
,"B16BBDz") != 0) return False
;
2125 if (strcmp(str2
,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")
2130 if (strcmp(str2
,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz")
2135 if (strcmp(str2
,"DN") != 0) return False
;
2139 if (strcmp(str2
,"B16BBDzWWzzz") != 0) return False
;
2142 default: return False
;
2145 *rdata_len
= mdrcnt
;
2146 *rdata
= REALLOC(*rdata
,*rdata_len
);
2149 p2
= p
+ struct_len
;
2151 StrnCpy(p
,local_machine
,16);
2157 struct srv_info_struct
*servers
=NULL
;
2160 uint32 servertype
= lp_default_server_announce();
2162 pstrcpy(comment
,string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH
));
2164 if ((count
=get_server_info(SV_TYPE_ALL
,&servers
,global_myworkgroup
))>0) {
2165 for (i
=0;i
<count
;i
++)
2166 if (strequal(servers
[i
].name
,local_machine
))
2168 servertype
= servers
[i
].type
;
2169 pstrcpy(comment
,servers
[i
].comment
);
2172 if (servers
) free(servers
);
2174 SCVAL(p
,0,lp_major_announce_version());
2175 SCVAL(p
,1,lp_minor_announce_version());
2176 SIVAL(p
,2,servertype
);
2178 if (mdrcnt
== struct_len
) {
2181 SIVAL(p
,6,PTR_DIFF(p2
,*rdata
));
2182 standard_sub(conn
,comment
);
2183 StrnCpy(p2
,comment
,MAX(mdrcnt
- struct_len
,0));
2184 p2
= skip_string(p2
,1);
2189 return False
; /* not yet implemented */
2192 *rdata_len
= PTR_DIFF(p2
,*rdata
);
2195 *rparam
= REALLOC(*rparam
,*rparam_len
);
2196 SSVAL(*rparam
,0,NERR_Success
);
2197 SSVAL(*rparam
,2,0); /* converter word */
2198 SSVAL(*rparam
,4,*rdata_len
);
2204 /****************************************************************************
2205 get info about the server
2206 ****************************************************************************/
2207 static BOOL
api_NetWkstaGetInfo(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
2208 int mdrcnt
,int mprcnt
,
2209 char **rdata
,char **rparam
,
2210 int *rdata_len
,int *rparam_len
)
2212 char *str1
= param
+2;
2213 char *str2
= skip_string(str1
,1);
2214 char *p
= skip_string(str2
,1);
2216 extern pstring sesssetup_user
;
2217 int level
= SVAL(p
,0);
2219 DEBUG(4,("NetWkstaGetInfo level %d\n",level
));
2222 *rparam
= REALLOC(*rparam
,*rparam_len
);
2224 /* check it's a supported varient */
2225 if (!(level
==10 && strcsequal(str1
,"WrLh") && strcsequal(str2
,"zzzBBzz")))
2228 *rdata_len
= mdrcnt
+ 1024;
2229 *rdata
= REALLOC(*rdata
,*rdata_len
);
2231 SSVAL(*rparam
,0,NERR_Success
);
2232 SSVAL(*rparam
,2,0); /* converter word */
2238 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* host name */
2239 pstrcpy(p2
,local_machine
);
2241 p2
= skip_string(p2
,1);
2244 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
));
2245 pstrcpy(p2
,sesssetup_user
);
2246 p2
= skip_string(p2
,1);
2249 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* login domain */
2250 pstrcpy(p2
,global_myworkgroup
);
2252 p2
= skip_string(p2
,1);
2255 SCVAL(p
,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
2256 SCVAL(p
,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
2259 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
));
2260 pstrcpy(p2
,global_myworkgroup
); /* don't know. login domain?? */
2261 p2
= skip_string(p2
,1);
2264 SIVAL(p
,0,PTR_DIFF(p2
,*rdata
)); /* don't know */
2266 p2
= skip_string(p2
,1);
2269 *rdata_len
= PTR_DIFF(p2
,*rdata
);
2271 SSVAL(*rparam
,4,*rdata_len
);
2276 /****************************************************************************
2277 get info about a user
2279 struct user_info_11 {
2280 char usri11_name[21]; 0-20
2282 char *usri11_comment; 22-25
2283 char *usri11_usr_comment; 26-29
2284 unsigned short usri11_priv; 30-31
2285 unsigned long usri11_auth_flags; 32-35
2286 long usri11_password_age; 36-39
2287 char *usri11_homedir; 40-43
2288 char *usri11_parms; 44-47
2289 long usri11_last_logon; 48-51
2290 long usri11_last_logoff; 52-55
2291 unsigned short usri11_bad_pw_count; 56-57
2292 unsigned short usri11_num_logons; 58-59
2293 char *usri11_logon_server; 60-63
2294 unsigned short usri11_country_code; 64-65
2295 char *usri11_workstations; 66-69
2296 unsigned long usri11_max_storage; 70-73
2297 unsigned short usri11_units_per_week; 74-75
2298 unsigned char *usri11_logon_hours; 76-79
2299 unsigned short usri11_code_page; 80-81
2304 usri11_name specifies the user name for which information is retireved
2306 usri11_pad aligns the next data structure element to a word boundary
2308 usri11_comment is a null terminated ASCII comment
2310 usri11_user_comment is a null terminated ASCII comment about the user
2312 usri11_priv specifies the level of the privilege assigned to the user.
2313 The possible values are:
2315 Name Value Description
2316 USER_PRIV_GUEST 0 Guest privilege
2317 USER_PRIV_USER 1 User privilege
2318 USER_PRV_ADMIN 2 Administrator privilege
2320 usri11_auth_flags specifies the account operator privileges. The
2321 possible values are:
2323 Name Value Description
2324 AF_OP_PRINT 0 Print operator
2327 Leach, Naik [Page 28]
\f
2330 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2333 AF_OP_COMM 1 Communications operator
2334 AF_OP_SERVER 2 Server operator
2335 AF_OP_ACCOUNTS 3 Accounts operator
2338 usri11_password_age specifies how many seconds have elapsed since the
2339 password was last changed.
2341 usri11_home_dir points to a null terminated ASCII string that contains
2342 the path name of the user's home directory.
2344 usri11_parms points to a null terminated ASCII string that is set
2345 aside for use by applications.
2347 usri11_last_logon specifies the time when the user last logged on.
2348 This value is stored as the number of seconds elapsed since
2349 00:00:00, January 1, 1970.
2351 usri11_last_logoff specifies the time when the user last logged off.
2352 This value is stored as the number of seconds elapsed since
2353 00:00:00, January 1, 1970. A value of 0 means the last logoff
2356 usri11_bad_pw_count specifies the number of incorrect passwords
2357 entered since the last successful logon.
2359 usri11_log1_num_logons specifies the number of times this user has
2360 logged on. A value of -1 means the number of logons is unknown.
2362 usri11_logon_server points to a null terminated ASCII string that
2363 contains the name of the server to which logon requests are sent.
2364 A null string indicates logon requests should be sent to the
2367 usri11_country_code specifies the country code for the user's language
2370 usri11_workstations points to a null terminated ASCII string that
2371 contains the names of workstations the user may log on from.
2372 There may be up to 8 workstations, with the names separated by
2373 commas. A null strings indicates there are no restrictions.
2375 usri11_max_storage specifies the maximum amount of disk space the user
2376 can occupy. A value of 0xffffffff indicates there are no
2379 usri11_units_per_week specifies the equal number of time units into
2380 which a week is divided. This value must be equal to 168.
2382 usri11_logon_hours points to a 21 byte (168 bits) string that
2383 specifies the time during which the user can log on. Each bit
2384 represents one unique hour in a week. The first bit (bit 0, word
2385 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
2389 Leach, Naik [Page 29]
\f
2392 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2395 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
2396 are no restrictions.
2398 usri11_code_page specifies the code page for the user's language of
2401 All of the pointers in this data structure need to be treated
2402 specially. The pointer is a 32 bit pointer. The higher 16 bits need
2403 to be ignored. The converter word returned in the parameters section
2404 needs to be subtracted from the lower 16 bits to calculate an offset
2405 into the return buffer where this ASCII string resides.
2407 There is no auxiliary data in the response.
2409 ****************************************************************************/
2411 #define usri11_name 0
2412 #define usri11_pad 21
2413 #define usri11_comment 22
2414 #define usri11_usr_comment 26
2415 #define usri11_full_name 30
2416 #define usri11_priv 34
2417 #define usri11_auth_flags 36
2418 #define usri11_password_age 40
2419 #define usri11_homedir 44
2420 #define usri11_parms 48
2421 #define usri11_last_logon 52
2422 #define usri11_last_logoff 56
2423 #define usri11_bad_pw_count 60
2424 #define usri11_num_logons 62
2425 #define usri11_logon_server 64
2426 #define usri11_country_code 68
2427 #define usri11_workstations 70
2428 #define usri11_max_storage 74
2429 #define usri11_units_per_week 78
2430 #define usri11_logon_hours 80
2431 #define usri11_code_page 84
2432 #define usri11_end 86
2434 #define USER_PRIV_GUEST 0
2435 #define USER_PRIV_USER 1
2436 #define USER_PRIV_ADMIN 2
2438 #define AF_OP_PRINT 0
2439 #define AF_OP_COMM 1
2440 #define AF_OP_SERVER 2
2441 #define AF_OP_ACCOUNTS 3
2444 static BOOL
api_RNetUserGetInfo(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
2445 int mdrcnt
,int mprcnt
,
2446 char **rdata
,char **rparam
,
2447 int *rdata_len
,int *rparam_len
)
2449 char *str1
= param
+2;
2450 char *str2
= skip_string(str1
,1);
2451 char *UserName
= skip_string(str2
,1);
2452 char *p
= skip_string(UserName
,1);
2453 int uLevel
= SVAL(p
,0);
2456 /* get NIS home of a previously validated user - simeon */
2457 /* With share level security vuid will always be zero.
2458 Don't depend on vuser being non-null !!. JRA */
2459 user_struct
*vuser
= get_valid_user_struct(vuid
);
2461 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser
->uid
, vuser
->name
));
2464 *rparam
= REALLOC(*rparam
,*rparam_len
);
2466 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel
));
2468 /* check it's a supported variant */
2469 if (strcmp(str1
,"zWrLh") != 0) return False
;
2472 case 0: p2
= "B21"; break;
2473 case 1: p2
= "B21BB16DWzzWz"; break;
2474 case 2: p2
= "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
2475 case 10: p2
= "B21Bzzz"; break;
2476 case 11: p2
= "B21BzzzWDDzzDDWWzWzDWb21W"; break;
2477 default: return False
;
2480 if (strcmp(p2
,str2
) != 0) return False
;
2482 *rdata_len
= mdrcnt
+ 1024;
2483 *rdata
= REALLOC(*rdata
,*rdata_len
);
2485 SSVAL(*rparam
,0,NERR_Success
);
2486 SSVAL(*rparam
,2,0); /* converter word */
2489 p2
= p
+ usri11_end
;
2492 fstrcpy(p
+usri11_name
,UserName
); /* 21 bytes - user name */
2496 SCVAL(p
,usri11_pad
,0); /* padding - 1 byte */
2501 SIVAL(p
,usri11_comment
,PTR_DIFF(p2
,p
)); /* comment */
2502 pstrcpy(p2
,"Comment");
2503 p2
= skip_string(p2
,1);
2505 SIVAL(p
,usri11_usr_comment
,PTR_DIFF(p2
,p
)); /* user_comment */
2506 pstrcpy(p2
,"UserComment");
2507 p2
= skip_string(p2
,1);
2509 /* EEK! the cifsrap.txt doesn't have this in!!!! */
2510 SIVAL(p
,usri11_full_name
,PTR_DIFF(p2
,p
)); /* full name */
2511 pstrcpy(p2
,((vuser
!= NULL
) ? vuser
->real_name
: UserName
));
2512 p2
= skip_string(p2
,1);
2515 if (uLevel
== 11) /* modelled after NTAS 3.51 reply */
2517 SSVAL(p
,usri11_priv
,conn
->admin_user
?USER_PRIV_ADMIN
:USER_PRIV_USER
);
2518 SIVAL(p
,usri11_auth_flags
,AF_OP_PRINT
); /* auth flags */
2519 SIVALS(p
,usri11_password_age
,-1); /* password age */
2520 SIVAL(p
,usri11_homedir
,PTR_DIFF(p2
,p
)); /* home dir */
2521 pstrcpy(p2
, lp_logon_home());
2522 p2
= skip_string(p2
,1);
2523 SIVAL(p
,usri11_parms
,PTR_DIFF(p2
,p
)); /* parms */
2525 p2
= skip_string(p2
,1);
2526 SIVAL(p
,usri11_last_logon
,0); /* last logon */
2527 SIVAL(p
,usri11_last_logoff
,0); /* last logoff */
2528 SSVALS(p
,usri11_bad_pw_count
,-1); /* bad pw counts */
2529 SSVALS(p
,usri11_num_logons
,-1); /* num logons */
2530 SIVAL(p
,usri11_logon_server
,PTR_DIFF(p2
,p
)); /* logon server */
2531 pstrcpy(p2
,"\\\\*");
2532 p2
= skip_string(p2
,1);
2533 SSVAL(p
,usri11_country_code
,0); /* country code */
2535 SIVAL(p
,usri11_workstations
,PTR_DIFF(p2
,p
)); /* workstations */
2537 p2
= skip_string(p2
,1);
2539 SIVALS(p
,usri11_max_storage
,-1); /* max storage */
2540 SSVAL(p
,usri11_units_per_week
,168); /* units per week */
2541 SIVAL(p
,usri11_logon_hours
,PTR_DIFF(p2
,p
)); /* logon hours */
2543 /* a simple way to get logon hours at all times. */
2545 SCVAL(p2
,21,0); /* fix zero termination */
2546 p2
= skip_string(p2
,1);
2548 SSVAL(p
,usri11_code_page
,0); /* code page */
2550 if (uLevel
== 1 || uLevel
== 2)
2552 memset(p
+22,' ',16); /* password */
2553 SIVALS(p
,38,-1); /* password age */
2555 conn
->admin_user
?USER_PRIV_ADMIN
:USER_PRIV_USER
);
2556 SIVAL(p
,44,PTR_DIFF(p2
,*rdata
)); /* home dir */
2557 pstrcpy(p2
,lp_logon_home());
2558 p2
= skip_string(p2
,1);
2559 SIVAL(p
,48,PTR_DIFF(p2
,*rdata
)); /* comment */
2561 SSVAL(p
,52,0); /* flags */
2562 SIVAL(p
,54,PTR_DIFF(p2
,*rdata
)); /* script_path */
2563 pstrcpy(p2
,lp_logon_script());
2564 standard_sub( conn
, p2
);
2565 p2
= skip_string(p2
,1);
2568 SIVAL(p
,60,0); /* auth_flags */
2569 SIVAL(p
,64,PTR_DIFF(p2
,*rdata
)); /* full_name */
2570 pstrcpy(p2
,((vuser
!= NULL
) ? vuser
->real_name
: UserName
));
2571 p2
= skip_string(p2
,1);
2572 SIVAL(p
,68,0); /* urs_comment */
2573 SIVAL(p
,72,PTR_DIFF(p2
,*rdata
)); /* parms */
2575 p2
= skip_string(p2
,1);
2576 SIVAL(p
,76,0); /* workstations */
2577 SIVAL(p
,80,0); /* last_logon */
2578 SIVAL(p
,84,0); /* last_logoff */
2579 SIVALS(p
,88,-1); /* acct_expires */
2580 SIVALS(p
,92,-1); /* max_storage */
2581 SSVAL(p
,96,168); /* units_per_week */
2582 SIVAL(p
,98,PTR_DIFF(p2
,*rdata
)); /* logon_hours */
2585 SSVALS(p
,102,-1); /* bad_pw_count */
2586 SSVALS(p
,104,-1); /* num_logons */
2587 SIVAL(p
,106,PTR_DIFF(p2
,*rdata
)); /* logon_server */
2588 pstrcpy(p2
,"\\\\%L");
2589 standard_sub_basic(p2
);
2590 p2
= skip_string(p2
,1);
2591 SSVAL(p
,110,49); /* country_code */
2592 SSVAL(p
,112,860); /* code page */
2596 *rdata_len
= PTR_DIFF(p2
,*rdata
);
2598 SSVAL(*rparam
,4,*rdata_len
); /* is this right?? */
2603 /*******************************************************************
2604 get groups that a user is a member of
2605 ******************************************************************/
2606 static BOOL
api_NetUserGetGroups(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
2607 int mdrcnt
,int mprcnt
,
2608 char **rdata
,char **rparam
,
2609 int *rdata_len
,int *rparam_len
)
2611 char *str1
= param
+2;
2612 char *str2
= skip_string(str1
,1);
2613 char *UserName
= skip_string(str2
,1);
2614 char *p
= skip_string(UserName
,1);
2615 int uLevel
= SVAL(p
,0);
2620 *rparam
= REALLOC(*rparam
,*rparam_len
);
2622 /* check it's a supported varient */
2623 if (strcmp(str1
,"zWrLeh") != 0) return False
;
2625 case 0: p2
= "B21"; break;
2626 default: return False
;
2628 if (strcmp(p2
,str2
) != 0) return False
;
2630 *rdata_len
= mdrcnt
+ 1024;
2631 *rdata
= REALLOC(*rdata
,*rdata_len
);
2633 SSVAL(*rparam
,0,NERR_Success
);
2634 SSVAL(*rparam
,2,0); /* converter word */
2638 /* XXXX we need a real SAM database some day */
2639 pstrcpy(p
,"Users"); p
+= 21; count
++;
2640 pstrcpy(p
,"Domain Users"); p
+= 21; count
++;
2641 pstrcpy(p
,"Guests"); p
+= 21; count
++;
2642 pstrcpy(p
,"Domain Guests"); p
+= 21; count
++;
2644 *rdata_len
= PTR_DIFF(p
,*rdata
);
2646 SSVAL(*rparam
,4,count
); /* is this right?? */
2647 SSVAL(*rparam
,6,count
); /* is this right?? */
2653 static BOOL
api_WWkstaUserLogon(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
2654 int mdrcnt
,int mprcnt
,
2655 char **rdata
,char **rparam
,
2656 int *rdata_len
,int *rparam_len
)
2658 char *str1
= param
+2;
2659 char *str2
= skip_string(str1
,1);
2660 char *p
= skip_string(str2
,1);
2662 struct pack_desc desc
;
2668 memset((char *)&desc
,'\0',sizeof(desc
));
2670 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel
,name
));
2672 /* check it's a supported varient */
2673 if (strcmp(str1
,"OOWb54WrLh") != 0) return False
;
2674 if (uLevel
!= 1 || strcmp(str2
,"WB21BWDWWDDDDDDDzzzD") != 0) return False
;
2675 if (mdrcnt
> 0) *rdata
= REALLOC(*rdata
,mdrcnt
);
2677 desc
.buflen
= mdrcnt
;
2678 desc
.subformat
= NULL
;
2681 if (init_package(&desc
,1,0))
2683 PACKI(&desc
,"W",0); /* code */
2684 PACKS(&desc
,"B21",name
); /* eff. name */
2685 PACKS(&desc
,"B",""); /* pad */
2687 conn
->admin_user
?USER_PRIV_ADMIN
:USER_PRIV_USER
);
2688 PACKI(&desc
,"D",0); /* auth flags XXX */
2689 PACKI(&desc
,"W",0); /* num logons */
2690 PACKI(&desc
,"W",0); /* bad pw count */
2691 PACKI(&desc
,"D",0); /* last logon */
2692 PACKI(&desc
,"D",-1); /* last logoff */
2693 PACKI(&desc
,"D",-1); /* logoff time */
2694 PACKI(&desc
,"D",-1); /* kickoff time */
2695 PACKI(&desc
,"D",0); /* password age */
2696 PACKI(&desc
,"D",0); /* password can change */
2697 PACKI(&desc
,"D",-1); /* password must change */
2700 fstrcpy(mypath
,"\\\\");
2701 fstrcat(mypath
,local_machine
);
2703 PACKS(&desc
,"z",mypath
); /* computer */
2705 PACKS(&desc
,"z",global_myworkgroup
);/* domain */
2707 /* JHT - By calling lp_logon_script() and standard_sub() we have */
2708 /* made sure all macros are fully substituted and available */
2710 pstring logon_script
;
2711 pstrcpy(logon_script
,lp_logon_script());
2712 standard_sub( conn
, logon_script
);
2713 PACKS(&desc
,"z", logon_script
); /* script path */
2715 /* End of JHT mods */
2717 PACKI(&desc
,"D",0x00000000); /* reserved */
2720 *rdata_len
= desc
.usedlen
;
2722 *rparam
= REALLOC(*rparam
,*rparam_len
);
2723 SSVALS(*rparam
,0,desc
.errcode
);
2725 SSVAL(*rparam
,4,desc
.neededlen
);
2727 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc
.errcode
));
2732 /****************************************************************************
2733 api_WAccessGetUserPerms
2734 ****************************************************************************/
2735 static BOOL
api_WAccessGetUserPerms(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
2736 int mdrcnt
,int mprcnt
,
2737 char **rdata
,char **rparam
,
2738 int *rdata_len
,int *rparam_len
)
2740 char *str1
= param
+2;
2741 char *str2
= skip_string(str1
,1);
2742 char *user
= skip_string(str2
,1);
2743 char *resource
= skip_string(user
,1);
2745 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user
,resource
));
2747 /* check it's a supported varient */
2748 if (strcmp(str1
,"zzh") != 0) return False
;
2749 if (strcmp(str2
,"") != 0) return False
;
2752 *rparam
= REALLOC(*rparam
,*rparam_len
);
2753 SSVALS(*rparam
,0,0); /* errorcode */
2754 SSVAL(*rparam
,2,0); /* converter word */
2755 SSVAL(*rparam
,4,0x7f); /* permission flags */
2760 /****************************************************************************
2761 api_WPrintJobEnumerate
2762 ****************************************************************************/
2763 static BOOL
api_WPrintJobGetInfo(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
2764 int mdrcnt
,int mprcnt
,
2765 char **rdata
,char **rparam
,
2766 int *rdata_len
,int *rparam_len
)
2768 char *str1
= param
+2;
2769 char *str2
= skip_string(str1
,1);
2770 char *p
= skip_string(str2
,1);
2776 struct pack_desc desc
;
2777 print_queue_struct
*queue
=NULL
;
2778 print_status_struct status
;
2782 memset((char *)&desc
,'\0',sizeof(desc
));
2783 memset((char *)&status
,'\0',sizeof(status
));
2785 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel
,SVAL(p
,0)));
2787 /* check it's a supported varient */
2788 if (strcmp(str1
,"WWrLh") != 0) return False
;
2789 if (!check_printjob_info(&desc
,uLevel
,str2
)) return False
;
2791 printjob_decode(SVAL(p
,0), &snum
, &job
);
2793 if (snum
< 0 || !VALID_SNUM(snum
)) return(False
);
2795 count
= get_printqueue(snum
,conn
,&queue
,&status
);
2796 for (i
= 0; i
< count
; i
++) {
2797 if ((queue
[i
].job
& 0xFF) == job
) break;
2799 if (mdrcnt
> 0) *rdata
= REALLOC(*rdata
,mdrcnt
);
2801 desc
.buflen
= mdrcnt
;
2803 if (init_package(&desc
,1,0)) {
2805 fill_printjob_info(conn
,snum
,uLevel
,&desc
,&queue
[i
],i
);
2806 *rdata_len
= desc
.usedlen
;
2809 desc
.errcode
= NERR_JobNotFound
;
2815 *rparam
= REALLOC(*rparam
,*rparam_len
);
2816 SSVALS(*rparam
,0,desc
.errcode
);
2818 SSVAL(*rparam
,4,desc
.neededlen
);
2820 if (queue
) free(queue
);
2822 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc
.errcode
));
2826 static BOOL
api_WPrintJobEnumerate(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
2827 int mdrcnt
,int mprcnt
,
2828 char **rdata
,char **rparam
,
2829 int *rdata_len
,int *rparam_len
)
2831 char *str1
= param
+2;
2832 char *str2
= skip_string(str1
,1);
2833 char *p
= skip_string(str2
,1);
2839 struct pack_desc desc
;
2840 print_queue_struct
*queue
=NULL
;
2841 print_status_struct status
;
2843 memset((char *)&desc
,'\0',sizeof(desc
));
2844 memset((char *)&status
,'\0',sizeof(status
));
2846 p
= skip_string(p
,1);
2849 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel
,name
));
2851 /* check it's a supported varient */
2852 if (strcmp(str1
,"zWrLeh") != 0) return False
;
2853 if (uLevel
> 2) return False
; /* defined only for uLevel 0,1,2 */
2854 if (!check_printjob_info(&desc
,uLevel
,str2
)) return False
;
2856 snum
= lp_servicenumber(name
);
2857 if (snum
< 0 && pcap_printername_ok(name
,NULL
)) {
2858 int pnum
= lp_servicenumber(PRINTERS_NAME
);
2860 lp_add_printer(name
,pnum
);
2861 snum
= lp_servicenumber(name
);
2865 if (snum
< 0 || !VALID_SNUM(snum
)) return(False
);
2867 count
= get_printqueue(snum
,conn
,&queue
,&status
);
2868 if (mdrcnt
> 0) *rdata
= REALLOC(*rdata
,mdrcnt
);
2870 desc
.buflen
= mdrcnt
;
2872 if (init_package(&desc
,count
,0)) {
2874 for (i
= 0; i
< count
; i
++) {
2875 fill_printjob_info(conn
,snum
,uLevel
,&desc
,&queue
[i
],i
);
2876 if (desc
.errcode
== NERR_Success
) succnt
= i
+1;
2880 *rdata_len
= desc
.usedlen
;
2883 *rparam
= REALLOC(*rparam
,*rparam_len
);
2884 SSVALS(*rparam
,0,desc
.errcode
);
2886 SSVAL(*rparam
,4,succnt
);
2887 SSVAL(*rparam
,6,count
);
2889 if (queue
) free(queue
);
2891 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc
.errcode
));
2895 static int check_printdest_info(struct pack_desc
* desc
,
2896 int uLevel
, char* id
)
2898 desc
->subformat
= NULL
;
2900 case 0: desc
->format
= "B9"; break;
2901 case 1: desc
->format
= "B9B21WWzW"; break;
2902 case 2: desc
->format
= "z"; break;
2903 case 3: desc
->format
= "zzzWWzzzWW"; break;
2904 default: return False
;
2906 if (strcmp(desc
->format
,id
) != 0) return False
;
2910 static void fill_printdest_info(connection_struct
*conn
, int snum
, int uLevel
,
2911 struct pack_desc
* desc
)
2914 strncpy(buf
,SERVICE(snum
),sizeof(buf
)-1);
2915 buf
[sizeof(buf
)-1] = 0;
2918 PACKS(desc
,"B9",buf
); /* szName */
2920 PACKS(desc
,"B21",""); /* szUserName */
2921 PACKI(desc
,"W",0); /* uJobId */
2922 PACKI(desc
,"W",0); /* fsStatus */
2923 PACKS(desc
,"z",""); /* pszStatus */
2924 PACKI(desc
,"W",0); /* time */
2927 if (uLevel
== 2 || uLevel
== 3) {
2928 PACKS(desc
,"z",buf
); /* pszPrinterName */
2930 PACKS(desc
,"z",""); /* pszUserName */
2931 PACKS(desc
,"z",""); /* pszLogAddr */
2932 PACKI(desc
,"W",0); /* uJobId */
2933 PACKI(desc
,"W",0); /* fsStatus */
2934 PACKS(desc
,"z",""); /* pszStatus */
2935 PACKS(desc
,"z",""); /* pszComment */
2936 PACKS(desc
,"z","NULL"); /* pszDrivers */
2937 PACKI(desc
,"W",0); /* time */
2938 PACKI(desc
,"W",0); /* pad1 */
2943 static BOOL
api_WPrintDestGetInfo(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
2944 int mdrcnt
,int mprcnt
,
2945 char **rdata
,char **rparam
,
2946 int *rdata_len
,int *rparam_len
)
2948 char *str1
= param
+2;
2949 char *str2
= skip_string(str1
,1);
2950 char *p
= skip_string(str2
,1);
2951 char* PrinterName
= p
;
2953 struct pack_desc desc
;
2956 memset((char *)&desc
,'\0',sizeof(desc
));
2958 p
= skip_string(p
,1);
2961 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel
,PrinterName
));
2963 /* check it's a supported varient */
2964 if (strcmp(str1
,"zWrLh") != 0) return False
;
2965 if (!check_printdest_info(&desc
,uLevel
,str2
)) return False
;
2967 snum
= lp_servicenumber(PrinterName
);
2968 if (snum
< 0 && pcap_printername_ok(PrinterName
,NULL
)) {
2969 int pnum
= lp_servicenumber(PRINTERS_NAME
);
2971 lp_add_printer(PrinterName
,pnum
);
2972 snum
= lp_servicenumber(PrinterName
);
2978 desc
.errcode
= NERR_DestNotFound
;
2982 if (mdrcnt
> 0) *rdata
= REALLOC(*rdata
,mdrcnt
);
2984 desc
.buflen
= mdrcnt
;
2985 if (init_package(&desc
,1,0)) {
2986 fill_printdest_info(conn
,snum
,uLevel
,&desc
);
2988 *rdata_len
= desc
.usedlen
;
2992 *rparam
= REALLOC(*rparam
,*rparam_len
);
2993 SSVALS(*rparam
,0,desc
.errcode
);
2995 SSVAL(*rparam
,4,desc
.neededlen
);
2997 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc
.errcode
));
3001 static BOOL
api_WPrintDestEnum(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
3002 int mdrcnt
,int mprcnt
,
3003 char **rdata
,char **rparam
,
3004 int *rdata_len
,int *rparam_len
)
3006 char *str1
= param
+2;
3007 char *str2
= skip_string(str1
,1);
3008 char *p
= skip_string(str2
,1);
3012 struct pack_desc desc
;
3013 int services
= lp_numservices();
3015 memset((char *)&desc
,'\0',sizeof(desc
));
3019 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel
));
3021 /* check it's a supported varient */
3022 if (strcmp(str1
,"WrLeh") != 0) return False
;
3023 if (!check_printdest_info(&desc
,uLevel
,str2
)) return False
;
3026 for (i
= 0; i
< services
; i
++)
3027 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
))
3030 if (mdrcnt
> 0) *rdata
= REALLOC(*rdata
,mdrcnt
);
3032 desc
.buflen
= mdrcnt
;
3033 if (init_package(&desc
,queuecnt
,0)) {
3036 for (i
= 0; i
< services
; i
++) {
3037 if (lp_snum_ok(i
) && lp_print_ok(i
) && lp_browseable(i
)) {
3038 fill_printdest_info(conn
,i
,uLevel
,&desc
);
3040 if (desc
.errcode
== NERR_Success
) succnt
= n
;
3045 *rdata_len
= desc
.usedlen
;
3048 *rparam
= REALLOC(*rparam
,*rparam_len
);
3049 SSVALS(*rparam
,0,desc
.errcode
);
3051 SSVAL(*rparam
,4,succnt
);
3052 SSVAL(*rparam
,6,queuecnt
);
3054 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc
.errcode
));
3058 static BOOL
api_WPrintDriverEnum(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
3059 int mdrcnt
,int mprcnt
,
3060 char **rdata
,char **rparam
,
3061 int *rdata_len
,int *rparam_len
)
3063 char *str1
= param
+2;
3064 char *str2
= skip_string(str1
,1);
3065 char *p
= skip_string(str2
,1);
3068 struct pack_desc desc
;
3070 memset((char *)&desc
,'\0',sizeof(desc
));
3074 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel
));
3076 /* check it's a supported varient */
3077 if (strcmp(str1
,"WrLeh") != 0) return False
;
3078 if (uLevel
!= 0 || strcmp(str2
,"B41") != 0) return False
;
3080 if (mdrcnt
> 0) *rdata
= REALLOC(*rdata
,mdrcnt
);
3082 desc
.buflen
= mdrcnt
;
3083 if (init_package(&desc
,1,0)) {
3084 PACKS(&desc
,"B41","NULL");
3087 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
3089 *rdata_len
= desc
.usedlen
;
3092 *rparam
= REALLOC(*rparam
,*rparam_len
);
3093 SSVALS(*rparam
,0,desc
.errcode
);
3095 SSVAL(*rparam
,4,succnt
);
3098 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc
.errcode
));
3102 static BOOL
api_WPrintQProcEnum(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
3103 int mdrcnt
,int mprcnt
,
3104 char **rdata
,char **rparam
,
3105 int *rdata_len
,int *rparam_len
)
3107 char *str1
= param
+2;
3108 char *str2
= skip_string(str1
,1);
3109 char *p
= skip_string(str2
,1);
3112 struct pack_desc desc
;
3114 memset((char *)&desc
,'\0',sizeof(desc
));
3118 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel
));
3120 /* check it's a supported varient */
3121 if (strcmp(str1
,"WrLeh") != 0) return False
;
3122 if (uLevel
!= 0 || strcmp(str2
,"B13") != 0) return False
;
3124 if (mdrcnt
> 0) *rdata
= REALLOC(*rdata
,mdrcnt
);
3126 desc
.buflen
= mdrcnt
;
3128 if (init_package(&desc
,1,0)) {
3129 PACKS(&desc
,"B13","lpd");
3132 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
3134 *rdata_len
= desc
.usedlen
;
3137 *rparam
= REALLOC(*rparam
,*rparam_len
);
3138 SSVALS(*rparam
,0,desc
.errcode
);
3140 SSVAL(*rparam
,4,succnt
);
3143 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc
.errcode
));
3147 static BOOL
api_WPrintPortEnum(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
3148 int mdrcnt
,int mprcnt
,
3149 char **rdata
,char **rparam
,
3150 int *rdata_len
,int *rparam_len
)
3152 char *str1
= param
+2;
3153 char *str2
= skip_string(str1
,1);
3154 char *p
= skip_string(str2
,1);
3157 struct pack_desc desc
;
3159 memset((char *)&desc
,'\0',sizeof(desc
));
3163 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel
));
3165 /* check it's a supported varient */
3166 if (strcmp(str1
,"WrLeh") != 0) return False
;
3167 if (uLevel
!= 0 || strcmp(str2
,"B9") != 0) return False
;
3169 if (mdrcnt
> 0) *rdata
= REALLOC(*rdata
,mdrcnt
);
3170 memset((char *)&desc
,'\0',sizeof(desc
));
3172 desc
.buflen
= mdrcnt
;
3174 if (init_package(&desc
,1,0)) {
3175 PACKS(&desc
,"B13","lp0");
3178 succnt
= (desc
.errcode
== NERR_Success
? 1 : 0);
3180 *rdata_len
= desc
.usedlen
;
3183 *rparam
= REALLOC(*rparam
,*rparam_len
);
3184 SSVALS(*rparam
,0,desc
.errcode
);
3186 SSVAL(*rparam
,4,succnt
);
3189 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc
.errcode
));
3193 /****************************************************************************
3194 Start the first part of an RPC reply which began with an SMBtrans request.
3195 ****************************************************************************/
3197 static BOOL
api_rpc_trans_reply(char *outbuf
, pipes_struct
*p
)
3199 char *rdata
= malloc(p
->max_trans_reply
);
3203 DEBUG(0,("api_rpc_trans_reply: malloc fail.\n"));
3207 if((data_len
= (int)read_from_pipe( p
, rdata
, (size_t)p
->max_trans_reply
)) < 0) {
3212 send_trans_reply(outbuf
, NULL
, 0, rdata
, data_len
, p
->out_data
.current_pdu_len
> data_len
);
3218 /****************************************************************************
3219 WaitNamedPipeHandleState
3220 ****************************************************************************/
3222 static BOOL
api_WNPHS(char *outbuf
, pipes_struct
*p
, char *param
, int param_len
)
3226 if (!param
|| param_len
< 2)
3229 priority
= SVAL(param
,0);
3230 DEBUG(4,("WaitNamedPipeHandleState priority %x\n", priority
));
3232 if (wait_rpc_pipe_hnd_state(p
, priority
)) {
3233 /* now send the reply */
3234 send_trans_reply(outbuf
, NULL
, 0, NULL
, 0, False
);
3241 /****************************************************************************
3242 SetNamedPipeHandleState
3243 ****************************************************************************/
3245 static BOOL
api_SNPHS(char *outbuf
, pipes_struct
*p
, char *param
, int param_len
)
3249 if (!param
|| param_len
< 2)
3253 DEBUG(4,("SetNamedPipeHandleState to code %x\n", id
));
3255 if (set_rpc_pipe_hnd_state(p
, id
)) {
3256 /* now send the reply */
3257 send_trans_reply(outbuf
, NULL
, 0, NULL
, 0, False
);
3264 /****************************************************************************
3265 When no reply is generated, indicate unsupported.
3266 ****************************************************************************/
3268 static BOOL
api_no_reply(char *outbuf
, int max_rdata_len
)
3273 SSVAL(rparam
,0,NERR_notsupported
);
3274 SSVAL(rparam
,2,0); /* converter word */
3276 DEBUG(3,("Unsupported API fd command\n"));
3278 /* now send the reply */
3279 send_trans_reply(outbuf
, rparam
, 4, NULL
, 0, False
);
3284 /****************************************************************************
3285 Handle remote api calls delivered to a named pipe already opened.
3286 ****************************************************************************/
3288 static int api_fd_reply(connection_struct
*conn
,uint16 vuid
,char *outbuf
,
3289 uint16
*setup
,char *data
,char *params
,
3290 int suwcnt
,int tdscnt
,int tpscnt
,int mdrcnt
,int mprcnt
)
3293 pipes_struct
*p
= NULL
;
3297 DEBUG(5,("api_fd_reply\n"));
3299 /* First find out the name of this file. */
3301 DEBUG(0,("Unexpected named pipe transaction.\n"));
3305 /* Get the file handle and hence the file name. */
3307 * NB. The setup array has already been transformed
3308 * via SVAL and so is in gost byte order.
3310 pnum
= ((int)setup
[1]) & 0xFFFF;
3311 subcommand
= ((int)setup
[0]) & 0xFFFF;
3313 if(!(p
= get_rpc_pipe(pnum
))) {
3314 DEBUG(1,("api_fd_reply: INVALID PIPE HANDLE: %x\n", pnum
));
3315 return api_no_reply(outbuf
, mdrcnt
);
3318 DEBUG(3,("Got API command 0x%x on pipe \"%s\" (pnum %x)", subcommand
, p
->name
, pnum
));
3320 /* record maximum data length that can be transmitted in an SMBtrans */
3321 p
->max_trans_reply
= mdrcnt
;
3323 DEBUG(10,("api_fd_reply: p:%p max_trans_reply: %d\n", p
, p
->max_trans_reply
));
3325 switch (subcommand
) {
3327 /* dce/rpc command */
3328 reply
= write_to_pipe(p
, data
, tdscnt
);
3330 reply
= api_rpc_trans_reply(outbuf
, p
);
3333 /* Wait Named Pipe Handle state */
3334 reply
= api_WNPHS(outbuf
, p
, params
, tpscnt
);
3337 /* Set Named Pipe Handle state */
3338 reply
= api_SNPHS(outbuf
, p
, params
, tpscnt
);
3343 return api_no_reply(outbuf
, mdrcnt
);
3348 /****************************************************************************
3349 The buffer was too small
3350 ****************************************************************************/
3352 static BOOL
api_TooSmall(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
3353 int mdrcnt
,int mprcnt
,
3354 char **rdata
,char **rparam
,
3355 int *rdata_len
,int *rparam_len
)
3357 *rparam_len
= MIN(*rparam_len
,mprcnt
);
3358 *rparam
= REALLOC(*rparam
,*rparam_len
);
3362 SSVAL(*rparam
,0,NERR_BufTooSmall
);
3364 DEBUG(3,("Supplied buffer too small in API command\n"));
3370 /****************************************************************************
3371 The request is not supported
3372 ****************************************************************************/
3374 static BOOL
api_Unsupported(connection_struct
*conn
,uint16 vuid
, char *param
,char *data
,
3375 int mdrcnt
,int mprcnt
,
3376 char **rdata
,char **rparam
,
3377 int *rdata_len
,int *rparam_len
)
3380 *rparam
= REALLOC(*rparam
,*rparam_len
);
3384 SSVAL(*rparam
,0,NERR_notsupported
);
3385 SSVAL(*rparam
,2,0); /* converter word */
3387 DEBUG(3,("Unsupported API command\n"));
3399 BOOL (*fn
)(connection_struct
*,uint16
,char *,char *,
3400 int,int,char **,char **,int *,int *);
3402 } api_commands
[] = {
3403 {"RNetShareEnum", 0, api_RNetShareEnum
,0},
3404 {"RNetShareGetInfo", 1, api_RNetShareGetInfo
,0},
3405 {"RNetServerGetInfo", 13, api_RNetServerGetInfo
,0},
3406 {"RNetGroupGetUsers", 52, api_RNetGroupGetUsers
,0},
3407 {"RNetUserGetInfo", 56, api_RNetUserGetInfo
,0},
3408 {"NetUserGetGroups", 59, api_NetUserGetGroups
,0},
3409 {"NetWkstaGetInfo", 63, api_NetWkstaGetInfo
,0},
3411 {"DosPrintQEnum", 69, api_DosPrintQEnum
,0},
3412 {"DosPrintQGetInfo", 70, api_DosPrintQGetInfo
,0},
3413 {"WPrintQueuePause", 74, api_WPrintQueuePurge
,0},
3414 {"WPrintQueueResume", 75, api_WPrintQueuePurge
,0},
3415 {"WPrintJobEnumerate",76, api_WPrintJobEnumerate
,0},
3416 {"WPrintJobGetInfo", 77, api_WPrintJobGetInfo
,0},
3417 {"RDosPrintJobDel", 81, api_RDosPrintJobDel
,0},
3418 {"RDosPrintJobPause", 82, api_RDosPrintJobDel
,0},
3419 {"RDosPrintJobResume",83, api_RDosPrintJobDel
,0},
3420 {"WPrintDestEnum", 84, api_WPrintDestEnum
,0},
3421 {"WPrintDestGetInfo", 85, api_WPrintDestGetInfo
,0},
3423 {"NetRemoteTOD", 91, api_NetRemoteTOD
,0},
3425 {"WPrintQueuePurge", 103, api_WPrintQueuePurge
,0},
3427 {"NetServerEnum", 104, api_RNetServerEnum
,0},
3428 {"WAccessGetUserPerms",105, api_WAccessGetUserPerms
,0},
3429 {"SetUserPassword", 115, api_SetUserPassword
,0},
3430 {"WWkstaUserLogon", 132, api_WWkstaUserLogon
,0},
3432 {"PrintJobInfo", 147, api_PrintJobInfo
,0},
3433 {"WPrintDriverEnum", 205, api_WPrintDriverEnum
,0},
3434 {"WPrintQProcEnum", 206, api_WPrintQProcEnum
,0},
3435 {"WPrintPortEnum", 207, api_WPrintPortEnum
,0},
3437 {"SamOEMChangePassword", 214, api_SamOEMChangePassword
,0},
3438 {NULL
, -1, api_Unsupported
,0}};
3441 /****************************************************************************
3442 Handle remote api calls
3443 ****************************************************************************/
3445 static int api_reply(connection_struct
*conn
,uint16 vuid
,char *outbuf
,char *data
,char *params
,
3446 int tdscnt
,int tpscnt
,int mdrcnt
,int mprcnt
)
3450 char *rparam
= NULL
;
3457 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
3461 api_command
= SVAL(params
,0);
3463 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
3466 skip_string(params
+2,1),
3467 tdscnt
,tpscnt
,mdrcnt
,mprcnt
));
3469 for (i
=0;api_commands
[i
].name
;i
++) {
3470 if (api_commands
[i
].id
== api_command
&& api_commands
[i
].fn
) {
3471 DEBUG(3,("Doing %s\n",api_commands
[i
].name
));
3476 rdata
= (char *)malloc(1024);
3478 memset(rdata
,'\0',1024);
3480 rparam
= (char *)malloc(1024);
3482 memset(rparam
,'\0',1024);
3484 if(!rdata
|| !rparam
) {
3485 DEBUG(0,("api_reply: malloc fail !\n"));
3489 reply
= api_commands
[i
].fn(conn
,vuid
,params
,data
,mdrcnt
,mprcnt
,
3490 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
3493 if (rdata_len
> mdrcnt
||
3494 rparam_len
> mprcnt
) {
3495 reply
= api_TooSmall(conn
,vuid
,params
,data
,mdrcnt
,mprcnt
,
3496 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
3499 /* if we get False back then it's actually unsupported */
3501 api_Unsupported(conn
,vuid
,params
,data
,mdrcnt
,mprcnt
,
3502 &rdata
,&rparam
,&rdata_len
,&rparam_len
);
3504 send_trans_reply(outbuf
, rparam
, rparam_len
, rdata
, rdata_len
, False
);
3514 /****************************************************************************
3515 handle named pipe commands
3516 ****************************************************************************/
3517 static int named_pipe(connection_struct
*conn
,uint16 vuid
, char *outbuf
,char *name
,
3518 uint16
*setup
,char *data
,char *params
,
3519 int suwcnt
,int tdscnt
,int tpscnt
,
3520 int msrcnt
,int mdrcnt
,int mprcnt
)
3522 DEBUG(3,("named pipe command on <%s> name\n", name
));
3524 if (strequal(name
,"LANMAN"))
3525 return api_reply(conn
,vuid
,outbuf
,data
,params
,tdscnt
,tpscnt
,mdrcnt
,mprcnt
);
3527 if (strequal(name
,"WKSSVC") ||
3528 strequal(name
,"SRVSVC") ||
3529 strequal(name
,"WINREG") ||
3530 strequal(name
,"SAMR") ||
3531 strequal(name
,"LSARPC"))
3533 DEBUG(4,("named pipe command from Win95 (wow!)\n"));
3534 return api_fd_reply(conn
,vuid
,outbuf
,setup
,data
,params
,suwcnt
,tdscnt
,tpscnt
,mdrcnt
,mprcnt
);
3537 if (strlen(name
) < 1)
3538 return api_fd_reply(conn
,vuid
,outbuf
,setup
,data
,params
,suwcnt
,tdscnt
,tpscnt
,mdrcnt
,mprcnt
);
3541 DEBUG(3,("unknown named pipe: setup 0x%X setup1=%d\n", (int)setup
[0],(int)setup
[1]));
3547 /****************************************************************************
3548 Reply to a SMBtrans.
3549 ****************************************************************************/
3551 int reply_trans(connection_struct
*conn
, char *inbuf
,char *outbuf
, int size
, int bufsize
)
3554 int name_offset
= 0;
3555 char *data
=NULL
,*params
=NULL
;
3558 uint16 vuid
= SVAL(inbuf
,smb_uid
);
3559 unsigned int tpscnt
= SVAL(inbuf
,smb_vwv0
);
3560 unsigned int tdscnt
= SVAL(inbuf
,smb_vwv1
);
3561 unsigned int mprcnt
= SVAL(inbuf
,smb_vwv2
);
3562 unsigned int mdrcnt
= SVAL(inbuf
,smb_vwv3
);
3563 unsigned int msrcnt
= CVAL(inbuf
,smb_vwv4
);
3564 BOOL close_on_completion
= BITSETW(inbuf
+smb_vwv5
,0);
3565 BOOL one_way
= BITSETW(inbuf
+smb_vwv5
,1);
3566 unsigned int pscnt
= SVAL(inbuf
,smb_vwv9
);
3567 unsigned int psoff
= SVAL(inbuf
,smb_vwv10
);
3568 unsigned int dscnt
= SVAL(inbuf
,smb_vwv11
);
3569 unsigned int dsoff
= SVAL(inbuf
,smb_vwv12
);
3570 unsigned int suwcnt
= CVAL(inbuf
,smb_vwv13
);
3572 memset(name
, '\0',sizeof(name
));
3573 fstrcpy(name
,smb_buf(inbuf
));
3575 if (dscnt
> tdscnt
|| pscnt
> tpscnt
) {
3576 exit_server("invalid trans parameters\n");
3580 if((data
= (char *)malloc(tdscnt
)) == NULL
) {
3581 DEBUG(0,("reply_trans: data malloc fail for %u bytes !\n", tdscnt
));
3582 return(ERROR(ERRDOS
,ERRnomem
));
3584 if ((dsoff
+dscnt
< dsoff
) || (dsoff
+dscnt
< dscnt
))
3586 if (smb_base(inbuf
)+dsoff
+dscnt
> inbuf
+ size
)
3589 memcpy(data
,smb_base(inbuf
)+dsoff
,dscnt
);
3593 if((params
= (char *)malloc(tpscnt
)) == NULL
) {
3594 DEBUG(0,("reply_trans: param malloc fail for %u bytes !\n", tpscnt
));
3596 return(ERROR(ERRDOS
,ERRnomem
));
3598 if ((psoff
+pscnt
< psoff
) || (psoff
+pscnt
< pscnt
))
3600 if (smb_base(inbuf
)+psoff
+pscnt
> inbuf
+ size
)
3603 memcpy(params
,smb_base(inbuf
)+psoff
,pscnt
);
3608 if((setup
= (uint16
*)malloc(suwcnt
*sizeof(uint16
))) == NULL
) {
3609 DEBUG(0,("reply_trans: setup malloc fail for %u bytes !\n", (unsigned int)(suwcnt
* sizeof(uint16
))));
3612 return(ERROR(ERRDOS
,ERRnomem
));
3614 if (inbuf
+smb_vwv14
+(suwcnt
*SIZEOFWORD
) > inbuf
+ size
)
3616 if ((smb_vwv14
+(suwcnt
*SIZEOFWORD
) < smb_vwv14
) || (smb_vwv14
+(suwcnt
*SIZEOFWORD
) < (suwcnt
*SIZEOFWORD
)))
3619 for (i
=0;i
<suwcnt
;i
++)
3620 setup
[i
] = SVAL(inbuf
,smb_vwv14
+i
*SIZEOFWORD
);
3623 if (pscnt
< tpscnt
|| dscnt
< tdscnt
) {
3624 /* We need to send an interim response then receive the rest
3625 of the parameter/data bytes */
3626 outsize
= set_message(outbuf
,0,0,True
);
3628 send_smb(Client
,outbuf
);
3631 /* receive the rest of the trans packet */
3632 while (pscnt
< tpscnt
|| dscnt
< tdscnt
) {
3634 unsigned int pcnt
,poff
,dcnt
,doff
,pdisp
,ddisp
;
3636 ret
= receive_next_smb(inbuf
,bufsize
,SMB_SECONDARY_WAIT
);
3638 if ((ret
&& (CVAL(inbuf
, smb_com
) != SMBtranss
)) || !ret
) {
3640 DEBUG(0,("reply_trans: Invalid secondary trans packet\n"));
3642 DEBUG(0,("reply_trans: %s in getting secondary trans response.\n",
3643 (smb_read_error
== READ_ERROR
) ? "error" : "timeout" ));
3648 return(ERROR(ERRSRV
,ERRerror
));
3653 /* Revise total_params and total_data in case they have changed downwards */
3654 if (SVAL(inbuf
,smb_vwv0
) < tpscnt
)
3655 tpscnt
= SVAL(inbuf
,smb_vwv0
);
3656 if (SVAL(inbuf
,smb_vwv1
) < tdscnt
)
3657 tdscnt
= SVAL(inbuf
,smb_vwv1
);
3659 pcnt
= SVAL(inbuf
,smb_vwv2
);
3660 poff
= SVAL(inbuf
,smb_vwv3
);
3661 pdisp
= SVAL(inbuf
,smb_vwv4
);
3663 dcnt
= SVAL(inbuf
,smb_vwv5
);
3664 doff
= SVAL(inbuf
,smb_vwv6
);
3665 ddisp
= SVAL(inbuf
,smb_vwv7
);
3670 if (dscnt
> tdscnt
|| pscnt
> tpscnt
)
3674 if (pdisp
+pcnt
>= tpscnt
)
3676 if ((pdisp
+pcnt
< pdisp
) || (pdisp
+pcnt
< pcnt
))
3678 if (smb_base(inbuf
) + poff
+ pcnt
>= inbuf
+ bufsize
)
3680 if (params
+ pdisp
< params
)
3683 memcpy(params
+pdisp
,smb_base(inbuf
)+poff
,pcnt
);
3687 if (ddisp
+dcnt
>= tdscnt
)
3689 if ((ddisp
+dcnt
< ddisp
) || (ddisp
+dcnt
< dcnt
))
3691 if (smb_base(inbuf
) + doff
+ dcnt
>= inbuf
+ bufsize
)
3693 if (data
+ ddisp
< data
)
3696 memcpy(data
+ddisp
,smb_base(inbuf
)+doff
,dcnt
);
3700 DEBUG(3,("trans <%s> data=%d params=%d setup=%d\n",
3701 name
,tdscnt
,tpscnt
,suwcnt
));
3704 * WinCE wierdness....
3707 if (name
[0] == '\\' && (StrnCaseCmp(&name
[1],local_machine
, strlen(local_machine
)) == 0) &&
3708 (name
[strlen(local_machine
)+1] == '\\'))
3709 name_offset
= strlen(local_machine
)+1;
3711 if (strncmp(&name
[name_offset
],"\\PIPE\\",strlen("\\PIPE\\")) == 0) {
3712 DEBUG(5,("calling named_pipe\n"));
3713 outsize
= named_pipe(conn
,vuid
,outbuf
,
3714 name
+name_offset
+strlen("\\PIPE\\"),setup
,data
,params
,
3715 suwcnt
,tdscnt
,tpscnt
,msrcnt
,mdrcnt
,mprcnt
);
3717 DEBUG(3,("invalid pipe name\n"));
3729 if (close_on_completion
)
3730 close_cnum(conn
,vuid
);
3736 return(ERROR(ERRSRV
,ERRnosupport
));
3742 DEBUG(0,("reply_trans: invalid trans parameters\n"));
3746 return(ERROR(ERRSRV
,ERRerror
));