2 Unix SMB/Netbios implementation.
4 Inter-process communication and named pipe handling
5 Copyright (C) Andrew Tridgell 1992-1995
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 This file handles the named pipe and mailslot calls
23 in the SMBtrans protocol
33 extern int DEBUGLEVEL;
35 extern files_struct Files[];
36 extern connection_struct Connections[];
38 extern fstring local_machine;
40 #define NERR_Success 0
41 #define NERR_badpass 86
42 #define NERR_notsupported 50
44 #define NERR_BASE (2100)
45 #define NERR_BufTooSmall (NERR_BASE+23)
46 #define NERR_JobNotFound (NERR_BASE+51)
47 #define NERR_DestNotFound (NERR_BASE+52)
48 #define ERROR_INVALID_LEVEL 124
49 #define ERROR_MORE_DATA 234
51 #define REALLOC(ptr,size) Realloc(ptr,MAX((size),4*1024))
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 */
62 #define MAJOR_VERSION 4
63 #define MINOR_VERSION 0
67 static BOOL api_Unsupported(int cnum,int uid, char *param,char *data,
68 int mdrcnt,int mprcnt,
69 char **rdata,char **rparam,
70 int *rdata_len,int *rparam_len);
71 static BOOL api_TooSmall(int cnum,int uid, char *param,char *data,
72 int mdrcnt,int mprcnt,
73 char **rdata,char **rparam,
74 int *rdata_len,int *rparam_len);
77 static int CopyExpanded(int cnum, int snum, char** dst, char* src, int* n)
82 if (!src || !dst || !n || !(*dst)) return(0);
84 StrnCpy(buf,src,sizeof(buf)/2);
85 string_sub(buf,"%S",lp_servicename(snum));
86 standard_sub(cnum,buf);
94 static int CopyAndAdvance(char** dst, char* src, int* n)
97 if (!src || !dst || !n || !(*dst)) return(0);
105 static int StrlenExpanded(int cnum, int snum, char* s)
109 StrnCpy(buf,s,sizeof(buf)/2);
110 string_sub(buf,"%S",lp_servicename(snum));
111 standard_sub(cnum,buf);
112 return strlen(buf) + 1;
115 static char* Expand(int cnum, int snum, char* s)
118 if (!s) return(NULL);
119 StrnCpy(buf,s,sizeof(buf)/2);
120 string_sub(buf,"%S",lp_servicename(snum));
121 standard_sub(cnum,buf);
125 /*******************************************************************
126 check a API string for validity when we only need to check the prefix
127 ******************************************************************/
128 static BOOL prefix_ok(char *str,char *prefix)
130 return(strncmp(str,prefix,strlen(prefix)) == 0);
134 /****************************************************************************
136 ****************************************************************************/
137 static void send_trans_reply(char *outbuf,char *data,char *param,uint16 *setup,
138 int ldata,int lparam,int lsetup)
141 int this_ldata,this_lparam;
142 int tot_data=0,tot_param=0;
145 this_lparam = MIN(lparam,maxxmit - (500+lsetup*SIZEOFWORD)); /* hack */
146 this_ldata = MIN(ldata,maxxmit - (500+lsetup*SIZEOFWORD+this_lparam));
148 align = (this_lparam%4);
150 set_message(outbuf,10+lsetup,align+this_ldata+this_lparam,True);
152 memcpy(smb_buf(outbuf),param,this_lparam);
154 memcpy(smb_buf(outbuf)+this_lparam+align,data,this_ldata);
156 SSVAL(outbuf,smb_vwv0,lparam);
157 SSVAL(outbuf,smb_vwv1,ldata);
158 SSVAL(outbuf,smb_vwv3,this_lparam);
159 SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf),outbuf));
160 SSVAL(outbuf,smb_vwv5,0);
161 SSVAL(outbuf,smb_vwv6,this_ldata);
162 SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+this_lparam+align,outbuf));
163 SSVAL(outbuf,smb_vwv8,0);
164 SSVAL(outbuf,smb_vwv9,lsetup);
165 for (i=0;i<lsetup;i++)
166 SSVAL(outbuf,smb_vwv10+i*SIZEOFWORD,setup[i]);
169 send_smb(Client,outbuf);
171 tot_data = this_ldata;
172 tot_param = this_lparam;
174 while (tot_data < ldata || tot_param < lparam)
176 this_lparam = MIN(lparam-tot_param,maxxmit - 500); /* hack */
177 this_ldata = MIN(ldata-tot_data,maxxmit - (500+this_lparam));
179 align = (this_lparam%4);
181 set_message(outbuf,10,this_ldata+this_lparam+align,False);
183 memcpy(smb_buf(outbuf),param+tot_param,this_lparam);
185 memcpy(smb_buf(outbuf)+this_lparam+align,data+tot_data,this_ldata);
187 SSVAL(outbuf,smb_vwv3,this_lparam);
188 SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf),outbuf));
189 SSVAL(outbuf,smb_vwv5,tot_param);
190 SSVAL(outbuf,smb_vwv6,this_ldata);
191 SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+this_lparam+align,outbuf));
192 SSVAL(outbuf,smb_vwv8,tot_data);
193 SSVAL(outbuf,smb_vwv9,0);
196 send_smb(Client,outbuf);
198 tot_data += this_ldata;
199 tot_param += this_lparam;
204 char* format; /* formatstring for structure */
205 char* subformat; /* subformat for structure */
206 char* base; /* baseaddress of buffer */
207 int buflen; /* remaining size for fixed part; on init: length of base */
208 int subcount; /* count of substructures */
209 char* structbuf; /* pointer into buffer for remaining fixed part */
210 int stringlen; /* remaining size for variable part */
211 char* stringbuf; /* pointer into buffer for remaining variable part */
212 int neededlen; /* total needed size */
213 int usedlen; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
214 char* curpos; /* current position; pointer into format or subformat */
218 static int get_counter(char** p)
221 if (!p || !(*p)) return(1);
222 if (!isdigit(**p)) return 1;
226 n = 10 * n + (i - '0');
233 static int getlen(char* p)
239 case 'W': /* word (2 byte) */
242 case 'N': /* count of substructures (word) at end */
245 case 'D': /* double word (4 byte) */
246 case 'z': /* offset to zero terminated string (4 byte) */
247 case 'l': /* offset to user data (4 byte) */
250 case 'b': /* offset to data (with counter) (4 byte) */
254 case 'B': /* byte (with optional counter) */
255 n += get_counter(&p);
262 static BOOL init_package(struct pack_desc* p, int count, int subcount)
267 if (!p->format || !p->base) return(False);
269 i = count * getlen(p->format);
270 if (p->subformat) i += subcount * getlen(p->subformat);
271 p->structbuf = p->base;
275 p->curpos = p->format;
278 p->errcode = NERR_BufTooSmall;
281 p->errcode = NERR_Success;
284 p->stringbuf = p->base + i;
286 return(p->errcode == NERR_Success);
290 static int package(struct pack_desc* p, ...)
293 static int package(va_alist)
299 int needed=0, stringneeded;
301 int is_string=0, stringused;
308 p = va_arg(args,struct pack_desc *);
313 p->curpos = p->format;
315 p->curpos = p->subformat;
320 str = va_arg(args,char*);
321 if (strncmp(str,p->curpos,strlen(str)) != 0) {
322 DEBUG(2,("type error in package: %s instead of %*s\n",str,
323 strlen(str),p->curpos));
333 if (!p->curpos) return(0);
335 switch( *p->curpos++ ) {
336 case 'W': /* word (2 byte) */
338 temp = va_arg(args,int);
339 if (p->buflen >= needed) SSVAL(p->structbuf,0,temp);
341 case 'N': /* count of substructures (word) at end */
343 p->subcount = va_arg(args,int);
344 if (p->buflen >= needed) SSVAL(p->structbuf,0,p->subcount);
346 case 'D': /* double word (4 byte) */
348 temp = va_arg(args,int);
349 if (p->buflen >= needed) SIVAL(p->structbuf,0,temp);
351 case 'B': /* byte (with optional counter) */
352 needed = get_counter(&p->curpos);
354 char *s = va_arg(args,char*);
355 if (p->buflen >= needed) StrnCpy(p->structbuf,s?s:"",needed);
358 case 'z': /* offset to zero terminated string (4 byte) */
359 str = va_arg(args,char*);
360 stringneeded = (str ? strlen(str)+1 : 0);
363 case 'l': /* offset to user data (4 byte) */
364 str = va_arg(args,char*);
365 stringneeded = va_arg(args,int);
368 case 'b': /* offset to data (with counter) (4 byte) */
369 str = va_arg(args,char*);
370 stringneeded = get_counter(&p->curpos);
375 if (stringneeded >= 0) {
377 if (p->buflen >= needed) {
378 stringused = stringneeded;
379 if (stringused > p->stringlen) {
380 stringused = (is_string ? p->stringlen : 0);
381 if (p->errcode == NERR_Success) p->errcode = ERROR_MORE_DATA;
384 SIVAL(p->structbuf,0,0);
386 SIVAL(p->structbuf,0,PTR_DIFF(p->stringbuf,p->base));
387 memcpy(p->stringbuf,str?str:"",stringused);
388 if (is_string) p->stringbuf[stringused-1] = '\0';
389 p->stringbuf += stringused;
390 p->stringlen -= stringused;
391 p->usedlen += stringused;
394 p->neededlen += stringneeded;
396 p->neededlen += needed;
397 if (p->buflen >= needed) {
398 p->structbuf += needed;
400 p->usedlen += needed;
403 if (p->errcode == NERR_Success) p->errcode = NERR_BufTooSmall;
409 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
410 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
412 #define PACK(desc,t,v) package(desc,v)
413 #define PACKl(desc,t,v,l) package(desc,v,l)
416 static void PACKI(struct pack_desc* desc,char *t,int v)
421 static void PACKS(struct pack_desc* desc,char *t,char *v)
427 /****************************************************************************
429 ****************************************************************************/
431 static void PackDriverData(struct pack_desc* desc)
433 char drivdata[4+4+32];
434 SIVAL(drivdata,0,sizeof drivdata); /* cb */
435 SIVAL(drivdata,4,1000); /* lVersion */
436 memset(drivdata+8,0,32); /* szDeviceName */
437 strcpy(drivdata+8,"NULL");
438 PACKl(desc,"l",drivdata,sizeof drivdata); /* pDriverData */
441 static int check_printq_info(struct pack_desc* desc,
442 int uLevel, const char* id1, const char* id2)
444 desc->subformat = NULL;
447 desc->format = "B13";
450 desc->format = "B13BWWWzzzzzWW";
453 desc->format = "B13BWWWzzzzzWN";
454 desc->subformat = "WB21BB16B10zWWzDDz";
457 desc->format = "zWWWWzzzzWWzzl";
460 desc->format = "zWWWWzzzzWNzzl";
461 desc->subformat = "WWzWWDDzz";
466 default: return False;
468 if (strcmp(desc->format,id1) != 0) return False;
469 if (desc->subformat && strcmp(desc->subformat,id2) != 0) return False;
473 static void fill_printjob_info(int cnum, int snum, int uLevel,
474 struct pack_desc* desc,
475 print_queue_struct* queue, int n)
477 time_t t = queue->time;
479 /* the client expects localtime */
482 PACKI(desc,"W",((snum%0xFF)<<8) | (queue->job%0xFF)); /* uJobId */
484 PACKS(desc,"B21",queue->user); /* szUserName */
485 PACKS(desc,"B",""); /* pad */
486 PACKS(desc,"B16",""); /* szNotifyName */
487 PACKS(desc,"B10","PM_Q_RAW"); /* szDataType */
488 PACKS(desc,"z",""); /* pszParms */
489 PACKI(desc,"W",n+1); /* uPosition */
490 PACKI(desc,"W",queue->status); /* fsStatus */
491 PACKS(desc,"z",""); /* pszStatus */
492 PACKI(desc,"D",t); /* ulSubmitted */
493 PACKI(desc,"D",queue->size); /* ulSize */
494 PACKS(desc,"z",queue->file); /* pszComment */
496 if (uLevel == 2 || uLevel == 3) {
497 PACKI(desc,"W",queue->priority); /* uPriority */
498 PACKS(desc,"z",queue->user); /* pszUserName */
499 PACKI(desc,"W",n+1); /* uPosition */
500 PACKI(desc,"W",queue->status); /* fsStatus */
501 PACKI(desc,"D",t); /* ulSubmitted */
502 PACKI(desc,"D",queue->size); /* ulSize */
503 PACKS(desc,"z","Samba"); /* pszComment */
504 PACKS(desc,"z",queue->file); /* pszDocument */
506 PACKS(desc,"z",""); /* pszNotifyName */
507 PACKS(desc,"z","PM_Q_RAW"); /* pszDataType */
508 PACKS(desc,"z",""); /* pszParms */
509 PACKS(desc,"z",""); /* pszStatus */
510 PACKS(desc,"z",SERVICE(snum)); /* pszQueue */
511 PACKS(desc,"z","lpd"); /* pszQProcName */
512 PACKS(desc,"z",""); /* pszQProcParms */
513 PACKS(desc,"z","NULL"); /* pszDriverName */
514 PackDriverData(desc); /* pDriverData */
515 PACKS(desc,"z",""); /* pszPrinterName */
520 static void fill_printq_info(int cnum, int snum, int uLevel,
521 struct pack_desc* desc,
522 int count, print_queue_struct* queue,
523 print_status_struct* status)
526 PACKS(desc,"B13",SERVICE(snum));
528 PACKS(desc,"z",Expand(cnum,snum,SERVICE(snum)));
530 if (uLevel == 1 || uLevel == 2) {
531 PACKS(desc,"B",""); /* alignment */
532 PACKI(desc,"W",5); /* priority */
533 PACKI(desc,"W",0); /* start time */
534 PACKI(desc,"W",0); /* until time */
535 PACKS(desc,"z",""); /* pSepFile */
536 PACKS(desc,"z","lpd"); /* pPrProc */
537 PACKS(desc,"z",SERVICE(snum)); /* pDestinations */
538 PACKS(desc,"z",""); /* pParms */
540 PACKS(desc,"z","UNKNOWN PRINTER");
541 PACKI(desc,"W",LPSTAT_ERROR);
543 else if (!status || !status->message[0]) {
544 PACKS(desc,"z",Expand(cnum,snum,lp_comment(snum)));
545 PACKI(desc,"W",LPSTAT_OK); /* status */
547 PACKS(desc,"z",status->message);
548 PACKI(desc,"W",status->status); /* status */
550 PACKI(desc,(uLevel == 1 ? "W" : "N"),count);
552 if (uLevel == 3 || uLevel == 4) {
553 PACKI(desc,"W",5); /* uPriority */
554 PACKI(desc,"W",0); /* uStarttime */
555 PACKI(desc,"W",0); /* uUntiltime */
556 PACKI(desc,"W",5); /* pad1 */
557 PACKS(desc,"z",""); /* pszSepFile */
558 PACKS(desc,"z","WinPrint"); /* pszPrProc */
559 PACKS(desc,"z",""); /* pszParms */
560 if (!status || !status->message[0]) {
561 PACKS(desc,"z",Expand(cnum,snum,lp_comment(snum))); /* pszComment */
562 PACKI(desc,"W",LPSTAT_OK); /* fsStatus */
564 PACKS(desc,"z",status->message); /* pszComment */
565 PACKI(desc,"W",status->status); /* fsStatus */
567 PACKI(desc,(uLevel == 3 ? "W" : "N"),count); /* cJobs */
568 PACKS(desc,"z",SERVICE(snum)); /* pszPrinters */
569 PACKS(desc,"z",lp_printerdriver(snum)); /* pszDriverName */
570 PackDriverData(desc); /* pDriverData */
572 if (uLevel == 2 || uLevel == 4) {
574 for (i=0;i<count;i++)
575 fill_printjob_info(cnum,snum,uLevel == 2 ? 1 : 2,desc,&queue[i],i);
578 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n",SERVICE(snum),count));
581 static BOOL api_DosPrintQGetInfo(int cnum,int uid, char *param,char *data,
582 int mdrcnt,int mprcnt,
583 char **rdata,char **rparam,
584 int *rdata_len,int *rparam_len)
586 char *str1 = param+2;
587 char *str2 = skip_string(str1,1);
588 char *p = skip_string(str2,1);
594 struct pack_desc desc;
595 print_queue_struct *queue=NULL;
596 print_status_struct status;
598 bzero(&status,sizeof(status));
599 bzero(&desc,sizeof(desc));
601 p = skip_string(p,1);
606 /* remove any trailing username */
607 if ((p = strchr(QueueName,'%'))) *p = 0;
609 DEBUG(3,("PrintQueue uLevel=%d name=%s\n",uLevel,QueueName));
611 /* check it's a supported varient */
612 if (!prefix_ok(str1,"zWrLh")) return False;
613 if (!check_printq_info(&desc,uLevel,str2,str3)) return False;
615 snum = lp_servicenumber(QueueName);
616 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
617 int pnum = lp_servicenumber(PRINTERS_NAME);
619 lp_add_printer(QueueName,pnum);
620 snum = lp_servicenumber(QueueName);
624 if (snum < 0 || !VALID_SNUM(snum)) return(False);
626 count = get_printqueue(snum,cnum,&queue,&status);
627 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
629 desc.buflen = mdrcnt;
630 if (init_package(&desc,1,count)) {
631 desc.subcount = count;
632 fill_printq_info(cnum,snum,uLevel,&desc,count,queue,&status);
635 *rdata_len = desc.usedlen;
638 *rparam = REALLOC(*rparam,*rparam_len);
639 SSVALS(*rparam,0,desc.errcode);
641 SSVAL(*rparam,4,desc.neededlen);
643 DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode));
645 if (queue) free(queue);
651 /****************************************************************************
652 view list of all print jobs on all queues
653 ****************************************************************************/
654 static BOOL api_DosPrintQEnum(int cnum, int uid, char* param, char* data,
655 int mdrcnt, int mprcnt,
656 char **rdata, char** rparam,
657 int *rdata_len, int *rparam_len)
659 char *param_format = param+2;
660 char *output_format1 = skip_string(param_format,1);
661 char *p = skip_string(output_format1,1);
662 int uLevel = SVAL(p,0);
663 char *output_format2 = p + 4;
664 int services = lp_numservices();
666 struct pack_desc desc;
667 print_queue_struct **queue = NULL;
668 print_status_struct *status = NULL;
669 int* subcntarr = NULL;
670 int queuecnt, subcnt=0, succnt=0;
672 bzero(&desc,sizeof(desc));
674 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
676 if (!prefix_ok(param_format,"WrLeh")) return False;
677 if (!check_printq_info(&desc,uLevel,output_format1,output_format2))
680 for (i = 0; i < services; i++)
681 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
684 queue = (print_queue_struct**)malloc(queuecnt*sizeof(print_queue_struct*));
685 memset(queue,0,queuecnt*sizeof(print_queue_struct*));
686 status = (print_status_struct*)malloc(queuecnt*sizeof(print_status_struct));
687 memset(status,0,queuecnt*sizeof(print_status_struct));
688 subcntarr = (int*)malloc(queuecnt*sizeof(int));
691 for (i = 0; i < services; i++)
692 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
693 subcntarr[n] = get_printqueue(i,cnum,&queue[n],&status[n]);
694 subcnt += subcntarr[n];
698 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
700 desc.buflen = mdrcnt;
702 if (init_package(&desc,queuecnt,subcnt)) {
705 for (i = 0; i < services; i++)
706 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
707 fill_printq_info(cnum,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]);
709 if (desc.errcode == NERR_Success) succnt = n;
713 if (subcntarr) free(subcntarr);
715 *rdata_len = desc.usedlen;
717 *rparam = REALLOC(*rparam,*rparam_len);
718 SSVALS(*rparam,0,desc.errcode);
720 SSVAL(*rparam,4,succnt);
721 SSVAL(*rparam,6,queuecnt);
723 for (i = 0; i < queuecnt; i++) {
724 if (queue && queue[i]) free(queue[i]);
727 if (queue) free(queue);
728 if (status) free(status);
733 /****************************************************************************
734 get info level for a server list query
735 ****************************************************************************/
736 static BOOL check_server_info(int uLevel, char* id)
740 if (strcmp(id,"B16") != 0) return False;
743 if (strcmp(id,"B16BBDz") != 0) return False;
751 struct srv_info_struct
761 /*******************************************************************
762 get server info lists from the files saved by nmbd. Return the
764 ******************************************************************/
765 static int get_server_info(uint32 servertype,
766 struct srv_info_struct **servers,
775 strcpy(fname,lp_lockdir());
776 trim_string(fname,NULL,"/");
778 strcat(fname,SERVER_LIST);
780 f = fopen(fname,"r");
783 DEBUG(4,("Can't open %s - %s\n",fname,strerror(errno)));
787 /* request for everything is code for request all servers */
788 if (servertype == SV_TYPE_ALL) servertype &= ~SV_TYPE_DOMAIN_ENUM;
790 DEBUG(4,("Servertype search: %8x\n",servertype));
795 struct srv_info_struct *s;
800 fgets(line,sizeof(line)-1,f);
801 if (!*line) continue;
803 if (count == alloced) {
805 (*servers) = (struct srv_info_struct *)
806 Realloc(*servers,sizeof(**servers)*alloced);
807 if (!(*servers)) return(0);
808 bzero((char *)((*servers)+count),sizeof(**servers)*(alloced-count));
810 s = &(*servers)[count];
812 if (!next_token(&ptr,s->name , NULL)) continue;
813 if (!next_token(&ptr,stype , NULL)) continue;
814 if (!next_token(&ptr,s->comment, NULL)) continue;
815 if (!next_token(&ptr,s->domain , NULL)) {
816 /* this allows us to cope with an old nmbd */
817 strcpy(s->domain,lp_workgroup());
820 if (sscanf(stype,"%X",&s->type) != 1) {
821 DEBUG(4,("r:host file "));
825 /* doesn't match up: don't want it */
826 if (!(servertype & s->type)) {
827 DEBUG(4,("r:serv type "));
831 if ((servertype & SV_TYPE_DOMAIN_ENUM) !=
832 (s->type & SV_TYPE_DOMAIN_ENUM))
834 DEBUG(4,("s: dom mismatch "));
838 if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM))
845 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
846 s->name, s->type, s->comment, s->domain));
848 s->server_added = True;
853 DEBUG(4,("%20s %8x %25s %15s\n",
854 s->name, s->type, s->comment, s->domain));
863 /*******************************************************************
864 fill in a server info structure
865 ******************************************************************/
866 static int fill_srv_info(struct srv_info_struct *service,
867 int uLevel, char **buf, int *buflen,
868 char **stringbuf, int *stringspace, char *baseaddr)
877 case 0: struct_len = 16; break;
878 case 1: struct_len = 26; break;
888 len = strlen(service->comment)+1;
892 if (buflen) *buflen = struct_len;
893 if (stringspace) *stringspace = len;
894 return struct_len + len;
899 if (*buflen < struct_len) return -1;
908 l2 = *buflen - struct_len;
910 if (!baseaddr) baseaddr = p;
915 StrnCpy(p,service->name,15);
919 StrnCpy(p,service->name,15);
920 SIVAL(p,18,service->type);
921 SIVAL(p,22,PTR_DIFF(p2,baseaddr));
922 len += CopyAndAdvance(&p2,service->comment,&l2);
928 *buf = p + struct_len;
929 *buflen -= struct_len;
942 static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
944 return(strcmp(s1->name,s2->name));
947 /****************************************************************************
948 view list of servers available (or possibly domains). The info is
949 extracted from lists saved by nmbd on the local host
950 ****************************************************************************/
951 static BOOL api_RNetServerEnum(int cnum, int uid, char *param, char *data,
952 int mdrcnt, int mprcnt, char **rdata,
953 char **rparam, int *rdata_len, int *rparam_len)
955 char *str1 = param+2;
956 char *str2 = skip_string(str1,1);
957 char *p = skip_string(str2,1);
958 int uLevel = SVAL(p,0);
959 int buf_len = SVAL(p,2);
960 uint32 servertype = IVAL(p,4);
962 int data_len, fixed_len, string_len;
964 struct srv_info_struct *servers=NULL;
965 int counted=0,total=0;
969 BOOL local_request = servertype & SV_TYPE_LOCAL_LIST_ONLY;
971 if (servertype == SV_TYPE_ALL) servertype &= ~SV_TYPE_DOMAIN_ENUM;
973 domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
977 if (!prefix_ok(str1,"WrLehD")) return False;
978 if (!check_server_info(uLevel,str2)) return False;
980 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
981 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
982 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
984 if (strcmp(str1, "WrLehDz") == 0) {
985 StrnCpy(domain, p, sizeof(fstring)-1);
987 StrnCpy(domain, lp_workgroup(), sizeof(fstring)-1);
990 if (lp_browse_list())
991 total = get_server_info(servertype,&servers,domain);
993 data_len = fixed_len = string_len = 0;
995 qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
1000 for (i=0;i<total;i++)
1002 struct srv_info_struct *s = &servers[i];
1003 if (lastname && strequal(lastname,s->name)) continue;
1005 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1006 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1007 s->name, s->type, s->comment, s->domain));
1009 if (data_len <= buf_len)
1013 string_len += s_len;
1018 *rdata_len = fixed_len + string_len;
1019 *rdata = REALLOC(*rdata,*rdata_len);
1020 bzero(*rdata,*rdata_len);
1022 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1028 char *lastname=NULL;
1029 int count2 = counted;
1030 for (i = 0; i < total && count2;i++)
1032 struct srv_info_struct *s = &servers[i];
1033 if (lastname && strequal(lastname,s->name)) continue;
1035 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1036 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1037 s->name, s->type, s->comment, s->domain));
1043 *rparam = REALLOC(*rparam,*rparam_len);
1044 SSVAL(*rparam,0,NERR_Success);
1046 SSVAL(*rparam,4,counted);
1047 SSVAL(*rparam,6,total);
1049 if (servers) free(servers);
1051 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1052 domain,uLevel,counted,total));
1058 /****************************************************************************
1059 get info about a share
1060 ****************************************************************************/
1061 static BOOL check_share_info(int uLevel, char* id)
1065 if (strcmp(id,"B13") != 0) return False;
1068 if (strcmp(id,"B13BWz") != 0) return False;
1071 if (strcmp(id,"B13BWzWWWzB9B") != 0) return False;
1074 if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) return False;
1076 default: return False;
1081 static int fill_share_info(int cnum, int snum, int uLevel,
1082 char** buf, int* buflen,
1083 char** stringbuf, int* stringspace, char* baseaddr)
1092 case 0: struct_len = 13; break;
1093 case 1: struct_len = 20; break;
1094 case 2: struct_len = 40; break;
1095 case 91: struct_len = 68; break;
1103 if (uLevel > 0) len += StrlenExpanded(cnum,snum,lp_comment(snum));
1104 if (uLevel > 1) len += strlen(lp_pathname(snum)) + 1;
1105 if (buflen) *buflen = struct_len;
1106 if (stringspace) *stringspace = len;
1107 return struct_len + len;
1112 if ((*buflen) < struct_len) return -1;
1120 p2 = p + struct_len;
1121 l2 = (*buflen) - struct_len;
1123 if (!baseaddr) baseaddr = p;
1125 StrnCpy(p,lp_servicename(snum),13);
1131 type = STYPE_DISKTREE;
1132 if (lp_print_ok(snum)) type = STYPE_PRINTQ;
1133 if (strequal("IPC$",lp_servicename(snum))) type = STYPE_IPC;
1134 SSVAL(p,14,type); /* device type */
1135 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1136 len += CopyExpanded(cnum,snum,&p2,lp_comment(snum),&l2);
1141 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1142 SSVALS(p,22,-1); /* max uses */
1143 SSVAL(p,24,1); /* current uses */
1144 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1145 len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1146 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1151 memset(p+40,0,SHPWLEN+2);
1163 (*buf) = p + struct_len;
1164 (*buflen) -= struct_len;
1166 (*stringspace) = l2;
1176 static BOOL api_RNetShareGetInfo(int cnum,int uid, char *param,char *data,
1177 int mdrcnt,int mprcnt,
1178 char **rdata,char **rparam,
1179 int *rdata_len,int *rparam_len)
1181 char *str1 = param+2;
1182 char *str2 = skip_string(str1,1);
1183 char *netname = skip_string(str2,1);
1184 char *p = skip_string(netname,1);
1185 int uLevel = SVAL(p,0);
1186 int snum = find_service(netname);
1188 if (snum < 0) return False;
1190 /* check it's a supported varient */
1191 if (!prefix_ok(str1,"zWrLh")) return False;
1192 if (!check_share_info(uLevel,str2)) return False;
1194 *rdata = REALLOC(*rdata,mdrcnt);
1196 *rdata_len = fill_share_info(cnum,snum,uLevel,&p,&mdrcnt,0,0,0);
1197 if (*rdata_len < 0) return False;
1200 *rparam = REALLOC(*rparam,*rparam_len);
1201 SSVAL(*rparam,0,NERR_Success);
1202 SSVAL(*rparam,2,0); /* converter word */
1203 SSVAL(*rparam,4,*rdata_len);
1208 /****************************************************************************
1209 view list of shares available
1210 ****************************************************************************/
1211 static BOOL api_RNetShareEnum(int cnum,int uid, char *param,char *data,
1212 int mdrcnt,int mprcnt,
1213 char **rdata,char **rparam,
1214 int *rdata_len,int *rparam_len)
1216 char *str1 = param+2;
1217 char *str2 = skip_string(str1,1);
1218 char *p = skip_string(str2,1);
1219 int uLevel = SVAL(p,0);
1220 int buf_len = SVAL(p,2);
1222 int count=lp_numservices();
1223 int total=0,counted=0;
1225 int data_len, fixed_len, string_len;
1228 if (!prefix_ok(str1,"WrLeh")) return False;
1229 if (!check_share_info(uLevel,str2)) return False;
1231 data_len = fixed_len = string_len = 0;
1232 for (i=0;i<count;i++)
1233 if (lp_browseable(i) && lp_snum_ok(i))
1236 data_len += fill_share_info(cnum,i,uLevel,0,&f_len,0,&s_len,0);
1237 if (data_len <= buf_len)
1241 string_len += s_len;
1244 *rdata_len = fixed_len + string_len;
1245 *rdata = REALLOC(*rdata,*rdata_len);
1246 memset(*rdata,0,*rdata_len);
1248 p2 = (*rdata) + fixed_len; /* auxillery data (strings) will go here */
1252 for (i = 0; i < count;i++)
1253 if (lp_browseable(i) && lp_snum_ok(i))
1254 if (fill_share_info(cnum,i,uLevel,&p,&f_len,&p2,&s_len,*rdata) < 0)
1258 *rparam = REALLOC(*rparam,*rparam_len);
1259 SSVAL(*rparam,0,NERR_Success);
1261 SSVAL(*rparam,4,counted);
1262 SSVAL(*rparam,6,total);
1264 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1265 counted,total,uLevel,
1266 buf_len,*rdata_len,mdrcnt));
1272 /****************************************************************************
1273 get the time of day info
1274 ****************************************************************************/
1275 static BOOL api_NetRemoteTOD(int cnum,int uid, char *param,char *data,
1276 int mdrcnt,int mprcnt,
1277 char **rdata,char **rparam,
1278 int *rdata_len,int *rparam_len)
1282 *rparam = REALLOC(*rparam,*rparam_len);
1285 *rdata = REALLOC(*rdata,*rdata_len);
1287 SSVAL(*rparam,0,NERR_Success);
1288 SSVAL(*rparam,2,0); /* converter word */
1294 time_t unixdate = time(NULL);
1296 put_dos_date3(p,0,unixdate); /* this is the time that is looked at
1297 by NT in a "net time" operation,
1298 it seems to ignore the one below */
1300 /* the client expects to get localtime, not GMT, in this bit
1301 (I think, this needs testing) */
1302 t = LocalTime(&unixdate);
1304 SIVAL(p,4,0); /* msecs ? */
1305 CVAL(p,8) = t->tm_hour;
1306 CVAL(p,9) = t->tm_min;
1307 CVAL(p,10) = t->tm_sec;
1308 CVAL(p,11) = 0; /* hundredths of seconds */
1309 SSVALS(p,12,TimeDiff(unixdate)/60); /* timezone in minutes from GMT */
1310 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
1311 CVAL(p,16) = t->tm_mday;
1312 CVAL(p,17) = t->tm_mon + 1;
1313 SSVAL(p,18,1900+t->tm_year);
1314 CVAL(p,20) = t->tm_wday;
1321 /****************************************************************************
1322 set the user password
1323 ****************************************************************************/
1324 static BOOL api_SetUserPassword(int cnum,int uid, char *param,char *data,
1325 int mdrcnt,int mprcnt,
1326 char **rdata,char **rparam,
1327 int *rdata_len,int *rparam_len)
1329 char *p = skip_string(param+2,2);
1331 fstring pass1,pass2;
1335 p = skip_string(p,1);
1337 StrnCpy(pass1,p,16);
1338 StrnCpy(pass2,p+16,16);
1341 *rparam = REALLOC(*rparam,*rparam_len);
1345 SSVAL(*rparam,0,NERR_badpass);
1346 SSVAL(*rparam,2,0); /* converter word */
1348 DEBUG(3,("Set password for <%s>\n",user));
1350 if (password_ok(user,pass1,strlen(pass1),NULL,False) &&
1351 chgpasswd(user,pass1,pass2))
1353 SSVAL(*rparam,0,NERR_Success);
1356 bzero(pass1,sizeof(fstring));
1357 bzero(pass2,sizeof(fstring));
1362 /****************************************************************************
1365 ****************************************************************************/
1366 static BOOL api_RDosPrintJobDel(int cnum,int uid, char *param,char *data,
1367 int mdrcnt,int mprcnt,
1368 char **rdata,char **rparam,
1369 int *rdata_len,int *rparam_len)
1371 int function = SVAL(param,0);
1372 char *str1 = param+2;
1373 char *str2 = skip_string(str1,1);
1374 char *p = skip_string(str2,1);
1375 int jobid = (SVAL(p,0)&0xFF); /* the snum and jobid are encoded
1376 by the print queue api */
1377 int snum = (SVAL(p,0)>>8);
1381 /* check it's a supported varient */
1382 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
1386 *rparam = REALLOC(*rparam,*rparam_len);
1390 SSVAL(*rparam,0,NERR_Success);
1392 if (snum >= 0 && VALID_SNUM(snum))
1394 print_queue_struct *queue=NULL;
1396 count = get_printqueue(snum,cnum,&queue,NULL);
1398 for (i=0;i<count;i++)
1399 if ((queue[i].job%0xFF) == jobid)
1402 case 81: /* delete */
1403 DEBUG(3,("Deleting queue entry %d\n",queue[i].job));
1404 del_printqueue(cnum,snum,queue[i].job);
1406 case 82: /* pause */
1407 case 83: /* resume */
1408 DEBUG(3,("%s queue entry %d\n",
1409 (function==82?"pausing":"resuming"),queue[i].job));
1410 status_printjob(cnum,snum,queue[i].job,
1411 (function==82?LPQ_PAUSED:LPQ_QUEUED));
1418 SSVAL(*rparam,0,NERR_JobNotFound);
1420 if (queue) free(queue);
1423 SSVAL(*rparam,2,0); /* converter word */
1428 static BOOL api_WPrintQueuePurge(int cnum,int uid, char *param,char *data,
1429 int mdrcnt,int mprcnt,
1430 char **rdata,char **rparam,
1431 int *rdata_len,int *rparam_len)
1433 char *str1 = param+2;
1434 char *str2 = skip_string(str1,1);
1435 char *QueueName = skip_string(str2,1);
1438 /* check it's a supported varient */
1439 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
1443 *rparam = REALLOC(*rparam,*rparam_len);
1447 SSVAL(*rparam,0,NERR_Success);
1448 SSVAL(*rparam,2,0); /* converter word */
1450 snum = lp_servicenumber(QueueName);
1451 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
1452 int pnum = lp_servicenumber(PRINTERS_NAME);
1454 lp_add_printer(QueueName,pnum);
1455 snum = lp_servicenumber(QueueName);
1459 if (snum >= 0 && VALID_SNUM(snum)) {
1460 print_queue_struct *queue=NULL;
1464 count = get_printqueue(snum,cnum,&queue,NULL);
1465 for (i = 0; i < count; i++)
1466 del_printqueue(cnum,snum,queue[i].job);
1468 if (queue) free(queue);
1471 DEBUG(3,("Print queue purge, queue=%s\n",QueueName));
1477 /****************************************************************************
1478 set the property of a print job (undocumented?)
1479 ? function = 0xb -> set name of print job
1480 ? function = 0x6 -> move print job up/down
1481 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
1482 or <WWsTP> <WB21BB16B10zWWzDDz>
1483 ****************************************************************************/
1484 static int check_printjob_info(struct pack_desc* desc,
1485 int uLevel, char* id)
1487 desc->subformat = NULL;
1489 case 0: desc->format = "W"; break;
1490 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
1491 case 2: desc->format = "WWzWWDDzz"; break;
1492 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
1493 default: return False;
1495 if (strcmp(desc->format,id) != 0) return False;
1499 static BOOL api_PrintJobInfo(int cnum,int uid,char *param,char *data,
1500 int mdrcnt,int mprcnt,
1501 char **rdata,char **rparam,
1502 int *rdata_len,int *rparam_len)
1504 struct pack_desc desc;
1505 char *str1 = param+2;
1506 char *str2 = skip_string(str1,1);
1507 char *p = skip_string(str2,1);
1508 int jobid = (SVAL(p,0)&0xFF); /* the snum and jobid are encoded
1509 by the print queue api */
1510 int snum = (SVAL(p,0)>>8);
1511 int uLevel = SVAL(p,2);
1512 int function = SVAL(p,4); /* what is this ?? */
1517 *rparam = REALLOC(*rparam,*rparam_len);
1521 /* check it's a supported varient */
1522 if ((strcmp(str1,"WWsTP")) || (!check_printjob_info(&desc,uLevel,str2)))
1526 case 0x6: /* change job place in the queue, data gives the new place */
1527 if (snum >= 0 && VALID_SNUM(snum))
1529 print_queue_struct *queue=NULL;
1533 count = get_printqueue(snum,cnum,&queue,NULL);
1534 for (i=0;i<count;i++) /* find job */
1535 if ((queue[i].job%0xFF) == jobid) break;
1538 desc.errcode=NERR_JobNotFound;
1539 if (queue) free(queue);
1542 desc.errcode=NERR_Success;
1546 int place= SVAL(data,0);
1547 /* we currently have no way of doing this. Can any unix do it? */
1548 if (i < place) /* move down */;
1549 else if (i > place ) /* move up */;
1552 desc.errcode=NERR_notsupported; /* not yet supported */
1553 if (queue) free(queue);
1556 else desc.errcode=NERR_JobNotFound;
1558 case 0xb: /* change print job name, data gives the name */
1559 /* jobid, snum should be zero */
1566 if (issafe(*s)) name[l++] = *s;
1571 DEBUG(3,("Setting print name to %s\n",name));
1573 for (i=0;i<MAX_OPEN_FILES;i++)
1574 if (Files[i].open && Files[i].print_file)
1580 if (!become_user(Files[i].cnum,uid) ||
1581 !become_service(Files[i].cnum,True))
1584 if (sys_rename(Files[i].name,name) == 0)
1585 string_set(&Files[i].name,name);
1589 desc.errcode=NERR_Success;
1592 default: /* not implemented */
1596 SSVALS(*rparam,0,desc.errcode);
1597 SSVAL(*rparam,2,0); /* converter word */
1603 /****************************************************************************
1604 get info about the server
1605 ****************************************************************************/
1606 static BOOL api_RNetServerGetInfo(int cnum,int uid, char *param,char *data,
1607 int mdrcnt,int mprcnt,
1608 char **rdata,char **rparam,
1609 int *rdata_len,int *rparam_len)
1611 char *str1 = param+2;
1612 char *str2 = skip_string(str1,1);
1613 char *p = skip_string(str2,1);
1614 int uLevel = SVAL(p,0);
1618 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
1620 /* check it's a supported varient */
1621 if (!prefix_ok(str1,"WrLh")) return False;
1624 if (strcmp(str2,"B16") != 0) return False;
1628 if (strcmp(str2,"B16BBDz") != 0) return False;
1632 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")
1637 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz")
1642 if (strcmp(str2,"DN") != 0) return False;
1646 if (strcmp(str2,"B16BBDzWWzzz") != 0) return False;
1649 default: return False;
1652 *rdata_len = mdrcnt;
1653 *rdata = REALLOC(*rdata,*rdata_len);
1656 p2 = p + struct_len;
1658 StrnCpy(p,local_machine,16);
1664 struct srv_info_struct *servers=NULL;
1667 uint32 servertype=SV_TYPE_SERVER_UNIX|SV_TYPE_WORKSTATION|
1668 SV_TYPE_SERVER|SV_TYPE_TIME_SOURCE;
1670 strcpy(comment,lp_serverstring());
1672 if ((count=get_server_info(SV_TYPE_ALL,&servers,lp_workgroup()))>0) {
1673 for (i=0;i<count;i++)
1674 if (strequal(servers[i].name,local_machine)) {
1675 servertype = servers[i].type;
1676 strcpy(comment,servers[i].comment);
1679 if (servers) free(servers);
1681 SCVAL(p,0,MAJOR_VERSION);
1682 SCVAL(p,1,MINOR_VERSION);
1683 SIVAL(p,2,servertype);
1685 if (mdrcnt == struct_len) {
1688 SIVAL(p,6,PTR_DIFF(p2,*rdata));
1689 standard_sub(cnum,comment);
1690 StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
1691 p2 = skip_string(p2,1);
1696 return False; /* not yet implemented */
1699 *rdata_len = PTR_DIFF(p2,*rdata);
1702 *rparam = REALLOC(*rparam,*rparam_len);
1703 SSVAL(*rparam,0,NERR_Success);
1704 SSVAL(*rparam,2,0); /* converter word */
1705 SSVAL(*rparam,4,*rdata_len);
1711 /****************************************************************************
1712 get info about the server
1713 ****************************************************************************/
1714 static BOOL api_NetWkstaGetInfo(int cnum,int uid, char *param,char *data,
1715 int mdrcnt,int mprcnt,
1716 char **rdata,char **rparam,
1717 int *rdata_len,int *rparam_len)
1719 char *str1 = param+2;
1720 char *str2 = skip_string(str1,1);
1721 char *p = skip_string(str2,1);
1723 extern pstring sesssetup_user;
1724 int level = SVAL(p,0);
1726 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
1729 *rparam = REALLOC(*rparam,*rparam_len);
1731 /* check it's a supported varient */
1732 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz")))
1735 *rdata_len = mdrcnt + 1024;
1736 *rdata = REALLOC(*rdata,*rdata_len);
1738 SSVAL(*rparam,0,NERR_Success);
1739 SSVAL(*rparam,2,0); /* converter word */
1744 SIVAL(p,0,PTR_DIFF(p2,*rdata));
1745 strcpy(p2,local_machine);
1746 p2 = skip_string(p2,1);
1749 SIVAL(p,0,PTR_DIFF(p2,*rdata));
1750 strcpy(p2,sesssetup_user);
1751 p2 = skip_string(p2,1);
1754 SIVAL(p,0,PTR_DIFF(p2,*rdata));
1755 strcpy(p2,lp_workgroup());
1756 p2 = skip_string(p2,1);
1759 SCVAL(p,0,MAJOR_VERSION);
1760 SCVAL(p,1,MINOR_VERSION);
1763 SIVAL(p,0,PTR_DIFF(p2,*rdata));
1764 strcpy(p2,lp_workgroup()); /* login domain?? */
1765 p2 = skip_string(p2,1);
1768 SIVAL(p,0,PTR_DIFF(p2,*rdata));
1770 p2 = skip_string(p2,1);
1773 *rdata_len = PTR_DIFF(p2,*rdata);
1775 SSVAL(*rparam,4,*rdata_len);
1781 /****************************************************************************
1782 get info about a user
1783 ****************************************************************************/
1785 #define USER_PRIV_GUEST 0
1786 #define USER_PRIV_USER 1
1787 #define USER_PRIV_ADMIN 2
1789 static BOOL api_RNetUserGetInfo(int cnum,int uid, char *param,char *data,
1790 int mdrcnt,int mprcnt,
1791 char **rdata,char **rparam,
1792 int *rdata_len,int *rparam_len)
1794 char *str1 = param+2;
1795 char *str2 = skip_string(str1,1);
1796 char *UserName = skip_string(str2,1);
1797 char *p = skip_string(UserName,1);
1798 int uLevel = SVAL(p,0);
1802 *rparam = REALLOC(*rparam,*rparam_len);
1804 /* check it's a supported varient */
1805 if (strcmp(str1,"zWrLh") != 0) return False;
1807 case 0: p2 = "B21"; break;
1808 case 1: p2 = "B21BB16DWzzWz"; break;
1809 case 2: p2 = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
1810 case 10: p2 = "B21Bzzz"; break;
1811 case 11: p2 = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
1812 default: return False;
1814 if (strcmp(p2,str2) != 0) return False;
1816 *rdata_len = mdrcnt + 1024;
1817 *rdata = REALLOC(*rdata,*rdata_len);
1819 SSVAL(*rparam,0,NERR_Success);
1820 SSVAL(*rparam,2,0); /* converter word */
1831 SIVAL(p,22,PTR_DIFF(p2,p)); /* comment */
1832 strcpy(p2,"<Comment>");
1833 p2 = skip_string(p2,1);
1834 SIVAL(p,26,PTR_DIFF(p2,p)); /* user_comment */
1835 strcpy(p2,"<UserComment>");
1836 p2 = skip_string(p2,1);
1837 SIVAL(p,30,PTR_DIFF(p2,p)); /* full name */
1838 strcpy(p2,"<FullName>");
1839 p2 = skip_string(p2,1);
1841 if (uLevel == 11) { /* modelled after NTAS 3.51 reply */
1843 Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
1844 SIVAL(p,36,0); /* auth flags */
1845 SIVALS(p,40,-1); /* password age */
1846 SIVAL(p,44,PTR_DIFF(p2,p)); /* home dir */
1847 strcpy(p2,"\\\\%L\\HOMES");
1848 standard_sub_basic(p2);
1849 p2 = skip_string(p2,1);
1850 SIVAL(p,48,PTR_DIFF(p2,p)); /* parms */
1852 p2 = skip_string(p2,1);
1853 SIVAL(p,52,0); /* last logon */
1854 SIVAL(p,56,0); /* last logoff */
1855 SSVALS(p,60,-1); /* bad pw counts */
1856 SSVALS(p,62,-1); /* num logons */
1857 SIVAL(p,64,PTR_DIFF(p2,p)); /* logon server */
1859 p2 = skip_string(p2,1);
1860 SSVAL(p,68,0); /* country code */
1862 SIVAL(p,70,PTR_DIFF(p2,p)); /* workstations */
1864 p2 = skip_string(p2,1);
1866 SIVALS(p,74,-1); /* max storage */
1867 SSVAL(p,78,168); /* units per week */
1868 SIVAL(p,80,PTR_DIFF(p2,p)); /* logon hours */
1870 SCVAL(p2,21,0); /* fix zero termination */
1871 p2 = skip_string(p2,1);
1873 SSVAL(p,84,0); /* code page */
1875 if (uLevel == 1 || uLevel == 2) {
1876 memset(p+22,' ',16); /* password */
1877 SIVALS(p,38,-1); /* password age */
1879 Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
1880 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
1881 strcpy(p2,"\\\\%L\\HOMES");
1882 standard_sub_basic(p2);
1883 p2 = skip_string(p2,1);
1884 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
1886 SSVAL(p,52,0); /* flags */
1887 SIVAL(p,54,0); /* script_path */
1889 SIVAL(p,60,0); /* auth_flags */
1890 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
1891 strcpy(p2,"<Full Name>");
1892 p2 = skip_string(p2,1);
1893 SIVAL(p,68,0); /* urs_comment */
1894 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
1896 p2 = skip_string(p2,1);
1897 SIVAL(p,76,0); /* workstations */
1898 SIVAL(p,80,0); /* last_logon */
1899 SIVAL(p,84,0); /* last_logoff */
1900 SIVALS(p,88,-1); /* acct_expires */
1901 SIVALS(p,92,-1); /* max_storage */
1902 SSVAL(p,96,168); /* units_per_week */
1903 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
1906 SSVALS(p,102,-1); /* bad_pw_count */
1907 SSVALS(p,104,-1); /* num_logons */
1908 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
1909 strcpy(p2,"\\\\%L");
1910 standard_sub_basic(p2);
1911 p2 = skip_string(p2,1);
1912 SSVAL(p,110,49); /* country_code */
1913 SSVAL(p,112,860); /* code page */
1918 *rdata_len = PTR_DIFF(p2,*rdata);
1920 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
1926 /*******************************************************************
1927 get groups that a user is a member of
1928 ******************************************************************/
1929 static BOOL api_NetUserGetGroups(int cnum,int uid, char *param,char *data,
1930 int mdrcnt,int mprcnt,
1931 char **rdata,char **rparam,
1932 int *rdata_len,int *rparam_len)
1934 char *str1 = param+2;
1935 char *str2 = skip_string(str1,1);
1936 char *UserName = skip_string(str2,1);
1937 char *p = skip_string(UserName,1);
1938 int uLevel = SVAL(p,0);
1943 *rparam = REALLOC(*rparam,*rparam_len);
1945 /* check it's a supported varient */
1946 if (strcmp(str1,"zWrLeh") != 0) return False;
1948 case 0: p2 = "B21"; break;
1949 default: return False;
1951 if (strcmp(p2,str2) != 0) return False;
1953 *rdata_len = mdrcnt + 1024;
1954 *rdata = REALLOC(*rdata,*rdata_len);
1956 SSVAL(*rparam,0,NERR_Success);
1957 SSVAL(*rparam,2,0); /* converter word */
1961 /* XXXX we need a real SAM database some day */
1962 strcpy(p,"Users"); p += 21; count++;
1963 strcpy(p,"Domain Users"); p += 21; count++;
1964 strcpy(p,"Guests"); p += 21; count++;
1965 strcpy(p,"Domain Guests"); p += 21; count++;
1967 *rdata_len = PTR_DIFF(p,*rdata);
1969 SSVAL(*rparam,4,count); /* is this right?? */
1970 SSVAL(*rparam,6,count); /* is this right?? */
1976 static BOOL api_WWkstaUserLogon(int cnum,int uid, char *param,char *data,
1977 int mdrcnt,int mprcnt,
1978 char **rdata,char **rparam,
1979 int *rdata_len,int *rparam_len)
1981 char *str1 = param+2;
1982 char *str2 = skip_string(str1,1);
1983 char *p = skip_string(str2,1);
1985 struct pack_desc desc;
1991 bzero(&desc,sizeof(desc));
1993 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
1995 /* check it's a supported varient */
1996 if (strcmp(str1,"OOWb54WrLh") != 0) return False;
1997 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) return False;
1998 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2000 desc.buflen = mdrcnt;
2001 desc.subformat = NULL;
2006 if (init_package(&desc,1,0)) {
2007 PACKI(&desc,"W",0); /* code */
2008 PACKS(&desc,"B21",name); /* eff. name */
2009 PACKS(&desc,"B",""); /* pad */
2011 Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2012 PACKI(&desc,"D",0); /* auth flags XXX */
2013 PACKI(&desc,"W",0); /* num logons */
2014 PACKI(&desc,"W",0); /* bad pw count */
2015 PACKI(&desc,"D",-1); /* last logon */
2016 PACKI(&desc,"D",-1); /* last logoff */
2017 PACKI(&desc,"D",-1); /* logoff time */
2018 PACKI(&desc,"D",-1); /* kickoff time */
2019 PACKI(&desc,"D",0); /* password age */
2020 PACKI(&desc,"D",0); /* password can change */
2021 PACKI(&desc,"D",-1); /* password must change */
2024 strcpy(mypath,"\\\\");
2025 strcat(mypath,local_machine);
2027 PACKS(&desc,"z",mypath); /* computer */
2029 PACKS(&desc,"z",lp_workgroup());/* domain */
2030 PACKS(&desc,"z",lp_logon_script()); /* script path */
2031 PACKI(&desc,"D",0); /* reserved */
2034 *rdata_len = desc.usedlen;
2036 *rparam = REALLOC(*rparam,*rparam_len);
2037 SSVALS(*rparam,0,desc.errcode);
2039 SSVAL(*rparam,4,desc.neededlen);
2041 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
2046 /****************************************************************************
2047 api_WAccessGetUserPerms
2048 ****************************************************************************/
2049 static BOOL api_WAccessGetUserPerms(int cnum,int uid, char *param,char *data,
2050 int mdrcnt,int mprcnt,
2051 char **rdata,char **rparam,
2052 int *rdata_len,int *rparam_len)
2054 char *str1 = param+2;
2055 char *str2 = skip_string(str1,1);
2056 char *user = skip_string(str2,1);
2057 char *resource = skip_string(user,1);
2059 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
2061 /* check it's a supported varient */
2062 if (strcmp(str1,"zzh") != 0) return False;
2063 if (strcmp(str2,"") != 0) return False;
2066 *rparam = REALLOC(*rparam,*rparam_len);
2067 SSVALS(*rparam,0,0); /* errorcode */
2068 SSVAL(*rparam,2,0); /* converter word */
2069 SSVAL(*rparam,4,0x7f); /* permission flags */
2074 /****************************************************************************
2075 api_WPrintJobEnumerate
2076 ****************************************************************************/
2077 static BOOL api_WPrintJobGetInfo(int cnum,int uid, char *param,char *data,
2078 int mdrcnt,int mprcnt,
2079 char **rdata,char **rparam,
2080 int *rdata_len,int *rparam_len)
2082 char *str1 = param+2;
2083 char *str2 = skip_string(str1,1);
2084 char *p = skip_string(str2,1);
2085 int uJobId = SVAL(p,0);
2091 struct pack_desc desc;
2092 print_queue_struct *queue=NULL;
2093 print_status_struct status;
2098 bzero(&desc,sizeof(desc));
2099 bzero(&status,sizeof(status));
2101 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,uJobId));
2103 /* check it's a supported varient */
2104 if (strcmp(str1,"WWrLh") != 0) return False;
2105 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2107 snum = (unsigned int)uJobId >> 8; /*## valid serice number??*/
2108 job = uJobId & 0xFF;
2110 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2112 count = get_printqueue(snum,cnum,&queue,&status);
2113 for (i = 0; i < count; i++) {
2114 if ((queue[i].job % 0xFF) == job) break;
2116 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2118 desc.buflen = mdrcnt;
2120 if (init_package(&desc,1,0)) {
2122 fill_printjob_info(cnum,snum,uLevel,&desc,&queue[i],i);
2123 *rdata_len = desc.usedlen;
2126 desc.errcode = NERR_JobNotFound;
2132 *rparam = REALLOC(*rparam,*rparam_len);
2133 SSVALS(*rparam,0,desc.errcode);
2135 SSVAL(*rparam,4,desc.neededlen);
2137 if (queue) free(queue);
2139 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
2143 static BOOL api_WPrintJobEnumerate(int cnum,int uid, char *param,char *data,
2144 int mdrcnt,int mprcnt,
2145 char **rdata,char **rparam,
2146 int *rdata_len,int *rparam_len)
2148 char *str1 = param+2;
2149 char *str2 = skip_string(str1,1);
2150 char *p = skip_string(str2,1);
2156 struct pack_desc desc;
2157 print_queue_struct *queue=NULL;
2158 print_status_struct status;
2160 bzero(&desc,sizeof(desc));
2161 bzero(&status,sizeof(status));
2163 p = skip_string(p,1);
2167 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
2169 /* check it's a supported varient */
2170 if (strcmp(str1,"zWrLeh") != 0) return False;
2171 if (uLevel > 2) return False; /* defined only for uLevel 0,1,2 */
2172 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2174 snum = lp_servicenumber(name);
2175 if (snum < 0 && pcap_printername_ok(name,NULL)) {
2176 int pnum = lp_servicenumber(PRINTERS_NAME);
2178 lp_add_printer(name,pnum);
2179 snum = lp_servicenumber(name);
2183 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2185 count = get_printqueue(snum,cnum,&queue,&status);
2186 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2188 desc.buflen = mdrcnt;
2190 if (init_package(&desc,count,0)) {
2192 for (i = 0; i < count; i++) {
2193 fill_printjob_info(cnum,snum,uLevel,&desc,&queue[i],i);
2194 if (desc.errcode == NERR_Success) succnt = i+1;
2198 *rdata_len = desc.usedlen;
2201 *rparam = REALLOC(*rparam,*rparam_len);
2202 SSVALS(*rparam,0,desc.errcode);
2204 SSVAL(*rparam,4,succnt);
2205 SSVAL(*rparam,6,count);
2207 if (queue) free(queue);
2209 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
2213 static int check_printdest_info(struct pack_desc* desc,
2214 int uLevel, char* id)
2216 desc->subformat = NULL;
2218 case 0: desc->format = "B9"; break;
2219 case 1: desc->format = "B9B21WWzW"; break;
2220 case 2: desc->format = "z"; break;
2221 case 3: desc->format = "zzzWWzzzWW"; break;
2222 default: return False;
2224 if (strcmp(desc->format,id) != 0) return False;
2228 static void fill_printdest_info(int cnum, int snum, int uLevel,
2229 struct pack_desc* desc)
2232 strcpy(buf,SERVICE(snum));
2235 PACKS(desc,"B9",buf); /* szName */
2237 PACKS(desc,"B21",""); /* szUserName */
2238 PACKI(desc,"W",0); /* uJobId */
2239 PACKI(desc,"W",0); /* fsStatus */
2240 PACKS(desc,"z",""); /* pszStatus */
2241 PACKI(desc,"W",0); /* time */
2244 if (uLevel == 2 || uLevel == 3) {
2245 PACKS(desc,"z",buf); /* pszPrinterName */
2247 PACKS(desc,"z",""); /* pszUserName */
2248 PACKS(desc,"z",""); /* pszLogAddr */
2249 PACKI(desc,"W",0); /* uJobId */
2250 PACKI(desc,"W",0); /* fsStatus */
2251 PACKS(desc,"z",""); /* pszStatus */
2252 PACKS(desc,"z",""); /* pszComment */
2253 PACKS(desc,"z","NULL"); /* pszDrivers */
2254 PACKI(desc,"W",0); /* time */
2255 PACKI(desc,"W",0); /* pad1 */
2260 static BOOL api_WPrintDestGetInfo(int cnum,int uid, char *param,char *data,
2261 int mdrcnt,int mprcnt,
2262 char **rdata,char **rparam,
2263 int *rdata_len,int *rparam_len)
2265 char *str1 = param+2;
2266 char *str2 = skip_string(str1,1);
2267 char *p = skip_string(str2,1);
2268 char* PrinterName = p;
2270 struct pack_desc desc;
2273 bzero(&desc,sizeof(desc));
2275 p = skip_string(p,1);
2279 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
2281 /* check it's a supported varient */
2282 if (strcmp(str1,"zWrLh") != 0) return False;
2283 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2285 snum = lp_servicenumber(PrinterName);
2286 if (snum < 0 && pcap_printername_ok(PrinterName,NULL)) {
2287 int pnum = lp_servicenumber(PRINTERS_NAME);
2289 lp_add_printer(PrinterName,pnum);
2290 snum = lp_servicenumber(PrinterName);
2296 desc.errcode = NERR_DestNotFound;
2300 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2302 desc.buflen = mdrcnt;
2303 if (init_package(&desc,1,0)) {
2304 fill_printdest_info(cnum,snum,uLevel,&desc);
2306 *rdata_len = desc.usedlen;
2310 *rparam = REALLOC(*rparam,*rparam_len);
2311 SSVALS(*rparam,0,desc.errcode);
2313 SSVAL(*rparam,4,desc.neededlen);
2315 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
2319 static BOOL api_WPrintDestEnum(int cnum,int uid, char *param,char *data,
2320 int mdrcnt,int mprcnt,
2321 char **rdata,char **rparam,
2322 int *rdata_len,int *rparam_len)
2324 char *str1 = param+2;
2325 char *str2 = skip_string(str1,1);
2326 char *p = skip_string(str2,1);
2330 struct pack_desc desc;
2331 int services = lp_numservices();
2333 bzero(&desc,sizeof(desc));
2338 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
2340 /* check it's a supported varient */
2341 if (strcmp(str1,"WrLeh") != 0) return False;
2342 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2345 for (i = 0; i < services; i++)
2346 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
2349 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2351 desc.buflen = mdrcnt;
2352 if (init_package(&desc,queuecnt,0)) {
2355 for (i = 0; i < services; i++) {
2356 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
2357 fill_printdest_info(cnum,i,uLevel,&desc);
2359 if (desc.errcode == NERR_Success) succnt = n;
2364 *rdata_len = desc.usedlen;
2367 *rparam = REALLOC(*rparam,*rparam_len);
2368 SSVALS(*rparam,0,desc.errcode);
2370 SSVAL(*rparam,4,succnt);
2371 SSVAL(*rparam,6,queuecnt);
2373 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
2377 static BOOL api_WPrintDriverEnum(int cnum,int uid, char *param,char *data,
2378 int mdrcnt,int mprcnt,
2379 char **rdata,char **rparam,
2380 int *rdata_len,int *rparam_len)
2382 char *str1 = param+2;
2383 char *str2 = skip_string(str1,1);
2384 char *p = skip_string(str2,1);
2387 struct pack_desc desc;
2389 bzero(&desc,sizeof(desc));
2394 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
2396 /* check it's a supported varient */
2397 if (strcmp(str1,"WrLeh") != 0) return False;
2398 if (uLevel != 0 || strcmp(str2,"B41") != 0) return False;
2400 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2402 desc.buflen = mdrcnt;
2403 if (init_package(&desc,1,0)) {
2404 PACKS(&desc,"B41","NULL");
2407 succnt = (desc.errcode == NERR_Success ? 1 : 0);
2409 *rdata_len = desc.usedlen;
2412 *rparam = REALLOC(*rparam,*rparam_len);
2413 SSVALS(*rparam,0,desc.errcode);
2415 SSVAL(*rparam,4,succnt);
2418 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
2422 static BOOL api_WPrintQProcEnum(int cnum,int uid, char *param,char *data,
2423 int mdrcnt,int mprcnt,
2424 char **rdata,char **rparam,
2425 int *rdata_len,int *rparam_len)
2427 char *str1 = param+2;
2428 char *str2 = skip_string(str1,1);
2429 char *p = skip_string(str2,1);
2432 struct pack_desc desc;
2434 bzero(&desc,sizeof(desc));
2439 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
2441 /* check it's a supported varient */
2442 if (strcmp(str1,"WrLeh") != 0) return False;
2443 if (uLevel != 0 || strcmp(str2,"B13") != 0) return False;
2445 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2447 desc.buflen = mdrcnt;
2449 if (init_package(&desc,1,0)) {
2450 PACKS(&desc,"B13","lpd");
2453 succnt = (desc.errcode == NERR_Success ? 1 : 0);
2455 *rdata_len = desc.usedlen;
2458 *rparam = REALLOC(*rparam,*rparam_len);
2459 SSVALS(*rparam,0,desc.errcode);
2461 SSVAL(*rparam,4,succnt);
2464 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
2468 static BOOL api_WPrintPortEnum(int cnum,int uid, char *param,char *data,
2469 int mdrcnt,int mprcnt,
2470 char **rdata,char **rparam,
2471 int *rdata_len,int *rparam_len)
2473 char *str1 = param+2;
2474 char *str2 = skip_string(str1,1);
2475 char *p = skip_string(str2,1);
2478 struct pack_desc desc;
2480 bzero(&desc,sizeof(desc));
2485 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
2487 /* check it's a supported varient */
2488 if (strcmp(str1,"WrLeh") != 0) return False;
2489 if (uLevel != 0 || strcmp(str2,"B9") != 0) return False;
2491 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2492 bzero(&desc,sizeof(desc));
2494 desc.buflen = mdrcnt;
2496 if (init_package(&desc,1,0)) {
2497 PACKS(&desc,"B13","lp0");
2500 succnt = (desc.errcode == NERR_Success ? 1 : 0);
2502 *rdata_len = desc.usedlen;
2505 *rparam = REALLOC(*rparam,*rparam_len);
2506 SSVALS(*rparam,0,desc.errcode);
2508 SSVAL(*rparam,4,succnt);
2511 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
2522 } api_fd_commands [] =
2524 { "SetNmdPpHndState", "lsarpc", 1, api_LsarpcSNPHS },
2525 { "TransactNmPipe", "lsarpc", 0x26, api_LsarpcTNP },
2526 { NULL, NULL, -1, api_Unsupported }
2529 /****************************************************************************
2530 handle remote api calls delivered to a named pipe already opened.
2531 ****************************************************************************/
2532 static int api_fd_reply(int cnum,int uid,char *outbuf,
2533 uint16 *setup,char *data,char *params,
2534 int suwcnt,int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
2537 char *rparam = NULL;
2545 /* First find out the name of this file. */
2548 DEBUG(0,("Unexpected named pipe transaction.\n"));
2552 /* Get the file handle and hence the file name. */
2554 subcommand = setup[0];
2556 DEBUG(3,("Got API command %d on pipe %s ",subcommand,Files[fd].name));
2557 DEBUG(3,("(tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
2558 tdscnt,tpscnt,mdrcnt,mprcnt));
2560 for (i=0;api_fd_commands[i].name;i++)
2561 if (strequal(api_fd_commands[i].pipename, Files[fd].name) &&
2562 api_fd_commands[i].subcommand == subcommand &&
2563 api_fd_commands[i].fn)
2565 DEBUG(3,("Doing %s\n",api_fd_commands[i].name));
2569 rdata = (char *)malloc(1024); if (rdata) bzero(rdata,1024);
2570 rparam = (char *)malloc(1024); if (rparam) bzero(rparam,1024);
2572 reply = api_fd_commands[i].fn(cnum,uid,params,data,mdrcnt,mprcnt,
2573 &rdata,&rparam,&rdata_len,&rparam_len);
2575 if (rdata_len > mdrcnt ||
2576 rparam_len > mprcnt)
2578 reply = api_TooSmall(cnum,uid,params,data,mdrcnt,mprcnt,
2579 &rdata,&rparam,&rdata_len,&rparam_len);
2583 /* if we get False back then it's actually unsupported */
2585 api_Unsupported(cnum,uid,params,data,mdrcnt,mprcnt,
2586 &rdata,&rparam,&rdata_len,&rparam_len);
2588 /* now send the reply */
2589 send_trans_reply(outbuf,rdata,rparam,NULL,rdata_len,rparam_len,0);
2601 /****************************************************************************
2602 the buffer was too small
2603 ****************************************************************************/
2604 static BOOL api_TooSmall(int cnum,int uid, char *param,char *data,
2605 int mdrcnt,int mprcnt,
2606 char **rdata,char **rparam,
2607 int *rdata_len,int *rparam_len)
2609 *rparam_len = MIN(*rparam_len,mprcnt);
2610 *rparam = REALLOC(*rparam,*rparam_len);
2614 SSVAL(*rparam,0,NERR_BufTooSmall);
2616 DEBUG(3,("Supplied buffer too small in API command\n"));
2622 /****************************************************************************
2623 the request is not supported
2624 ****************************************************************************/
2625 static BOOL api_Unsupported(int cnum,int uid, char *param,char *data,
2626 int mdrcnt,int mprcnt,
2627 char **rdata,char **rparam,
2628 int *rdata_len,int *rparam_len)
2631 *rparam = REALLOC(*rparam,*rparam_len);
2635 SSVAL(*rparam,0,NERR_notsupported);
2636 SSVAL(*rparam,2,0); /* converter word */
2638 DEBUG(3,("Unsupported API command\n"));
2652 } api_commands[] = {
2653 {"RNetShareEnum", 0, api_RNetShareEnum,0},
2654 {"RNetShareGetInfo", 1, api_RNetShareGetInfo,0},
2655 {"RNetServerGetInfo", 13, api_RNetServerGetInfo,0},
2656 {"RNetUserGetInfo", 56, api_RNetUserGetInfo,0},
2657 {"NetUserGetGroups", 59, api_NetUserGetGroups,0},
2658 {"NetWkstaGetInfo", 63, api_NetWkstaGetInfo,0},
2659 {"DosPrintQEnum", 69, api_DosPrintQEnum,0},
2660 {"DosPrintQGetInfo", 70, api_DosPrintQGetInfo,0},
2661 {"WPrintJobEnumerate",76, api_WPrintJobEnumerate,0},
2662 {"WPrintJobGetInfo", 77, api_WPrintJobGetInfo,0},
2663 {"RDosPrintJobDel", 81, api_RDosPrintJobDel,0},
2664 {"RDosPrintJobPause", 82, api_RDosPrintJobDel,0},
2665 {"RDosPrintJobResume",83, api_RDosPrintJobDel,0},
2666 {"WPrintDestEnum", 84, api_WPrintDestEnum,0},
2667 {"WPrintDestGetInfo", 85, api_WPrintDestGetInfo,0},
2668 {"NetRemoteTOD", 91, api_NetRemoteTOD,0},
2669 {"WPrintQueuePurge", 103, api_WPrintQueuePurge,0},
2670 {"NetServerEnum", 104, api_RNetServerEnum,0},
2671 {"WAccessGetUserPerms",105, api_WAccessGetUserPerms,0},
2672 {"SetUserPassword", 115, api_SetUserPassword,0},
2673 {"WWkstaUserLogon", 132, api_WWkstaUserLogon,0},
2674 {"PrintJobInfo", 147, api_PrintJobInfo,0},
2675 {"WPrintDriverEnum", 205, api_WPrintDriverEnum,0},
2676 {"WPrintQProcEnum", 206, api_WPrintQProcEnum,0},
2677 {"WPrintPortEnum", 207, api_WPrintPortEnum,0},
2678 {NULL, -1, api_Unsupported,0}};
2681 /****************************************************************************
2682 handle remote api calls
2683 ****************************************************************************/
2684 static int api_reply(int cnum,int uid,char *outbuf,char *data,char *params,
2685 int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
2687 int api_command = SVAL(params,0);
2689 char *rparam = NULL;
2695 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
2696 api_command,params+2,skip_string(params+2,1),
2697 tdscnt,tpscnt,mdrcnt,mprcnt));
2699 for (i=0;api_commands[i].name;i++)
2700 if (api_commands[i].id == api_command && api_commands[i].fn)
2702 DEBUG(3,("Doing %s\n",api_commands[i].name));
2706 rdata = (char *)malloc(1024); if (rdata) bzero(rdata,1024);
2707 rparam = (char *)malloc(1024); if (rparam) bzero(rparam,1024);
2709 reply = api_commands[i].fn(cnum,uid,params,data,mdrcnt,mprcnt,
2710 &rdata,&rparam,&rdata_len,&rparam_len);
2713 if (rdata_len > mdrcnt ||
2714 rparam_len > mprcnt)
2716 reply = api_TooSmall(cnum,uid,params,data,mdrcnt,mprcnt,
2717 &rdata,&rparam,&rdata_len,&rparam_len);
2721 /* if we get False back then it's actually unsupported */
2723 api_Unsupported(cnum,uid,params,data,mdrcnt,mprcnt,
2724 &rdata,&rparam,&rdata_len,&rparam_len);
2728 /* now send the reply */
2729 send_trans_reply(outbuf,rdata,rparam,NULL,rdata_len,rparam_len,0);
2739 /****************************************************************************
2740 handle named pipe commands
2741 ****************************************************************************/
2742 static int named_pipe(int cnum,int uid, char *outbuf,char *name,
2743 uint16 *setup,char *data,char *params,
2744 int suwcnt,int tdscnt,int tpscnt,
2745 int msrcnt,int mdrcnt,int mprcnt)
2748 if (strequal(name,"LANMAN"))
2749 return(api_reply(cnum,uid,outbuf,data,params,tdscnt,tpscnt,mdrcnt,mprcnt));
2751 if (strlen(name) < 1)
2752 return(api_fd_reply(cnum,uid,outbuf,setup,data,params,suwcnt,tdscnt,tpscnt,mdrcnt,mprcnt));
2755 DEBUG(3,("named pipe command on <%s> 0x%X setup1=%d\n",
2756 name,(int)setup[0],(int)setup[1]));
2762 /****************************************************************************
2764 ****************************************************************************/
2765 int reply_trans(char *inbuf,char *outbuf)
2769 char *data=NULL,*params=NULL;
2773 int cnum = SVAL(inbuf,smb_tid);
2774 int uid = SVAL(inbuf,smb_uid);
2776 int tpscnt = SVAL(inbuf,smb_vwv0);
2777 int tdscnt = SVAL(inbuf,smb_vwv1);
2778 int mprcnt = SVAL(inbuf,smb_vwv2);
2779 int mdrcnt = SVAL(inbuf,smb_vwv3);
2780 int msrcnt = CVAL(inbuf,smb_vwv4);
2781 BOOL close_on_completion = BITSETW(inbuf+smb_vwv5,0);
2782 BOOL one_way = BITSETW(inbuf+smb_vwv5,1);
2783 int pscnt = SVAL(inbuf,smb_vwv9);
2784 int psoff = SVAL(inbuf,smb_vwv10);
2785 int dscnt = SVAL(inbuf,smb_vwv11);
2786 int dsoff = SVAL(inbuf,smb_vwv12);
2787 int suwcnt = CVAL(inbuf,smb_vwv13);
2789 StrnCpy(name,smb_buf(inbuf),sizeof(name)-1);
2793 data = (char *)malloc(tdscnt);
2794 memcpy(data,smb_base(inbuf)+dsoff,dscnt);
2798 params = (char *)malloc(tpscnt);
2799 memcpy(params,smb_base(inbuf)+psoff,pscnt);
2805 setup = (uint16 *)malloc(suwcnt*sizeof(setup[0]));
2806 for (i=0;i<suwcnt;i++)
2807 setup[i] = SVAL(inbuf,smb_vwv14+i*SIZEOFWORD);
2811 if (pscnt < tpscnt || dscnt < tdscnt)
2813 /* We need to send an interim response then receive the rest
2814 of the parameter/data bytes */
2815 outsize = set_message(outbuf,0,0,True);
2817 send_smb(Client,outbuf);
2820 /* receive the rest of the trans packet */
2821 while (pscnt < tpscnt || dscnt < tdscnt)
2823 int pcnt,poff,dcnt,doff,pdisp,ddisp;
2825 if (!receive_smb(Client,inbuf, SMB_SECONDARY_WAIT*1000) ||
2826 CVAL(inbuf, smb_com) != SMBtrans)
2828 DEBUG(2,("Invalid secondary trans2 packet\n"));
2829 if (params) free(params);
2830 if (data) free(data);
2831 if (setup) free(setup);
2832 return(ERROR(ERRSRV,ERRerror));
2837 tpscnt = SVAL(inbuf,smb_vwv0);
2838 tdscnt = SVAL(inbuf,smb_vwv1);
2840 pcnt = SVAL(inbuf,smb_vwv2);
2841 poff = SVAL(inbuf,smb_vwv3);
2842 pdisp = SVAL(inbuf,smb_vwv4);
2844 dcnt = SVAL(inbuf,smb_vwv5);
2845 doff = SVAL(inbuf,smb_vwv6);
2846 ddisp = SVAL(inbuf,smb_vwv7);
2852 memcpy(params+pdisp,smb_base(inbuf)+poff,pcnt);
2854 memcpy(data+ddisp,smb_base(inbuf)+doff,dcnt);
2858 DEBUG(3,("trans <%s> data=%d params=%d setup=%d\n",name,tdscnt,tpscnt,suwcnt));
2861 if (strncmp(name,"\\PIPE\\",strlen("\\PIPE\\")) == 0)
2862 outsize = named_pipe(cnum,uid,outbuf,name+strlen("\\PIPE\\"),setup,data,params,
2863 suwcnt,tdscnt,tpscnt,msrcnt,mdrcnt,mprcnt);
2866 if (data) free(data);
2867 if (params) free(params);
2868 if (setup) free(setup);
2870 if (close_on_completion)
2871 close_cnum(cnum,uid);
2877 return(ERROR(ERRSRV,ERRnosupport));