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 ****************************************************************************/
1666 static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param,char *data,
1667 int mdrcnt,int mprcnt,
1668 char **rdata,char **rparam,
1669 int *rdata_len,int *rparam_len)
1671 char *p = skip_string(param+2,2);
1673 fstring pass1,pass2;
1677 p = skip_string(p,1);
1679 memset(pass1,'\0',sizeof(pass1));
1680 memset(pass2,'\0',sizeof(pass2));
1682 memcpy(pass2,p+16,16);
1685 *rparam = REALLOC(*rparam,*rparam_len);
1689 SSVAL(*rparam,0,NERR_badpass);
1690 SSVAL(*rparam,2,0); /* converter word */
1692 DEBUG(3,("Set password for <%s>\n",user));
1695 * Pass the user through the NT -> unix user mapping
1699 (void)map_username(user);
1702 * Do any UNIX username case mangling.
1704 (void)Get_Pwnam( user, True);
1707 * Attempt the plaintext password change first.
1708 * Older versions of Windows seem to do this.
1711 if (password_ok(user, pass1,strlen(pass1),NULL) &&
1712 chgpasswd(user,pass1,pass2,False))
1714 SSVAL(*rparam,0,NERR_Success);
1718 * If the plaintext change failed, attempt
1719 * the encrypted. NT will generate this
1720 * after trying the samr method.
1723 if(SVAL(*rparam,0) != NERR_Success)
1725 struct smb_passwd *sampw = NULL;
1727 if(check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &sampw) &&
1728 change_lanman_password(sampw,(unsigned char *)pass1,(unsigned char *)pass2))
1730 SSVAL(*rparam,0,NERR_Success);
1734 memset((char *)pass1,'\0',sizeof(fstring));
1735 memset((char *)pass2,'\0',sizeof(fstring));
1740 /****************************************************************************
1741 Set the user password (SamOEM version - gets plaintext).
1742 ****************************************************************************/
1744 static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char *param,char *data,
1745 int mdrcnt,int mprcnt,
1746 char **rdata,char **rparam,
1747 int *rdata_len,int *rparam_len)
1750 char *p = param + 2;
1752 *rparam = REALLOC(*rparam,*rparam_len);
1756 SSVAL(*rparam,0,NERR_badpass);
1759 * Check the parameter definition is correct.
1761 if(!strequal(param + 2, "zsT")) {
1762 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", param + 2));
1765 p = skip_string(p, 1);
1767 if(!strequal(p, "B516B16")) {
1768 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p));
1771 p = skip_string(p,1);
1774 p = skip_string(p,1);
1776 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user));
1779 * Pass the user through the NT -> unix user mapping
1783 (void)map_username(user);
1786 * Do any UNIX username case mangling.
1788 (void)Get_Pwnam( user, True);
1790 if (pass_oem_change(user, (uchar*) data, (uchar *)&data[516], NULL, NULL))
1792 SSVAL(*rparam,0,NERR_Success);
1798 /****************************************************************************
1801 ****************************************************************************/
1802 static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char *param,char *data,
1803 int mdrcnt,int mprcnt,
1804 char **rdata,char **rparam,
1805 int *rdata_len,int *rparam_len)
1807 int function = SVAL(param,0);
1808 char *str1 = param+2;
1809 char *str2 = skip_string(str1,1);
1810 char *p = skip_string(str2,1);
1814 printjob_decode(SVAL(p,0), &snum, &jobid);
1816 /* check it's a supported varient */
1817 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
1821 *rparam = REALLOC(*rparam,*rparam_len);
1825 SSVAL(*rparam,0,NERR_Success);
1827 if (snum >= 0 && VALID_SNUM(snum))
1829 print_queue_struct *queue=NULL;
1831 count = get_printqueue(snum,conn,&queue,NULL);
1833 for (i=0;i<count;i++)
1834 if ((queue[i].job&0xFF) == jobid)
1837 case 81: /* delete */
1838 DEBUG(3,("Deleting queue entry %d\n",queue[i].job));
1839 del_printqueue(conn,snum,queue[i].job);
1841 case 82: /* pause */
1842 case 83: /* resume */
1843 DEBUG(3,("%s queue entry %d\n",
1844 (function==82?"pausing":"resuming"),queue[i].job));
1845 status_printjob(conn,snum,queue[i].job,
1846 (function==82?LPQ_PAUSED:LPQ_QUEUED));
1853 SSVAL(*rparam,0,NERR_JobNotFound);
1855 if (queue) free(queue);
1858 SSVAL(*rparam,2,0); /* converter word */
1863 /****************************************************************************
1864 Purge a print queue - or pause or resume it.
1865 ****************************************************************************/
1866 static BOOL api_WPrintQueuePurge(connection_struct *conn,uint16 vuid, char *param,char *data,
1867 int mdrcnt,int mprcnt,
1868 char **rdata,char **rparam,
1869 int *rdata_len,int *rparam_len)
1871 int function = SVAL(param,0);
1872 char *str1 = param+2;
1873 char *str2 = skip_string(str1,1);
1874 char *QueueName = skip_string(str2,1);
1877 /* check it's a supported varient */
1878 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
1882 *rparam = REALLOC(*rparam,*rparam_len);
1886 SSVAL(*rparam,0,NERR_Success);
1887 SSVAL(*rparam,2,0); /* converter word */
1889 snum = lp_servicenumber(QueueName);
1890 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
1891 int pnum = lp_servicenumber(PRINTERS_NAME);
1893 lp_add_printer(QueueName,pnum);
1894 snum = lp_servicenumber(QueueName);
1898 if (snum >= 0 && VALID_SNUM(snum)) {
1902 case 74: /* Pause queue */
1903 case 75: /* Resume queue */
1904 status_printqueue(conn,snum,(function==74?LPSTAT_STOPPED:LPSTAT_OK));
1905 DEBUG(3,("Print queue %s, queue=%s\n",
1906 (function==74?"pause":"resume"),QueueName));
1908 case 103: /* Purge */
1910 print_queue_struct *queue=NULL;
1912 count = get_printqueue(snum,conn,&queue,NULL);
1913 for (i = 0; i < count; i++)
1914 del_printqueue(conn,snum,queue[i].job);
1916 if (queue) free(queue);
1917 DEBUG(3,("Print queue purge, queue=%s\n",QueueName));
1927 /****************************************************************************
1928 set the property of a print job (undocumented?)
1929 ? function = 0xb -> set name of print job
1930 ? function = 0x6 -> move print job up/down
1931 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
1932 or <WWsTP> <WB21BB16B10zWWzDDz>
1933 ****************************************************************************/
1934 static int check_printjob_info(struct pack_desc* desc,
1935 int uLevel, char* id)
1937 desc->subformat = NULL;
1939 case 0: desc->format = "W"; break;
1940 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
1941 case 2: desc->format = "WWzWWDDzz"; break;
1942 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
1943 default: return False;
1945 if (strcmp(desc->format,id) != 0) return False;
1949 static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,char *data,
1950 int mdrcnt,int mprcnt,
1951 char **rdata,char **rparam,
1952 int *rdata_len,int *rparam_len)
1954 struct pack_desc desc;
1955 char *str1 = param+2;
1956 char *str2 = skip_string(str1,1);
1957 char *p = skip_string(str2,1);
1959 int uLevel = SVAL(p,2);
1960 int function = SVAL(p,4); /* what is this ?? */
1965 printjob_decode(SVAL(p,0), &snum, &jobid);
1968 *rparam = REALLOC(*rparam,*rparam_len);
1972 /* check it's a supported varient */
1973 if ((strcmp(str1,"WWsTP")) ||
1974 (!check_printjob_info(&desc,uLevel,str2)))
1978 case 0x6: /* change job place in the queue,
1979 data gives the new place */
1980 if (snum >= 0 && VALID_SNUM(snum)) {
1981 print_queue_struct *queue=NULL;
1985 count = get_printqueue(snum,conn,&queue,NULL);
1986 for (i=0;i<count;i++) /* find job */
1987 if ((queue[i].job&0xFF) == jobid) break;
1990 desc.errcode=NERR_JobNotFound;
1991 if (queue) free(queue);
1993 desc.errcode=NERR_Success;
1997 int place= SVAL(data,0);
1998 /* we currently have no way of
1999 doing this. Can any unix do it? */
2000 if (i < place) /* move down */;
2001 else if (i > place ) /* move up */;
2004 desc.errcode=NERR_notsupported; /* not yet
2006 if (queue) free(queue);
2009 desc.errcode=NERR_JobNotFound;
2013 case 0xb: /* change print job name, data gives the name */
2014 /* jobid, snum should be zero */
2015 if (isalpha((int)*s)) {
2018 while (l<64 && *s) {
2019 if (issafe(*s)) name[l++] = *s;
2024 DEBUG(3,("Setting print name to %s\n",name));
2026 fsp = file_find_print();
2029 connection_struct *fconn = fsp->conn;
2032 if (!become_user(fconn,vuid) ||
2033 !become_service(fconn,True))
2036 if (dos_rename(fsp->fsp_name,name) == 0) {
2037 string_set(&fsp->fsp_name,name);
2042 desc.errcode=NERR_Success;
2045 default: /* not implemented */
2049 SSVALS(*rparam,0,desc.errcode);
2050 SSVAL(*rparam,2,0); /* converter word */
2056 /****************************************************************************
2057 get info about the server
2058 ****************************************************************************/
2059 static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2060 int mdrcnt,int mprcnt,
2061 char **rdata,char **rparam,
2062 int *rdata_len,int *rparam_len)
2064 char *str1 = param+2;
2065 char *str2 = skip_string(str1,1);
2066 char *p = skip_string(str2,1);
2067 int uLevel = SVAL(p,0);
2071 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
2073 /* check it's a supported varient */
2074 if (!prefix_ok(str1,"WrLh")) return False;
2077 if (strcmp(str2,"B16") != 0) return False;
2081 if (strcmp(str2,"B16BBDz") != 0) return False;
2085 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")
2090 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz")
2095 if (strcmp(str2,"DN") != 0) return False;
2099 if (strcmp(str2,"B16BBDzWWzzz") != 0) return False;
2102 default: return False;
2105 *rdata_len = mdrcnt;
2106 *rdata = REALLOC(*rdata,*rdata_len);
2109 p2 = p + struct_len;
2111 StrnCpy(p,local_machine,16);
2117 struct srv_info_struct *servers=NULL;
2120 uint32 servertype= lp_default_server_announce();
2122 pstrcpy(comment,string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH));
2124 if ((count=get_server_info(SV_TYPE_ALL,&servers,global_myworkgroup))>0) {
2125 for (i=0;i<count;i++)
2126 if (strequal(servers[i].name,local_machine))
2128 servertype = servers[i].type;
2129 pstrcpy(comment,servers[i].comment);
2132 if (servers) free(servers);
2134 SCVAL(p,0,lp_major_announce_version());
2135 SCVAL(p,1,lp_minor_announce_version());
2136 SIVAL(p,2,servertype);
2138 if (mdrcnt == struct_len) {
2141 SIVAL(p,6,PTR_DIFF(p2,*rdata));
2142 standard_sub(conn,comment);
2143 StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
2144 p2 = skip_string(p2,1);
2149 return False; /* not yet implemented */
2152 *rdata_len = PTR_DIFF(p2,*rdata);
2155 *rparam = REALLOC(*rparam,*rparam_len);
2156 SSVAL(*rparam,0,NERR_Success);
2157 SSVAL(*rparam,2,0); /* converter word */
2158 SSVAL(*rparam,4,*rdata_len);
2164 /****************************************************************************
2165 get info about the server
2166 ****************************************************************************/
2167 static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2168 int mdrcnt,int mprcnt,
2169 char **rdata,char **rparam,
2170 int *rdata_len,int *rparam_len)
2172 char *str1 = param+2;
2173 char *str2 = skip_string(str1,1);
2174 char *p = skip_string(str2,1);
2176 extern pstring sesssetup_user;
2177 int level = SVAL(p,0);
2179 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
2182 *rparam = REALLOC(*rparam,*rparam_len);
2184 /* check it's a supported varient */
2185 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz")))
2188 *rdata_len = mdrcnt + 1024;
2189 *rdata = REALLOC(*rdata,*rdata_len);
2191 SSVAL(*rparam,0,NERR_Success);
2192 SSVAL(*rparam,2,0); /* converter word */
2198 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
2199 pstrcpy(p2,local_machine);
2201 p2 = skip_string(p2,1);
2204 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2205 pstrcpy(p2,sesssetup_user);
2206 p2 = skip_string(p2,1);
2209 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
2210 pstrcpy(p2,global_myworkgroup);
2212 p2 = skip_string(p2,1);
2215 SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
2216 SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
2219 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2220 pstrcpy(p2,global_myworkgroup); /* don't know. login domain?? */
2221 p2 = skip_string(p2,1);
2224 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
2226 p2 = skip_string(p2,1);
2229 *rdata_len = PTR_DIFF(p2,*rdata);
2231 SSVAL(*rparam,4,*rdata_len);
2236 /****************************************************************************
2237 get info about a user
2239 struct user_info_11 {
2240 char usri11_name[21]; 0-20
2242 char *usri11_comment; 22-25
2243 char *usri11_usr_comment; 26-29
2244 unsigned short usri11_priv; 30-31
2245 unsigned long usri11_auth_flags; 32-35
2246 long usri11_password_age; 36-39
2247 char *usri11_homedir; 40-43
2248 char *usri11_parms; 44-47
2249 long usri11_last_logon; 48-51
2250 long usri11_last_logoff; 52-55
2251 unsigned short usri11_bad_pw_count; 56-57
2252 unsigned short usri11_num_logons; 58-59
2253 char *usri11_logon_server; 60-63
2254 unsigned short usri11_country_code; 64-65
2255 char *usri11_workstations; 66-69
2256 unsigned long usri11_max_storage; 70-73
2257 unsigned short usri11_units_per_week; 74-75
2258 unsigned char *usri11_logon_hours; 76-79
2259 unsigned short usri11_code_page; 80-81
2264 usri11_name specifies the user name for which information is retireved
2266 usri11_pad aligns the next data structure element to a word boundary
2268 usri11_comment is a null terminated ASCII comment
2270 usri11_user_comment is a null terminated ASCII comment about the user
2272 usri11_priv specifies the level of the privilege assigned to the user.
2273 The possible values are:
2275 Name Value Description
2276 USER_PRIV_GUEST 0 Guest privilege
2277 USER_PRIV_USER 1 User privilege
2278 USER_PRV_ADMIN 2 Administrator privilege
2280 usri11_auth_flags specifies the account operator privileges. The
2281 possible values are:
2283 Name Value Description
2284 AF_OP_PRINT 0 Print operator
2287 Leach, Naik [Page 28]
\r\f
2290 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2293 AF_OP_COMM 1 Communications operator
2294 AF_OP_SERVER 2 Server operator
2295 AF_OP_ACCOUNTS 3 Accounts operator
2298 usri11_password_age specifies how many seconds have elapsed since the
2299 password was last changed.
2301 usri11_home_dir points to a null terminated ASCII string that contains
2302 the path name of the user's home directory.
2304 usri11_parms points to a null terminated ASCII string that is set
2305 aside for use by applications.
2307 usri11_last_logon specifies the time when the user last logged on.
2308 This value is stored as the number of seconds elapsed since
2309 00:00:00, January 1, 1970.
2311 usri11_last_logoff specifies the time when the user last logged off.
2312 This value is stored as the number of seconds elapsed since
2313 00:00:00, January 1, 1970. A value of 0 means the last logoff
2316 usri11_bad_pw_count specifies the number of incorrect passwords
2317 entered since the last successful logon.
2319 usri11_log1_num_logons specifies the number of times this user has
2320 logged on. A value of -1 means the number of logons is unknown.
2322 usri11_logon_server points to a null terminated ASCII string that
2323 contains the name of the server to which logon requests are sent.
2324 A null string indicates logon requests should be sent to the
2327 usri11_country_code specifies the country code for the user's language
2330 usri11_workstations points to a null terminated ASCII string that
2331 contains the names of workstations the user may log on from.
2332 There may be up to 8 workstations, with the names separated by
2333 commas. A null strings indicates there are no restrictions.
2335 usri11_max_storage specifies the maximum amount of disk space the user
2336 can occupy. A value of 0xffffffff indicates there are no
2339 usri11_units_per_week specifies the equal number of time units into
2340 which a week is divided. This value must be equal to 168.
2342 usri11_logon_hours points to a 21 byte (168 bits) string that
2343 specifies the time during which the user can log on. Each bit
2344 represents one unique hour in a week. The first bit (bit 0, word
2345 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
2349 Leach, Naik [Page 29]
\r\f
2352 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2355 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
2356 are no restrictions.
2358 usri11_code_page specifies the code page for the user's language of
2361 All of the pointers in this data structure need to be treated
2362 specially. The pointer is a 32 bit pointer. The higher 16 bits need
2363 to be ignored. The converter word returned in the parameters section
2364 needs to be subtracted from the lower 16 bits to calculate an offset
2365 into the return buffer where this ASCII string resides.
2367 There is no auxiliary data in the response.
2369 ****************************************************************************/
2371 #define usri11_name 0
2372 #define usri11_pad 21
2373 #define usri11_comment 22
2374 #define usri11_usr_comment 26
2375 #define usri11_full_name 30
2376 #define usri11_priv 34
2377 #define usri11_auth_flags 36
2378 #define usri11_password_age 40
2379 #define usri11_homedir 44
2380 #define usri11_parms 48
2381 #define usri11_last_logon 52
2382 #define usri11_last_logoff 56
2383 #define usri11_bad_pw_count 60
2384 #define usri11_num_logons 62
2385 #define usri11_logon_server 64
2386 #define usri11_country_code 68
2387 #define usri11_workstations 70
2388 #define usri11_max_storage 74
2389 #define usri11_units_per_week 78
2390 #define usri11_logon_hours 80
2391 #define usri11_code_page 84
2392 #define usri11_end 86
2394 #define USER_PRIV_GUEST 0
2395 #define USER_PRIV_USER 1
2396 #define USER_PRIV_ADMIN 2
2398 #define AF_OP_PRINT 0
2399 #define AF_OP_COMM 1
2400 #define AF_OP_SERVER 2
2401 #define AF_OP_ACCOUNTS 3
2404 static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2405 int mdrcnt,int mprcnt,
2406 char **rdata,char **rparam,
2407 int *rdata_len,int *rparam_len)
2409 char *str1 = param+2;
2410 char *str2 = skip_string(str1,1);
2411 char *UserName = skip_string(str2,1);
2412 char *p = skip_string(UserName,1);
2413 int uLevel = SVAL(p,0);
2416 /* get NIS home of a previously validated user - simeon */
2417 /* With share level security vuid will always be zero.
2418 Don't depend on vuser being non-null !!. JRA */
2419 user_struct *vuser = get_valid_user_struct(vuid);
2421 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid, vuser->name));
2424 *rparam = REALLOC(*rparam,*rparam_len);
2426 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
2428 /* check it's a supported variant */
2429 if (strcmp(str1,"zWrLh") != 0) return False;
2432 case 0: p2 = "B21"; break;
2433 case 1: p2 = "B21BB16DWzzWz"; break;
2434 case 2: p2 = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
2435 case 10: p2 = "B21Bzzz"; break;
2436 case 11: p2 = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
2437 default: return False;
2440 if (strcmp(p2,str2) != 0) return False;
2442 *rdata_len = mdrcnt + 1024;
2443 *rdata = REALLOC(*rdata,*rdata_len);
2445 SSVAL(*rparam,0,NERR_Success);
2446 SSVAL(*rparam,2,0); /* converter word */
2449 p2 = p + usri11_end;
2452 fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
2456 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
2461 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
2462 pstrcpy(p2,"Comment");
2463 p2 = skip_string(p2,1);
2465 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
2466 pstrcpy(p2,"UserComment");
2467 p2 = skip_string(p2,1);
2469 /* EEK! the cifsrap.txt doesn't have this in!!!! */
2470 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
2471 pstrcpy(p2,((vuser != NULL) ? vuser->real_name : UserName));
2472 p2 = skip_string(p2,1);
2475 if (uLevel == 11) /* modelled after NTAS 3.51 reply */
2477 SSVAL(p,usri11_priv,conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2478 SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
2479 SIVALS(p,usri11_password_age,-1); /* password age */
2480 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
2481 pstrcpy(p2, lp_logon_home());
2482 p2 = skip_string(p2,1);
2483 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
2485 p2 = skip_string(p2,1);
2486 SIVAL(p,usri11_last_logon,0); /* last logon */
2487 SIVAL(p,usri11_last_logoff,0); /* last logoff */
2488 SSVALS(p,usri11_bad_pw_count,-1); /* bad pw counts */
2489 SSVALS(p,usri11_num_logons,-1); /* num logons */
2490 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
2491 pstrcpy(p2,"\\\\*");
2492 p2 = skip_string(p2,1);
2493 SSVAL(p,usri11_country_code,0); /* country code */
2495 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
2497 p2 = skip_string(p2,1);
2499 SIVALS(p,usri11_max_storage,-1); /* max storage */
2500 SSVAL(p,usri11_units_per_week,168); /* units per week */
2501 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
2503 /* a simple way to get logon hours at all times. */
2505 SCVAL(p2,21,0); /* fix zero termination */
2506 p2 = skip_string(p2,1);
2508 SSVAL(p,usri11_code_page,0); /* code page */
2510 if (uLevel == 1 || uLevel == 2)
2512 memset(p+22,' ',16); /* password */
2513 SIVALS(p,38,-1); /* password age */
2515 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2516 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
2517 pstrcpy(p2,lp_logon_home());
2518 p2 = skip_string(p2,1);
2519 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
2521 SSVAL(p,52,0); /* flags */
2522 SIVAL(p,54,PTR_DIFF(p2,*rdata)); /* script_path */
2523 pstrcpy(p2,lp_logon_script());
2524 standard_sub( conn, p2 );
2525 p2 = skip_string(p2,1);
2528 SIVAL(p,60,0); /* auth_flags */
2529 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
2530 pstrcpy(p2,((vuser != NULL) ? vuser->real_name : UserName));
2531 p2 = skip_string(p2,1);
2532 SIVAL(p,68,0); /* urs_comment */
2533 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
2535 p2 = skip_string(p2,1);
2536 SIVAL(p,76,0); /* workstations */
2537 SIVAL(p,80,0); /* last_logon */
2538 SIVAL(p,84,0); /* last_logoff */
2539 SIVALS(p,88,-1); /* acct_expires */
2540 SIVALS(p,92,-1); /* max_storage */
2541 SSVAL(p,96,168); /* units_per_week */
2542 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
2545 SSVALS(p,102,-1); /* bad_pw_count */
2546 SSVALS(p,104,-1); /* num_logons */
2547 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
2548 pstrcpy(p2,"\\\\%L");
2549 standard_sub_basic(p2);
2550 p2 = skip_string(p2,1);
2551 SSVAL(p,110,49); /* country_code */
2552 SSVAL(p,112,860); /* code page */
2556 *rdata_len = PTR_DIFF(p2,*rdata);
2558 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
2563 /*******************************************************************
2564 get groups that a user is a member of
2565 ******************************************************************/
2566 static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *param,char *data,
2567 int mdrcnt,int mprcnt,
2568 char **rdata,char **rparam,
2569 int *rdata_len,int *rparam_len)
2571 char *str1 = param+2;
2572 char *str2 = skip_string(str1,1);
2573 char *UserName = skip_string(str2,1);
2574 char *p = skip_string(UserName,1);
2575 int uLevel = SVAL(p,0);
2580 *rparam = REALLOC(*rparam,*rparam_len);
2582 /* check it's a supported varient */
2583 if (strcmp(str1,"zWrLeh") != 0) return False;
2585 case 0: p2 = "B21"; break;
2586 default: return False;
2588 if (strcmp(p2,str2) != 0) return False;
2590 *rdata_len = mdrcnt + 1024;
2591 *rdata = REALLOC(*rdata,*rdata_len);
2593 SSVAL(*rparam,0,NERR_Success);
2594 SSVAL(*rparam,2,0); /* converter word */
2598 /* XXXX we need a real SAM database some day */
2599 pstrcpy(p,"Users"); p += 21; count++;
2600 pstrcpy(p,"Domain Users"); p += 21; count++;
2601 pstrcpy(p,"Guests"); p += 21; count++;
2602 pstrcpy(p,"Domain Guests"); p += 21; count++;
2604 *rdata_len = PTR_DIFF(p,*rdata);
2606 SSVAL(*rparam,4,count); /* is this right?? */
2607 SSVAL(*rparam,6,count); /* is this right?? */
2613 static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param,char *data,
2614 int mdrcnt,int mprcnt,
2615 char **rdata,char **rparam,
2616 int *rdata_len,int *rparam_len)
2618 char *str1 = param+2;
2619 char *str2 = skip_string(str1,1);
2620 char *p = skip_string(str2,1);
2622 struct pack_desc desc;
2628 memset((char *)&desc,'\0',sizeof(desc));
2630 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
2632 /* check it's a supported varient */
2633 if (strcmp(str1,"OOWb54WrLh") != 0) return False;
2634 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) return False;
2635 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2637 desc.buflen = mdrcnt;
2638 desc.subformat = NULL;
2641 if (init_package(&desc,1,0))
2643 PACKI(&desc,"W",0); /* code */
2644 PACKS(&desc,"B21",name); /* eff. name */
2645 PACKS(&desc,"B",""); /* pad */
2647 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2648 PACKI(&desc,"D",0); /* auth flags XXX */
2649 PACKI(&desc,"W",0); /* num logons */
2650 PACKI(&desc,"W",0); /* bad pw count */
2651 PACKI(&desc,"D",0); /* last logon */
2652 PACKI(&desc,"D",-1); /* last logoff */
2653 PACKI(&desc,"D",-1); /* logoff time */
2654 PACKI(&desc,"D",-1); /* kickoff time */
2655 PACKI(&desc,"D",0); /* password age */
2656 PACKI(&desc,"D",0); /* password can change */
2657 PACKI(&desc,"D",-1); /* password must change */
2660 fstrcpy(mypath,"\\\\");
2661 fstrcat(mypath,local_machine);
2663 PACKS(&desc,"z",mypath); /* computer */
2665 PACKS(&desc,"z",global_myworkgroup);/* domain */
2667 /* JHT - By calling lp_logon_script() and standard_sub() we have */
2668 /* made sure all macros are fully substituted and available */
2670 pstring logon_script;
2671 pstrcpy(logon_script,lp_logon_script());
2672 standard_sub( conn, logon_script );
2673 PACKS(&desc,"z", logon_script); /* script path */
2675 /* End of JHT mods */
2677 PACKI(&desc,"D",0x00000000); /* reserved */
2680 *rdata_len = desc.usedlen;
2682 *rparam = REALLOC(*rparam,*rparam_len);
2683 SSVALS(*rparam,0,desc.errcode);
2685 SSVAL(*rparam,4,desc.neededlen);
2687 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
2692 /****************************************************************************
2693 api_WAccessGetUserPerms
2694 ****************************************************************************/
2695 static BOOL api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid, char *param,char *data,
2696 int mdrcnt,int mprcnt,
2697 char **rdata,char **rparam,
2698 int *rdata_len,int *rparam_len)
2700 char *str1 = param+2;
2701 char *str2 = skip_string(str1,1);
2702 char *user = skip_string(str2,1);
2703 char *resource = skip_string(user,1);
2705 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
2707 /* check it's a supported varient */
2708 if (strcmp(str1,"zzh") != 0) return False;
2709 if (strcmp(str2,"") != 0) return False;
2712 *rparam = REALLOC(*rparam,*rparam_len);
2713 SSVALS(*rparam,0,0); /* errorcode */
2714 SSVAL(*rparam,2,0); /* converter word */
2715 SSVAL(*rparam,4,0x7f); /* permission flags */
2720 /****************************************************************************
2721 api_WPrintJobEnumerate
2722 ****************************************************************************/
2723 static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2724 int mdrcnt,int mprcnt,
2725 char **rdata,char **rparam,
2726 int *rdata_len,int *rparam_len)
2728 char *str1 = param+2;
2729 char *str2 = skip_string(str1,1);
2730 char *p = skip_string(str2,1);
2736 struct pack_desc desc;
2737 print_queue_struct *queue=NULL;
2738 print_status_struct status;
2742 memset((char *)&desc,'\0',sizeof(desc));
2743 memset((char *)&status,'\0',sizeof(status));
2745 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
2747 /* check it's a supported varient */
2748 if (strcmp(str1,"WWrLh") != 0) return False;
2749 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2751 printjob_decode(SVAL(p,0), &snum, &job);
2753 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2755 count = get_printqueue(snum,conn,&queue,&status);
2756 for (i = 0; i < count; i++) {
2757 if ((queue[i].job & 0xFF) == job) break;
2759 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2761 desc.buflen = mdrcnt;
2763 if (init_package(&desc,1,0)) {
2765 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
2766 *rdata_len = desc.usedlen;
2769 desc.errcode = NERR_JobNotFound;
2775 *rparam = REALLOC(*rparam,*rparam_len);
2776 SSVALS(*rparam,0,desc.errcode);
2778 SSVAL(*rparam,4,desc.neededlen);
2780 if (queue) free(queue);
2782 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
2786 static BOOL api_WPrintJobEnumerate(connection_struct *conn,uint16 vuid, char *param,char *data,
2787 int mdrcnt,int mprcnt,
2788 char **rdata,char **rparam,
2789 int *rdata_len,int *rparam_len)
2791 char *str1 = param+2;
2792 char *str2 = skip_string(str1,1);
2793 char *p = skip_string(str2,1);
2799 struct pack_desc desc;
2800 print_queue_struct *queue=NULL;
2801 print_status_struct status;
2803 memset((char *)&desc,'\0',sizeof(desc));
2804 memset((char *)&status,'\0',sizeof(status));
2806 p = skip_string(p,1);
2809 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
2811 /* check it's a supported varient */
2812 if (strcmp(str1,"zWrLeh") != 0) return False;
2813 if (uLevel > 2) return False; /* defined only for uLevel 0,1,2 */
2814 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2816 snum = lp_servicenumber(name);
2817 if (snum < 0 && pcap_printername_ok(name,NULL)) {
2818 int pnum = lp_servicenumber(PRINTERS_NAME);
2820 lp_add_printer(name,pnum);
2821 snum = lp_servicenumber(name);
2825 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2827 count = get_printqueue(snum,conn,&queue,&status);
2828 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2830 desc.buflen = mdrcnt;
2832 if (init_package(&desc,count,0)) {
2834 for (i = 0; i < count; i++) {
2835 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
2836 if (desc.errcode == NERR_Success) succnt = i+1;
2840 *rdata_len = desc.usedlen;
2843 *rparam = REALLOC(*rparam,*rparam_len);
2844 SSVALS(*rparam,0,desc.errcode);
2846 SSVAL(*rparam,4,succnt);
2847 SSVAL(*rparam,6,count);
2849 if (queue) free(queue);
2851 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
2855 static int check_printdest_info(struct pack_desc* desc,
2856 int uLevel, char* id)
2858 desc->subformat = NULL;
2860 case 0: desc->format = "B9"; break;
2861 case 1: desc->format = "B9B21WWzW"; break;
2862 case 2: desc->format = "z"; break;
2863 case 3: desc->format = "zzzWWzzzWW"; break;
2864 default: return False;
2866 if (strcmp(desc->format,id) != 0) return False;
2870 static void fill_printdest_info(connection_struct *conn, int snum, int uLevel,
2871 struct pack_desc* desc)
2874 strncpy(buf,SERVICE(snum),sizeof(buf)-1);
2875 buf[sizeof(buf)-1] = 0;
2878 PACKS(desc,"B9",buf); /* szName */
2880 PACKS(desc,"B21",""); /* szUserName */
2881 PACKI(desc,"W",0); /* uJobId */
2882 PACKI(desc,"W",0); /* fsStatus */
2883 PACKS(desc,"z",""); /* pszStatus */
2884 PACKI(desc,"W",0); /* time */
2887 if (uLevel == 2 || uLevel == 3) {
2888 PACKS(desc,"z",buf); /* pszPrinterName */
2890 PACKS(desc,"z",""); /* pszUserName */
2891 PACKS(desc,"z",""); /* pszLogAddr */
2892 PACKI(desc,"W",0); /* uJobId */
2893 PACKI(desc,"W",0); /* fsStatus */
2894 PACKS(desc,"z",""); /* pszStatus */
2895 PACKS(desc,"z",""); /* pszComment */
2896 PACKS(desc,"z","NULL"); /* pszDrivers */
2897 PACKI(desc,"W",0); /* time */
2898 PACKI(desc,"W",0); /* pad1 */
2903 static BOOL api_WPrintDestGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2904 int mdrcnt,int mprcnt,
2905 char **rdata,char **rparam,
2906 int *rdata_len,int *rparam_len)
2908 char *str1 = param+2;
2909 char *str2 = skip_string(str1,1);
2910 char *p = skip_string(str2,1);
2911 char* PrinterName = p;
2913 struct pack_desc desc;
2916 memset((char *)&desc,'\0',sizeof(desc));
2918 p = skip_string(p,1);
2921 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
2923 /* check it's a supported varient */
2924 if (strcmp(str1,"zWrLh") != 0) return False;
2925 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2927 snum = lp_servicenumber(PrinterName);
2928 if (snum < 0 && pcap_printername_ok(PrinterName,NULL)) {
2929 int pnum = lp_servicenumber(PRINTERS_NAME);
2931 lp_add_printer(PrinterName,pnum);
2932 snum = lp_servicenumber(PrinterName);
2938 desc.errcode = NERR_DestNotFound;
2942 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2944 desc.buflen = mdrcnt;
2945 if (init_package(&desc,1,0)) {
2946 fill_printdest_info(conn,snum,uLevel,&desc);
2948 *rdata_len = desc.usedlen;
2952 *rparam = REALLOC(*rparam,*rparam_len);
2953 SSVALS(*rparam,0,desc.errcode);
2955 SSVAL(*rparam,4,desc.neededlen);
2957 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
2961 static BOOL api_WPrintDestEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
2962 int mdrcnt,int mprcnt,
2963 char **rdata,char **rparam,
2964 int *rdata_len,int *rparam_len)
2966 char *str1 = param+2;
2967 char *str2 = skip_string(str1,1);
2968 char *p = skip_string(str2,1);
2972 struct pack_desc desc;
2973 int services = lp_numservices();
2975 memset((char *)&desc,'\0',sizeof(desc));
2979 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
2981 /* check it's a supported varient */
2982 if (strcmp(str1,"WrLeh") != 0) return False;
2983 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2986 for (i = 0; i < services; i++)
2987 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
2990 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2992 desc.buflen = mdrcnt;
2993 if (init_package(&desc,queuecnt,0)) {
2996 for (i = 0; i < services; i++) {
2997 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
2998 fill_printdest_info(conn,i,uLevel,&desc);
3000 if (desc.errcode == NERR_Success) succnt = n;
3005 *rdata_len = desc.usedlen;
3008 *rparam = REALLOC(*rparam,*rparam_len);
3009 SSVALS(*rparam,0,desc.errcode);
3011 SSVAL(*rparam,4,succnt);
3012 SSVAL(*rparam,6,queuecnt);
3014 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
3018 static BOOL api_WPrintDriverEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3019 int mdrcnt,int mprcnt,
3020 char **rdata,char **rparam,
3021 int *rdata_len,int *rparam_len)
3023 char *str1 = param+2;
3024 char *str2 = skip_string(str1,1);
3025 char *p = skip_string(str2,1);
3028 struct pack_desc desc;
3030 memset((char *)&desc,'\0',sizeof(desc));
3034 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
3036 /* check it's a supported varient */
3037 if (strcmp(str1,"WrLeh") != 0) return False;
3038 if (uLevel != 0 || strcmp(str2,"B41") != 0) return False;
3040 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3042 desc.buflen = mdrcnt;
3043 if (init_package(&desc,1,0)) {
3044 PACKS(&desc,"B41","NULL");
3047 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3049 *rdata_len = desc.usedlen;
3052 *rparam = REALLOC(*rparam,*rparam_len);
3053 SSVALS(*rparam,0,desc.errcode);
3055 SSVAL(*rparam,4,succnt);
3058 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
3062 static BOOL api_WPrintQProcEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3063 int mdrcnt,int mprcnt,
3064 char **rdata,char **rparam,
3065 int *rdata_len,int *rparam_len)
3067 char *str1 = param+2;
3068 char *str2 = skip_string(str1,1);
3069 char *p = skip_string(str2,1);
3072 struct pack_desc desc;
3074 memset((char *)&desc,'\0',sizeof(desc));
3078 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
3080 /* check it's a supported varient */
3081 if (strcmp(str1,"WrLeh") != 0) return False;
3082 if (uLevel != 0 || strcmp(str2,"B13") != 0) return False;
3084 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3086 desc.buflen = mdrcnt;
3088 if (init_package(&desc,1,0)) {
3089 PACKS(&desc,"B13","lpd");
3092 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3094 *rdata_len = desc.usedlen;
3097 *rparam = REALLOC(*rparam,*rparam_len);
3098 SSVALS(*rparam,0,desc.errcode);
3100 SSVAL(*rparam,4,succnt);
3103 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
3107 static BOOL api_WPrintPortEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3108 int mdrcnt,int mprcnt,
3109 char **rdata,char **rparam,
3110 int *rdata_len,int *rparam_len)
3112 char *str1 = param+2;
3113 char *str2 = skip_string(str1,1);
3114 char *p = skip_string(str2,1);
3117 struct pack_desc desc;
3119 memset((char *)&desc,'\0',sizeof(desc));
3123 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
3125 /* check it's a supported varient */
3126 if (strcmp(str1,"WrLeh") != 0) return False;
3127 if (uLevel != 0 || strcmp(str2,"B9") != 0) return False;
3129 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3130 memset((char *)&desc,'\0',sizeof(desc));
3132 desc.buflen = mdrcnt;
3134 if (init_package(&desc,1,0)) {
3135 PACKS(&desc,"B13","lp0");
3138 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3140 *rdata_len = desc.usedlen;
3143 *rparam = REALLOC(*rparam,*rparam_len);
3144 SSVALS(*rparam,0,desc.errcode);
3146 SSVAL(*rparam,4,succnt);
3149 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
3153 /****************************************************************************
3154 Start the first part of an RPC reply which began with an SMBtrans request.
3155 ****************************************************************************/
3157 static BOOL api_rpc_trans_reply(char *outbuf, pipes_struct *p)
3159 char *rdata = malloc(p->max_trans_reply);
3163 DEBUG(0,("api_rpc_trans_reply: malloc fail.\n"));
3167 if((data_len = read_from_pipe( p, rdata, p->max_trans_reply)) < 0) {
3172 send_trans_reply(outbuf, NULL, 0, rdata, data_len, (int)prs_offset(&p->rdata) > data_len);
3178 /****************************************************************************
3179 WaitNamedPipeHandleState
3180 ****************************************************************************/
3182 static BOOL api_WNPHS(char *outbuf, pipes_struct *p, char *param, int param_len)
3186 if (!param || param_len < 2)
3189 priority = SVAL(param,0);
3190 DEBUG(4,("WaitNamedPipeHandleState priority %x\n", priority));
3192 if (wait_rpc_pipe_hnd_state(p, priority)) {
3193 /* now send the reply */
3194 send_trans_reply(outbuf, NULL, 0, NULL, 0, False);
3201 /****************************************************************************
3202 SetNamedPipeHandleState
3203 ****************************************************************************/
3205 static BOOL api_SNPHS(char *outbuf, pipes_struct *p, char *param, int param_len)
3209 if (!param || param_len < 2)
3213 DEBUG(4,("SetNamedPipeHandleState to code %x\n", id));
3215 if (set_rpc_pipe_hnd_state(p, id)) {
3216 /* now send the reply */
3217 send_trans_reply(outbuf, NULL, 0, NULL, 0, False);
3224 /****************************************************************************
3225 When no reply is generated, indicate unsupported.
3226 ****************************************************************************/
3228 static BOOL api_no_reply(char *outbuf, int max_rdata_len)
3233 SSVAL(rparam,0,NERR_notsupported);
3234 SSVAL(rparam,2,0); /* converter word */
3236 DEBUG(3,("Unsupported API fd command\n"));
3238 /* now send the reply */
3239 send_trans_reply(outbuf, rparam, 4, NULL, 0, False);
3244 /****************************************************************************
3245 Handle remote api calls delivered to a named pipe already opened.
3246 ****************************************************************************/
3248 static int api_fd_reply(connection_struct *conn,uint16 vuid,char *outbuf,
3249 uint16 *setup,char *data,char *params,
3250 int suwcnt,int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
3253 pipes_struct *p = NULL;
3257 DEBUG(5,("api_fd_reply\n"));
3259 /* First find out the name of this file. */
3261 DEBUG(0,("Unexpected named pipe transaction.\n"));
3265 /* Get the file handle and hence the file name. */
3267 * NB. The setup array has already been transformed
3268 * via SVAL and so is in gost byte order.
3270 pnum = ((int)setup[1]) & 0xFFFF;
3271 subcommand = ((int)setup[0]) & 0xFFFF;
3273 if(!(p = get_rpc_pipe(pnum))) {
3274 DEBUG(1,("api_fd_reply: INVALID PIPE HANDLE: %x\n", pnum));
3275 return api_no_reply(outbuf, mdrcnt);
3278 DEBUG(3,("Got API command 0x%x on pipe \"%s\" (pnum %x)", subcommand, p->name, pnum));
3280 /* record maximum data length that can be transmitted in an SMBtrans */
3281 p->max_trans_reply = mdrcnt;
3283 DEBUG(10,("api_fd_reply: p:%p max_trans_reply: %d\n", p, p->max_trans_reply));
3285 switch (subcommand) {
3287 /* dce/rpc command */
3288 reply = rpc_command(p, data, tdscnt);
3290 reply = api_rpc_trans_reply(outbuf, p);
3293 /* Wait Named Pipe Handle state */
3294 reply = api_WNPHS(outbuf, p, params, tpscnt);
3297 /* Set Named Pipe Handle state */
3298 reply = api_SNPHS(outbuf, p, params, tpscnt);
3303 return api_no_reply(outbuf, mdrcnt);
3308 /****************************************************************************
3309 The buffer was too small
3310 ****************************************************************************/
3312 static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param,char *data,
3313 int mdrcnt,int mprcnt,
3314 char **rdata,char **rparam,
3315 int *rdata_len,int *rparam_len)
3317 *rparam_len = MIN(*rparam_len,mprcnt);
3318 *rparam = REALLOC(*rparam,*rparam_len);
3322 SSVAL(*rparam,0,NERR_BufTooSmall);
3324 DEBUG(3,("Supplied buffer too small in API command\n"));
3330 /****************************************************************************
3331 The request is not supported
3332 ****************************************************************************/
3334 static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param,char *data,
3335 int mdrcnt,int mprcnt,
3336 char **rdata,char **rparam,
3337 int *rdata_len,int *rparam_len)
3340 *rparam = REALLOC(*rparam,*rparam_len);
3344 SSVAL(*rparam,0,NERR_notsupported);
3345 SSVAL(*rparam,2,0); /* converter word */
3347 DEBUG(3,("Unsupported API command\n"));
3359 BOOL (*fn)(connection_struct *,uint16,char *,char *,
3360 int,int,char **,char **,int *,int *);
3362 } api_commands[] = {
3363 {"RNetShareEnum", 0, api_RNetShareEnum,0},
3364 {"RNetShareGetInfo", 1, api_RNetShareGetInfo,0},
3365 {"RNetServerGetInfo", 13, api_RNetServerGetInfo,0},
3366 {"RNetGroupGetUsers", 52, api_RNetGroupGetUsers,0},
3367 {"RNetUserGetInfo", 56, api_RNetUserGetInfo,0},
3368 {"NetUserGetGroups", 59, api_NetUserGetGroups,0},
3369 {"NetWkstaGetInfo", 63, api_NetWkstaGetInfo,0},
3370 {"DosPrintQEnum", 69, api_DosPrintQEnum,0},
3371 {"DosPrintQGetInfo", 70, api_DosPrintQGetInfo,0},
3372 {"WPrintQueuePause", 74, api_WPrintQueuePurge,0},
3373 {"WPrintQueueResume", 75, api_WPrintQueuePurge,0},
3374 {"WPrintJobEnumerate",76, api_WPrintJobEnumerate,0},
3375 {"WPrintJobGetInfo", 77, api_WPrintJobGetInfo,0},
3376 {"RDosPrintJobDel", 81, api_RDosPrintJobDel,0},
3377 {"RDosPrintJobPause", 82, api_RDosPrintJobDel,0},
3378 {"RDosPrintJobResume",83, api_RDosPrintJobDel,0},
3379 {"WPrintDestEnum", 84, api_WPrintDestEnum,0},
3380 {"WPrintDestGetInfo", 85, api_WPrintDestGetInfo,0},
3381 {"NetRemoteTOD", 91, api_NetRemoteTOD,0},
3382 {"WPrintQueuePurge", 103, api_WPrintQueuePurge,0},
3383 {"NetServerEnum", 104, api_RNetServerEnum,0},
3384 {"WAccessGetUserPerms",105, api_WAccessGetUserPerms,0},
3385 {"SetUserPassword", 115, api_SetUserPassword,0},
3386 {"WWkstaUserLogon", 132, api_WWkstaUserLogon,0},
3387 {"PrintJobInfo", 147, api_PrintJobInfo,0},
3388 {"WPrintDriverEnum", 205, api_WPrintDriverEnum,0},
3389 {"WPrintQProcEnum", 206, api_WPrintQProcEnum,0},
3390 {"WPrintPortEnum", 207, api_WPrintPortEnum,0},
3391 {"SamOEMChangePassword", 214, api_SamOEMChangePassword,0},
3392 {NULL, -1, api_Unsupported,0}};
3395 /****************************************************************************
3396 Handle remote api calls
3397 ****************************************************************************/
3399 static int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data,char *params,
3400 int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
3404 char *rparam = NULL;
3411 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
3415 api_command = SVAL(params,0);
3417 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
3420 skip_string(params+2,1),
3421 tdscnt,tpscnt,mdrcnt,mprcnt));
3423 for (i=0;api_commands[i].name;i++) {
3424 if (api_commands[i].id == api_command && api_commands[i].fn) {
3425 DEBUG(3,("Doing %s\n",api_commands[i].name));
3430 rdata = (char *)malloc(1024);
3432 memset(rdata,'\0',1024);
3434 rparam = (char *)malloc(1024);
3436 memset(rparam,'\0',1024);
3438 if(!rdata || !rparam) {
3439 DEBUG(0,("api_reply: malloc fail !\n"));
3443 reply = api_commands[i].fn(conn,vuid,params,data,mdrcnt,mprcnt,
3444 &rdata,&rparam,&rdata_len,&rparam_len);
3447 if (rdata_len > mdrcnt ||
3448 rparam_len > mprcnt) {
3449 reply = api_TooSmall(conn,vuid,params,data,mdrcnt,mprcnt,
3450 &rdata,&rparam,&rdata_len,&rparam_len);
3453 /* if we get False back then it's actually unsupported */
3455 api_Unsupported(conn,vuid,params,data,mdrcnt,mprcnt,
3456 &rdata,&rparam,&rdata_len,&rparam_len);
3458 send_trans_reply(outbuf, rparam, rparam_len, rdata, rdata_len, False);
3468 /****************************************************************************
3469 handle named pipe commands
3470 ****************************************************************************/
3471 static int named_pipe(connection_struct *conn,uint16 vuid, char *outbuf,char *name,
3472 uint16 *setup,char *data,char *params,
3473 int suwcnt,int tdscnt,int tpscnt,
3474 int msrcnt,int mdrcnt,int mprcnt)
3476 DEBUG(3,("named pipe command on <%s> name\n", name));
3478 if (strequal(name,"LANMAN"))
3479 return api_reply(conn,vuid,outbuf,data,params,tdscnt,tpscnt,mdrcnt,mprcnt);
3481 if (strequal(name,"WKSSVC") ||
3482 strequal(name,"SRVSVC") ||
3483 strequal(name,"WINREG") ||
3484 strequal(name,"SAMR") ||
3485 strequal(name,"LSARPC"))
3487 DEBUG(4,("named pipe command from Win95 (wow!)\n"));
3488 return api_fd_reply(conn,vuid,outbuf,setup,data,params,suwcnt,tdscnt,tpscnt,mdrcnt,mprcnt);
3491 if (strlen(name) < 1)
3492 return api_fd_reply(conn,vuid,outbuf,setup,data,params,suwcnt,tdscnt,tpscnt,mdrcnt,mprcnt);
3495 DEBUG(3,("unknown named pipe: setup 0x%X setup1=%d\n", (int)setup[0],(int)setup[1]));
3501 /****************************************************************************
3502 Reply to a SMBtrans.
3503 ****************************************************************************/
3505 int reply_trans(connection_struct *conn, char *inbuf,char *outbuf, int size, int bufsize)
3508 int name_offset = 0;
3509 char *data=NULL,*params=NULL;
3512 uint16 vuid = SVAL(inbuf,smb_uid);
3513 int tpscnt = SVAL(inbuf,smb_vwv0);
3514 int tdscnt = SVAL(inbuf,smb_vwv1);
3515 int mprcnt = SVAL(inbuf,smb_vwv2);
3516 int mdrcnt = SVAL(inbuf,smb_vwv3);
3517 int msrcnt = CVAL(inbuf,smb_vwv4);
3518 BOOL close_on_completion = BITSETW(inbuf+smb_vwv5,0);
3519 BOOL one_way = BITSETW(inbuf+smb_vwv5,1);
3520 int pscnt = SVAL(inbuf,smb_vwv9);
3521 int psoff = SVAL(inbuf,smb_vwv10);
3522 int dscnt = SVAL(inbuf,smb_vwv11);
3523 int dsoff = SVAL(inbuf,smb_vwv12);
3524 int suwcnt = CVAL(inbuf,smb_vwv13);
3526 memset(name, '\0',sizeof(name));
3527 fstrcpy(name,smb_buf(inbuf));
3529 if (dscnt > tdscnt || pscnt > tpscnt) {
3530 exit_server("invalid trans parameters\n");
3534 if((data = (char *)malloc(tdscnt)) == NULL) {
3535 DEBUG(0,("reply_trans: data malloc fail for %d bytes !\n", tdscnt));
3536 return(ERROR(ERRDOS,ERRnomem));
3538 memcpy(data,smb_base(inbuf)+dsoff,dscnt);
3542 if((params = (char *)malloc(tpscnt)) == NULL) {
3543 DEBUG(0,("reply_trans: param malloc fail for %d bytes !\n", tpscnt));
3544 return(ERROR(ERRDOS,ERRnomem));
3546 memcpy(params,smb_base(inbuf)+psoff,pscnt);
3551 if((setup = (uint16 *)malloc(suwcnt*sizeof(uint16))) == NULL) {
3552 DEBUG(0,("reply_trans: setup malloc fail for %d bytes !\n", (int)(suwcnt * sizeof(uint16))));
3553 return(ERROR(ERRDOS,ERRnomem));
3555 for (i=0;i<suwcnt;i++)
3556 setup[i] = SVAL(inbuf,smb_vwv14+i*SIZEOFWORD);
3560 if (pscnt < tpscnt || dscnt < tdscnt) {
3561 /* We need to send an interim response then receive the rest
3562 of the parameter/data bytes */
3563 outsize = set_message(outbuf,0,0,True);
3565 send_smb(Client,outbuf);
3568 /* receive the rest of the trans packet */
3569 while (pscnt < tpscnt || dscnt < tdscnt) {
3571 int pcnt,poff,dcnt,doff,pdisp,ddisp;
3573 ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
3575 if ((ret && (CVAL(inbuf, smb_com) != SMBtranss)) || !ret) {
3577 DEBUG(0,("reply_trans: Invalid secondary trans packet\n"));
3579 DEBUG(0,("reply_trans: %s in getting secondary trans response.\n",
3580 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
3588 return(ERROR(ERRSRV,ERRerror));
3593 tpscnt = SVAL(inbuf,smb_vwv0);
3594 tdscnt = SVAL(inbuf,smb_vwv1);
3596 pcnt = SVAL(inbuf,smb_vwv2);
3597 poff = SVAL(inbuf,smb_vwv3);
3598 pdisp = SVAL(inbuf,smb_vwv4);
3600 dcnt = SVAL(inbuf,smb_vwv5);
3601 doff = SVAL(inbuf,smb_vwv6);
3602 ddisp = SVAL(inbuf,smb_vwv7);
3607 if (dscnt > tdscnt || pscnt > tpscnt) {
3608 exit_server("invalid trans parameters\n");
3612 memcpy(params+pdisp,smb_base(inbuf)+poff,pcnt);
3614 memcpy(data+ddisp,smb_base(inbuf)+doff,dcnt);
3618 DEBUG(3,("trans <%s> data=%d params=%d setup=%d\n",
3619 name,tdscnt,tpscnt,suwcnt));
3622 * WinCE wierdness....
3625 if (name[0] == '\\' && (StrnCaseCmp(&name[1],local_machine, strlen(local_machine)) == 0) &&
3626 (name[strlen(local_machine)+1] == '\\'))
3627 name_offset = strlen(local_machine)+1;
3629 if (strncmp(&name[name_offset],"\\PIPE\\",strlen("\\PIPE\\")) == 0) {
3630 DEBUG(5,("calling named_pipe\n"));
3631 outsize = named_pipe(conn,vuid,outbuf,
3632 name+name_offset+strlen("\\PIPE\\"),setup,data,params,
3633 suwcnt,tdscnt,tpscnt,msrcnt,mdrcnt,mprcnt);
3635 DEBUG(3,("invalid pipe name\n"));
3647 if (close_on_completion)
3648 close_cnum(conn,vuid);
3654 return(ERROR(ERRSRV,ERRnosupport));