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)
52 #define ACCESS_READ 0x01
53 #define ACCESS_WRITE 0x02
54 #define ACCESS_CREATE 0x04
56 #define SHPWLEN 8 /* share password length */
57 #define NNLEN 12 /* 8.3 net name length */
58 #define SNLEN 15 /* service name length */
59 #define QNLEN 12 /* queue name maximum length */
62 extern int smb_read_error;
64 static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param,char *data,
65 int mdrcnt,int mprcnt,
66 char **rdata,char **rparam,
67 int *rdata_len,int *rparam_len);
68 static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param,char *data,
69 int mdrcnt,int mprcnt,
70 char **rdata,char **rparam,
71 int *rdata_len,int *rparam_len);
74 static int CopyExpanded(connection_struct *conn,
75 int snum, char** dst, char* src, int* n)
80 if (!src || !dst || !n || !(*dst)) return(0);
82 StrnCpy(buf,src,sizeof(buf)/2);
83 pstring_sub(buf,"%S",lp_servicename(snum));
84 standard_sub(conn,buf);
92 static int CopyAndAdvance(char** dst, char* src, int* n)
95 if (!src || !dst || !n || !(*dst)) return(0);
96 StrnCpy(*dst,src,*n-1);
103 static int StrlenExpanded(connection_struct *conn, int snum, char* s)
107 StrnCpy(buf,s,sizeof(buf)/2);
108 pstring_sub(buf,"%S",lp_servicename(snum));
109 standard_sub(conn,buf);
110 return strlen(buf) + 1;
113 static char* Expand(connection_struct *conn, int snum, char* s)
116 if (!s) return(NULL);
117 StrnCpy(buf,s,sizeof(buf)/2);
118 pstring_sub(buf,"%S",lp_servicename(snum));
119 standard_sub(conn,buf);
123 /*******************************************************************
124 check a API string for validity when we only need to check the prefix
125 ******************************************************************/
126 static BOOL prefix_ok(char *str,char *prefix)
128 return(strncmp(str,prefix,strlen(prefix)) == 0);
131 /*******************************************************************
132 copies parameters and data, as needed, into the smb buffer
134 *both* the data and params sections should be aligned. this
135 is fudged in the rpc pipes by
136 at present, only the data section is. this may be a possible
137 cause of some of the ipc problems being experienced. lkcl26dec97
139 ******************************************************************/
141 static void copy_trans_params_and_data(char *outbuf, int align,
142 char *rparam, int param_offset, int param_len,
143 char *rdata, int data_offset, int data_len)
145 char *copy_into = smb_buf(outbuf)+1;
153 DEBUG(5,("copy_trans_params_and_data: params[%d..%d] data[%d..%d]\n",
154 param_offset, param_offset + param_len,
155 data_offset , data_offset + data_len));
158 memcpy(copy_into, &rparam[param_offset], param_len);
160 copy_into += param_len + align;
163 memcpy(copy_into, &rdata[data_offset], data_len);
166 /****************************************************************************
168 ****************************************************************************/
170 static void send_trans_reply(char *outbuf,
171 char *rparam, int rparam_len,
172 char *rdata, int rdata_len,
173 BOOL buffer_too_large)
175 int this_ldata,this_lparam;
176 int tot_data_sent = 0;
177 int tot_param_sent = 0;
180 int ldata = rdata ? rdata_len : 0;
181 int lparam = rparam ? rparam_len : 0;
183 if (buffer_too_large)
184 DEBUG(5,("send_trans_reply: buffer %d too large\n", ldata ));
186 this_lparam = MIN(lparam,max_send - 500); /* hack */
187 this_ldata = MIN(ldata,max_send - (500+this_lparam));
189 align = ((this_lparam)%4);
191 set_message(outbuf,10,1+align+this_ldata+this_lparam,True);
193 if (buffer_too_large)
195 /* issue a buffer size warning. on a DCE/RPC pipe, expect an SMBreadX... */
196 SIVAL(outbuf, smb_flg2, FLAGS2_32_BIT_ERROR_CODES);
197 SIVAL(outbuf, smb_rcls, 0x80000000 | NT_STATUS_ACCESS_VIOLATION);
200 copy_trans_params_and_data(outbuf, align,
201 rparam, tot_param_sent, this_lparam,
202 rdata, tot_data_sent, this_ldata);
204 SSVAL(outbuf,smb_vwv0,lparam);
205 SSVAL(outbuf,smb_vwv1,ldata);
206 SSVAL(outbuf,smb_vwv3,this_lparam);
207 SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf)+1,outbuf));
208 SSVAL(outbuf,smb_vwv5,0);
209 SSVAL(outbuf,smb_vwv6,this_ldata);
210 SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+1+this_lparam+align,outbuf));
211 SSVAL(outbuf,smb_vwv8,0);
212 SSVAL(outbuf,smb_vwv9,0);
215 send_smb(Client,outbuf);
217 tot_data_sent = this_ldata;
218 tot_param_sent = this_lparam;
220 while (tot_data_sent < ldata || tot_param_sent < lparam)
222 this_lparam = MIN(lparam-tot_param_sent, max_send - 500); /* hack */
223 this_ldata = MIN(ldata -tot_data_sent, max_send - (500+this_lparam));
231 align = (this_lparam%4);
233 set_message(outbuf,10,1+this_ldata+this_lparam+align,False);
235 copy_trans_params_and_data(outbuf, align,
236 rparam, tot_param_sent, this_lparam,
237 rdata, tot_data_sent, this_ldata);
239 SSVAL(outbuf,smb_vwv3,this_lparam);
240 SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf)+1,outbuf));
241 SSVAL(outbuf,smb_vwv5,tot_param_sent);
242 SSVAL(outbuf,smb_vwv6,this_ldata);
243 SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+1+this_lparam+align,outbuf));
244 SSVAL(outbuf,smb_vwv8,tot_data_sent);
245 SSVAL(outbuf,smb_vwv9,0);
248 send_smb(Client,outbuf);
250 tot_data_sent += this_ldata;
251 tot_param_sent += this_lparam;
256 char* format; /* formatstring for structure */
257 char* subformat; /* subformat for structure */
258 char* base; /* baseaddress of buffer */
259 int buflen; /* remaining size for fixed part; on init: length of base */
260 int subcount; /* count of substructures */
261 char* structbuf; /* pointer into buffer for remaining fixed part */
262 int stringlen; /* remaining size for variable part */
263 char* stringbuf; /* pointer into buffer for remaining variable part */
264 int neededlen; /* total needed size */
265 int usedlen; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
266 char* curpos; /* current position; pointer into format or subformat */
270 static int get_counter(char** p)
273 if (!p || !(*p)) return(1);
274 if (!isdigit((int)**p)) return 1;
278 n = 10 * n + (i - '0');
285 static int getlen(char* p)
291 case 'W': /* word (2 byte) */
294 case 'N': /* count of substructures (word) at end */
297 case 'D': /* double word (4 byte) */
298 case 'z': /* offset to zero terminated string (4 byte) */
299 case 'l': /* offset to user data (4 byte) */
302 case 'b': /* offset to data (with counter) (4 byte) */
306 case 'B': /* byte (with optional counter) */
307 n += get_counter(&p);
314 static BOOL init_package(struct pack_desc* p, int count, int subcount)
319 if (!p->format || !p->base) return(False);
321 i = count * getlen(p->format);
322 if (p->subformat) i += subcount * getlen(p->subformat);
323 p->structbuf = p->base;
327 p->curpos = p->format;
331 p->errcode = ERRmoredata;
334 p->errcode = NERR_Success;
337 p->stringbuf = p->base + i;
339 return(p->errcode == NERR_Success);
343 static int package(struct pack_desc* p, ...)
346 static int package(va_alist)
352 int needed=0, stringneeded;
354 int is_string=0, stringused;
361 p = va_arg(args,struct pack_desc *);
366 p->curpos = p->format;
368 p->curpos = p->subformat;
373 str = va_arg(args,char*);
374 SMB_ASSERT(strncmp(str,p->curpos,strlen(str)) == 0);
383 switch( *p->curpos++ ) {
384 case 'W': /* word (2 byte) */
386 temp = va_arg(args,int);
387 if (p->buflen >= needed) SSVAL(p->structbuf,0,temp);
389 case 'N': /* count of substructures (word) at end */
391 p->subcount = va_arg(args,int);
392 if (p->buflen >= needed) SSVAL(p->structbuf,0,p->subcount);
394 case 'D': /* double word (4 byte) */
396 temp = va_arg(args,int);
397 if (p->buflen >= needed) SIVAL(p->structbuf,0,temp);
399 case 'B': /* byte (with optional counter) */
400 needed = get_counter(&p->curpos);
402 char *s = va_arg(args,char*);
403 if (p->buflen >= needed) StrnCpy(p->structbuf,s?s:"",needed-1);
406 case 'z': /* offset to zero terminated string (4 byte) */
407 str = va_arg(args,char*);
408 stringneeded = (str ? strlen(str)+1 : 0);
411 case 'l': /* offset to user data (4 byte) */
412 str = va_arg(args,char*);
413 stringneeded = va_arg(args,int);
416 case 'b': /* offset to data (with counter) (4 byte) */
417 str = va_arg(args,char*);
418 stringneeded = get_counter(&p->curpos);
423 if (stringneeded >= 0) {
425 if (p->buflen >= needed) {
426 stringused = stringneeded;
427 if (stringused > p->stringlen) {
428 stringused = (is_string ? p->stringlen : 0);
429 if (p->errcode == NERR_Success) p->errcode = ERRmoredata;
432 SIVAL(p->structbuf,0,0);
434 SIVAL(p->structbuf,0,PTR_DIFF(p->stringbuf,p->base));
435 memcpy(p->stringbuf,str?str:"",stringused);
436 if (is_string) p->stringbuf[stringused-1] = '\0';
437 p->stringbuf += stringused;
438 p->stringlen -= stringused;
439 p->usedlen += stringused;
442 p->neededlen += stringneeded;
444 p->neededlen += needed;
445 if (p->buflen >= needed) {
446 p->structbuf += needed;
448 p->usedlen += needed;
451 if (p->errcode == NERR_Success) p->errcode = ERRmoredata;
457 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
458 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
460 #define PACK(desc,t,v) package(desc,v)
461 #define PACKl(desc,t,v,l) package(desc,v,l)
464 static void PACKI(struct pack_desc* desc,char *t,int v)
469 static void PACKS(struct pack_desc* desc,char *t,char *v)
475 /****************************************************************************
477 ****************************************************************************/
479 static void PackDriverData(struct pack_desc* desc)
481 char drivdata[4+4+32];
482 SIVAL(drivdata,0,sizeof drivdata); /* cb */
483 SIVAL(drivdata,4,1000); /* lVersion */
484 memset(drivdata+8,0,32); /* szDeviceName */
485 pstrcpy(drivdata+8,"NULL");
486 PACKl(desc,"l",drivdata,sizeof drivdata); /* pDriverData */
489 static int check_printq_info(struct pack_desc* desc,
490 int uLevel, char *id1, char *id2)
492 desc->subformat = NULL;
495 desc->format = "B13";
498 desc->format = "B13BWWWzzzzzWW";
501 desc->format = "B13BWWWzzzzzWN";
502 desc->subformat = "WB21BB16B10zWWzDDz";
505 desc->format = "zWWWWzzzzWWzzl";
508 desc->format = "zWWWWzzzzWNzzl";
509 desc->subformat = "WWzWWDDzz";
515 desc->format = "WzzzzzzzzN";
516 desc->subformat = "z";
518 default: return False;
520 if (strcmp(desc->format,id1) != 0) return False;
521 if (desc->subformat && strcmp(desc->subformat,id2) != 0) return False;
525 static void fill_printjob_info(connection_struct *conn, int snum, int uLevel,
526 struct pack_desc* desc,
527 print_queue_struct* queue, int n)
529 time_t t = queue->time;
531 /* the client expects localtime */
534 PACKI(desc,"W",printjob_encode(snum, queue->job)); /* uJobId */
536 PACKS(desc,"B21",queue->user); /* szUserName */
537 PACKS(desc,"B",""); /* pad */
538 PACKS(desc,"B16",""); /* szNotifyName */
539 PACKS(desc,"B10","PM_Q_RAW"); /* szDataType */
540 PACKS(desc,"z",""); /* pszParms */
541 PACKI(desc,"W",n+1); /* uPosition */
542 PACKI(desc,"W",queue->status); /* fsStatus */
543 PACKS(desc,"z",""); /* pszStatus */
544 PACKI(desc,"D",t); /* ulSubmitted */
545 PACKI(desc,"D",queue->size); /* ulSize */
546 PACKS(desc,"z",queue->file); /* pszComment */
548 if (uLevel == 2 || uLevel == 3) {
549 PACKI(desc,"W",queue->priority); /* uPriority */
550 PACKS(desc,"z",queue->user); /* pszUserName */
551 PACKI(desc,"W",n+1); /* uPosition */
552 PACKI(desc,"W",queue->status); /* fsStatus */
553 PACKI(desc,"D",t); /* ulSubmitted */
554 PACKI(desc,"D",queue->size); /* ulSize */
555 PACKS(desc,"z","Samba"); /* pszComment */
556 PACKS(desc,"z",queue->file); /* pszDocument */
558 PACKS(desc,"z",""); /* pszNotifyName */
559 PACKS(desc,"z","PM_Q_RAW"); /* pszDataType */
560 PACKS(desc,"z",""); /* pszParms */
561 PACKS(desc,"z",""); /* pszStatus */
562 PACKS(desc,"z",SERVICE(snum)); /* pszQueue */
563 PACKS(desc,"z","lpd"); /* pszQProcName */
564 PACKS(desc,"z",""); /* pszQProcParms */
565 PACKS(desc,"z","NULL"); /* pszDriverName */
566 PackDriverData(desc); /* pDriverData */
567 PACKS(desc,"z",""); /* pszPrinterName */
572 static void fill_printq_info(connection_struct *conn, int snum, int uLevel,
573 struct pack_desc* desc,
574 int count, print_queue_struct* queue,
575 print_status_struct* status)
580 PACKS(desc,"B13",SERVICE(snum));
585 PACKS(desc,"z",Expand(conn,snum,SERVICE(snum)));
589 if (uLevel == 1 || uLevel == 2) {
590 PACKS(desc,"B",""); /* alignment */
591 PACKI(desc,"W",5); /* priority */
592 PACKI(desc,"W",0); /* start time */
593 PACKI(desc,"W",0); /* until time */
594 PACKS(desc,"z",""); /* pSepFile */
595 PACKS(desc,"z","lpd"); /* pPrProc */
596 PACKS(desc,"z",SERVICE(snum)); /* pDestinations */
597 PACKS(desc,"z",""); /* pParms */
599 PACKS(desc,"z","UNKNOWN PRINTER");
600 PACKI(desc,"W",LPSTAT_ERROR);
602 else if (!status || !status->message[0]) {
603 PACKS(desc,"z",Expand(conn,snum,lp_comment(snum)));
604 PACKI(desc,"W",LPSTAT_OK); /* status */
606 PACKS(desc,"z",status->message);
607 PACKI(desc,"W",status->status); /* status */
609 PACKI(desc,(uLevel == 1 ? "W" : "N"),count);
611 if (uLevel == 3 || uLevel == 4) {
612 PACKI(desc,"W",5); /* uPriority */
613 PACKI(desc,"W",0); /* uStarttime */
614 PACKI(desc,"W",0); /* uUntiltime */
615 PACKI(desc,"W",5); /* pad1 */
616 PACKS(desc,"z",""); /* pszSepFile */
617 PACKS(desc,"z","WinPrint"); /* pszPrProc */
618 PACKS(desc,"z",""); /* pszParms */
619 if (!status || !status->message[0]) {
620 PACKS(desc,"z",Expand(conn,snum,lp_comment(snum))); /* pszComment */
621 PACKI(desc,"W",LPSTAT_OK); /* fsStatus */
623 PACKS(desc,"z",status->message); /* pszComment */
624 PACKI(desc,"W",status->status); /* fsStatus */
626 PACKI(desc,(uLevel == 3 ? "W" : "N"),count); /* cJobs */
627 PACKS(desc,"z",SERVICE(snum)); /* pszPrinters */
628 PACKS(desc,"z",lp_printerdriver(snum)); /* pszDriverName */
629 PackDriverData(desc); /* pDriverData */
631 if (uLevel == 2 || uLevel == 4) {
633 for (i=0;i<count;i++)
634 fill_printjob_info(conn,snum,uLevel == 2 ? 1 : 2,desc,&queue[i],i);
639 pstring tok,driver,datafile,langmon,helpfile,datatype;
644 pstrcpy(fname,lp_driverfile());
645 f=sys_fopen(fname,"r");
647 DEBUG(3,("fill_printq_info: Can't open %s - %s\n",fname,strerror(errno)));
648 desc->errcode=NERR_notsupported;
652 if((p=(char *)malloc(8192*sizeof(char))) == NULL) {
653 DEBUG(0,("fill_printq_info: malloc fail !\n"));
654 desc->errcode=NERR_notsupported;
659 memset(p, '\0',8192*sizeof(char));
662 /* lookup the long printer driver name in the file description */
663 while (f && !feof(f) && !ok)
665 p = q; /* reset string pointer */
668 if (next_token(&p,tok,":",sizeof(tok)) &&
669 (strlen(lp_printerdriver(snum)) == strlen(tok)) &&
670 (!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum)))))
675 /* driver file name */
676 if (ok && !next_token(&p,driver,":",sizeof(driver))) ok = 0;
678 if (ok && !next_token(&p,datafile,":",sizeof(datafile))) ok = 0;
680 * for the next tokens - which may be empty - I have to check for empty
681 * tokens first because the next_token function will skip all empty
689 } else if (!next_token(&p,helpfile,":",sizeof(helpfile))) ok = 0;
693 /* language monitor */
697 } else if (!next_token(&p,langmon,":",sizeof(langmon))) ok = 0;
700 /* default data type */
701 if (ok && !next_token(&p,datatype,":",sizeof(datatype))) ok = 0;
704 PACKI(desc,"W",0x0400); /* don't know */
705 PACKS(desc,"z",lp_printerdriver(snum)); /* long printer name */
706 PACKS(desc,"z",driver); /* Driverfile Name */
707 PACKS(desc,"z",datafile); /* Datafile name */
708 PACKS(desc,"z",langmon); /* language monitor */
709 PACKS(desc,"z",lp_driverlocation(snum)); /* share to retrieve files */
710 PACKS(desc,"z",datatype); /* default data type */
711 PACKS(desc,"z",helpfile); /* helpfile name */
712 PACKS(desc,"z",driver); /* driver name */
713 DEBUG(3,("Driver:%s:\n",driver));
714 DEBUG(3,("Data File:%s:\n",datafile));
715 DEBUG(3,("Language Monitor:%s:\n",langmon));
716 DEBUG(3,("Data Type:%s:\n",datatype));
717 DEBUG(3,("Help File:%s:\n",helpfile));
718 PACKI(desc,"N",count); /* number of files to copy */
719 for (i=0;i<count;i++)
721 /* no need to check return value here - it was already tested in
722 * get_printerdrivernumber
724 next_token(&p,tok,",",sizeof(tok));
725 PACKS(desc,"z",tok); /* driver files to copy */
726 DEBUG(3,("file:%s:\n",tok));
729 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n",
730 SERVICE(snum),count));
732 DEBUG(3,("fill_printq_info: Can't supply driver files\n"));
733 desc->errcode=NERR_notsupported;
739 /* This function returns the number of files for a given driver */
740 static int get_printerdrivernumber(int snum)
748 pstrcpy(fname,lp_driverfile());
750 DEBUG(4,("In get_printerdrivernumber: %s\n",fname));
751 f=sys_fopen(fname,"r");
753 DEBUG(3,("get_printerdrivernumber: Can't open %s - %s\n",fname,strerror(errno)));
757 if((p=(char *)malloc(8192*sizeof(char))) == NULL) {
758 DEBUG(3,("get_printerdrivernumber: malloc fail !\n"));
763 q=p; /* need it to free memory because p change ! */
765 /* lookup the long printer driver name in the file description */
766 while (!feof(f) && !ok)
768 p = q; /* reset string pointer */
770 if (next_token(&p,tok,":",sizeof(tok)) &&
771 (!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum)))))
780 if (*p++ == ':') i--;
785 /* count the number of files */
786 while (next_token(&p,tok,",",sizeof(tok)))
794 static BOOL api_DosPrintQGetInfo(connection_struct *conn,
795 uint16 vuid, char *param,char *data,
796 int mdrcnt,int mprcnt,
797 char **rdata,char **rparam,
798 int *rdata_len,int *rparam_len)
800 char *str1 = param+2;
801 char *str2 = skip_string(str1,1);
802 char *p = skip_string(str2,1);
808 struct pack_desc desc;
809 print_queue_struct *queue=NULL;
810 print_status_struct status;
812 memset((char *)&status,'\0',sizeof(status));
813 memset((char *)&desc,'\0',sizeof(desc));
815 p = skip_string(p,1);
819 /* remove any trailing username */
820 if ((p = strchr(QueueName,'%'))) *p = 0;
822 DEBUG(3,("PrintQueue uLevel=%d name=%s\n",uLevel,QueueName));
824 /* check it's a supported varient */
825 if (!prefix_ok(str1,"zWrLh")) return False;
826 if (!check_printq_info(&desc,uLevel,str2,str3)) {
828 * Patch from Scott Moomaw <scott@bridgewater.edu>
829 * to return the 'invalid info level' error if an
830 * unknown level was requested.
834 *rparam = REALLOC(*rparam,*rparam_len);
835 SSVALS(*rparam,0,ERROR_INVALID_LEVEL);
841 snum = lp_servicenumber(QueueName);
842 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
843 int pnum = lp_servicenumber(PRINTERS_NAME);
845 lp_add_printer(QueueName,pnum);
846 snum = lp_servicenumber(QueueName);
850 if (snum < 0 || !VALID_SNUM(snum)) return(False);
853 count = get_printerdrivernumber(snum);
854 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count));
856 count = get_printqueue(snum, conn,&queue,&status);
859 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
861 desc.buflen = mdrcnt;
862 if (init_package(&desc,1,count)) {
863 desc.subcount = count;
864 fill_printq_info(conn,snum,uLevel,&desc,count,queue,&status);
865 } else if(uLevel == 0) {
867 * This is a *disgusting* hack.
868 * This is *so* bad that even I'm embarrassed (and I
869 * have no shame). Here's the deal :
870 * Until we get the correct SPOOLSS code into smbd
871 * then when we're running with NT SMB support then
872 * NT makes this call with a level of zero, and then
873 * immediately follows it with an open request to
874 * the \\SRVSVC pipe. If we allow that open to
875 * succeed then NT barfs when it cannot open the
876 * \\SPOOLSS pipe immediately after and continually
877 * whines saying "Printer name is invalid" forever
878 * after. If we cause *JUST THIS NEXT OPEN* of \\SRVSVC
879 * to fail, then NT downgrades to using the downlevel code
880 * and everything works as well as before. I hate
881 * myself for adding this code.... JRA.
884 fail_next_srvsvc_open();
887 *rdata_len = desc.usedlen;
890 *rparam = REALLOC(*rparam,*rparam_len);
891 SSVALS(*rparam,0,desc.errcode);
893 SSVAL(*rparam,4,desc.neededlen);
895 DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode));
897 if (queue) free(queue);
903 /****************************************************************************
904 view list of all print jobs on all queues
905 ****************************************************************************/
906 static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid, char* param, char* data,
907 int mdrcnt, int mprcnt,
908 char **rdata, char** rparam,
909 int *rdata_len, int *rparam_len)
911 char *param_format = param+2;
912 char *output_format1 = skip_string(param_format,1);
913 char *p = skip_string(output_format1,1);
914 int uLevel = SVAL(p,0);
915 char *output_format2 = p + 4;
916 int services = lp_numservices();
918 struct pack_desc desc;
919 print_queue_struct **queue = NULL;
920 print_status_struct *status = NULL;
921 int* subcntarr = NULL;
922 int queuecnt, subcnt=0, succnt=0;
924 memset((char *)&desc,'\0',sizeof(desc));
926 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
928 if (!prefix_ok(param_format,"WrLeh")) return False;
929 if (!check_printq_info(&desc,uLevel,output_format1,output_format2)) {
931 * Patch from Scott Moomaw <scott@bridgewater.edu>
932 * to return the 'invalid info level' error if an
933 * unknown level was requested.
937 *rparam = REALLOC(*rparam,*rparam_len);
938 SSVALS(*rparam,0,ERROR_INVALID_LEVEL);
945 for (i = 0; i < services; i++)
946 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
949 if((queue = (print_queue_struct**)malloc(queuecnt*sizeof(print_queue_struct*))) == NULL) {
950 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
953 memset(queue,0,queuecnt*sizeof(print_queue_struct*));
954 if((status = (print_status_struct*)malloc(queuecnt*sizeof(print_status_struct))) == NULL) {
955 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
958 memset(status,0,queuecnt*sizeof(print_status_struct));
959 if((subcntarr = (int*)malloc(queuecnt*sizeof(int))) == NULL) {
960 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
965 for (i = 0; i < services; i++)
966 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
967 subcntarr[n] = get_printqueue(i, conn,&queue[n],&status[n]);
968 subcnt += subcntarr[n];
972 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
974 desc.buflen = mdrcnt;
976 if (init_package(&desc,queuecnt,subcnt)) {
979 for (i = 0; i < services; i++)
980 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
981 fill_printq_info(conn,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]);
983 if (desc.errcode == NERR_Success) succnt = n;
987 if (subcntarr) free(subcntarr);
989 *rdata_len = desc.usedlen;
991 *rparam = REALLOC(*rparam,*rparam_len);
992 SSVALS(*rparam,0,desc.errcode);
994 SSVAL(*rparam,4,succnt);
995 SSVAL(*rparam,6,queuecnt);
997 for (i = 0; i < queuecnt; i++) {
998 if (queue && queue[i]) free(queue[i]);
1001 if (queue) free(queue);
1002 if (status) free(status);
1007 /****************************************************************************
1008 get info level for a server list query
1009 ****************************************************************************/
1010 static BOOL check_server_info(int uLevel, char* id)
1014 if (strcmp(id,"B16") != 0) return False;
1017 if (strcmp(id,"B16BBDz") != 0) return False;
1025 struct srv_info_struct
1035 /*******************************************************************
1036 get server info lists from the files saved by nmbd. Return the
1038 ******************************************************************/
1039 static int get_server_info(uint32 servertype,
1040 struct srv_info_struct **servers,
1048 BOOL local_list_only;
1050 pstrcpy(fname,lp_lockdir());
1051 trim_string(fname,NULL,"/");
1053 pstrcat(fname,SERVER_LIST);
1055 f = sys_fopen(fname,"r");
1058 DEBUG(4,("Can't open %s - %s\n",fname,strerror(errno)));
1062 /* request for everything is code for request all servers */
1063 if (servertype == SV_TYPE_ALL)
1064 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1066 local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY);
1068 DEBUG(4,("Servertype search: %8x\n",servertype));
1073 struct srv_info_struct *s;
1078 fgets(line,sizeof(line)-1,f);
1079 if (!*line) continue;
1081 if (count == alloced) {
1083 (*servers) = (struct srv_info_struct *)
1084 Realloc(*servers,sizeof(**servers)*alloced);
1085 if (!(*servers)) return(0);
1086 memset((char *)((*servers)+count),'\0',sizeof(**servers)*(alloced-count));
1088 s = &(*servers)[count];
1090 if (!next_token(&ptr,s->name , NULL, sizeof(s->name))) continue;
1091 if (!next_token(&ptr,stype , NULL, sizeof(stype))) continue;
1092 if (!next_token(&ptr,s->comment, NULL, sizeof(s->comment))) continue;
1093 if (!next_token(&ptr,s->domain , NULL, sizeof(s->domain))) {
1094 /* this allows us to cope with an old nmbd */
1095 pstrcpy(s->domain,global_myworkgroup);
1098 if (sscanf(stype,"%X",&s->type) != 1) {
1099 DEBUG(4,("r:host file "));
1103 /* Filter the servers/domains we return based on what was asked for. */
1105 /* Check to see if we are being asked for a local list only. */
1106 if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) {
1107 DEBUG(4,("r: local list only"));
1111 /* doesn't match up: don't want it */
1112 if (!(servertype & s->type)) {
1113 DEBUG(4,("r:serv type "));
1117 if ((servertype & SV_TYPE_DOMAIN_ENUM) !=
1118 (s->type & SV_TYPE_DOMAIN_ENUM))
1120 DEBUG(4,("s: dom mismatch "));
1124 if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM))
1129 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1130 s->type &= ~SV_TYPE_LOCAL_LIST_ONLY;
1134 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1135 s->name, s->type, s->comment, s->domain));
1137 s->server_added = True;
1142 DEBUG(4,("%20s %8x %25s %15s\n",
1143 s->name, s->type, s->comment, s->domain));
1152 /*******************************************************************
1153 fill in a server info structure
1154 ******************************************************************/
1155 static int fill_srv_info(struct srv_info_struct *service,
1156 int uLevel, char **buf, int *buflen,
1157 char **stringbuf, int *stringspace, char *baseaddr)
1166 case 0: struct_len = 16; break;
1167 case 1: struct_len = 26; break;
1177 len = strlen(service->comment)+1;
1181 if (buflen) *buflen = struct_len;
1182 if (stringspace) *stringspace = len;
1183 return struct_len + len;
1188 if (*buflen < struct_len) return -1;
1196 p2 = p + struct_len;
1197 l2 = *buflen - struct_len;
1199 if (!baseaddr) baseaddr = p;
1204 StrnCpy(p,service->name,15);
1208 StrnCpy(p,service->name,15);
1209 SIVAL(p,18,service->type);
1210 SIVAL(p,22,PTR_DIFF(p2,baseaddr));
1211 len += CopyAndAdvance(&p2,service->comment,&l2);
1217 *buf = p + struct_len;
1218 *buflen -= struct_len;
1231 static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
1233 return(strcmp(s1->name,s2->name));
1236 /****************************************************************************
1237 view list of servers available (or possibly domains). The info is
1238 extracted from lists saved by nmbd on the local host
1239 ****************************************************************************/
1240 static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid, char *param, char *data,
1241 int mdrcnt, int mprcnt, char **rdata,
1242 char **rparam, int *rdata_len, int *rparam_len)
1244 char *str1 = param+2;
1245 char *str2 = skip_string(str1,1);
1246 char *p = skip_string(str2,1);
1247 int uLevel = SVAL(p,0);
1248 int buf_len = SVAL(p,2);
1249 uint32 servertype = IVAL(p,4);
1251 int data_len, fixed_len, string_len;
1252 int f_len = 0, s_len = 0;
1253 struct srv_info_struct *servers=NULL;
1254 int counted=0,total=0;
1257 BOOL domain_request;
1260 /* If someone sets all the bits they don't really mean to set
1261 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1264 if (servertype == SV_TYPE_ALL)
1265 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1267 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1268 any other bit (they may just set this bit on it's own) they
1269 want all the locally seen servers. However this bit can be
1270 set on its own so set the requested servers to be
1271 ALL - DOMAIN_ENUM. */
1273 if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM))
1274 servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
1276 domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
1277 local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
1281 if (!prefix_ok(str1,"WrLehD")) return False;
1282 if (!check_server_info(uLevel,str2)) return False;
1284 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1285 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1286 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1288 if (strcmp(str1, "WrLehDz") == 0) {
1289 StrnCpy(domain, p, sizeof(fstring)-1);
1291 StrnCpy(domain, global_myworkgroup, sizeof(fstring)-1);
1294 if (lp_browse_list())
1295 total = get_server_info(servertype,&servers,domain);
1297 data_len = fixed_len = string_len = 0;
1300 qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
1303 char *lastname=NULL;
1305 for (i=0;i<total;i++)
1307 struct srv_info_struct *s = &servers[i];
1308 if (lastname && strequal(lastname,s->name)) continue;
1310 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1311 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1312 s->name, s->type, s->comment, s->domain));
1314 if (data_len <= buf_len) {
1317 string_len += s_len;
1324 *rdata_len = fixed_len + string_len;
1325 *rdata = REALLOC(*rdata,*rdata_len);
1326 memset(*rdata,'\0',*rdata_len);
1328 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1334 char *lastname=NULL;
1335 int count2 = counted;
1336 for (i = 0; i < total && count2;i++)
1338 struct srv_info_struct *s = &servers[i];
1339 if (lastname && strequal(lastname,s->name)) continue;
1341 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1342 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1343 s->name, s->type, s->comment, s->domain));
1349 *rparam = REALLOC(*rparam,*rparam_len);
1350 SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata));
1352 SSVAL(*rparam,4,counted);
1353 SSVAL(*rparam,6,counted+missed);
1355 if (servers) free(servers);
1357 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1358 domain,uLevel,counted,counted+missed));
1363 /****************************************************************************
1364 command 0x34 - suspected of being a "Lookup Names" stub api
1365 ****************************************************************************/
1366 static BOOL api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid, char *param, char *data,
1367 int mdrcnt, int mprcnt, char **rdata,
1368 char **rparam, int *rdata_len, int *rparam_len)
1370 char *str1 = param+2;
1371 char *str2 = skip_string(str1,1);
1372 char *p = skip_string(str2,1);
1373 int uLevel = SVAL(p,0);
1374 int buf_len = SVAL(p,2);
1378 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1379 str1, str2, p, uLevel, buf_len));
1381 if (!prefix_ok(str1,"zWrLeh")) return False;
1386 *rparam = REALLOC(*rparam,*rparam_len);
1388 SSVAL(*rparam,0,0x08AC); /* informational warning message */
1390 SSVAL(*rparam,4,counted);
1391 SSVAL(*rparam,6,counted+missed);
1396 /****************************************************************************
1397 get info about a share
1398 ****************************************************************************/
1399 static BOOL check_share_info(int uLevel, char* id)
1403 if (strcmp(id,"B13") != 0) return False;
1406 if (strcmp(id,"B13BWz") != 0) return False;
1409 if (strcmp(id,"B13BWzWWWzB9B") != 0) return False;
1412 if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) return False;
1414 default: return False;
1419 static int fill_share_info(connection_struct *conn, int snum, int uLevel,
1420 char** buf, int* buflen,
1421 char** stringbuf, int* stringspace, char* baseaddr)
1430 case 0: struct_len = 13; break;
1431 case 1: struct_len = 20; break;
1432 case 2: struct_len = 40; break;
1433 case 91: struct_len = 68; break;
1441 if (uLevel > 0) len += StrlenExpanded(conn,snum,lp_comment(snum));
1442 if (uLevel > 1) len += strlen(lp_pathname(snum)) + 1;
1443 if (buflen) *buflen = struct_len;
1444 if (stringspace) *stringspace = len;
1445 return struct_len + len;
1450 if ((*buflen) < struct_len) return -1;
1458 p2 = p + struct_len;
1459 l2 = (*buflen) - struct_len;
1461 if (!baseaddr) baseaddr = p;
1463 StrnCpy(p,lp_servicename(snum),13);
1469 type = STYPE_DISKTREE;
1470 if (lp_print_ok(snum)) type = STYPE_PRINTQ;
1471 if (strequal("IPC$",lp_servicename(snum))) type = STYPE_IPC;
1472 SSVAL(p,14,type); /* device type */
1473 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1474 len += CopyExpanded(conn,snum,&p2,lp_comment(snum),&l2);
1479 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1480 SSVALS(p,22,-1); /* max uses */
1481 SSVAL(p,24,1); /* current uses */
1482 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1483 len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1484 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1489 memset(p+40,0,SHPWLEN+2);
1501 (*buf) = p + struct_len;
1502 (*buflen) -= struct_len;
1504 (*stringspace) = l2;
1514 static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
1515 int mdrcnt,int mprcnt,
1516 char **rdata,char **rparam,
1517 int *rdata_len,int *rparam_len)
1519 char *str1 = param+2;
1520 char *str2 = skip_string(str1,1);
1521 char *netname = skip_string(str2,1);
1522 char *p = skip_string(netname,1);
1523 int uLevel = SVAL(p,0);
1524 int snum = find_service(netname);
1526 if (snum < 0) return False;
1528 /* check it's a supported varient */
1529 if (!prefix_ok(str1,"zWrLh")) return False;
1530 if (!check_share_info(uLevel,str2)) return False;
1532 *rdata = REALLOC(*rdata,mdrcnt);
1534 *rdata_len = fill_share_info(conn,snum,uLevel,&p,&mdrcnt,0,0,0);
1535 if (*rdata_len < 0) return False;
1538 *rparam = REALLOC(*rparam,*rparam_len);
1539 SSVAL(*rparam,0,NERR_Success);
1540 SSVAL(*rparam,2,0); /* converter word */
1541 SSVAL(*rparam,4,*rdata_len);
1546 /****************************************************************************
1547 view list of shares available
1548 ****************************************************************************/
1549 static BOOL api_RNetShareEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
1550 int mdrcnt,int mprcnt,
1551 char **rdata,char **rparam,
1552 int *rdata_len,int *rparam_len)
1554 char *str1 = param+2;
1555 char *str2 = skip_string(str1,1);
1556 char *p = skip_string(str2,1);
1557 int uLevel = SVAL(p,0);
1558 int buf_len = SVAL(p,2);
1560 int count=lp_numservices();
1561 int total=0,counted=0;
1562 BOOL missed = False;
1564 int data_len, fixed_len, string_len;
1565 int f_len = 0, s_len = 0;
1567 if (!prefix_ok(str1,"WrLeh")) return False;
1568 if (!check_share_info(uLevel,str2)) return False;
1570 data_len = fixed_len = string_len = 0;
1571 for (i=0;i<count;i++)
1572 if (lp_browseable(i) && lp_snum_ok(i))
1575 data_len += fill_share_info(conn,i,uLevel,0,&f_len,0,&s_len,0);
1576 if (data_len <= buf_len)
1580 string_len += s_len;
1585 *rdata_len = fixed_len + string_len;
1586 *rdata = REALLOC(*rdata,*rdata_len);
1587 memset(*rdata,0,*rdata_len);
1589 p2 = (*rdata) + fixed_len; /* auxillery data (strings) will go here */
1593 for (i = 0; i < count;i++)
1594 if (lp_browseable(i) && lp_snum_ok(i))
1595 if (fill_share_info(conn,i,uLevel,&p,&f_len,&p2,&s_len,*rdata) < 0)
1599 *rparam = REALLOC(*rparam,*rparam_len);
1600 SSVAL(*rparam,0,missed ? ERRmoredata : NERR_Success);
1602 SSVAL(*rparam,4,counted);
1603 SSVAL(*rparam,6,total);
1605 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1606 counted,total,uLevel,
1607 buf_len,*rdata_len,mdrcnt));
1613 /****************************************************************************
1614 get the time of day info
1615 ****************************************************************************/
1616 static BOOL api_NetRemoteTOD(connection_struct *conn,uint16 vuid, char *param,char *data,
1617 int mdrcnt,int mprcnt,
1618 char **rdata,char **rparam,
1619 int *rdata_len,int *rparam_len)
1623 *rparam = REALLOC(*rparam,*rparam_len);
1626 *rdata = REALLOC(*rdata,*rdata_len);
1628 SSVAL(*rparam,0,NERR_Success);
1629 SSVAL(*rparam,2,0); /* converter word */
1635 time_t unixdate = time(NULL);
1637 put_dos_date3(p,0,unixdate); /* this is the time that is looked at
1638 by NT in a "net time" operation,
1639 it seems to ignore the one below */
1641 /* the client expects to get localtime, not GMT, in this bit
1642 (I think, this needs testing) */
1643 t = LocalTime(&unixdate);
1645 SIVAL(p,4,0); /* msecs ? */
1646 CVAL(p,8) = t->tm_hour;
1647 CVAL(p,9) = t->tm_min;
1648 CVAL(p,10) = t->tm_sec;
1649 CVAL(p,11) = 0; /* hundredths of seconds */
1650 SSVALS(p,12,TimeDiff(unixdate)/60); /* timezone in minutes from GMT */
1651 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
1652 CVAL(p,16) = t->tm_mday;
1653 CVAL(p,17) = t->tm_mon + 1;
1654 SSVAL(p,18,1900+t->tm_year);
1655 CVAL(p,20) = t->tm_wday;
1662 /****************************************************************************
1663 Set the user password.
1664 *****************************************************************************/
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 to verify the old password against smbpasswd entries
1708 * Win98 clients send old and new password in plaintext for this call.
1712 fstring saved_pass2;
1713 struct smb_passwd *smbpw = NULL;
1716 * Save the new password as change_oem_password overwrites it
1720 fstrcpy(saved_pass2, pass2);
1722 if (check_plaintext_password(user,pass1,strlen(pass1),&smbpw) &&
1723 change_oem_password(smbpw,pass2,False))
1725 SSVAL(*rparam,0,NERR_Success);
1728 * If unix password sync was requested, attempt to change
1729 * the /etc/passwd database also. Return failure if this cannot
1733 if(lp_unix_password_sync() && !chgpasswd(user,pass1,saved_pass2,False))
1734 SSVAL(*rparam,0,NERR_badpass);
1739 * If the above failed, attempt the plaintext password change.
1740 * This tests against the /etc/passwd database only.
1743 if(SVAL(*rparam,0) != NERR_Success)
1745 if (password_ok(user, pass1,strlen(pass1),NULL) &&
1746 chgpasswd(user,pass1,pass2,False))
1748 SSVAL(*rparam,0,NERR_Success);
1753 * If the plaintext change failed, attempt
1754 * the old encrypted method. NT will generate this
1755 * after trying the samr method. Note that this
1756 * method is done as a last resort as this
1757 * password change method loses the NT password hash
1758 * and cannot change the UNIX password as no plaintext
1762 if(SVAL(*rparam,0) != NERR_Success)
1764 struct smb_passwd *sampw = NULL;
1766 if(check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &sampw) &&
1767 change_lanman_password(sampw,(unsigned char *)pass1,(unsigned char *)pass2))
1769 SSVAL(*rparam,0,NERR_Success);
1773 memset((char *)pass1,'\0',sizeof(fstring));
1774 memset((char *)pass2,'\0',sizeof(fstring));
1779 /****************************************************************************
1780 Set the user password (SamOEM version - gets plaintext).
1781 ****************************************************************************/
1783 static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char *param,char *data,
1784 int mdrcnt,int mprcnt,
1785 char **rdata,char **rparam,
1786 int *rdata_len,int *rparam_len)
1789 char *p = param + 2;
1791 *rparam = REALLOC(*rparam,*rparam_len);
1795 SSVAL(*rparam,0,NERR_badpass);
1798 * Check the parameter definition is correct.
1800 if(!strequal(param + 2, "zsT")) {
1801 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", param + 2));
1804 p = skip_string(p, 1);
1806 if(!strequal(p, "B516B16")) {
1807 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p));
1810 p = skip_string(p,1);
1813 p = skip_string(p,1);
1815 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user));
1818 * Pass the user through the NT -> unix user mapping
1822 (void)map_username(user);
1825 * Do any UNIX username case mangling.
1827 (void)Get_Pwnam( user, True);
1829 if (pass_oem_change(user, (uchar*) data, (uchar *)&data[516], NULL, NULL))
1831 SSVAL(*rparam,0,NERR_Success);
1837 /****************************************************************************
1840 ****************************************************************************/
1841 static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char *param,char *data,
1842 int mdrcnt,int mprcnt,
1843 char **rdata,char **rparam,
1844 int *rdata_len,int *rparam_len)
1846 int function = SVAL(param,0);
1847 char *str1 = param+2;
1848 char *str2 = skip_string(str1,1);
1849 char *p = skip_string(str2,1);
1853 printjob_decode(SVAL(p,0), &snum, &jobid);
1855 /* check it's a supported varient */
1856 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
1860 *rparam = REALLOC(*rparam,*rparam_len);
1864 SSVAL(*rparam,0,NERR_Success);
1866 if (snum >= 0 && VALID_SNUM(snum))
1868 print_queue_struct *queue=NULL;
1870 count = get_printqueue(snum,conn,&queue,NULL);
1872 for (i=0;i<count;i++)
1873 if ((queue[i].job&0xFF) == jobid)
1876 case 81: /* delete */
1877 DEBUG(3,("Deleting queue entry %d\n",queue[i].job));
1878 del_printqueue(conn,snum,queue[i].job);
1880 case 82: /* pause */
1881 case 83: /* resume */
1882 DEBUG(3,("%s queue entry %d\n",
1883 (function==82?"pausing":"resuming"),queue[i].job));
1884 status_printjob(conn,snum,queue[i].job,
1885 (function==82?LPQ_PAUSED:LPQ_QUEUED));
1892 SSVAL(*rparam,0,NERR_JobNotFound);
1894 if (queue) free(queue);
1897 SSVAL(*rparam,2,0); /* converter word */
1902 /****************************************************************************
1903 Purge a print queue - or pause or resume it.
1904 ****************************************************************************/
1905 static BOOL api_WPrintQueuePurge(connection_struct *conn,uint16 vuid, char *param,char *data,
1906 int mdrcnt,int mprcnt,
1907 char **rdata,char **rparam,
1908 int *rdata_len,int *rparam_len)
1910 int function = SVAL(param,0);
1911 char *str1 = param+2;
1912 char *str2 = skip_string(str1,1);
1913 char *QueueName = skip_string(str2,1);
1916 /* check it's a supported varient */
1917 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
1921 *rparam = REALLOC(*rparam,*rparam_len);
1925 SSVAL(*rparam,0,NERR_Success);
1926 SSVAL(*rparam,2,0); /* converter word */
1928 snum = lp_servicenumber(QueueName);
1929 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
1930 int pnum = lp_servicenumber(PRINTERS_NAME);
1932 lp_add_printer(QueueName,pnum);
1933 snum = lp_servicenumber(QueueName);
1937 if (snum >= 0 && VALID_SNUM(snum)) {
1941 case 74: /* Pause queue */
1942 case 75: /* Resume queue */
1943 status_printqueue(conn,snum,(function==74?LPSTAT_STOPPED:LPSTAT_OK));
1944 DEBUG(3,("Print queue %s, queue=%s\n",
1945 (function==74?"pause":"resume"),QueueName));
1947 case 103: /* Purge */
1949 print_queue_struct *queue=NULL;
1951 count = get_printqueue(snum,conn,&queue,NULL);
1952 for (i = 0; i < count; i++)
1953 del_printqueue(conn,snum,queue[i].job);
1955 if (queue) free(queue);
1956 DEBUG(3,("Print queue purge, queue=%s\n",QueueName));
1966 /****************************************************************************
1967 set the property of a print job (undocumented?)
1968 ? function = 0xb -> set name of print job
1969 ? function = 0x6 -> move print job up/down
1970 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
1971 or <WWsTP> <WB21BB16B10zWWzDDz>
1972 ****************************************************************************/
1973 static int check_printjob_info(struct pack_desc* desc,
1974 int uLevel, char* id)
1976 desc->subformat = NULL;
1978 case 0: desc->format = "W"; break;
1979 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
1980 case 2: desc->format = "WWzWWDDzz"; break;
1981 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
1982 default: return False;
1984 if (strcmp(desc->format,id) != 0) return False;
1988 static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,char *data,
1989 int mdrcnt,int mprcnt,
1990 char **rdata,char **rparam,
1991 int *rdata_len,int *rparam_len)
1993 struct pack_desc desc;
1994 char *str1 = param+2;
1995 char *str2 = skip_string(str1,1);
1996 char *p = skip_string(str2,1);
1998 int uLevel = SVAL(p,2);
1999 int function = SVAL(p,4); /* what is this ?? */
2004 printjob_decode(SVAL(p,0), &snum, &jobid);
2007 *rparam = REALLOC(*rparam,*rparam_len);
2011 /* check it's a supported varient */
2012 if ((strcmp(str1,"WWsTP")) ||
2013 (!check_printjob_info(&desc,uLevel,str2)))
2017 case 0x6: /* change job place in the queue,
2018 data gives the new place */
2019 if (snum >= 0 && VALID_SNUM(snum)) {
2020 print_queue_struct *queue=NULL;
2024 count = get_printqueue(snum,conn,&queue,NULL);
2025 for (i=0;i<count;i++) /* find job */
2026 if ((queue[i].job&0xFF) == jobid) break;
2029 desc.errcode=NERR_JobNotFound;
2030 if (queue) free(queue);
2032 desc.errcode=NERR_Success;
2036 int place= SVAL(data,0);
2037 /* we currently have no way of
2038 doing this. Can any unix do it? */
2039 if (i < place) /* move down */;
2040 else if (i > place ) /* move up */;
2043 desc.errcode=NERR_notsupported; /* not yet
2045 if (queue) free(queue);
2048 desc.errcode=NERR_JobNotFound;
2052 case 0xb: /* change print job name, data gives the name */
2053 /* jobid, snum should be zero */
2054 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();
2070 connection_struct *fconn = fsp->conn;
2074 if (!become_user(fconn,vuid) ||
2075 !become_service(fconn,True))
2078 pstrcpy(zfrom, dos_to_unix(fsp->fsp_name,False));
2079 pstrcpy(zto, dos_to_unix(name,False));
2081 if (fsp->conn->vfs_ops.rename(zfrom,zto) == 0) {
2082 string_set(&fsp->fsp_name,name);
2088 desc.errcode=NERR_Success;
2091 default: /* not implemented */
2095 SSVALS(*rparam,0,desc.errcode);
2096 SSVAL(*rparam,2,0); /* converter word */
2102 /****************************************************************************
2103 get info about the server
2104 ****************************************************************************/
2105 static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2106 int mdrcnt,int mprcnt,
2107 char **rdata,char **rparam,
2108 int *rdata_len,int *rparam_len)
2110 char *str1 = param+2;
2111 char *str2 = skip_string(str1,1);
2112 char *p = skip_string(str2,1);
2113 int uLevel = SVAL(p,0);
2117 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
2119 /* check it's a supported varient */
2120 if (!prefix_ok(str1,"WrLh")) return False;
2123 if (strcmp(str2,"B16") != 0) return False;
2127 if (strcmp(str2,"B16BBDz") != 0) return False;
2131 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")
2136 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz")
2141 if (strcmp(str2,"DN") != 0) return False;
2145 if (strcmp(str2,"B16BBDzWWzzz") != 0) return False;
2148 default: return False;
2151 *rdata_len = mdrcnt;
2152 *rdata = REALLOC(*rdata,*rdata_len);
2155 p2 = p + struct_len;
2157 StrnCpy(p,local_machine,16);
2163 struct srv_info_struct *servers=NULL;
2166 uint32 servertype= lp_default_server_announce();
2168 pstrcpy(comment,string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH));
2170 if ((count=get_server_info(SV_TYPE_ALL,&servers,global_myworkgroup))>0) {
2171 for (i=0;i<count;i++)
2172 if (strequal(servers[i].name,local_machine))
2174 servertype = servers[i].type;
2175 pstrcpy(comment,servers[i].comment);
2178 if (servers) free(servers);
2180 SCVAL(p,0,lp_major_announce_version());
2181 SCVAL(p,1,lp_minor_announce_version());
2182 SIVAL(p,2,servertype);
2184 if (mdrcnt == struct_len) {
2187 SIVAL(p,6,PTR_DIFF(p2,*rdata));
2188 standard_sub(conn,comment);
2189 StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
2190 p2 = skip_string(p2,1);
2195 return False; /* not yet implemented */
2198 *rdata_len = PTR_DIFF(p2,*rdata);
2201 *rparam = REALLOC(*rparam,*rparam_len);
2202 SSVAL(*rparam,0,NERR_Success);
2203 SSVAL(*rparam,2,0); /* converter word */
2204 SSVAL(*rparam,4,*rdata_len);
2210 /****************************************************************************
2211 get info about the server
2212 ****************************************************************************/
2213 static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2214 int mdrcnt,int mprcnt,
2215 char **rdata,char **rparam,
2216 int *rdata_len,int *rparam_len)
2218 char *str1 = param+2;
2219 char *str2 = skip_string(str1,1);
2220 char *p = skip_string(str2,1);
2222 extern pstring sesssetup_user;
2223 int level = SVAL(p,0);
2225 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
2228 *rparam = REALLOC(*rparam,*rparam_len);
2230 /* check it's a supported varient */
2231 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz")))
2234 *rdata_len = mdrcnt + 1024;
2235 *rdata = REALLOC(*rdata,*rdata_len);
2237 SSVAL(*rparam,0,NERR_Success);
2238 SSVAL(*rparam,2,0); /* converter word */
2244 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
2245 pstrcpy(p2,local_machine);
2247 p2 = skip_string(p2,1);
2250 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2251 pstrcpy(p2,sesssetup_user);
2252 p2 = skip_string(p2,1);
2255 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
2256 pstrcpy(p2,global_myworkgroup);
2258 p2 = skip_string(p2,1);
2261 SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
2262 SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
2265 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2266 pstrcpy(p2,global_myworkgroup); /* don't know. login domain?? */
2267 p2 = skip_string(p2,1);
2270 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
2272 p2 = skip_string(p2,1);
2275 *rdata_len = PTR_DIFF(p2,*rdata);
2277 SSVAL(*rparam,4,*rdata_len);
2282 /****************************************************************************
2283 get info about a user
2285 struct user_info_11 {
2286 char usri11_name[21]; 0-20
2288 char *usri11_comment; 22-25
2289 char *usri11_usr_comment; 26-29
2290 unsigned short usri11_priv; 30-31
2291 unsigned long usri11_auth_flags; 32-35
2292 long usri11_password_age; 36-39
2293 char *usri11_homedir; 40-43
2294 char *usri11_parms; 44-47
2295 long usri11_last_logon; 48-51
2296 long usri11_last_logoff; 52-55
2297 unsigned short usri11_bad_pw_count; 56-57
2298 unsigned short usri11_num_logons; 58-59
2299 char *usri11_logon_server; 60-63
2300 unsigned short usri11_country_code; 64-65
2301 char *usri11_workstations; 66-69
2302 unsigned long usri11_max_storage; 70-73
2303 unsigned short usri11_units_per_week; 74-75
2304 unsigned char *usri11_logon_hours; 76-79
2305 unsigned short usri11_code_page; 80-81
2310 usri11_name specifies the user name for which information is retireved
2312 usri11_pad aligns the next data structure element to a word boundary
2314 usri11_comment is a null terminated ASCII comment
2316 usri11_user_comment is a null terminated ASCII comment about the user
2318 usri11_priv specifies the level of the privilege assigned to the user.
2319 The possible values are:
2321 Name Value Description
2322 USER_PRIV_GUEST 0 Guest privilege
2323 USER_PRIV_USER 1 User privilege
2324 USER_PRV_ADMIN 2 Administrator privilege
2326 usri11_auth_flags specifies the account operator privileges. The
2327 possible values are:
2329 Name Value Description
2330 AF_OP_PRINT 0 Print operator
2333 Leach, Naik [Page 28]
\r\f
2336 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2339 AF_OP_COMM 1 Communications operator
2340 AF_OP_SERVER 2 Server operator
2341 AF_OP_ACCOUNTS 3 Accounts operator
2344 usri11_password_age specifies how many seconds have elapsed since the
2345 password was last changed.
2347 usri11_home_dir points to a null terminated ASCII string that contains
2348 the path name of the user's home directory.
2350 usri11_parms points to a null terminated ASCII string that is set
2351 aside for use by applications.
2353 usri11_last_logon specifies the time when the user last logged on.
2354 This value is stored as the number of seconds elapsed since
2355 00:00:00, January 1, 1970.
2357 usri11_last_logoff specifies the time when the user last logged off.
2358 This value is stored as the number of seconds elapsed since
2359 00:00:00, January 1, 1970. A value of 0 means the last logoff
2362 usri11_bad_pw_count specifies the number of incorrect passwords
2363 entered since the last successful logon.
2365 usri11_log1_num_logons specifies the number of times this user has
2366 logged on. A value of -1 means the number of logons is unknown.
2368 usri11_logon_server points to a null terminated ASCII string that
2369 contains the name of the server to which logon requests are sent.
2370 A null string indicates logon requests should be sent to the
2373 usri11_country_code specifies the country code for the user's language
2376 usri11_workstations points to a null terminated ASCII string that
2377 contains the names of workstations the user may log on from.
2378 There may be up to 8 workstations, with the names separated by
2379 commas. A null strings indicates there are no restrictions.
2381 usri11_max_storage specifies the maximum amount of disk space the user
2382 can occupy. A value of 0xffffffff indicates there are no
2385 usri11_units_per_week specifies the equal number of time units into
2386 which a week is divided. This value must be equal to 168.
2388 usri11_logon_hours points to a 21 byte (168 bits) string that
2389 specifies the time during which the user can log on. Each bit
2390 represents one unique hour in a week. The first bit (bit 0, word
2391 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
2395 Leach, Naik [Page 29]
\r\f
2398 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2401 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
2402 are no restrictions.
2404 usri11_code_page specifies the code page for the user's language of
2407 All of the pointers in this data structure need to be treated
2408 specially. The pointer is a 32 bit pointer. The higher 16 bits need
2409 to be ignored. The converter word returned in the parameters section
2410 needs to be subtracted from the lower 16 bits to calculate an offset
2411 into the return buffer where this ASCII string resides.
2413 There is no auxiliary data in the response.
2415 ****************************************************************************/
2417 #define usri11_name 0
2418 #define usri11_pad 21
2419 #define usri11_comment 22
2420 #define usri11_usr_comment 26
2421 #define usri11_full_name 30
2422 #define usri11_priv 34
2423 #define usri11_auth_flags 36
2424 #define usri11_password_age 40
2425 #define usri11_homedir 44
2426 #define usri11_parms 48
2427 #define usri11_last_logon 52
2428 #define usri11_last_logoff 56
2429 #define usri11_bad_pw_count 60
2430 #define usri11_num_logons 62
2431 #define usri11_logon_server 64
2432 #define usri11_country_code 68
2433 #define usri11_workstations 70
2434 #define usri11_max_storage 74
2435 #define usri11_units_per_week 78
2436 #define usri11_logon_hours 80
2437 #define usri11_code_page 84
2438 #define usri11_end 86
2440 #define USER_PRIV_GUEST 0
2441 #define USER_PRIV_USER 1
2442 #define USER_PRIV_ADMIN 2
2444 #define AF_OP_PRINT 0
2445 #define AF_OP_COMM 1
2446 #define AF_OP_SERVER 2
2447 #define AF_OP_ACCOUNTS 3
2450 static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2451 int mdrcnt,int mprcnt,
2452 char **rdata,char **rparam,
2453 int *rdata_len,int *rparam_len)
2455 char *str1 = param+2;
2456 char *str2 = skip_string(str1,1);
2457 char *UserName = skip_string(str2,1);
2458 char *p = skip_string(UserName,1);
2459 int uLevel = SVAL(p,0);
2462 /* get NIS home of a previously validated user - simeon */
2463 /* With share level security vuid will always be zero.
2464 Don't depend on vuser being non-null !!. JRA */
2465 user_struct *vuser = get_valid_user_struct(vuid);
2467 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid, vuser->name));
2470 *rparam = REALLOC(*rparam,*rparam_len);
2472 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
2474 /* check it's a supported variant */
2475 if (strcmp(str1,"zWrLh") != 0) return False;
2478 case 0: p2 = "B21"; break;
2479 case 1: p2 = "B21BB16DWzzWz"; break;
2480 case 2: p2 = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
2481 case 10: p2 = "B21Bzzz"; break;
2482 case 11: p2 = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
2483 default: return False;
2486 if (strcmp(p2,str2) != 0) return False;
2488 *rdata_len = mdrcnt + 1024;
2489 *rdata = REALLOC(*rdata,*rdata_len);
2491 SSVAL(*rparam,0,NERR_Success);
2492 SSVAL(*rparam,2,0); /* converter word */
2495 p2 = p + usri11_end;
2498 fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
2502 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
2507 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
2508 pstrcpy(p2,"Comment");
2509 p2 = skip_string(p2,1);
2511 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
2512 pstrcpy(p2,"UserComment");
2513 p2 = skip_string(p2,1);
2515 /* EEK! the cifsrap.txt doesn't have this in!!!! */
2516 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
2517 pstrcpy(p2,((vuser != NULL) ? vuser->real_name : UserName));
2518 p2 = skip_string(p2,1);
2521 if (uLevel == 11) /* modelled after NTAS 3.51 reply */
2523 SSVAL(p,usri11_priv,conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2524 SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
2525 SIVALS(p,usri11_password_age,-1); /* password age */
2526 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
2527 pstrcpy(p2, lp_logon_home());
2528 p2 = skip_string(p2,1);
2529 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
2531 p2 = skip_string(p2,1);
2532 SIVAL(p,usri11_last_logon,0); /* last logon */
2533 SIVAL(p,usri11_last_logoff,0); /* last logoff */
2534 SSVALS(p,usri11_bad_pw_count,-1); /* bad pw counts */
2535 SSVALS(p,usri11_num_logons,-1); /* num logons */
2536 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
2537 pstrcpy(p2,"\\\\*");
2538 p2 = skip_string(p2,1);
2539 SSVAL(p,usri11_country_code,0); /* country code */
2541 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
2543 p2 = skip_string(p2,1);
2545 SIVALS(p,usri11_max_storage,-1); /* max storage */
2546 SSVAL(p,usri11_units_per_week,168); /* units per week */
2547 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
2549 /* a simple way to get logon hours at all times. */
2551 SCVAL(p2,21,0); /* fix zero termination */
2552 p2 = skip_string(p2,1);
2554 SSVAL(p,usri11_code_page,0); /* code page */
2556 if (uLevel == 1 || uLevel == 2)
2558 memset(p+22,' ',16); /* password */
2559 SIVALS(p,38,-1); /* password age */
2561 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2562 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
2563 pstrcpy(p2,lp_logon_home());
2564 p2 = skip_string(p2,1);
2565 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
2567 SSVAL(p,52,0); /* flags */
2568 SIVAL(p,54,PTR_DIFF(p2,*rdata)); /* script_path */
2569 pstrcpy(p2,lp_logon_script());
2570 standard_sub( conn, p2 );
2571 p2 = skip_string(p2,1);
2574 SIVAL(p,60,0); /* auth_flags */
2575 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
2576 pstrcpy(p2,((vuser != NULL) ? vuser->real_name : UserName));
2577 p2 = skip_string(p2,1);
2578 SIVAL(p,68,0); /* urs_comment */
2579 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
2581 p2 = skip_string(p2,1);
2582 SIVAL(p,76,0); /* workstations */
2583 SIVAL(p,80,0); /* last_logon */
2584 SIVAL(p,84,0); /* last_logoff */
2585 SIVALS(p,88,-1); /* acct_expires */
2586 SIVALS(p,92,-1); /* max_storage */
2587 SSVAL(p,96,168); /* units_per_week */
2588 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
2591 SSVALS(p,102,-1); /* bad_pw_count */
2592 SSVALS(p,104,-1); /* num_logons */
2593 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
2594 pstrcpy(p2,"\\\\%L");
2595 standard_sub_basic(p2);
2596 p2 = skip_string(p2,1);
2597 SSVAL(p,110,49); /* country_code */
2598 SSVAL(p,112,860); /* code page */
2602 *rdata_len = PTR_DIFF(p2,*rdata);
2604 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
2609 /*******************************************************************
2610 get groups that a user is a member of
2611 ******************************************************************/
2612 static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *param,char *data,
2613 int mdrcnt,int mprcnt,
2614 char **rdata,char **rparam,
2615 int *rdata_len,int *rparam_len)
2617 char *str1 = param+2;
2618 char *str2 = skip_string(str1,1);
2619 char *UserName = skip_string(str2,1);
2620 char *p = skip_string(UserName,1);
2621 int uLevel = SVAL(p,0);
2626 *rparam = REALLOC(*rparam,*rparam_len);
2628 /* check it's a supported varient */
2629 if (strcmp(str1,"zWrLeh") != 0) return False;
2631 case 0: p2 = "B21"; break;
2632 default: return False;
2634 if (strcmp(p2,str2) != 0) return False;
2636 *rdata_len = mdrcnt + 1024;
2637 *rdata = REALLOC(*rdata,*rdata_len);
2639 SSVAL(*rparam,0,NERR_Success);
2640 SSVAL(*rparam,2,0); /* converter word */
2644 /* XXXX we need a real SAM database some day */
2645 pstrcpy(p,"Users"); p += 21; count++;
2646 pstrcpy(p,"Domain Users"); p += 21; count++;
2647 pstrcpy(p,"Guests"); p += 21; count++;
2648 pstrcpy(p,"Domain Guests"); p += 21; count++;
2650 *rdata_len = PTR_DIFF(p,*rdata);
2652 SSVAL(*rparam,4,count); /* is this right?? */
2653 SSVAL(*rparam,6,count); /* is this right?? */
2659 static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param,char *data,
2660 int mdrcnt,int mprcnt,
2661 char **rdata,char **rparam,
2662 int *rdata_len,int *rparam_len)
2664 char *str1 = param+2;
2665 char *str2 = skip_string(str1,1);
2666 char *p = skip_string(str2,1);
2668 struct pack_desc desc;
2674 memset((char *)&desc,'\0',sizeof(desc));
2676 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
2678 /* check it's a supported varient */
2679 if (strcmp(str1,"OOWb54WrLh") != 0) return False;
2680 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) return False;
2681 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2683 desc.buflen = mdrcnt;
2684 desc.subformat = NULL;
2687 if (init_package(&desc,1,0))
2689 PACKI(&desc,"W",0); /* code */
2690 PACKS(&desc,"B21",name); /* eff. name */
2691 PACKS(&desc,"B",""); /* pad */
2693 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2694 PACKI(&desc,"D",0); /* auth flags XXX */
2695 PACKI(&desc,"W",0); /* num logons */
2696 PACKI(&desc,"W",0); /* bad pw count */
2697 PACKI(&desc,"D",0); /* last logon */
2698 PACKI(&desc,"D",-1); /* last logoff */
2699 PACKI(&desc,"D",-1); /* logoff time */
2700 PACKI(&desc,"D",-1); /* kickoff time */
2701 PACKI(&desc,"D",0); /* password age */
2702 PACKI(&desc,"D",0); /* password can change */
2703 PACKI(&desc,"D",-1); /* password must change */
2706 fstrcpy(mypath,"\\\\");
2707 fstrcat(mypath,local_machine);
2709 PACKS(&desc,"z",mypath); /* computer */
2711 PACKS(&desc,"z",global_myworkgroup);/* domain */
2713 /* JHT - By calling lp_logon_script() and standard_sub() we have */
2714 /* made sure all macros are fully substituted and available */
2716 pstring logon_script;
2717 pstrcpy(logon_script,lp_logon_script());
2718 standard_sub( conn, logon_script );
2719 PACKS(&desc,"z", logon_script); /* script path */
2721 /* End of JHT mods */
2723 PACKI(&desc,"D",0x00000000); /* reserved */
2726 *rdata_len = desc.usedlen;
2728 *rparam = REALLOC(*rparam,*rparam_len);
2729 SSVALS(*rparam,0,desc.errcode);
2731 SSVAL(*rparam,4,desc.neededlen);
2733 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
2738 /****************************************************************************
2739 api_WAccessGetUserPerms
2740 ****************************************************************************/
2741 static BOOL api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid, char *param,char *data,
2742 int mdrcnt,int mprcnt,
2743 char **rdata,char **rparam,
2744 int *rdata_len,int *rparam_len)
2746 char *str1 = param+2;
2747 char *str2 = skip_string(str1,1);
2748 char *user = skip_string(str2,1);
2749 char *resource = skip_string(user,1);
2751 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
2753 /* check it's a supported varient */
2754 if (strcmp(str1,"zzh") != 0) return False;
2755 if (strcmp(str2,"") != 0) return False;
2758 *rparam = REALLOC(*rparam,*rparam_len);
2759 SSVALS(*rparam,0,0); /* errorcode */
2760 SSVAL(*rparam,2,0); /* converter word */
2761 SSVAL(*rparam,4,0x7f); /* permission flags */
2766 /****************************************************************************
2767 api_WPrintJobEnumerate
2768 ****************************************************************************/
2769 static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2770 int mdrcnt,int mprcnt,
2771 char **rdata,char **rparam,
2772 int *rdata_len,int *rparam_len)
2774 char *str1 = param+2;
2775 char *str2 = skip_string(str1,1);
2776 char *p = skip_string(str2,1);
2782 struct pack_desc desc;
2783 print_queue_struct *queue=NULL;
2784 print_status_struct status;
2788 memset((char *)&desc,'\0',sizeof(desc));
2789 memset((char *)&status,'\0',sizeof(status));
2791 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
2793 /* check it's a supported varient */
2794 if (strcmp(str1,"WWrLh") != 0) return False;
2795 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2797 printjob_decode(SVAL(p,0), &snum, &job);
2799 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2801 count = get_printqueue(snum,conn,&queue,&status);
2802 for (i = 0; i < count; i++) {
2803 if ((queue[i].job & 0xFF) == job) break;
2805 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2807 desc.buflen = mdrcnt;
2809 if (init_package(&desc,1,0)) {
2811 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
2812 *rdata_len = desc.usedlen;
2815 desc.errcode = NERR_JobNotFound;
2821 *rparam = REALLOC(*rparam,*rparam_len);
2822 SSVALS(*rparam,0,desc.errcode);
2824 SSVAL(*rparam,4,desc.neededlen);
2826 if (queue) free(queue);
2828 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
2832 static BOOL api_WPrintJobEnumerate(connection_struct *conn,uint16 vuid, char *param,char *data,
2833 int mdrcnt,int mprcnt,
2834 char **rdata,char **rparam,
2835 int *rdata_len,int *rparam_len)
2837 char *str1 = param+2;
2838 char *str2 = skip_string(str1,1);
2839 char *p = skip_string(str2,1);
2845 struct pack_desc desc;
2846 print_queue_struct *queue=NULL;
2847 print_status_struct status;
2849 memset((char *)&desc,'\0',sizeof(desc));
2850 memset((char *)&status,'\0',sizeof(status));
2852 p = skip_string(p,1);
2855 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
2857 /* check it's a supported varient */
2858 if (strcmp(str1,"zWrLeh") != 0) return False;
2859 if (uLevel > 2) return False; /* defined only for uLevel 0,1,2 */
2860 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2862 snum = lp_servicenumber(name);
2863 if (snum < 0 && pcap_printername_ok(name,NULL)) {
2864 int pnum = lp_servicenumber(PRINTERS_NAME);
2866 lp_add_printer(name,pnum);
2867 snum = lp_servicenumber(name);
2871 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2873 count = get_printqueue(snum,conn,&queue,&status);
2874 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2876 desc.buflen = mdrcnt;
2878 if (init_package(&desc,count,0)) {
2880 for (i = 0; i < count; i++) {
2881 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
2882 if (desc.errcode == NERR_Success) succnt = i+1;
2886 *rdata_len = desc.usedlen;
2889 *rparam = REALLOC(*rparam,*rparam_len);
2890 SSVALS(*rparam,0,desc.errcode);
2892 SSVAL(*rparam,4,succnt);
2893 SSVAL(*rparam,6,count);
2895 if (queue) free(queue);
2897 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
2901 static int check_printdest_info(struct pack_desc* desc,
2902 int uLevel, char* id)
2904 desc->subformat = NULL;
2906 case 0: desc->format = "B9"; break;
2907 case 1: desc->format = "B9B21WWzW"; break;
2908 case 2: desc->format = "z"; break;
2909 case 3: desc->format = "zzzWWzzzWW"; break;
2910 default: return False;
2912 if (strcmp(desc->format,id) != 0) return False;
2916 static void fill_printdest_info(connection_struct *conn, int snum, int uLevel,
2917 struct pack_desc* desc)
2920 strncpy(buf,SERVICE(snum),sizeof(buf)-1);
2921 buf[sizeof(buf)-1] = 0;
2924 PACKS(desc,"B9",buf); /* szName */
2926 PACKS(desc,"B21",""); /* szUserName */
2927 PACKI(desc,"W",0); /* uJobId */
2928 PACKI(desc,"W",0); /* fsStatus */
2929 PACKS(desc,"z",""); /* pszStatus */
2930 PACKI(desc,"W",0); /* time */
2933 if (uLevel == 2 || uLevel == 3) {
2934 PACKS(desc,"z",buf); /* pszPrinterName */
2936 PACKS(desc,"z",""); /* pszUserName */
2937 PACKS(desc,"z",""); /* pszLogAddr */
2938 PACKI(desc,"W",0); /* uJobId */
2939 PACKI(desc,"W",0); /* fsStatus */
2940 PACKS(desc,"z",""); /* pszStatus */
2941 PACKS(desc,"z",""); /* pszComment */
2942 PACKS(desc,"z","NULL"); /* pszDrivers */
2943 PACKI(desc,"W",0); /* time */
2944 PACKI(desc,"W",0); /* pad1 */
2949 static BOOL api_WPrintDestGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2950 int mdrcnt,int mprcnt,
2951 char **rdata,char **rparam,
2952 int *rdata_len,int *rparam_len)
2954 char *str1 = param+2;
2955 char *str2 = skip_string(str1,1);
2956 char *p = skip_string(str2,1);
2957 char* PrinterName = p;
2959 struct pack_desc desc;
2962 memset((char *)&desc,'\0',sizeof(desc));
2964 p = skip_string(p,1);
2967 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
2969 /* check it's a supported varient */
2970 if (strcmp(str1,"zWrLh") != 0) return False;
2971 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2973 snum = lp_servicenumber(PrinterName);
2974 if (snum < 0 && pcap_printername_ok(PrinterName,NULL)) {
2975 int pnum = lp_servicenumber(PRINTERS_NAME);
2977 lp_add_printer(PrinterName,pnum);
2978 snum = lp_servicenumber(PrinterName);
2984 desc.errcode = NERR_DestNotFound;
2988 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2990 desc.buflen = mdrcnt;
2991 if (init_package(&desc,1,0)) {
2992 fill_printdest_info(conn,snum,uLevel,&desc);
2994 *rdata_len = desc.usedlen;
2998 *rparam = REALLOC(*rparam,*rparam_len);
2999 SSVALS(*rparam,0,desc.errcode);
3001 SSVAL(*rparam,4,desc.neededlen);
3003 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
3007 static BOOL api_WPrintDestEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3008 int mdrcnt,int mprcnt,
3009 char **rdata,char **rparam,
3010 int *rdata_len,int *rparam_len)
3012 char *str1 = param+2;
3013 char *str2 = skip_string(str1,1);
3014 char *p = skip_string(str2,1);
3018 struct pack_desc desc;
3019 int services = lp_numservices();
3021 memset((char *)&desc,'\0',sizeof(desc));
3025 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
3027 /* check it's a supported varient */
3028 if (strcmp(str1,"WrLeh") != 0) return False;
3029 if (!check_printdest_info(&desc,uLevel,str2)) return False;
3032 for (i = 0; i < services; i++)
3033 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
3036 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3038 desc.buflen = mdrcnt;
3039 if (init_package(&desc,queuecnt,0)) {
3042 for (i = 0; i < services; i++) {
3043 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
3044 fill_printdest_info(conn,i,uLevel,&desc);
3046 if (desc.errcode == NERR_Success) succnt = n;
3051 *rdata_len = desc.usedlen;
3054 *rparam = REALLOC(*rparam,*rparam_len);
3055 SSVALS(*rparam,0,desc.errcode);
3057 SSVAL(*rparam,4,succnt);
3058 SSVAL(*rparam,6,queuecnt);
3060 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
3064 static BOOL api_WPrintDriverEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3065 int mdrcnt,int mprcnt,
3066 char **rdata,char **rparam,
3067 int *rdata_len,int *rparam_len)
3069 char *str1 = param+2;
3070 char *str2 = skip_string(str1,1);
3071 char *p = skip_string(str2,1);
3074 struct pack_desc desc;
3076 memset((char *)&desc,'\0',sizeof(desc));
3080 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
3082 /* check it's a supported varient */
3083 if (strcmp(str1,"WrLeh") != 0) return False;
3084 if (uLevel != 0 || strcmp(str2,"B41") != 0) return False;
3086 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3088 desc.buflen = mdrcnt;
3089 if (init_package(&desc,1,0)) {
3090 PACKS(&desc,"B41","NULL");
3093 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3095 *rdata_len = desc.usedlen;
3098 *rparam = REALLOC(*rparam,*rparam_len);
3099 SSVALS(*rparam,0,desc.errcode);
3101 SSVAL(*rparam,4,succnt);
3104 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
3108 static BOOL api_WPrintQProcEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3109 int mdrcnt,int mprcnt,
3110 char **rdata,char **rparam,
3111 int *rdata_len,int *rparam_len)
3113 char *str1 = param+2;
3114 char *str2 = skip_string(str1,1);
3115 char *p = skip_string(str2,1);
3118 struct pack_desc desc;
3120 memset((char *)&desc,'\0',sizeof(desc));
3124 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
3126 /* check it's a supported varient */
3127 if (strcmp(str1,"WrLeh") != 0) return False;
3128 if (uLevel != 0 || strcmp(str2,"B13") != 0) return False;
3130 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3132 desc.buflen = mdrcnt;
3134 if (init_package(&desc,1,0)) {
3135 PACKS(&desc,"B13","lpd");
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,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
3153 static BOOL api_WPrintPortEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3154 int mdrcnt,int mprcnt,
3155 char **rdata,char **rparam,
3156 int *rdata_len,int *rparam_len)
3158 char *str1 = param+2;
3159 char *str2 = skip_string(str1,1);
3160 char *p = skip_string(str2,1);
3163 struct pack_desc desc;
3165 memset((char *)&desc,'\0',sizeof(desc));
3169 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
3171 /* check it's a supported varient */
3172 if (strcmp(str1,"WrLeh") != 0) return False;
3173 if (uLevel != 0 || strcmp(str2,"B9") != 0) return False;
3175 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3176 memset((char *)&desc,'\0',sizeof(desc));
3178 desc.buflen = mdrcnt;
3180 if (init_package(&desc,1,0)) {
3181 PACKS(&desc,"B13","lp0");
3184 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3186 *rdata_len = desc.usedlen;
3189 *rparam = REALLOC(*rparam,*rparam_len);
3190 SSVALS(*rparam,0,desc.errcode);
3192 SSVAL(*rparam,4,succnt);
3195 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
3199 /****************************************************************************
3200 Start the first part of an RPC reply which began with an SMBtrans request.
3201 ****************************************************************************/
3203 static BOOL api_rpc_trans_reply(char *outbuf, pipes_struct *p)
3205 char *rdata = malloc(p->max_trans_reply);
3209 DEBUG(0,("api_rpc_trans_reply: malloc fail.\n"));
3213 if((data_len = read_from_pipe( p, rdata, p->max_trans_reply)) < 0) {
3218 send_trans_reply(outbuf, NULL, 0, rdata, data_len, (int)prs_offset(&p->out_data.rdata) > data_len);
3224 /****************************************************************************
3225 WaitNamedPipeHandleState
3226 ****************************************************************************/
3228 static BOOL api_WNPHS(char *outbuf, pipes_struct *p, char *param, int param_len)
3232 if (!param || param_len < 2)
3235 priority = SVAL(param,0);
3236 DEBUG(4,("WaitNamedPipeHandleState priority %x\n", priority));
3238 if (wait_rpc_pipe_hnd_state(p, priority)) {
3239 /* now send the reply */
3240 send_trans_reply(outbuf, NULL, 0, NULL, 0, False);
3247 /****************************************************************************
3248 SetNamedPipeHandleState
3249 ****************************************************************************/
3251 static BOOL api_SNPHS(char *outbuf, pipes_struct *p, char *param, int param_len)
3255 if (!param || param_len < 2)
3259 DEBUG(4,("SetNamedPipeHandleState to code %x\n", id));
3261 if (set_rpc_pipe_hnd_state(p, id)) {
3262 /* now send the reply */
3263 send_trans_reply(outbuf, NULL, 0, NULL, 0, False);
3270 /****************************************************************************
3271 When no reply is generated, indicate unsupported.
3272 ****************************************************************************/
3274 static BOOL api_no_reply(char *outbuf, int max_rdata_len)
3279 SSVAL(rparam,0,NERR_notsupported);
3280 SSVAL(rparam,2,0); /* converter word */
3282 DEBUG(3,("Unsupported API fd command\n"));
3284 /* now send the reply */
3285 send_trans_reply(outbuf, rparam, 4, NULL, 0, False);
3290 /****************************************************************************
3291 Handle remote api calls delivered to a named pipe already opened.
3292 ****************************************************************************/
3294 static int api_fd_reply(connection_struct *conn,uint16 vuid,char *outbuf,
3295 uint16 *setup,char *data,char *params,
3296 int suwcnt,int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
3299 pipes_struct *p = NULL;
3303 DEBUG(5,("api_fd_reply\n"));
3305 /* First find out the name of this file. */
3307 DEBUG(0,("Unexpected named pipe transaction.\n"));
3311 /* Get the file handle and hence the file name. */
3313 * NB. The setup array has already been transformed
3314 * via SVAL and so is in gost byte order.
3316 pnum = ((int)setup[1]) & 0xFFFF;
3317 subcommand = ((int)setup[0]) & 0xFFFF;
3319 if(!(p = get_rpc_pipe(pnum))) {
3320 DEBUG(1,("api_fd_reply: INVALID PIPE HANDLE: %x\n", pnum));
3321 return api_no_reply(outbuf, mdrcnt);
3324 DEBUG(3,("Got API command 0x%x on pipe \"%s\" (pnum %x)", subcommand, p->name, pnum));
3326 /* record maximum data length that can be transmitted in an SMBtrans */
3327 p->max_trans_reply = mdrcnt;
3329 DEBUG(10,("api_fd_reply: p:%p max_trans_reply: %d\n", p, p->max_trans_reply));
3331 switch (subcommand) {
3333 /* dce/rpc command */
3334 reply = write_to_pipe(p, data, tdscnt);
3336 reply = api_rpc_trans_reply(outbuf, p);
3339 /* Wait Named Pipe Handle state */
3340 reply = api_WNPHS(outbuf, p, params, tpscnt);
3343 /* Set Named Pipe Handle state */
3344 reply = api_SNPHS(outbuf, p, params, tpscnt);
3349 return api_no_reply(outbuf, mdrcnt);
3354 /****************************************************************************
3355 The buffer was too small
3356 ****************************************************************************/
3358 static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param,char *data,
3359 int mdrcnt,int mprcnt,
3360 char **rdata,char **rparam,
3361 int *rdata_len,int *rparam_len)
3363 *rparam_len = MIN(*rparam_len,mprcnt);
3364 *rparam = REALLOC(*rparam,*rparam_len);
3368 SSVAL(*rparam,0,NERR_BufTooSmall);
3370 DEBUG(3,("Supplied buffer too small in API command\n"));
3376 /****************************************************************************
3377 The request is not supported
3378 ****************************************************************************/
3380 static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param,char *data,
3381 int mdrcnt,int mprcnt,
3382 char **rdata,char **rparam,
3383 int *rdata_len,int *rparam_len)
3386 *rparam = REALLOC(*rparam,*rparam_len);
3390 SSVAL(*rparam,0,NERR_notsupported);
3391 SSVAL(*rparam,2,0); /* converter word */
3393 DEBUG(3,("Unsupported API command\n"));
3405 BOOL (*fn)(connection_struct *,uint16,char *,char *,
3406 int,int,char **,char **,int *,int *);
3408 } api_commands[] = {
3409 {"RNetShareEnum", 0, api_RNetShareEnum,0},
3410 {"RNetShareGetInfo", 1, api_RNetShareGetInfo,0},
3411 {"RNetServerGetInfo", 13, api_RNetServerGetInfo,0},
3412 {"RNetGroupGetUsers", 52, api_RNetGroupGetUsers,0},
3413 {"RNetUserGetInfo", 56, api_RNetUserGetInfo,0},
3414 {"NetUserGetGroups", 59, api_NetUserGetGroups,0},
3415 {"NetWkstaGetInfo", 63, api_NetWkstaGetInfo,0},
3416 {"DosPrintQEnum", 69, api_DosPrintQEnum,0},
3417 {"DosPrintQGetInfo", 70, api_DosPrintQGetInfo,0},
3418 {"WPrintQueuePause", 74, api_WPrintQueuePurge,0},
3419 {"WPrintQueueResume", 75, api_WPrintQueuePurge,0},
3420 {"WPrintJobEnumerate",76, api_WPrintJobEnumerate,0},
3421 {"WPrintJobGetInfo", 77, api_WPrintJobGetInfo,0},
3422 {"RDosPrintJobDel", 81, api_RDosPrintJobDel,0},
3423 {"RDosPrintJobPause", 82, api_RDosPrintJobDel,0},
3424 {"RDosPrintJobResume",83, api_RDosPrintJobDel,0},
3425 {"WPrintDestEnum", 84, api_WPrintDestEnum,0},
3426 {"WPrintDestGetInfo", 85, api_WPrintDestGetInfo,0},
3427 {"NetRemoteTOD", 91, api_NetRemoteTOD,0},
3428 {"WPrintQueuePurge", 103, api_WPrintQueuePurge,0},
3429 {"NetServerEnum", 104, api_RNetServerEnum,0},
3430 {"WAccessGetUserPerms",105, api_WAccessGetUserPerms,0},
3431 {"SetUserPassword", 115, api_SetUserPassword,0},
3432 {"WWkstaUserLogon", 132, api_WWkstaUserLogon,0},
3433 {"PrintJobInfo", 147, api_PrintJobInfo,0},
3434 {"WPrintDriverEnum", 205, api_WPrintDriverEnum,0},
3435 {"WPrintQProcEnum", 206, api_WPrintQProcEnum,0},
3436 {"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 int tpscnt = SVAL(inbuf,smb_vwv0);
3560 int tdscnt = SVAL(inbuf,smb_vwv1);
3561 int mprcnt = SVAL(inbuf,smb_vwv2);
3562 int mdrcnt = SVAL(inbuf,smb_vwv3);
3563 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 int pscnt = SVAL(inbuf,smb_vwv9);
3567 int psoff = SVAL(inbuf,smb_vwv10);
3568 int dscnt = SVAL(inbuf,smb_vwv11);
3569 int dsoff = SVAL(inbuf,smb_vwv12);
3570 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 %d bytes !\n", tdscnt));
3582 return(ERROR(ERRDOS,ERRnomem));
3584 memcpy(data,smb_base(inbuf)+dsoff,dscnt);
3588 if((params = (char *)malloc(tpscnt)) == NULL) {
3589 DEBUG(0,("reply_trans: param malloc fail for %d bytes !\n", tpscnt));
3590 return(ERROR(ERRDOS,ERRnomem));
3592 memcpy(params,smb_base(inbuf)+psoff,pscnt);
3597 if((setup = (uint16 *)malloc(suwcnt*sizeof(uint16))) == NULL) {
3598 DEBUG(0,("reply_trans: setup malloc fail for %d bytes !\n", (int)(suwcnt * sizeof(uint16))));
3599 return(ERROR(ERRDOS,ERRnomem));
3601 for (i=0;i<suwcnt;i++)
3602 setup[i] = SVAL(inbuf,smb_vwv14+i*SIZEOFWORD);
3606 if (pscnt < tpscnt || dscnt < tdscnt) {
3607 /* We need to send an interim response then receive the rest
3608 of the parameter/data bytes */
3609 outsize = set_message(outbuf,0,0,True);
3611 send_smb(Client,outbuf);
3614 /* receive the rest of the trans packet */
3615 while (pscnt < tpscnt || dscnt < tdscnt) {
3617 int pcnt,poff,dcnt,doff,pdisp,ddisp;
3619 ret = receive_next_smb(inbuf,bufsize,SMB_SECONDARY_WAIT);
3621 if ((ret && (CVAL(inbuf, smb_com) != SMBtranss)) || !ret) {
3623 DEBUG(0,("reply_trans: Invalid secondary trans packet\n"));
3625 DEBUG(0,("reply_trans: %s in getting secondary trans response.\n",
3626 (smb_read_error == READ_ERROR) ? "error" : "timeout" ));
3634 return(ERROR(ERRSRV,ERRerror));
3639 tpscnt = SVAL(inbuf,smb_vwv0);
3640 tdscnt = SVAL(inbuf,smb_vwv1);
3642 pcnt = SVAL(inbuf,smb_vwv2);
3643 poff = SVAL(inbuf,smb_vwv3);
3644 pdisp = SVAL(inbuf,smb_vwv4);
3646 dcnt = SVAL(inbuf,smb_vwv5);
3647 doff = SVAL(inbuf,smb_vwv6);
3648 ddisp = SVAL(inbuf,smb_vwv7);
3653 if (dscnt > tdscnt || pscnt > tpscnt) {
3654 exit_server("invalid trans parameters\n");
3658 memcpy(params+pdisp,smb_base(inbuf)+poff,pcnt);
3660 memcpy(data+ddisp,smb_base(inbuf)+doff,dcnt);
3664 DEBUG(3,("trans <%s> data=%d params=%d setup=%d\n",
3665 name,tdscnt,tpscnt,suwcnt));
3668 * WinCE wierdness....
3671 if (name[0] == '\\' && (StrnCaseCmp(&name[1],local_machine, strlen(local_machine)) == 0) &&
3672 (name[strlen(local_machine)+1] == '\\'))
3673 name_offset = strlen(local_machine)+1;
3675 if (strncmp(&name[name_offset],"\\PIPE\\",strlen("\\PIPE\\")) == 0) {
3676 DEBUG(5,("calling named_pipe\n"));
3677 outsize = named_pipe(conn,vuid,outbuf,
3678 name+name_offset+strlen("\\PIPE\\"),setup,data,params,
3679 suwcnt,tdscnt,tpscnt,msrcnt,mdrcnt,mprcnt);
3681 DEBUG(3,("invalid pipe name\n"));
3693 if (close_on_completion)
3694 close_cnum(conn,vuid);
3700 return(ERROR(ERRSRV,ERRnosupport));