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 */
64 static int CopyExpanded(int cnum, int snum, char** dst, char* src, int* n)
69 if (!src || !dst || !n || !(*dst)) return(0);
71 StrnCpy(buf,src,sizeof(buf)/2);
72 string_sub(buf,"%S",lp_servicename(snum));
73 standard_sub(cnum,buf);
81 static int CopyAndAdvance(char** dst, char* src, int* n)
84 if (!src || !dst || !n || !(*dst)) return(0);
92 static int StrlenExpanded(int cnum, int snum, char* s)
96 StrnCpy(buf,s,sizeof(buf)/2);
97 string_sub(buf,"%S",lp_servicename(snum));
98 standard_sub(cnum,buf);
99 return strlen(buf) + 1;
102 static char* Expand(int cnum, int snum, char* s)
105 if (!s) return(NULL);
106 StrnCpy(buf,s,sizeof(buf)/2);
107 string_sub(buf,"%S",lp_servicename(snum));
108 standard_sub(cnum,buf);
112 /*******************************************************************
113 check a API string for validity when we only need to check the prefix
114 ******************************************************************/
115 static BOOL prefix_ok(char *str,char *prefix)
117 return(strncmp(str,prefix,strlen(prefix)) == 0);
121 /****************************************************************************
123 ****************************************************************************/
124 static void send_trans_reply(char *outbuf,char *data,char *param,uint16 *setup,
125 int ldata,int lparam,int lsetup)
128 int this_ldata,this_lparam;
129 int tot_data=0,tot_param=0;
132 this_lparam = MIN(lparam,maxxmit - (500+lsetup*SIZEOFWORD)); /* hack */
133 this_ldata = MIN(ldata,maxxmit - (500+lsetup*SIZEOFWORD+this_lparam));
135 align = (this_lparam%4);
137 set_message(outbuf,10+lsetup,align+this_ldata+this_lparam,True);
139 memcpy(smb_buf(outbuf),param,this_lparam);
141 memcpy(smb_buf(outbuf)+this_lparam+align,data,this_ldata);
143 SSVAL(outbuf,smb_vwv0,lparam);
144 SSVAL(outbuf,smb_vwv1,ldata);
145 SSVAL(outbuf,smb_vwv3,this_lparam);
146 SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf),outbuf));
147 SSVAL(outbuf,smb_vwv5,0);
148 SSVAL(outbuf,smb_vwv6,this_ldata);
149 SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+this_lparam+align,outbuf));
150 SSVAL(outbuf,smb_vwv8,0);
151 SSVAL(outbuf,smb_vwv9,lsetup);
152 for (i=0;i<lsetup;i++)
153 SSVAL(outbuf,smb_vwv10+i*SIZEOFWORD,setup[i]);
156 send_smb(Client,outbuf);
158 tot_data = this_ldata;
159 tot_param = this_lparam;
161 while (tot_data < ldata || tot_param < lparam)
163 this_lparam = MIN(lparam-tot_param,maxxmit - 500); /* hack */
164 this_ldata = MIN(ldata-tot_data,maxxmit - (500+this_lparam));
166 align = (this_lparam%4);
168 set_message(outbuf,10,this_ldata+this_lparam+align,False);
170 memcpy(smb_buf(outbuf),param+tot_param,this_lparam);
172 memcpy(smb_buf(outbuf)+this_lparam+align,data+tot_data,this_ldata);
174 SSVAL(outbuf,smb_vwv3,this_lparam);
175 SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf),outbuf));
176 SSVAL(outbuf,smb_vwv5,tot_param);
177 SSVAL(outbuf,smb_vwv6,this_ldata);
178 SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+this_lparam+align,outbuf));
179 SSVAL(outbuf,smb_vwv8,tot_data);
180 SSVAL(outbuf,smb_vwv9,0);
183 send_smb(Client,outbuf);
185 tot_data += this_ldata;
186 tot_param += this_lparam;
192 /****************************************************************************
194 ****************************************************************************/
197 char* format; /* formatstring for structure */
198 char* subformat; /* subformat for structure */
199 char* base; /* baseaddress of buffer */
200 int buflen; /* remaining size for fixed part; on init: length of base */
201 int subcount; /* count of substructures */
202 char* structbuf; /* pointer into buffer for remaining fixed part */
203 int stringlen; /* remaining size for variable part */
204 char* stringbuf; /* pointer into buffer for remaining variable part */
205 int neededlen; /* total needed size */
206 int usedlen; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
207 char* curpos; /* current position; pointer into format or subformat */
211 static int get_counter(char** p)
214 if (!p || !(*p)) return(1);
215 if (!isdigit(**p)) return 1;
219 n = 10 * n + (i - '0');
226 static int getlen(char* p)
232 case 'W': /* word (2 byte) */
235 case 'N': /* count of substructures (word) at end */
238 case 'D': /* double word (4 byte) */
239 case 'z': /* offset to zero terminated string (4 byte) */
240 case 'l': /* offset to user data (4 byte) */
243 case 'b': /* offset to data (with counter) (4 byte) */
247 case 'B': /* byte (with optional counter) */
248 n += get_counter(&p);
255 static BOOL init_package(struct pack_desc* p, int count, int subcount)
260 if (!p->format || !p->base) return(False);
262 i = count * getlen(p->format);
263 if (p->subformat) i += subcount * getlen(p->subformat);
264 p->structbuf = p->base;
268 p->curpos = p->format;
271 p->errcode = NERR_BufTooSmall;
274 p->errcode = NERR_Success;
277 p->stringbuf = p->base + i;
279 return(p->errcode == NERR_Success);
283 static int package(struct pack_desc* p, ...)
286 static int package(va_alist)
292 int needed=0, stringneeded;
294 int is_string=0, stringused;
301 p = va_arg(args,struct pack_desc *);
306 p->curpos = p->format;
308 p->curpos = p->subformat;
313 str = va_arg(args,char*);
314 if (strncmp(str,p->curpos,strlen(str)) != 0) {
315 DEBUG(2,("type error in package: %s instead of %*s\n",str,
316 strlen(str),p->curpos));
326 if (!p->curpos) return(0);
328 switch( *p->curpos++ ) {
329 case 'W': /* word (2 byte) */
331 temp = va_arg(args,int);
332 if (p->buflen >= needed) SSVAL(p->structbuf,0,temp);
334 case 'N': /* count of substructures (word) at end */
336 p->subcount = va_arg(args,int);
337 if (p->buflen >= needed) SSVAL(p->structbuf,0,p->subcount);
339 case 'D': /* double word (4 byte) */
341 temp = va_arg(args,int);
342 if (p->buflen >= needed) SIVAL(p->structbuf,0,temp);
344 case 'B': /* byte (with optional counter) */
345 needed = get_counter(&p->curpos);
347 char *s = va_arg(args,char*);
348 if (p->buflen >= needed) StrnCpy(p->structbuf,s?s:"",needed);
351 case 'z': /* offset to zero terminated string (4 byte) */
352 str = va_arg(args,char*);
353 stringneeded = (str ? strlen(str)+1 : 0);
356 case 'l': /* offset to user data (4 byte) */
357 str = va_arg(args,char*);
358 stringneeded = va_arg(args,int);
361 case 'b': /* offset to data (with counter) (4 byte) */
362 str = va_arg(args,char*);
363 stringneeded = get_counter(&p->curpos);
368 if (stringneeded >= 0) {
370 if (p->buflen >= needed) {
371 stringused = stringneeded;
372 if (stringused > p->stringlen) {
373 stringused = (is_string ? p->stringlen : 0);
374 if (p->errcode == NERR_Success) p->errcode = ERROR_MORE_DATA;
377 SIVAL(p->structbuf,0,0);
379 SIVAL(p->structbuf,0,PTR_DIFF(p->stringbuf,p->base));
380 memcpy(p->stringbuf,str?str:"",stringused);
381 if (is_string) p->stringbuf[stringused-1] = '\0';
382 p->stringbuf += stringused;
383 p->stringlen -= stringused;
384 p->usedlen += stringused;
387 p->neededlen += stringneeded;
389 p->neededlen += needed;
390 if (p->buflen >= needed) {
391 p->structbuf += needed;
393 p->usedlen += needed;
396 if (p->errcode == NERR_Success) p->errcode = NERR_BufTooSmall;
402 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
403 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
405 #define PACK(desc,t,v) package(desc,v)
406 #define PACKl(desc,t,v,l) package(desc,v,l)
409 static void PACKI(struct pack_desc* desc,char *t,int v)
414 static void PACKS(struct pack_desc* desc,char *t,char *v)
419 static void PackDriverData(struct pack_desc* desc)
421 char drivdata[4+4+32];
422 SIVAL(drivdata,0,sizeof drivdata); /* cb */
423 SIVAL(drivdata,4,1000); /* lVersion */
424 memset(drivdata+8,0,32); /* szDeviceName */
425 strcpy(drivdata+8,"NULL");
426 PACKl(desc,"l",drivdata,sizeof drivdata); /* pDriverData */
429 static int check_printq_info(struct pack_desc* desc,
430 int uLevel, const char* id1, const char* id2)
432 desc->subformat = NULL;
435 desc->format = "B13";
438 desc->format = "B13BWWWzzzzzWW";
441 desc->format = "B13BWWWzzzzzWN";
442 desc->subformat = "WB21BB16B10zWWzDDz";
445 desc->format = "zWWWWzzzzWWzzl";
448 desc->format = "zWWWWzzzzWNzzl";
449 desc->subformat = "WWzWWDDzz";
454 default: return False;
456 if (strcmp(desc->format,id1) != 0) return False;
457 if (desc->subformat && strcmp(desc->subformat,id2) != 0) return False;
461 static void fill_printjob_info(int cnum, int snum, int uLevel,
462 struct pack_desc* desc,
463 print_queue_struct* queue, int n)
465 time_t t = queue->time;
467 /* the client expects localtime */
470 PACKI(desc,"W",((snum%0xFF)<<8) | (queue->job%0xFF)); /* uJobId */
472 PACKS(desc,"B21",queue->user); /* szUserName */
473 PACKS(desc,"B",""); /* pad */
474 PACKS(desc,"B16",""); /* szNotifyName */
475 PACKS(desc,"B10","PM_Q_RAW"); /* szDataType */
476 PACKS(desc,"z",""); /* pszParms */
477 PACKI(desc,"W",n+1); /* uPosition */
478 PACKI(desc,"W",queue->status); /* fsStatus */
479 PACKS(desc,"z",""); /* pszStatus */
480 PACKI(desc,"D",t); /* ulSubmitted */
481 PACKI(desc,"D",queue->size); /* ulSize */
482 PACKS(desc,"z",queue->file); /* pszComment */
484 if (uLevel == 2 || uLevel == 3) {
485 PACKI(desc,"W",queue->priority); /* uPriority */
486 PACKS(desc,"z",queue->user); /* pszUserName */
487 PACKI(desc,"W",n+1); /* uPosition */
488 PACKI(desc,"W",queue->status); /* fsStatus */
489 PACKI(desc,"D",t); /* ulSubmitted */
490 PACKI(desc,"D",queue->size); /* ulSize */
491 PACKS(desc,"z","Samba"); /* pszComment */
492 PACKS(desc,"z",queue->file); /* pszDocument */
494 PACKS(desc,"z",""); /* pszNotifyName */
495 PACKS(desc,"z","PM_Q_RAW"); /* pszDataType */
496 PACKS(desc,"z",""); /* pszParms */
497 PACKS(desc,"z",""); /* pszStatus */
498 PACKS(desc,"z",SERVICE(snum)); /* pszQueue */
499 PACKS(desc,"z","lpd"); /* pszQProcName */
500 PACKS(desc,"z",""); /* pszQProcParms */
501 PACKS(desc,"z","NULL"); /* pszDriverName */
502 PackDriverData(desc); /* pDriverData */
503 PACKS(desc,"z",""); /* pszPrinterName */
508 static void fill_printq_info(int cnum, int snum, int uLevel,
509 struct pack_desc* desc,
510 int count, print_queue_struct* queue,
511 print_status_struct* status)
514 PACKS(desc,"B13",SERVICE(snum));
516 PACKS(desc,"z",Expand(cnum,snum,SERVICE(snum)));
518 if (uLevel == 1 || uLevel == 2) {
519 PACKS(desc,"B",""); /* alignment */
520 PACKI(desc,"W",5); /* priority */
521 PACKI(desc,"W",0); /* start time */
522 PACKI(desc,"W",0); /* until time */
523 PACKS(desc,"z",""); /* pSepFile */
524 PACKS(desc,"z","lpd"); /* pPrProc */
525 PACKS(desc,"z",SERVICE(snum)); /* pDestinations */
526 PACKS(desc,"z",""); /* pParms */
528 PACKS(desc,"z","UNKNOWN PRINTER");
529 PACKI(desc,"W",LPSTAT_ERROR);
531 else if (!status || !status->message[0]) {
532 PACKS(desc,"z",Expand(cnum,snum,lp_comment(snum)));
533 PACKI(desc,"W",LPSTAT_OK); /* status */
535 PACKS(desc,"z",status->message);
536 PACKI(desc,"W",status->status); /* status */
538 PACKI(desc,(uLevel == 1 ? "W" : "N"),count);
540 if (uLevel == 3 || uLevel == 4) {
541 PACKI(desc,"W",5); /* uPriority */
542 PACKI(desc,"W",0); /* uStarttime */
543 PACKI(desc,"W",0); /* uUntiltime */
544 PACKI(desc,"W",5); /* pad1 */
545 PACKS(desc,"z",""); /* pszSepFile */
546 PACKS(desc,"z","lpd"); /* pszPrProc */
547 PACKS(desc,"z",""); /* pszParms */
548 if (!status || !status->message[0]) {
549 PACKS(desc,"z",Expand(cnum,snum,lp_comment(snum))); /* pszComment */
550 PACKI(desc,"W",LPSTAT_OK); /* fsStatus */
552 PACKS(desc,"z",status->message); /* pszComment */
553 PACKI(desc,"W",status->status); /* fsStatus */
555 PACKI(desc,(uLevel == 3 ? "W" : "N"),count); /* cJobs */
556 PACKS(desc,"z",SERVICE(snum)); /* pszPrinters */
557 PACKS(desc,"z","NULL"); /* pszDriverName */
558 PackDriverData(desc); /* pDriverData */
560 if (uLevel == 2 || uLevel == 4) {
562 for (i=0;i<count;i++)
563 fill_printjob_info(cnum,snum,uLevel == 2 ? 1 : 2,desc,&queue[i],i);
566 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n",SERVICE(snum),count));
569 static BOOL api_DosPrintQGetInfo(int cnum,int uid, char *param,char *data,
570 int mdrcnt,int mprcnt,
571 char **rdata,char **rparam,
572 int *rdata_len,int *rparam_len)
574 char *str1 = param+2;
575 char *str2 = skip_string(str1,1);
576 char *p = skip_string(str2,1);
582 struct pack_desc desc;
583 print_queue_struct *queue=NULL;
584 print_status_struct status;
586 bzero(&status,sizeof(status));
587 bzero(&desc,sizeof(desc));
589 p = skip_string(p,1);
594 if ((p = strchr(QueueName,'%'))) *p = 0;
596 DEBUG(3,("PrintQueue uLevel=%d name=%s\n",uLevel,QueueName));
598 /* check it's a supported varient */
599 if (!prefix_ok(str1,"zWrLh")) return False;
600 if (!check_printq_info(&desc,uLevel,str2,str3)) return False;
602 snum = lp_servicenumber(QueueName);
603 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
604 int pnum = lp_servicenumber(PRINTERS_NAME);
606 lp_add_printer(QueueName,pnum);
607 snum = lp_servicenumber(QueueName);
611 if (snum < 0 || !VALID_SNUM(snum)) return(False);
613 count = get_printqueue(snum,cnum,&queue,&status);
614 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
616 desc.buflen = mdrcnt;
617 if (init_package(&desc,1,count)) {
618 desc.subcount = count;
619 fill_printq_info(cnum,snum,uLevel,&desc,count,queue,&status);
622 *rdata_len = desc.usedlen;
625 *rparam = REALLOC(*rparam,*rparam_len);
626 SSVALS(*rparam,0,desc.errcode);
628 SSVAL(*rparam,4,desc.neededlen);
630 DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode));
632 if (queue) free(queue);
638 /****************************************************************************
639 view list of all print jobs on all queues
640 ****************************************************************************/
641 static BOOL api_DosPrintQEnum(int cnum, int uid, char* param, char* data,
642 int mdrcnt, int mprcnt,
643 char **rdata, char** rparam,
644 int *rdata_len, int *rparam_len)
646 char *param_format = param+2;
647 char *output_format1 = skip_string(param_format,1);
648 char *p = skip_string(output_format1,1);
649 int uLevel = SVAL(p,0);
650 char *output_format2 = p + 4;
651 int services = lp_numservices();
653 struct pack_desc desc;
654 print_queue_struct **queue = NULL;
655 print_status_struct *status = NULL;
656 int* subcntarr = NULL;
657 int queuecnt, subcnt=0, succnt=0;
659 bzero(&desc,sizeof(desc));
661 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
663 if (prefix_ok(param_format,"WrLeh")) return False;
664 if (!check_printq_info(&desc,uLevel,output_format1,output_format2))
667 for (i = 0; i < services; i++)
668 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
671 queue = (print_queue_struct**)malloc(queuecnt*sizeof(print_queue_struct*));
672 memset(queue,0,queuecnt*sizeof(print_queue_struct*));
673 status = (print_status_struct*)malloc(queuecnt*sizeof(print_status_struct));
674 memset(status,0,queuecnt*sizeof(print_status_struct));
675 subcntarr = (int*)malloc(queuecnt*sizeof(int));
678 for (i = 0; i < services; i++)
679 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
680 subcntarr[n] = get_printqueue(i,cnum,&queue[n],&status[n]);
681 subcnt += subcntarr[n];
685 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
687 desc.buflen = mdrcnt;
689 if (init_package(&desc,queuecnt,subcnt)) {
692 for (i = 0; i < services; i++)
693 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
694 fill_printq_info(cnum,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]);
696 if (desc.errcode == NERR_Success) succnt = n;
700 if (subcntarr) free(subcntarr);
702 *rdata_len = desc.usedlen;
704 *rparam = REALLOC(*rparam,*rparam_len);
705 SSVALS(*rparam,0,desc.errcode);
707 SSVAL(*rparam,4,succnt);
708 SSVAL(*rparam,6,queuecnt);
710 for (i = 0; i < queuecnt; i++) {
711 if (queue && queue[i]) free(queue[i]);
714 if (queue) free(queue);
715 if (status) free(status);
720 /****************************************************************************
721 get info level for a server list query
722 ****************************************************************************/
723 static BOOL check_server_info(int uLevel, char* id)
727 if (strcmp(id,"B16") != 0) return False;
730 if (strcmp(id,"B16BBDz") != 0) return False;
738 /* used for server information: client, nameserv and ipc */
739 struct srv_info_struct
744 fstring domain; /* used ONLY in ipc.c NOT namework.c */
745 BOOL server_added; /* used ONLY in ipc.c NOT namework.c */
748 /*******************************************************************
749 filter out unwanted server info
750 This function returns True if the entry is wanted.
751 ******************************************************************/
752 static BOOL filter_server_info(struct srv_info_struct *server,
754 char *domain, uint32 request)
756 /* If no domain was specified, */
759 /* If entry's domain matches this server's domain,
760 accept this entry. */
761 if (strequal(lp_workgroup(), server->domain)) {
765 /* If specific domain requested, reject this entry. */
768 DEBUG(4,("primary domain:reject %8x %s %s\n",request,server->name,server->domain));
772 /* If the request was for a list of domain enumerators,
773 we don't care what domain this entry is in as long
774 as it is a domain enumerator. */
775 else if ((request & SV_TYPE_DOMAIN_ENUM) &&
776 (server->type & SV_TYPE_DOMAIN_ENUM))
781 DEBUG(4,("wrong domain: %8x: %s %s\n",server->type,server->name,server->domain));
785 /* If a domain name was specified, */
788 /* If this entry is in the requested domain, */
789 if (strequal(domain, server->domain))
792 if (request == SV_TYPE_LOCAL_LIST_ONLY &&
793 !(server->type & SV_TYPE_LOCAL_LIST_ONLY))
795 DEBUG(4,("rej:LOC %8x: ok %s %s\n",request,server->name,server->domain));
799 if ((request == (SV_TYPE_LOCAL_LIST_ONLY|SV_TYPE_DOMAIN_ENUM)) &&
800 !(server->type&SV_TYPE_DOMAIN_ENUM))
802 DEBUG(4,("rej:LOCDOM %8x: ok %s %s\n",request,server->name,server->domain));
809 /* If the user didn't pick a domain,
810 (I don't think this can happen.) */
813 DEBUG(4,("domain:%s %s %s\n",domain,server->name,server->domain));
821 /*******************************************************************
822 get server info lists from the files saved by nmbd. Return the
824 ******************************************************************/
825 static int get_server_info(uint32 servertype,
826 struct srv_info_struct **servers, BOOL domains,
835 strcpy(fname,lp_lockdir());
836 trim_string(fname,NULL,"/");
838 strcat(fname,SERVER_LIST);
840 f = fopen(fname,"r");
843 DEBUG(4,("Can't open %s - %s\n",fname,strerror(errno)));
847 /* request for everything is code for request all servers */
848 if (servertype == SV_TYPE_ALL) servertype &= ~SV_TYPE_DOMAIN_ENUM;
850 DEBUG(4,("Servertype search: %8x domains:%s\n",servertype,BOOLSTR(domains)));
855 struct srv_info_struct *s;
860 fgets(line,sizeof(line)-1,f);
861 if (!*line) continue;
863 if (count == alloced) {
865 (*servers) = (struct srv_info_struct *)
866 Realloc(*servers,sizeof(**servers)*alloced);
867 if (!(*servers)) return(0);
868 bzero((char *)((*servers)+count),sizeof(**servers)*(alloced-count));
870 s = &(*servers)[count];
872 if (!next_token(&ptr,s->name , NULL)) continue;
873 if (!next_token(&ptr,stype , NULL)) continue;
874 if (!next_token(&ptr,s->comment, NULL)) continue;
875 if (!next_token(&ptr,s->domain , NULL)) {
876 /* this allows us to cope with an old nmbd */
877 strcpy(s->domain,my_workgroup());
880 if (sscanf(stype,"%X",&s->type) != 1) {
881 DEBUG(4,("r:host file "));
885 /* doesn't match up: don't want it */
886 if (!(servertype & s->type)) {
887 DEBUG(4,("r:serv type "));
891 /* If all server, reject DOMIAN_ENUM entries? */
892 if ((servertype == ~SV_TYPE_DOMAIN_ENUM) &&
893 (s->type & SV_TYPE_DOMAIN_ENUM))
895 DEBUG(4,("s:all x dom "));
899 /* If a domain is specified, reject all except the
900 domain enumerators for the specified domain. */
901 if (domains && !(domain && *domain && strequal(domain, s->domain)))
903 if (!(s->type & SV_TYPE_DOMAIN_ENUM))
905 DEBUG(4,("r:dom enum "));
912 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
913 s->name, s->type, s->comment, s->domain));
915 s->type |= SV_TYPE_LOCAL_LIST_ONLY;
916 s->server_added = True;
921 DEBUG(4,("%20s %8x %25s %15s\n",
922 s->name, s->type, s->comment, s->domain));
931 /*******************************************************************
932 fill in a server info structure
933 ******************************************************************/
934 static int fill_srv_info(struct srv_info_struct *service,
935 int uLevel, char **buf, int *buflen,
936 char **stringbuf, int *stringspace, char *baseaddr)
945 case 0: struct_len = 16; break;
946 case 1: struct_len = 26; break;
956 len = strlen(service->comment)+1;
960 if (buflen) *buflen = struct_len;
961 if (stringspace) *stringspace = len;
962 return struct_len + len;
967 if (*buflen < struct_len) return -1;
976 l2 = *buflen - struct_len;
978 if (!baseaddr) baseaddr = p;
983 StrnCpy(p,service->name,15);
987 StrnCpy(p,service->name,15);
988 SIVAL(p,18,service->type);
989 SIVAL(p,22,PTR_DIFF(p2,baseaddr));
990 len += CopyAndAdvance(&p2,service->comment,&l2);
996 *buf = p + struct_len;
997 *buflen -= struct_len;
1010 static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
1012 return(strcmp(s1->name,s2->name));
1015 /****************************************************************************
1016 view list of servers available (or possibly domains). The info is
1017 extracted from lists saved by nmbd on the local host
1018 ****************************************************************************/
1019 static BOOL api_RNetServerEnum(int cnum, int uid, char *param, char *data,
1020 int mdrcnt, int mprcnt, char **rdata,
1021 char **rparam, int *rdata_len, int *rparam_len)
1023 char *str1 = param+2;
1024 char *str2 = skip_string(str1,1);
1025 char *p = skip_string(str2,1);
1026 int uLevel = SVAL(p,0);
1027 int buf_len = SVAL(p,2);
1028 uint32 servertype = IVAL(p,4);
1030 int data_len, fixed_len, string_len;
1032 struct srv_info_struct *servers=NULL;
1033 int counted=0,total=0;
1037 BOOL domain_request;
1038 BOOL local_request = servertype & SV_TYPE_LOCAL_LIST_ONLY;
1040 /*if (servertype == SV_TYPE_ALL) servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);*/
1041 if (servertype == SV_TYPE_ALL) servertype &= ~SV_TYPE_DOMAIN_ENUM;
1043 domain_request = servertype & SV_TYPE_DOMAIN_ENUM;
1048 if (!prefix_ok(str1,"WrLehD")) return False;
1049 if (!check_server_info(uLevel,str2)) return False;
1051 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1052 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1053 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1055 if (strcmp(str1, "WrLehDO") == 0)
1058 DEBUG(4, ("all domains\n"));
1060 else if (strcmp(str1, "WrLehDz") == 0)
1063 StrnCpy(domain, p, sizeof(fstring)-1);
1064 DEBUG(4, ("domains must match \"%s\"\n", domains));
1067 if (lp_browse_list())
1069 total = get_server_info(servertype,&servers,domains,domain);
1072 data_len = fixed_len = string_len = 0;
1074 qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
1078 char *lastname=NULL;
1080 for (i=0;i<total;i++)
1082 struct srv_info_struct *s = &servers[i];
1083 if (filter_server_info(s,domains,domain,
1084 local_request|domain_request))
1086 if (lastname && strequal(lastname,s->name)) continue;
1088 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1089 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1090 s->name, s->type, s->comment, s->domain));
1092 if (data_len <= buf_len)
1096 string_len += s_len;
1102 *rdata_len = fixed_len + string_len;
1103 *rdata = REALLOC(*rdata,*rdata_len);
1104 bzero(*rdata,*rdata_len);
1106 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1111 /* the real thing */
1113 char *lastname=NULL;
1114 int count2 = counted;
1115 for (i = 0; i < total && count2;i++)
1117 struct srv_info_struct *s = &servers[i];
1118 if (filter_server_info(s,domains,domain,local_request|domain_request))
1120 if (lastname && strequal(lastname,s->name)) continue;
1122 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1123 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1124 s->name, s->type, s->comment, s->domain));
1131 *rparam = REALLOC(*rparam,*rparam_len);
1132 SSVAL(*rparam,0,NERR_Success);
1134 SSVAL(*rparam,4,counted);
1135 SSVAL(*rparam,6,total);
1137 if (servers) free(servers);
1139 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1140 domain,uLevel,counted,total));
1146 /****************************************************************************
1147 get info about a share
1148 ****************************************************************************/
1149 static BOOL check_share_info(int uLevel, char* id)
1153 if (strcmp(id,"B13") != 0) return False;
1156 if (strcmp(id,"B13BWz") != 0) return False;
1159 if (strcmp(id,"B13BWzWWWzB9B") != 0) return False;
1162 if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) return False;
1164 default: return False;
1169 static int fill_share_info(int cnum, int snum, int uLevel,
1170 char** buf, int* buflen,
1171 char** stringbuf, int* stringspace, char* baseaddr)
1180 case 0: struct_len = 13; break;
1181 case 1: struct_len = 20; break;
1182 case 2: struct_len = 40; break;
1183 case 91: struct_len = 68; break;
1191 if (uLevel > 0) len += StrlenExpanded(cnum,snum,lp_comment(snum));
1192 if (uLevel > 1) len += strlen(lp_pathname(snum)) + 1;
1193 if (buflen) *buflen = struct_len;
1194 if (stringspace) *stringspace = len;
1195 return struct_len + len;
1200 if ((*buflen) < struct_len) return -1;
1208 p2 = p + struct_len;
1209 l2 = (*buflen) - struct_len;
1211 if (!baseaddr) baseaddr = p;
1213 StrnCpy(p,lp_servicename(snum),13);
1219 type = STYPE_DISKTREE;
1220 if (lp_print_ok(snum)) type = STYPE_PRINTQ;
1221 if (strequal("IPC$",lp_servicename(snum))) type = STYPE_IPC;
1222 SSVAL(p,14,type); /* device type */
1223 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1224 len += CopyExpanded(cnum,snum,&p2,lp_comment(snum),&l2);
1229 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1230 SSVALS(p,22,-1); /* max uses */
1231 SSVAL(p,24,1); /* current uses */
1232 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1233 len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1234 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1239 memset(p+40,0,SHPWLEN+2);
1251 (*buf) = p + struct_len;
1252 (*buflen) -= struct_len;
1254 (*stringspace) = l2;
1264 static BOOL api_RNetShareGetInfo(int cnum,int uid, char *param,char *data,
1265 int mdrcnt,int mprcnt,
1266 char **rdata,char **rparam,
1267 int *rdata_len,int *rparam_len)
1269 char *str1 = param+2;
1270 char *str2 = skip_string(str1,1);
1271 char *netname = skip_string(str2,1);
1272 char *p = skip_string(netname,1);
1273 int uLevel = SVAL(p,0);
1274 int snum = find_service(netname);
1276 if (snum < 0) return False;
1278 /* check it's a supported varient */
1279 if (!prefix_ok(str1,"zWrLh")) return False;
1280 if (!check_share_info(uLevel,str2)) return False;
1282 *rdata = REALLOC(*rdata,mdrcnt);
1284 *rdata_len = fill_share_info(cnum,snum,uLevel,&p,&mdrcnt,0,0,0);
1285 if (*rdata_len < 0) return False;
1288 *rparam = REALLOC(*rparam,*rparam_len);
1289 SSVAL(*rparam,0,NERR_Success);
1290 SSVAL(*rparam,2,0); /* converter word */
1291 SSVAL(*rparam,4,*rdata_len);
1296 /****************************************************************************
1297 view list of shares available
1298 ****************************************************************************/
1299 static BOOL api_RNetShareEnum(int cnum,int uid, char *param,char *data,
1300 int mdrcnt,int mprcnt,
1301 char **rdata,char **rparam,
1302 int *rdata_len,int *rparam_len)
1304 char *str1 = param+2;
1305 char *str2 = skip_string(str1,1);
1306 char *p = skip_string(str2,1);
1307 int uLevel = SVAL(p,0);
1308 int buf_len = SVAL(p,2);
1310 int count=lp_numservices();
1311 int total=0,counted=0;
1313 int data_len, fixed_len, string_len;
1316 if (!prefix_ok(str1,"WrLeh")) return False;
1317 if (!check_share_info(uLevel,str2)) return False;
1319 data_len = fixed_len = string_len = 0;
1320 for (i=0;i<count;i++)
1321 if (lp_browseable(i) && lp_snum_ok(i))
1324 data_len += fill_share_info(cnum,i,uLevel,0,&f_len,0,&s_len,0);
1325 if (data_len <= buf_len)
1329 string_len += s_len;
1332 *rdata_len = fixed_len + string_len;
1333 *rdata = REALLOC(*rdata,*rdata_len);
1334 memset(*rdata,0,*rdata_len);
1336 p2 = (*rdata) + fixed_len; /* auxillery data (strings) will go here */
1340 for (i = 0; i < count;i++)
1341 if (lp_browseable(i) && lp_snum_ok(i))
1342 if (fill_share_info(cnum,i,uLevel,&p,&f_len,&p2,&s_len,*rdata) < 0)
1346 *rparam = REALLOC(*rparam,*rparam_len);
1347 SSVAL(*rparam,0,NERR_Success);
1349 SSVAL(*rparam,4,counted);
1350 SSVAL(*rparam,6,total);
1352 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1353 counted,total,uLevel,
1354 buf_len,*rdata_len,mdrcnt));
1360 /****************************************************************************
1361 get the time of day info
1362 ****************************************************************************/
1363 static BOOL api_NetRemoteTOD(int cnum,int uid, char *param,char *data,
1364 int mdrcnt,int mprcnt,
1365 char **rdata,char **rparam,
1366 int *rdata_len,int *rparam_len)
1370 *rparam = REALLOC(*rparam,*rparam_len);
1373 *rdata = REALLOC(*rdata,*rdata_len);
1375 SSVAL(*rparam,0,NERR_Success);
1376 SSVAL(*rparam,2,0); /* converter word */
1382 time_t unixdate = time(NULL);
1384 put_dos_date3(p,0,unixdate); /* this is the time that is looked at
1385 by NT in a "net time" operation,
1386 it seems to ignore the one below */
1388 /* the client expects to get localtime, not GMT, in this bit
1389 (I think, this needs testing) */
1390 t = LocalTime(&unixdate);
1392 SIVAL(p,4,0); /* msecs ? */
1393 CVAL(p,8) = t->tm_hour;
1394 CVAL(p,9) = t->tm_min;
1395 CVAL(p,10) = t->tm_sec;
1396 CVAL(p,11) = 0; /* hundredths of seconds */
1397 SSVALS(p,12,TimeDiff(unixdate)/60); /* timezone in minutes from GMT */
1398 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
1399 CVAL(p,16) = t->tm_mday;
1400 CVAL(p,17) = t->tm_mon + 1;
1401 SSVAL(p,18,1900+t->tm_year);
1402 CVAL(p,20) = t->tm_wday;
1409 /****************************************************************************
1410 set the user password
1411 ****************************************************************************/
1412 static BOOL api_SetUserPassword(int cnum,int uid, char *param,char *data,
1413 int mdrcnt,int mprcnt,
1414 char **rdata,char **rparam,
1415 int *rdata_len,int *rparam_len)
1417 char *p = skip_string(param+2,2);
1419 fstring pass1,pass2;
1423 p = skip_string(p,1);
1425 StrnCpy(pass1,p,16);
1426 StrnCpy(pass2,p+16,16);
1429 *rparam = REALLOC(*rparam,*rparam_len);
1433 SSVAL(*rparam,0,NERR_Success);
1434 SSVAL(*rparam,2,0); /* converter word */
1436 DEBUG(3,("Set password for <%s>\n",user));
1438 if (!password_ok(user,pass1,strlen(pass1),NULL,False) ||
1439 !chgpasswd(user,pass1,pass2))
1440 SSVAL(*rparam,0,NERR_badpass);
1442 bzero(pass1,sizeof(fstring));
1443 bzero(pass2,sizeof(fstring));
1448 /****************************************************************************
1451 ****************************************************************************/
1452 static BOOL api_RDosPrintJobDel(int cnum,int uid, char *param,char *data,
1453 int mdrcnt,int mprcnt,
1454 char **rdata,char **rparam,
1455 int *rdata_len,int *rparam_len)
1457 int function = SVAL(param,0);
1458 char *str1 = param+2;
1459 char *str2 = skip_string(str1,1);
1460 char *p = skip_string(str2,1);
1461 int jobid = (SVAL(p,0)&0xFF); /* the snum and jobid are encoded
1462 by the print queue api */
1463 int snum = (SVAL(p,0)>>8);
1467 /* check it's a supported varient */
1468 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
1472 *rparam = REALLOC(*rparam,*rparam_len);
1476 SSVAL(*rparam,0,NERR_Success);
1478 if (snum >= 0 && VALID_SNUM(snum))
1480 print_queue_struct *queue=NULL;
1482 count = get_printqueue(snum,cnum,&queue,NULL);
1484 for (i=0;i<count;i++)
1485 if ((queue[i].job%0xFF) == jobid)
1488 case 81: /* delete */
1489 DEBUG(3,("Deleting queue entry %d\n",queue[i].job));
1490 del_printqueue(cnum,snum,queue[i].job);
1492 case 82: /* pause */
1493 case 83: /* resume */
1494 DEBUG(3,("%s queue entry %d\n",
1495 (function==82?"pausing":"resuming"),queue[i].job));
1496 status_printjob(cnum,snum,queue[i].job,
1497 (function==82?LPQ_PAUSED:LPQ_QUEUED));
1504 SSVAL(*rparam,0,NERR_JobNotFound);
1506 if (queue) free(queue);
1509 SSVAL(*rparam,2,0); /* converter word */
1514 static BOOL api_WPrintQueuePurge(int cnum,int uid, 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 *QueueName = skip_string(str2,1);
1524 /* check it's a supported varient */
1525 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
1529 *rparam = REALLOC(*rparam,*rparam_len);
1533 SSVAL(*rparam,0,NERR_Success);
1534 SSVAL(*rparam,2,0); /* converter word */
1536 snum = lp_servicenumber(QueueName);
1537 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
1538 int pnum = lp_servicenumber(PRINTERS_NAME);
1540 lp_add_printer(QueueName,pnum);
1541 snum = lp_servicenumber(QueueName);
1545 if (snum >= 0 && VALID_SNUM(snum)) {
1546 print_queue_struct *queue=NULL;
1550 count = get_printqueue(snum,cnum,&queue,NULL);
1551 for (i = 0; i < count; i++)
1552 del_printqueue(cnum,snum,queue[i].job);
1554 if (queue) free(queue);
1557 DEBUG(3,("Print queue purge, queue=%s\n",QueueName));
1563 /****************************************************************************
1564 set the property of a print job (undocumented?)
1565 ? function = 0xb -> set name of print job
1566 ? function = 0x6 -> move print job up/down
1567 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
1568 or <WWsTP> <WB21BB16B10zWWzDDz>
1569 ****************************************************************************/
1570 static int check_printjob_info(struct pack_desc* desc,
1571 int uLevel, char* id)
1573 desc->subformat = NULL;
1575 case 0: desc->format = "W"; break;
1576 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
1577 case 2: desc->format = "WWzWWDDzz"; break;
1578 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
1579 default: return False;
1581 if (strcmp(desc->format,id) != 0) return False;
1585 static BOOL api_PrintJobInfo(int cnum,int uid,char *param,char *data,
1586 int mdrcnt,int mprcnt,
1587 char **rdata,char **rparam,
1588 int *rdata_len,int *rparam_len)
1590 struct pack_desc desc;
1591 char *str1 = param+2;
1592 char *str2 = skip_string(str1,1);
1593 char *p = skip_string(str2,1);
1594 int jobid = (SVAL(p,0)&0xFF); /* the snum and jobid are encoded
1595 by the print queue api */
1596 int snum = (SVAL(p,0)>>8);
1597 int uLevel = SVAL(p,2);
1598 int function = SVAL(p,4); /* what is this ?? */
1603 *rparam = REALLOC(*rparam,*rparam_len);
1607 /* check it's a supported varient */
1608 if ((strcmp(str1,"WWsTP")) || (!check_printjob_info(&desc,uLevel,str2)))
1612 case 0x6: /* change job place in the queue, data gives the new place */
1613 if (snum >= 0 && VALID_SNUM(snum))
1615 print_queue_struct *queue=NULL;
1619 count = get_printqueue(snum,cnum,&queue,NULL);
1620 for (i=0;i<count;i++) /* find job */
1621 if ((queue[i].job%0xFF) == jobid) break;
1624 desc.errcode=NERR_JobNotFound;
1625 if (queue) free(queue);
1628 desc.errcode=NERR_Success;
1632 int place= SVAL(data,0);
1633 /* we currently have no way of doing this. Can any unix do it? */
1634 if (i < place) /* move down */;
1635 else if (i > place ) /* move up */;
1638 desc.errcode=NERR_notsupported; /* not yet supported */
1639 if (queue) free(queue);
1642 else desc.errcode=NERR_JobNotFound;
1644 case 0xb: /* change print job name, data gives the name */
1645 /* jobid, snum should be zero */
1652 if (issafe(*s)) name[l++] = *s;
1657 DEBUG(3,("Setting print name to %s\n",name));
1659 for (i=0;i<MAX_OPEN_FILES;i++)
1660 if (Files[i].open && Files[i].print_file)
1666 if (!become_user(Files[i].cnum,uid) ||
1667 !become_service(Files[i].cnum,True))
1670 if (sys_rename(Files[i].name,name) == 0)
1671 string_set(&Files[i].name,name);
1675 desc.errcode=NERR_Success;
1678 default: /* not implemented */
1682 SSVALS(*rparam,0,desc.errcode);
1683 SSVAL(*rparam,2,0); /* converter word */
1689 /****************************************************************************
1690 get info about the server
1691 ****************************************************************************/
1692 static BOOL api_RNetServerGetInfo(int cnum,int uid, char *param,char *data,
1693 int mdrcnt,int mprcnt,
1694 char **rdata,char **rparam,
1695 int *rdata_len,int *rparam_len)
1697 char *str1 = param+2;
1698 char *str2 = skip_string(str1,1);
1699 char *p = skip_string(str2,1);
1700 int uLevel = SVAL(p,0);
1704 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
1706 /* check it's a supported varient */
1707 if (!prefix_ok(str1,"WrLh")) return False;
1710 if (strcmp(str2,"B16") != 0) return False;
1714 if (strcmp(str2,"B16BBDz") != 0) return False;
1718 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")
1723 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz")
1728 if (strcmp(str2,"DN") != 0) return False;
1732 if (strcmp(str2,"B16BBDzWWzzz") != 0) return False;
1735 default: return False;
1738 *rdata_len = mdrcnt;
1739 *rdata = REALLOC(*rdata,*rdata_len);
1742 p2 = p + struct_len;
1744 StrnCpy(p,local_machine,16);
1750 struct srv_info_struct *servers=NULL;
1753 uint32 servertype=SV_TYPE_SERVER_UNIX|SV_TYPE_WORKSTATION|
1754 SV_TYPE_SERVER|SV_TYPE_TIME_SOURCE;
1756 strcpy(comment,lp_serverstring());
1758 if ((count=get_server_info(SV_TYPE_ALL,&servers,False,NULL))>0) {
1759 for (i=0;i<count;i++)
1760 if (strequal(servers[i].name,local_machine)) {
1761 servertype = servers[i].type;
1762 strcpy(comment,servers[i].comment);
1765 if (servers) free(servers);
1767 SCVAL(p,0,2); /* version_major */
1768 SCVAL(p,1,0); /* version_minor */
1769 SIVAL(p,2,servertype);
1770 if (mdrcnt == struct_len) {
1773 SIVAL(p,6,PTR_DIFF(p2,*rdata));
1774 standard_sub(cnum,comment);
1775 StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
1776 p2 = skip_string(p2,1);
1781 return False; /* not yet implemented */
1784 *rdata_len = PTR_DIFF(p2,*rdata);
1787 *rparam = REALLOC(*rparam,*rparam_len);
1788 SSVAL(*rparam,0,NERR_Success);
1789 SSVAL(*rparam,2,0); /* converter word */
1790 SSVAL(*rparam,4,*rdata_len);
1796 /****************************************************************************
1797 get info about the server
1798 ****************************************************************************/
1799 static BOOL api_NetWkstaGetInfo(int cnum,int uid, char *param,char *data,
1800 int mdrcnt,int mprcnt,
1801 char **rdata,char **rparam,
1802 int *rdata_len,int *rparam_len)
1804 char *str1 = param+2;
1805 char *str2 = skip_string(str1,1);
1806 char *p = skip_string(str2,1);
1808 extern pstring sesssetup_user;
1809 int level = SVAL(p,0);
1811 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
1814 *rparam = REALLOC(*rparam,*rparam_len);
1816 /* check it's a supported varient */
1817 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz")))
1820 *rdata_len = mdrcnt + 1024;
1821 *rdata = REALLOC(*rdata,*rdata_len);
1823 SSVAL(*rparam,0,NERR_Success);
1824 SSVAL(*rparam,2,0); /* converter word */
1829 SIVAL(p,0,PTR_DIFF(p2,*rdata));
1830 strcpy(p2,local_machine);
1831 p2 = skip_string(p2,1);
1834 SIVAL(p,0,PTR_DIFF(p2,*rdata));
1835 strcpy(p2,sesssetup_user);
1836 p2 = skip_string(p2,1);
1839 SIVAL(p,0,PTR_DIFF(p2,*rdata));
1840 strcpy(p2,my_workgroup());
1841 p2 = skip_string(p2,1);
1844 SCVAL(p,0,2); /* major version?? */
1845 SCVAL(p,1,1); /* minor version?? */
1848 SIVAL(p,0,PTR_DIFF(p2,*rdata));
1849 strcpy(p2,my_workgroup()); /* login domain?? */
1850 p2 = skip_string(p2,1);
1853 SIVAL(p,0,PTR_DIFF(p2,*rdata));
1855 p2 = skip_string(p2,1);
1858 *rdata_len = PTR_DIFF(p2,*rdata);
1860 SSVAL(*rparam,4,*rdata_len);
1866 /****************************************************************************
1867 get info about a user
1868 ****************************************************************************/
1870 #define USER_PRIV_GUEST 0
1871 #define USER_PRIV_USER 1
1872 #define USER_PRIV_ADMIN 2
1874 static BOOL api_RNetUserGetInfo(int cnum,int uid, char *param,char *data,
1875 int mdrcnt,int mprcnt,
1876 char **rdata,char **rparam,
1877 int *rdata_len,int *rparam_len)
1879 char *str1 = param+2;
1880 char *str2 = skip_string(str1,1);
1881 char *UserName = skip_string(str2,1);
1882 char *p = skip_string(UserName,1);
1883 int uLevel = SVAL(p,0);
1887 *rparam = REALLOC(*rparam,*rparam_len);
1889 /* check it's a supported varient */
1890 if (strcmp(str1,"zWrLh") != 0) return False;
1892 case 0: p2 = "B21"; break;
1893 case 1: p2 = "B21BB16DWzzWz"; break;
1894 case 2: p2 = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
1895 case 10: p2 = "B21Bzzz"; break;
1896 case 11: p2 = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
1897 default: return False;
1899 if (strcmp(p2,str2) != 0) return False;
1901 *rdata_len = mdrcnt + 1024;
1902 *rdata = REALLOC(*rdata,*rdata_len);
1904 SSVAL(*rparam,0,NERR_Success);
1905 SSVAL(*rparam,2,0); /* converter word */
1916 SIVAL(p,22,PTR_DIFF(p2,p)); /* comment */
1917 strcpy(p2,"<Comment>");
1918 p2 = skip_string(p2,1);
1919 SIVAL(p,26,PTR_DIFF(p2,p)); /* user_comment */
1920 strcpy(p2,"<UserComment>");
1921 p2 = skip_string(p2,1);
1922 SIVAL(p,30,PTR_DIFF(p2,p)); /* full name */
1923 strcpy(p2,"<FullName>");
1924 p2 = skip_string(p2,1);
1926 if (uLevel == 11) { /* modelled after NTAS 3.51 reply */
1927 SSVAL(p,34,USER_PRIV_USER); /* user privilege */
1928 SIVAL(p,36,0); /* auth flags */
1929 SIVALS(p,40,-1); /* password age */
1930 SIVAL(p,44,PTR_DIFF(p2,p)); /* home dir */
1931 strcpy(p2,"\\\\%L\\HOMES");
1932 standard_sub_basic(p2);
1933 p2 = skip_string(p2,1);
1934 SIVAL(p,48,PTR_DIFF(p2,p)); /* parms */
1936 p2 = skip_string(p2,1);
1937 SIVAL(p,52,0); /* last logon */
1938 SIVAL(p,56,0); /* last logoff */
1939 SSVALS(p,60,-1); /* bad pw counts */
1940 SSVALS(p,62,-1); /* num logons */
1941 SIVAL(p,64,PTR_DIFF(p2,p)); /* logon server */
1943 p2 = skip_string(p2,1);
1944 SSVAL(p,68,0); /* country code */
1946 SIVAL(p,70,PTR_DIFF(p2,p)); /* workstations */
1948 p2 = skip_string(p2,1);
1950 SIVALS(p,74,-1); /* max storage */
1951 SSVAL(p,78,168); /* units per week */
1952 SIVAL(p,80,PTR_DIFF(p2,p)); /* logon hours */
1954 SCVAL(p2,21,0); /* fix zero termination */
1955 p2 = skip_string(p2,1);
1957 SSVAL(p,84,0); /* code page */
1959 if (uLevel == 1 || uLevel == 2) {
1960 memset(p+22,' ',16); /* password */
1961 SIVALS(p,38,-1); /* password age */
1962 SSVAL(p,42,USER_PRIV_ADMIN); /* user privilege */
1963 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
1964 strcpy(p2,"\\\\%L\\HOMES");
1965 standard_sub_basic(p2);
1966 p2 = skip_string(p2,1);
1967 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
1969 SSVAL(p,52,0); /* flags */
1970 SIVAL(p,54,0); /* script_path */
1972 SIVAL(p,60,0); /* auth_flags */
1973 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
1974 strcpy(p2,"<Full Name>");
1975 p2 = skip_string(p2,1);
1976 SIVAL(p,68,0); /* urs_comment */
1977 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
1979 p2 = skip_string(p2,1);
1980 SIVAL(p,76,0); /* workstations */
1981 SIVAL(p,80,0); /* last_logon */
1982 SIVAL(p,84,0); /* last_logoff */
1983 SIVALS(p,88,-1); /* acct_expires */
1984 SIVALS(p,92,-1); /* max_storage */
1985 SSVAL(p,96,168); /* units_per_week */
1986 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
1989 SSVALS(p,102,-1); /* bad_pw_count */
1990 SSVALS(p,104,-1); /* num_logons */
1991 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
1992 strcpy(p2,"\\\\%L");
1993 standard_sub_basic(p2);
1994 p2 = skip_string(p2,1);
1995 SSVAL(p,110,49); /* country_code */
1996 SSVAL(p,112,860); /* code page */
2001 *rdata_len = PTR_DIFF(p2,*rdata);
2003 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
2009 /*******************************************************************
2010 get groups that a user is a member of
2011 ******************************************************************/
2012 static BOOL api_NetUserGetGroups(int cnum,int uid, char *param,char *data,
2013 int mdrcnt,int mprcnt,
2014 char **rdata,char **rparam,
2015 int *rdata_len,int *rparam_len)
2017 char *str1 = param+2;
2018 char *str2 = skip_string(str1,1);
2019 char *UserName = skip_string(str2,1);
2020 char *p = skip_string(UserName,1);
2021 int uLevel = SVAL(p,0);
2026 *rparam = REALLOC(*rparam,*rparam_len);
2028 /* check it's a supported varient */
2029 if (strcmp(str1,"zWrLeh") != 0) return False;
2031 case 0: p2 = "B21"; break;
2032 default: return False;
2034 if (strcmp(p2,str2) != 0) return False;
2036 *rdata_len = mdrcnt + 1024;
2037 *rdata = REALLOC(*rdata,*rdata_len);
2039 SSVAL(*rparam,0,NERR_Success);
2040 SSVAL(*rparam,2,0); /* converter word */
2044 /* XXXX we need a real SAM database some day */
2045 strcpy(p,"Users"); p += 21; count++;
2046 strcpy(p,"Domain Users"); p += 21; count++;
2047 strcpy(p,"Guests"); p += 21; count++;
2048 strcpy(p,"Domain Guests"); p += 21; count++;
2050 *rdata_len = PTR_DIFF(p,*rdata);
2052 SSVAL(*rparam,4,count); /* is this right?? */
2053 SSVAL(*rparam,6,count); /* is this right?? */
2059 static BOOL api_WWkstaUserLogon(int cnum,int uid, char *param,char *data,
2060 int mdrcnt,int mprcnt,
2061 char **rdata,char **rparam,
2062 int *rdata_len,int *rparam_len)
2064 char *str1 = param+2;
2065 char *str2 = skip_string(str1,1);
2066 char *p = skip_string(str2,1);
2068 struct pack_desc desc;
2074 bzero(&desc,sizeof(desc));
2076 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
2078 /* check it's a supported varient */
2079 if (strcmp(str1,"OOWb54WrLh") != 0) return False;
2080 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) return False;
2081 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2083 desc.buflen = mdrcnt;
2084 desc.subformat = NULL;
2089 if (init_package(&desc,1,0)) {
2090 PACKI(&desc,"W",0); /* code */
2091 PACKS(&desc,"B21",name); /* eff. name */
2092 PACKS(&desc,"B",""); /* pad */
2094 Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2095 PACKI(&desc,"D",0); /* auth flags XXX */
2096 PACKI(&desc,"W",0); /* num logons */
2097 PACKI(&desc,"W",0); /* bad pw count */
2098 PACKI(&desc,"D",-1); /* last logon */
2099 PACKI(&desc,"D",-1); /* last logoff */
2100 PACKI(&desc,"D",-1); /* logoff time */
2101 PACKI(&desc,"D",-1); /* kickoff time */
2102 PACKI(&desc,"D",0); /* password age */
2103 PACKI(&desc,"D",0); /* password can change */
2104 PACKI(&desc,"D",-1); /* password must change */
2107 strcpy(mypath,"\\\\");
2108 strcat(mypath,local_machine);
2110 PACKS(&desc,"z",mypath); /* computer */
2112 PACKS(&desc,"z",my_workgroup());/* domain */
2113 PACKS(&desc,"z",lp_logon_script()); /* script path */
2114 PACKI(&desc,"D",0); /* reserved */
2117 *rdata_len = desc.usedlen;
2119 *rparam = REALLOC(*rparam,*rparam_len);
2120 SSVALS(*rparam,0,desc.errcode);
2122 SSVAL(*rparam,4,desc.neededlen);
2124 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
2129 /****************************************************************************
2130 api_WAccessGetUserPerms
2131 ****************************************************************************/
2132 static BOOL api_WAccessGetUserPerms(int cnum,int uid, char *param,char *data,
2133 int mdrcnt,int mprcnt,
2134 char **rdata,char **rparam,
2135 int *rdata_len,int *rparam_len)
2137 char *str1 = param+2;
2138 char *str2 = skip_string(str1,1);
2139 char *user = skip_string(str2,1);
2140 char *resource = skip_string(user,1);
2142 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
2144 /* check it's a supported varient */
2145 if (strcmp(str1,"zzh") != 0) return False;
2146 if (strcmp(str2,"") != 0) return False;
2149 *rparam = REALLOC(*rparam,*rparam_len);
2150 SSVALS(*rparam,0,0); /* errorcode */
2151 SSVAL(*rparam,2,0); /* converter word */
2152 SSVAL(*rparam,4,0x7f); /* permission flags */
2157 /****************************************************************************
2158 api_WPrintJobEnumerate
2159 ****************************************************************************/
2160 static BOOL api_WPrintJobGetInfo(int cnum,int uid, char *param,char *data,
2161 int mdrcnt,int mprcnt,
2162 char **rdata,char **rparam,
2163 int *rdata_len,int *rparam_len)
2165 char *str1 = param+2;
2166 char *str2 = skip_string(str1,1);
2167 char *p = skip_string(str2,1);
2168 int uJobId = SVAL(p,0);
2174 struct pack_desc desc;
2175 print_queue_struct *queue=NULL;
2176 print_status_struct status;
2181 bzero(&desc,sizeof(desc));
2182 bzero(&status,sizeof(status));
2184 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,uJobId));
2186 /* check it's a supported varient */
2187 if (strcmp(str1,"WWrLh") != 0) return False;
2188 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2190 snum = (unsigned int)uJobId >> 8; /*## valid serice number??*/
2191 job = uJobId & 0xFF;
2193 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2195 count = get_printqueue(snum,cnum,&queue,&status);
2196 for (i = 0; i < count; i++) {
2197 if ((queue[i].job % 0xFF) == job) break;
2199 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2201 desc.buflen = mdrcnt;
2203 if (init_package(&desc,1,0)) {
2205 fill_printjob_info(cnum,snum,uLevel,&desc,&queue[i],i);
2206 *rdata_len = desc.usedlen;
2209 desc.errcode = NERR_JobNotFound;
2215 *rparam = REALLOC(*rparam,*rparam_len);
2216 SSVALS(*rparam,0,desc.errcode);
2218 SSVAL(*rparam,4,desc.neededlen);
2220 if (queue) free(queue);
2222 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
2226 static BOOL api_WPrintJobEnumerate(int cnum,int uid, char *param,char *data,
2227 int mdrcnt,int mprcnt,
2228 char **rdata,char **rparam,
2229 int *rdata_len,int *rparam_len)
2231 char *str1 = param+2;
2232 char *str2 = skip_string(str1,1);
2233 char *p = skip_string(str2,1);
2239 struct pack_desc desc;
2240 print_queue_struct *queue=NULL;
2241 print_status_struct status;
2243 bzero(&desc,sizeof(desc));
2244 bzero(&status,sizeof(status));
2246 p = skip_string(p,1);
2250 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
2252 /* check it's a supported varient */
2253 if (strcmp(str1,"zWrLeh") != 0) return False;
2254 if (uLevel > 2) return False; /* defined only for uLevel 0,1,2 */
2255 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2257 snum = lp_servicenumber(name);
2258 if (snum < 0 && pcap_printername_ok(name,NULL)) {
2259 int pnum = lp_servicenumber(PRINTERS_NAME);
2261 lp_add_printer(name,pnum);
2262 snum = lp_servicenumber(name);
2266 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2268 count = get_printqueue(snum,cnum,&queue,&status);
2269 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2271 desc.buflen = mdrcnt;
2273 if (init_package(&desc,count,0)) {
2275 for (i = 0; i < count; i++) {
2276 fill_printjob_info(cnum,snum,uLevel,&desc,&queue[i],i);
2277 if (desc.errcode == NERR_Success) succnt = i+1;
2281 *rdata_len = desc.usedlen;
2284 *rparam = REALLOC(*rparam,*rparam_len);
2285 SSVALS(*rparam,0,desc.errcode);
2287 SSVAL(*rparam,4,succnt);
2288 SSVAL(*rparam,6,count);
2290 if (queue) free(queue);
2292 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
2296 static int check_printdest_info(struct pack_desc* desc,
2297 int uLevel, char* id)
2299 desc->subformat = NULL;
2301 case 0: desc->format = "B9"; break;
2302 case 1: desc->format = "B9B21WWzW"; break;
2303 case 2: desc->format = "z"; break;
2304 case 3: desc->format = "zzzWWzzzWW"; break;
2305 default: return False;
2307 if (strcmp(desc->format,id) != 0) return False;
2311 static void fill_printdest_info(int cnum, int snum, int uLevel,
2312 struct pack_desc* desc)
2315 strcpy(buf,SERVICE(snum));
2318 PACKS(desc,"B9",buf); /* szName */
2320 PACKS(desc,"B21",""); /* szUserName */
2321 PACKI(desc,"W",0); /* uJobId */
2322 PACKI(desc,"W",0); /* fsStatus */
2323 PACKS(desc,"z",""); /* pszStatus */
2324 PACKI(desc,"W",0); /* time */
2327 if (uLevel == 2 || uLevel == 3) {
2328 PACKS(desc,"z",buf); /* pszPrinterName */
2330 PACKS(desc,"z",""); /* pszUserName */
2331 PACKS(desc,"z",""); /* pszLogAddr */
2332 PACKI(desc,"W",0); /* uJobId */
2333 PACKI(desc,"W",0); /* fsStatus */
2334 PACKS(desc,"z",""); /* pszStatus */
2335 PACKS(desc,"z",""); /* pszComment */
2336 PACKS(desc,"z","NULL"); /* pszDrivers */
2337 PACKI(desc,"W",0); /* time */
2338 PACKI(desc,"W",0); /* pad1 */
2343 static BOOL api_WPrintDestGetInfo(int cnum,int uid, char *param,char *data,
2344 int mdrcnt,int mprcnt,
2345 char **rdata,char **rparam,
2346 int *rdata_len,int *rparam_len)
2348 char *str1 = param+2;
2349 char *str2 = skip_string(str1,1);
2350 char *p = skip_string(str2,1);
2351 char* PrinterName = p;
2353 struct pack_desc desc;
2356 bzero(&desc,sizeof(desc));
2358 p = skip_string(p,1);
2362 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
2364 /* check it's a supported varient */
2365 if (strcmp(str1,"zWrLh") != 0) return False;
2366 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2368 snum = lp_servicenumber(PrinterName);
2369 if (snum < 0 && pcap_printername_ok(PrinterName,NULL)) {
2370 int pnum = lp_servicenumber(PRINTERS_NAME);
2372 lp_add_printer(PrinterName,pnum);
2373 snum = lp_servicenumber(PrinterName);
2379 desc.errcode = NERR_DestNotFound;
2383 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2385 desc.buflen = mdrcnt;
2386 if (init_package(&desc,1,0)) {
2387 fill_printdest_info(cnum,snum,uLevel,&desc);
2389 *rdata_len = desc.usedlen;
2393 *rparam = REALLOC(*rparam,*rparam_len);
2394 SSVALS(*rparam,0,desc.errcode);
2396 SSVAL(*rparam,4,desc.neededlen);
2398 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
2402 static BOOL api_WPrintDestEnum(int cnum,int uid, char *param,char *data,
2403 int mdrcnt,int mprcnt,
2404 char **rdata,char **rparam,
2405 int *rdata_len,int *rparam_len)
2407 char *str1 = param+2;
2408 char *str2 = skip_string(str1,1);
2409 char *p = skip_string(str2,1);
2413 struct pack_desc desc;
2414 int services = lp_numservices();
2416 bzero(&desc,sizeof(desc));
2421 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
2423 /* check it's a supported varient */
2424 if (strcmp(str1,"WrLeh") != 0) return False;
2425 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2428 for (i = 0; i < services; i++)
2429 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
2432 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2434 desc.buflen = mdrcnt;
2435 if (init_package(&desc,queuecnt,0)) {
2438 for (i = 0; i < services; i++) {
2439 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
2440 fill_printdest_info(cnum,i,uLevel,&desc);
2442 if (desc.errcode == NERR_Success) succnt = n;
2447 *rdata_len = desc.usedlen;
2450 *rparam = REALLOC(*rparam,*rparam_len);
2451 SSVALS(*rparam,0,desc.errcode);
2453 SSVAL(*rparam,4,succnt);
2454 SSVAL(*rparam,6,queuecnt);
2456 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
2460 static BOOL api_WPrintDriverEnum(int cnum,int uid, char *param,char *data,
2461 int mdrcnt,int mprcnt,
2462 char **rdata,char **rparam,
2463 int *rdata_len,int *rparam_len)
2465 char *str1 = param+2;
2466 char *str2 = skip_string(str1,1);
2467 char *p = skip_string(str2,1);
2470 struct pack_desc desc;
2472 bzero(&desc,sizeof(desc));
2477 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
2479 /* check it's a supported varient */
2480 if (strcmp(str1,"WrLeh") != 0) return False;
2481 if (uLevel != 0 || strcmp(str2,"B41") != 0) return False;
2483 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2485 desc.buflen = mdrcnt;
2486 if (init_package(&desc,1,0)) {
2487 PACKS(&desc,"B41","NULL");
2490 succnt = (desc.errcode == NERR_Success ? 1 : 0);
2492 *rdata_len = desc.usedlen;
2495 *rparam = REALLOC(*rparam,*rparam_len);
2496 SSVALS(*rparam,0,desc.errcode);
2498 SSVAL(*rparam,4,succnt);
2501 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
2505 static BOOL api_WPrintQProcEnum(int cnum,int uid, char *param,char *data,
2506 int mdrcnt,int mprcnt,
2507 char **rdata,char **rparam,
2508 int *rdata_len,int *rparam_len)
2510 char *str1 = param+2;
2511 char *str2 = skip_string(str1,1);
2512 char *p = skip_string(str2,1);
2515 struct pack_desc desc;
2517 bzero(&desc,sizeof(desc));
2522 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
2524 /* check it's a supported varient */
2525 if (strcmp(str1,"WrLeh") != 0) return False;
2526 if (uLevel != 0 || strcmp(str2,"B13") != 0) return False;
2528 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2530 desc.buflen = mdrcnt;
2532 if (init_package(&desc,1,0)) {
2533 PACKS(&desc,"B13","lpd");
2536 succnt = (desc.errcode == NERR_Success ? 1 : 0);
2538 *rdata_len = desc.usedlen;
2541 *rparam = REALLOC(*rparam,*rparam_len);
2542 SSVALS(*rparam,0,desc.errcode);
2544 SSVAL(*rparam,4,succnt);
2547 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
2551 static BOOL api_WPrintPortEnum(int cnum,int uid, char *param,char *data,
2552 int mdrcnt,int mprcnt,
2553 char **rdata,char **rparam,
2554 int *rdata_len,int *rparam_len)
2556 char *str1 = param+2;
2557 char *str2 = skip_string(str1,1);
2558 char *p = skip_string(str2,1);
2561 struct pack_desc desc;
2563 bzero(&desc,sizeof(desc));
2568 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
2570 /* check it's a supported varient */
2571 if (strcmp(str1,"WrLeh") != 0) return False;
2572 if (uLevel != 0 || strcmp(str2,"B9") != 0) return False;
2574 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2575 bzero(&desc,sizeof(desc));
2577 desc.buflen = mdrcnt;
2579 if (init_package(&desc,1,0)) {
2580 PACKS(&desc,"B13","lp0");
2583 succnt = (desc.errcode == NERR_Success ? 1 : 0);
2585 *rdata_len = desc.usedlen;
2588 *rparam = REALLOC(*rparam,*rparam_len);
2589 SSVALS(*rparam,0,desc.errcode);
2591 SSVAL(*rparam,4,succnt);
2594 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
2598 /****************************************************************************
2599 the buffer was too small
2600 ****************************************************************************/
2601 static BOOL api_TooSmall(int cnum,int uid, char *param,char *data,
2602 int mdrcnt,int mprcnt,
2603 char **rdata,char **rparam,
2604 int *rdata_len,int *rparam_len)
2606 *rparam_len = MIN(*rparam_len,mprcnt);
2607 *rparam = REALLOC(*rparam,*rparam_len);
2611 SSVAL(*rparam,0,NERR_BufTooSmall);
2613 DEBUG(3,("Supplied buffer too small in API command\n"));
2619 /****************************************************************************
2620 the request is not supported
2621 ****************************************************************************/
2622 static BOOL api_Unsupported(int cnum,int uid, char *param,char *data,
2623 int mdrcnt,int mprcnt,
2624 char **rdata,char **rparam,
2625 int *rdata_len,int *rparam_len)
2628 *rparam = REALLOC(*rparam,*rparam_len);
2632 SSVAL(*rparam,0,NERR_notsupported);
2633 SSVAL(*rparam,2,0); /* converter word */
2635 DEBUG(3,("Unsupported API command\n"));
2649 } api_commands[] = {
2650 {"RNetShareEnum", 0, api_RNetShareEnum,0},
2651 {"RNetShareGetInfo", 1, api_RNetShareGetInfo,0},
2652 {"RNetServerGetInfo", 13, api_RNetServerGetInfo,0},
2653 {"RNetUserGetInfo", 56, api_RNetUserGetInfo,0},
2654 {"NetUserGetGroups", 59, api_NetUserGetGroups,0},
2655 {"NetWkstaGetInfo", 63, api_NetWkstaGetInfo,0},
2656 {"DosPrintQEnum", 69, api_DosPrintQEnum,0},
2657 {"DosPrintQGetInfo", 70, api_DosPrintQGetInfo,0},
2658 {"WPrintJobEnumerate",76, api_WPrintJobEnumerate,0},
2659 {"WPrintJobGetInfo", 77, api_WPrintJobGetInfo,0},
2660 {"RDosPrintJobDel", 81, api_RDosPrintJobDel,0},
2661 {"RDosPrintJobPause", 82, api_RDosPrintJobDel,0},
2662 {"RDosPrintJobResume",83, api_RDosPrintJobDel,0},
2663 {"WPrintDestEnum", 84, api_WPrintDestEnum,0},
2664 {"WPrintDestGetInfo", 85, api_WPrintDestGetInfo,0},
2665 {"NetRemoteTOD", 91, api_NetRemoteTOD,0},
2666 {"WPrintQueuePurge", 103, api_WPrintQueuePurge,0},
2667 {"NetServerEnum", 104, api_RNetServerEnum,0},
2668 {"WAccessGetUserPerms",105, api_WAccessGetUserPerms,0},
2669 {"SetUserPassword", 115, api_SetUserPassword,0},
2670 {"WWkstaUserLogon", 132, api_WWkstaUserLogon,0},
2671 {"PrintJobInfo", 147, api_PrintJobInfo,0},
2672 {"WPrintDriverEnum", 205, api_WPrintDriverEnum,0},
2673 {"WPrintQProcEnum", 206, api_WPrintQProcEnum,0},
2674 {"WPrintPortEnum", 207, api_WPrintPortEnum,0},
2675 {NULL, -1, api_Unsupported,0}};
2678 /****************************************************************************
2679 handle remote api calls
2680 ****************************************************************************/
2681 static int api_reply(int cnum,int uid,char *outbuf,char *data,char *params,
2682 int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
2684 int api_command = SVAL(params,0);
2686 char *rparam = NULL;
2692 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
2693 api_command,params+2,skip_string(params+2,1),
2694 tdscnt,tpscnt,mdrcnt,mprcnt));
2696 for (i=0;api_commands[i].name;i++)
2697 if (api_commands[i].id == api_command && api_commands[i].fn)
2699 DEBUG(3,("Doing %s\n",api_commands[i].name));
2703 rdata = (char *)malloc(1024); if (rdata) bzero(rdata,1024);
2704 rparam = (char *)malloc(1024); if (rparam) bzero(rparam,1024);
2706 reply = api_commands[i].fn(cnum,uid,params,data,mdrcnt,mprcnt,
2707 &rdata,&rparam,&rdata_len,&rparam_len);
2710 if (rdata_len > mdrcnt ||
2711 rparam_len > mprcnt)
2713 reply = api_TooSmall(cnum,uid,params,data,mdrcnt,mprcnt,
2714 &rdata,&rparam,&rdata_len,&rparam_len);
2718 /* if we get False back then it's actually unsupported */
2720 api_Unsupported(cnum,uid,params,data,mdrcnt,mprcnt,
2721 &rdata,&rparam,&rdata_len,&rparam_len);
2725 /* now send the reply */
2726 send_trans_reply(outbuf,rdata,rparam,NULL,rdata_len,rparam_len,0);
2736 /****************************************************************************
2737 handle named pipe commands
2738 ****************************************************************************/
2739 static int named_pipe(int cnum,int uid, char *outbuf,char *name,
2740 uint16 *setup,char *data,char *params,
2741 int suwcnt,int tdscnt,int tpscnt,
2742 int msrcnt,int mdrcnt,int mprcnt)
2745 if (strequal(name,"LANMAN"))
2746 return(api_reply(cnum,uid,outbuf,data,params,tdscnt,tpscnt,mdrcnt,mprcnt));
2748 DEBUG(3,("named pipe command on <%s> 0x%X setup1=%d\n",
2749 name,(int)setup[0],(int)setup[1]));
2755 /****************************************************************************
2757 ****************************************************************************/
2758 int reply_trans(char *inbuf,char *outbuf)
2762 char *data=NULL,*params=NULL;
2766 int cnum = SVAL(inbuf,smb_tid);
2767 int uid = SVAL(inbuf,smb_uid);
2769 int tpscnt = SVAL(inbuf,smb_vwv0);
2770 int tdscnt = SVAL(inbuf,smb_vwv1);
2771 int mprcnt = SVAL(inbuf,smb_vwv2);
2772 int mdrcnt = SVAL(inbuf,smb_vwv3);
2773 int msrcnt = CVAL(inbuf,smb_vwv4);
2774 BOOL close_on_completion = BITSETW(inbuf+smb_vwv5,0);
2775 BOOL one_way = BITSETW(inbuf+smb_vwv5,1);
2776 int pscnt = SVAL(inbuf,smb_vwv9);
2777 int psoff = SVAL(inbuf,smb_vwv10);
2778 int dscnt = SVAL(inbuf,smb_vwv11);
2779 int dsoff = SVAL(inbuf,smb_vwv12);
2780 int suwcnt = CVAL(inbuf,smb_vwv13);
2782 StrnCpy(name,smb_buf(inbuf),sizeof(name)-1);
2786 data = (char *)malloc(tdscnt);
2787 memcpy(data,smb_base(inbuf)+dsoff,dscnt);
2791 params = (char *)malloc(tpscnt);
2792 memcpy(params,smb_base(inbuf)+psoff,pscnt);
2798 setup = (uint16 *)malloc(suwcnt*sizeof(setup[0]));
2799 for (i=0;i<suwcnt;i++)
2800 setup[i] = SVAL(inbuf,smb_vwv14+i*SIZEOFWORD);
2804 if (pscnt < tpscnt || dscnt < tdscnt)
2806 /* We need to send an interim response then receive the rest
2807 of the parameter/data bytes */
2808 outsize = set_message(outbuf,0,0,True);
2810 send_smb(Client,outbuf);
2813 /* receive the rest of the trans packet */
2814 while (pscnt < tpscnt || dscnt < tdscnt)
2816 int pcnt,poff,dcnt,doff,pdisp,ddisp;
2818 if (!receive_smb(Client,inbuf, SMB_SECONDARY_WAIT*1000) ||
2819 CVAL(inbuf, smb_com) != SMBtrans)
2821 DEBUG(2,("Invalid secondary trans2 packet\n"));
2822 if (params) free(params);
2823 if (data) free(data);
2824 if (setup) free(setup);
2825 return(ERROR(ERRSRV,ERRerror));
2830 tpscnt = SVAL(inbuf,smb_vwv0);
2831 tdscnt = SVAL(inbuf,smb_vwv1);
2833 pcnt = SVAL(inbuf,smb_vwv2);
2834 poff = SVAL(inbuf,smb_vwv3);
2835 pdisp = SVAL(inbuf,smb_vwv4);
2837 dcnt = SVAL(inbuf,smb_vwv5);
2838 doff = SVAL(inbuf,smb_vwv6);
2839 ddisp = SVAL(inbuf,smb_vwv7);
2845 memcpy(params+pdisp,smb_base(inbuf)+poff,pcnt);
2847 memcpy(data+ddisp,smb_base(inbuf)+doff,dcnt);
2851 DEBUG(3,("trans <%s> data=%d params=%d setup=%d\n",name,tdscnt,tpscnt,suwcnt));
2854 if (strncmp(name,"\\PIPE\\",strlen("\\PIPE\\")) == 0)
2855 outsize = named_pipe(cnum,uid,outbuf,name+strlen("\\PIPE\\"),setup,data,params,
2856 suwcnt,tdscnt,tpscnt,msrcnt,mdrcnt,mprcnt);
2859 if (data) free(data);
2860 if (params) free(params);
2861 if (setup) free(setup);
2863 if (close_on_completion)
2864 close_cnum(cnum,uid);
2870 return(ERROR(ERRSRV,ERRnosupport));