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
35 extern int DEBUGLEVEL;
37 extern files_struct Files[];
38 extern connection_struct Connections[];
40 extern fstring local_machine;
42 #define NERR_Success 0
43 #define NERR_badpass 86
44 #define NERR_notsupported 50
46 #define NERR_BASE (2100)
47 #define NERR_BufTooSmall (NERR_BASE+23)
48 #define NERR_JobNotFound (NERR_BASE+51)
49 #define NERR_DestNotFound (NERR_BASE+52)
50 #define ERROR_INVALID_LEVEL 124
51 #define ERROR_MORE_DATA 234
53 #define REALLOC(ptr,size) Realloc(ptr,MAX((size),4*1024))
55 #define ACCESS_READ 0x01
56 #define ACCESS_WRITE 0x02
57 #define ACCESS_CREATE 0x04
59 #define SHPWLEN 8 /* share password length */
60 #define NNLEN 12 /* 8.3 net name length */
61 #define SNLEN 15 /* service name length */
62 #define QNLEN 12 /* queue name maximum length */
66 static int CopyExpanded(int cnum, int snum, char** dst, char* src, int* n)
71 if (!src || !dst || !n || !(*dst)) return(0);
73 StrnCpy(buf,src,sizeof(buf)/2);
74 string_sub(buf,"%S",lp_servicename(snum));
75 standard_sub(cnum,buf);
83 static int CopyAndAdvance(char** dst, char* src, int* n)
86 if (!src || !dst || !n || !(*dst)) return(0);
94 static int StrlenExpanded(int cnum, int snum, char* s)
98 StrnCpy(buf,s,sizeof(buf)/2);
99 string_sub(buf,"%S",lp_servicename(snum));
100 standard_sub(cnum,buf);
101 return strlen(buf) + 1;
104 static char* Expand(int cnum, int snum, char* s)
107 if (!s) return(NULL);
108 StrnCpy(buf,s,sizeof(buf)/2);
109 string_sub(buf,"%S",lp_servicename(snum));
110 standard_sub(cnum,buf);
114 /*******************************************************************
115 check a API string for validity when we only need to check the prefix
116 ******************************************************************/
117 static BOOL prefix_ok(char *str,char *prefix)
119 return(strncmp(str,prefix,strlen(prefix)) == 0);
123 /****************************************************************************
125 ****************************************************************************/
126 static void send_trans_reply(char *outbuf,char *data,char *param,uint16 *setup,
127 int ldata,int lparam,int lsetup)
130 int this_ldata,this_lparam;
131 int tot_data=0,tot_param=0;
134 this_lparam = MIN(lparam,maxxmit - (500+lsetup*SIZEOFWORD)); /* hack */
135 this_ldata = MIN(ldata,maxxmit - (500+lsetup*SIZEOFWORD+this_lparam));
137 align = (this_lparam%4);
139 set_message(outbuf,10+lsetup,align+this_ldata+this_lparam,True);
141 memcpy(smb_buf(outbuf),param,this_lparam);
143 memcpy(smb_buf(outbuf)+this_lparam+align,data,this_ldata);
145 SSVAL(outbuf,smb_vwv0,lparam);
146 SSVAL(outbuf,smb_vwv1,ldata);
147 SSVAL(outbuf,smb_vwv3,this_lparam);
148 SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf),outbuf));
149 SSVAL(outbuf,smb_vwv5,0);
150 SSVAL(outbuf,smb_vwv6,this_ldata);
151 SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+this_lparam+align,outbuf));
152 SSVAL(outbuf,smb_vwv8,0);
153 SSVAL(outbuf,smb_vwv9,lsetup);
154 for (i=0;i<lsetup;i++)
155 SSVAL(outbuf,smb_vwv10+i*SIZEOFWORD,setup[i]);
158 send_smb(Client,outbuf);
160 tot_data = this_ldata;
161 tot_param = this_lparam;
163 while (tot_data < ldata || tot_param < lparam)
165 this_lparam = MIN(lparam-tot_param,maxxmit - 500); /* hack */
166 this_ldata = MIN(ldata-tot_data,maxxmit - (500+this_lparam));
168 align = (this_lparam%4);
170 set_message(outbuf,10,this_ldata+this_lparam+align,False);
172 memcpy(smb_buf(outbuf),param+tot_param,this_lparam);
174 memcpy(smb_buf(outbuf)+this_lparam+align,data+tot_data,this_ldata);
176 SSVAL(outbuf,smb_vwv3,this_lparam);
177 SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf),outbuf));
178 SSVAL(outbuf,smb_vwv5,tot_param);
179 SSVAL(outbuf,smb_vwv6,this_ldata);
180 SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+this_lparam+align,outbuf));
181 SSVAL(outbuf,smb_vwv8,tot_data);
182 SSVAL(outbuf,smb_vwv9,0);
185 send_smb(Client,outbuf);
187 tot_data += this_ldata;
188 tot_param += this_lparam;
194 /****************************************************************************
196 ****************************************************************************/
199 char* format; /* formatstring for structure */
200 char* subformat; /* subformat for structure */
201 char* base; /* baseaddress of buffer */
202 int buflen; /* remaining size for fixed part; on init: length of base */
203 int subcount; /* count of substructures */
204 char* structbuf; /* pointer into buffer for remaining fixed part */
205 int stringlen; /* remaining size for variable part */
206 char* stringbuf; /* pointer into buffer for remaining variable part */
207 int neededlen; /* total needed size */
208 int usedlen; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
209 char* curpos; /* current position; pointer into format or subformat */
213 static int get_counter(char** p)
216 if (!p || !(*p)) return(1);
217 if (!isdigit(**p)) return 1;
221 n = 10 * n + (i - '0');
228 static int getlen(char* p)
234 case 'W': /* word (2 byte) */
237 case 'N': /* count of substructures (word) at end */
240 case 'D': /* double word (4 byte) */
241 case 'z': /* offset to zero terminated string (4 byte) */
242 case 'l': /* offset to user data (4 byte) */
245 case 'b': /* offset to data (with counter) (4 byte) */
249 case 'B': /* byte (with optional counter) */
250 n += get_counter(&p);
257 static BOOL init_package(struct pack_desc* p, int count, int subcount)
262 if (!p->format || !p->base) return(False);
264 i = count * getlen(p->format);
265 if (p->subformat) i += subcount * getlen(p->subformat);
266 p->structbuf = p->base;
270 p->curpos = p->format;
273 p->errcode = NERR_BufTooSmall;
276 p->errcode = NERR_Success;
279 p->stringbuf = p->base + i;
281 return(p->errcode == NERR_Success);
285 static int package(struct pack_desc* p, ...)
288 static int package(va_alist)
294 int needed=0, stringneeded;
296 int is_string=0, stringused;
303 p = va_arg(args,struct pack_desc *);
308 p->curpos = p->format;
310 p->curpos = p->subformat;
315 str = va_arg(args,char*);
316 if (strncmp(str,p->curpos,strlen(str)) != 0) {
317 DEBUG(2,("type error in package: %s instead of %*s\n",str,
318 strlen(str),p->curpos));
328 if (!p->curpos) return(0);
330 switch( *p->curpos++ ) {
331 case 'W': /* word (2 byte) */
333 temp = va_arg(args,int);
334 if (p->buflen >= needed) SSVAL(p->structbuf,0,temp);
336 case 'N': /* count of substructures (word) at end */
338 p->subcount = va_arg(args,int);
339 if (p->buflen >= needed) SSVAL(p->structbuf,0,p->subcount);
341 case 'D': /* double word (4 byte) */
343 temp = va_arg(args,int);
344 if (p->buflen >= needed) SIVAL(p->structbuf,0,temp);
346 case 'B': /* byte (with optional counter) */
347 needed = get_counter(&p->curpos);
349 char *s = va_arg(args,char*);
350 if (p->buflen >= needed) StrnCpy(p->structbuf,s?s:"",needed);
353 case 'z': /* offset to zero terminated string (4 byte) */
354 str = va_arg(args,char*);
355 stringneeded = (str ? strlen(str)+1 : 0);
358 case 'l': /* offset to user data (4 byte) */
359 str = va_arg(args,char*);
360 stringneeded = va_arg(args,int);
363 case 'b': /* offset to data (with counter) (4 byte) */
364 str = va_arg(args,char*);
365 stringneeded = get_counter(&p->curpos);
370 if (stringneeded >= 0) {
372 if (p->buflen >= needed) {
373 stringused = stringneeded;
374 if (stringused > p->stringlen) {
375 stringused = (is_string ? p->stringlen : 0);
376 if (p->errcode == NERR_Success) p->errcode = ERROR_MORE_DATA;
379 SIVAL(p->structbuf,0,0);
381 SIVAL(p->structbuf,0,PTR_DIFF(p->stringbuf,p->base));
382 memcpy(p->stringbuf,str?str:"",stringused);
383 if (is_string) p->stringbuf[stringused-1] = '\0';
384 p->stringbuf += stringused;
385 p->stringlen -= stringused;
386 p->usedlen += stringused;
389 p->neededlen += stringneeded;
391 p->neededlen += needed;
392 if (p->buflen >= needed) {
393 p->structbuf += needed;
395 p->usedlen += needed;
398 if (p->errcode == NERR_Success) p->errcode = NERR_BufTooSmall;
404 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
405 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
407 #define PACK(desc,t,v) package(desc,v)
408 #define PACKl(desc,t,v,l) package(desc,v,l)
411 static void PACKI(struct pack_desc* desc,char *t,int v)
416 static void PACKS(struct pack_desc* desc,char *t,char *v)
421 static void PackDriverData(struct pack_desc* desc)
423 char drivdata[4+4+32];
424 SIVAL(drivdata,0,sizeof drivdata); /* cb */
425 SIVAL(drivdata,4,1000); /* lVersion */
426 memset(drivdata+8,0,32); /* szDeviceName */
427 strcpy(drivdata+8,"NULL");
428 PACKl(desc,"l",drivdata,sizeof drivdata); /* pDriverData */
431 static int check_printq_info(struct pack_desc* desc,
432 int uLevel, const char* id1, const char* id2)
434 desc->subformat = NULL;
437 desc->format = "B13";
440 desc->format = "B13BWWWzzzzzWW";
443 desc->format = "B13BWWWzzzzzWN";
444 desc->subformat = "WB21BB16B10zWWzDDz";
447 desc->format = "zWWWWzzzzWWzzl";
450 desc->format = "zWWWWzzzzWNzzl";
451 desc->subformat = "WWzWWDDzz";
456 default: return False;
458 if (strcmp(desc->format,id1) != 0) return False;
459 if (desc->subformat && strcmp(desc->subformat,id2) != 0) return False;
463 static void fill_printjob_info(int cnum, int snum, int uLevel,
464 struct pack_desc* desc,
465 print_queue_struct* queue, int n)
467 time_t t = queue->time;
469 /* the client expects localtime */
470 t += GMT_TO_LOCAL*TimeDiff(t);
472 PACKI(desc,"W",((snum%0xFF)<<8) | (queue->job%0xFF)); /* uJobId */
474 PACKS(desc,"B21",queue->user); /* szUserName */
475 PACKS(desc,"B",""); /* pad */
476 PACKS(desc,"B16",""); /* szNotifyName */
477 PACKS(desc,"B10","PM_Q_RAW"); /* szDataType */
478 PACKS(desc,"z",""); /* pszParms */
479 PACKI(desc,"W",n+1); /* uPosition */
480 PACKI(desc,"W",queue->status); /* fsStatus */
481 PACKS(desc,"z",""); /* pszStatus */
482 PACKI(desc,"D",queue->time); /* ulSubmitted */
483 PACKI(desc,"D",queue->size); /* ulSize */
484 PACKS(desc,"z",queue->file); /* pszComment */
486 if (uLevel == 2 || uLevel == 3) {
487 PACKI(desc,"W",queue->priority); /* uPriority */
488 PACKS(desc,"z",queue->user); /* pszUserName */
489 PACKI(desc,"W",n+1); /* uPosition */
490 PACKI(desc,"W",queue->status); /* fsStatus */
491 PACKI(desc,"D",queue->time); /* ulSubmitted */
492 PACKI(desc,"D",queue->size); /* ulSize */
493 PACKS(desc,"z","Samba"); /* pszComment */
494 PACKS(desc,"z",queue->file); /* pszDocument */
496 PACKS(desc,"z",""); /* pszNotifyName */
497 PACKS(desc,"z","PM_Q_RAW"); /* pszDataType */
498 PACKS(desc,"z",""); /* pszParms */
499 PACKS(desc,"z",""); /* pszStatus */
500 PACKS(desc,"z",SERVICE(snum)); /* pszQueue */
501 PACKS(desc,"z","lpd"); /* pszQProcName */
502 PACKS(desc,"z",""); /* pszQProcParms */
503 PACKS(desc,"z","NULL"); /* pszDriverName */
504 PackDriverData(desc); /* pDriverData */
505 PACKS(desc,"z",""); /* pszPrinterName */
510 static void fill_printq_info(int cnum, int snum, int uLevel,
511 struct pack_desc* desc,
512 int count, print_queue_struct* queue,
513 print_status_struct* status)
516 PACKS(desc,"B13",SERVICE(snum));
518 PACKS(desc,"z",Expand(cnum,snum,SERVICE(snum)));
520 if (uLevel == 1 || uLevel == 2) {
521 PACKS(desc,"B",""); /* alignment */
522 PACKI(desc,"W",5); /* priority */
523 PACKI(desc,"W",0); /* start time */
524 PACKI(desc,"W",0); /* until time */
525 PACKS(desc,"z",""); /* pSepFile */
526 PACKS(desc,"z","lpd"); /* pPrProc */
527 PACKS(desc,"z",SERVICE(snum)); /* pDestinations */
528 PACKS(desc,"z",""); /* pParms */
530 PACKS(desc,"z","UNKNOWN PRINTER");
531 PACKI(desc,"W",LPSTAT_ERROR);
533 else if (!status || !status->message[0]) {
534 PACKS(desc,"z",Expand(cnum,snum,lp_comment(snum)));
535 PACKI(desc,"W",LPSTAT_OK); /* status */
537 PACKS(desc,"z",status->message);
538 PACKI(desc,"W",status->status); /* status */
540 PACKI(desc,(uLevel == 1 ? "W" : "N"),count);
542 if (uLevel == 3 || uLevel == 4) {
543 PACKI(desc,"W",5); /* uPriority */
544 PACKI(desc,"W",0); /* uStarttime */
545 PACKI(desc,"W",0); /* uUntiltime */
546 PACKI(desc,"W",5); /* pad1 */
547 PACKS(desc,"z",""); /* pszSepFile */
548 PACKS(desc,"z","lpd"); /* pszPrProc */
549 PACKS(desc,"z",""); /* pszParms */
550 if (!status || !status->message[0]) {
551 PACKS(desc,"z",Expand(cnum,snum,lp_comment(snum))); /* pszComment */
552 PACKI(desc,"W",LPSTAT_OK); /* fsStatus */
554 PACKS(desc,"z",status->message); /* pszComment */
555 PACKI(desc,"W",status->status); /* fsStatus */
557 PACKI(desc,(uLevel == 3 ? "W" : "N"),count); /* cJobs */
558 PACKS(desc,"z",SERVICE(snum)); /* pszPrinters */
559 PACKS(desc,"z","NULL"); /* pszDriverName */
560 PackDriverData(desc); /* pDriverData */
562 if (uLevel == 2 || uLevel == 4) {
564 for (i=0;i<count;i++)
565 fill_printjob_info(cnum,snum,uLevel == 2 ? 1 : 2,desc,&queue[i],i);
568 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n",SERVICE(snum),count));
571 static BOOL api_DosPrintQGetInfo(int cnum,int uid, char *param,char *data,
572 int mdrcnt,int mprcnt,
573 char **rdata,char **rparam,
574 int *rdata_len,int *rparam_len)
576 char *str1 = param+2;
577 char *str2 = skip_string(str1,1);
578 char *p = skip_string(str2,1);
584 struct pack_desc desc;
585 print_queue_struct *queue=NULL;
586 print_status_struct status;
588 bzero(&status,sizeof(status));
589 bzero(&desc,sizeof(desc));
591 p = skip_string(p,1);
596 if ((p = strchr(QueueName,'%'))) *p = 0;
598 DEBUG(3,("PrintQueue uLevel=%d name=%s\n",uLevel,QueueName));
600 /* check it's a supported varient */
601 if (!prefix_ok(str1,"zWrLh")) return False;
602 if (!check_printq_info(&desc,uLevel,str2,str3)) return False;
604 snum = lp_servicenumber(QueueName);
605 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
606 int pnum = lp_servicenumber(PRINTERS_NAME);
608 lp_add_printer(QueueName,pnum);
609 snum = lp_servicenumber(QueueName);
613 if (snum < 0 || !VALID_SNUM(snum)) return(False);
615 count = get_printqueue(snum,cnum,&queue,&status);
616 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
618 desc.buflen = mdrcnt;
619 if (init_package(&desc,1,count)) {
620 desc.subcount = count;
621 fill_printq_info(cnum,snum,uLevel,&desc,count,queue,&status);
624 *rdata_len = desc.usedlen;
627 *rparam = REALLOC(*rparam,*rparam_len);
628 SSVALS(*rparam,0,desc.errcode);
630 SSVAL(*rparam,4,desc.neededlen);
632 DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode));
634 if (queue) free(queue);
640 /****************************************************************************
641 view list of all print jobs on all queues
642 ****************************************************************************/
643 static BOOL api_DosPrintQEnum(int cnum, int uid, char* param, char* data,
644 int mdrcnt, int mprcnt,
645 char **rdata, char** rparam,
646 int *rdata_len, int *rparam_len)
648 char *param_format = param+2;
649 char *output_format1 = skip_string(param_format,1);
650 char *p = skip_string(output_format1,1);
651 int uLevel = SVAL(p,0);
652 char *output_format2 = p + 4;
653 int services = lp_numservices();
655 struct pack_desc desc;
656 print_queue_struct **queue = NULL;
657 print_status_struct *status = NULL;
658 int* subcntarr = NULL;
659 int queuecnt, subcnt=0, succnt=0;
661 bzero(&desc,sizeof(desc));
663 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
665 if (prefix_ok(param_format,"WrLeh")) return False;
666 if (!check_printq_info(&desc,uLevel,output_format1,output_format2))
669 for (i = 0; i < services; i++)
670 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
673 queue = (print_queue_struct**)malloc(queuecnt*sizeof(print_queue_struct*));
674 memset(queue,0,queuecnt*sizeof(print_queue_struct*));
675 status = (print_status_struct*)malloc(queuecnt*sizeof(print_status_struct));
676 memset(status,0,queuecnt*sizeof(print_status_struct));
677 subcntarr = (int*)malloc(queuecnt*sizeof(int));
680 for (i = 0; i < services; i++)
681 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
682 subcntarr[n] = get_printqueue(i,cnum,&queue[n],&status[n]);
683 subcnt += subcntarr[n];
687 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
689 desc.buflen = mdrcnt;
691 if (init_package(&desc,queuecnt,subcnt)) {
694 for (i = 0; i < services; i++)
695 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
696 fill_printq_info(cnum,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]);
698 if (desc.errcode == NERR_Success) succnt = n;
702 if (subcntarr) free(subcntarr);
704 *rdata_len = desc.usedlen;
706 *rparam = REALLOC(*rparam,*rparam_len);
707 SSVALS(*rparam,0,desc.errcode);
709 SSVAL(*rparam,4,succnt);
710 SSVAL(*rparam,6,queuecnt);
712 for (i = 0; i < queuecnt; i++) {
713 if (queue && queue[i]) free(queue[i]);
716 if (queue) free(queue);
717 if (status) free(status);
722 /****************************************************************************
723 get info level for a server list query
724 ****************************************************************************/
725 static BOOL check_server_info(int uLevel, char* id)
729 if (strcmp(id,"B16") != 0) return False;
732 if (strcmp(id,"B16BBDz") != 0) return False;
740 /* used for server information: client, nameserv and ipc */
741 struct srv_info_struct
746 fstring domain; /* used ONLY in ipc.c NOT namework.c */
747 BOOL server_added; /* used ONLY in ipc.c NOT namework.c */
750 /*******************************************************************
751 filter out unwanted server info
752 ******************************************************************/
753 static BOOL filter_server_info(struct srv_info_struct *server,
757 return(strequal(domain, server->domain));
759 return (True); /* be indiscriminate: get all servers! */
762 /*******************************************************************
763 find server in the files saved by nmbd. Return True if we find it.
764 ******************************************************************/
765 static BOOL find_server(struct srv_info_struct *servers, int num_servers,
766 char *domain, char *name)
770 if (!servers || num_servers == 0) return (False);
772 for (count = 0; count < num_servers; count++) {
773 struct srv_info_struct *s;
777 if (strequal(name, s->name)) {
778 StrnCpy(domain, s->domain, sizeof(pstring)-1);
786 /*******************************************************************
787 get server info lists from the files saved by nmbd. Return the
789 ******************************************************************/
790 static int get_server_info(uint32 servertype,
791 struct srv_info_struct **servers)
799 strcpy(fname,lp_lockdir());
800 trim_string(fname,NULL,"/");
802 strcat(fname,SERVER_LIST);
804 f = fopen(fname,"r");
807 DEBUG(4,("Can't open %s - %s\n",fname,strerror(errno)));
810 if (servertype == SV_TYPE_ALL) servertype &= ~SV_TYPE_DOMAIN_ENUM;
815 struct srv_info_struct *s;
819 fgets(line,sizeof(line)-1,f);
820 if (!*line) continue;
822 if (count == alloced) {
824 (*servers) = (struct srv_info_struct *)
825 Realloc(*servers,sizeof(**servers)*alloced);
826 if (!(*servers)) return(0);
827 bzero((char *)((*servers)+count),sizeof(**servers)*(alloced-count));
829 s = &(*servers)[count];
831 s->server_added = True;
833 if (!next_token(&ptr,s->name , NULL)) continue;
834 if (!next_token(&ptr,stype , NULL)) continue;
835 if (!next_token(&ptr,s->comment, NULL)) continue;
836 if (!next_token(&ptr,s->domain , NULL)) {
837 /* this allows us to cop with an old nmbd */
838 strcpy(s->domain,my_workgroup());
841 if (sscanf(stype,"%X",&s->type) != 1) continue;
843 /* doesn't match up: don't want it */
844 if (!(servertype & s->type)) continue;
846 /* server entry is a domain, we haven't asked for domains: don't want it */
847 if ((s->type&SV_TYPE_DOMAIN_ENUM) && !(servertype&SV_TYPE_DOMAIN_ENUM))
850 DEBUG(4,("Server %20s %8x %25s %15s\n",
851 s->name, stype, s->comment, s->domain));
860 /*******************************************************************
861 fill in a server info structure
862 ******************************************************************/
863 static int fill_srv_info(struct srv_info_struct *service,
864 int uLevel, char **buf, int *buflen,
865 char **stringbuf, int *stringspace, char *baseaddr)
874 case 0: struct_len = 16; break;
875 case 1: struct_len = 26; break;
885 len = strlen(service->comment)+1;
889 if (buflen) *buflen = struct_len;
890 if (stringspace) *stringspace = len;
891 return struct_len + len;
896 if (*buflen < struct_len) return -1;
905 l2 = *buflen - struct_len;
907 if (!baseaddr) baseaddr = p;
912 StrnCpy(p,service->name,15);
916 StrnCpy(p,service->name,15);
917 SIVAL(p,18,service->type);
918 SIVAL(p,22,PTR_DIFF(p2,baseaddr));
919 len += CopyAndAdvance(&p2,service->comment,&l2);
925 *buf = p + struct_len;
926 *buflen -= struct_len;
939 /****************************************************************************
940 view list of servers available (or possibly domains). The info is
941 extracted from lists saved by nmbd on the local host
942 ****************************************************************************/
943 static BOOL api_RNetServerEnum(int cnum, int uid, char *param, char *data,
944 int mdrcnt, int mprcnt, char **rdata,
945 char **rparam, int *rdata_len, int *rparam_len)
947 char *str1 = param+2;
948 char *str2 = skip_string(str1,1);
949 char *p = skip_string(str2,1);
950 int uLevel = SVAL(p,0);
951 int buf_len = SVAL(p,2);
952 uint32 servertype = IVAL(p,4);
954 int data_len, fixed_len, string_len;
956 struct srv_info_struct *servers=NULL;
957 int counted=0,total=0;
960 BOOL domain_request = (servertype & SV_TYPE_DOMAIN_ENUM) &&
961 !(servertype == SV_TYPE_ALL);
966 if (!prefix_ok(str1,"WrLehD")) return False;
967 if (!check_server_info(uLevel,str2)) return False;
969 DEBUG(4, ("server request level: %s\n", str2));
971 if (strcmp(str1, "WrLehDO") == 0)
973 /* asking for servers. we will have to work out which workgroup was
974 requested, as we maintain lists for multiple workgroups */
976 else if (strcmp(str1, "WrLehDz") == 0)
978 /* asking for a specific workgroup */
979 StrnCpy(domain, p, sizeof(fstring)-1);
982 if (lp_browse_list())
984 total = get_server_info(servertype,&servers);
987 if (!domain[0] && !domain_request) {
988 extern fstring remote_machine;
989 /* must be a server request with an assumed domain. find a domain */
991 if (find_server(servers, total, domain, remote_machine)) {
992 DEBUG(4, ("No domain specified: using %s for %s\n",
993 domain, remote_machine));
995 /* default to soemthing sensible */
996 strcpy(domain,my_workgroup());
1000 data_len = fixed_len = string_len = 0;
1002 for (i=0;i<total;i++)
1003 if (filter_server_info(&servers[i],domain)) {
1004 data_len += fill_srv_info(&servers[i],uLevel,0,&f_len,0,&s_len,0);
1005 if (data_len <= buf_len)
1009 string_len += s_len;
1013 *rdata_len = fixed_len + string_len;
1014 *rdata = REALLOC(*rdata,*rdata_len);
1015 bzero(*rdata,*rdata_len);
1017 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1023 int count2 = counted;
1024 for (i = 0; i < total && count2;i++) {
1025 if (filter_server_info(&servers[i],domain)) {
1026 fill_srv_info(&servers[i],uLevel,&p,&f_len,&p2,&s_len,*rdata);
1033 *rparam = REALLOC(*rparam,*rparam_len);
1034 SSVAL(*rparam,0,NERR_Success);
1036 SSVAL(*rparam,4,counted);
1037 SSVAL(*rparam,6,total);
1039 if (servers) free(servers);
1041 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1042 domain,uLevel,counted,total));
1048 /****************************************************************************
1049 get info about a share
1050 ****************************************************************************/
1051 static BOOL check_share_info(int uLevel, char* id)
1055 if (strcmp(id,"B13") != 0) return False;
1058 if (strcmp(id,"B13BWz") != 0) return False;
1061 if (strcmp(id,"B13BWzWWWzB9B") != 0) return False;
1064 if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) return False;
1066 default: return False;
1071 static int fill_share_info(int cnum, int snum, int uLevel,
1072 char** buf, int* buflen,
1073 char** stringbuf, int* stringspace, char* baseaddr)
1082 case 0: struct_len = 13; break;
1083 case 1: struct_len = 20; break;
1084 case 2: struct_len = 40; break;
1085 case 91: struct_len = 68; break;
1093 if (uLevel > 0) len += StrlenExpanded(cnum,snum,lp_comment(snum));
1094 if (uLevel > 1) len += strlen(lp_pathname(snum)) + 1;
1095 if (buflen) *buflen = struct_len;
1096 if (stringspace) *stringspace = len;
1097 return struct_len + len;
1102 if ((*buflen) < struct_len) return -1;
1110 p2 = p + struct_len;
1111 l2 = (*buflen) - struct_len;
1113 if (!baseaddr) baseaddr = p;
1115 StrnCpy(p,lp_servicename(snum),13);
1121 type = STYPE_DISKTREE;
1122 if (lp_print_ok(snum)) type = STYPE_PRINTQ;
1123 if (strequal("IPC$",lp_servicename(snum))) type = STYPE_IPC;
1124 SSVAL(p,14,type); /* device type */
1125 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1126 len += CopyExpanded(cnum,snum,&p2,lp_comment(snum),&l2);
1131 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1132 SSVALS(p,22,-1); /* max uses */
1133 SSVAL(p,24,1); /* current uses */
1134 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1135 len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1136 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1141 memset(p+40,0,SHPWLEN+2);
1153 (*buf) = p + struct_len;
1154 (*buflen) -= struct_len;
1156 (*stringspace) = l2;
1166 static BOOL api_RNetShareGetInfo(int cnum,int uid, char *param,char *data,
1167 int mdrcnt,int mprcnt,
1168 char **rdata,char **rparam,
1169 int *rdata_len,int *rparam_len)
1171 char *str1 = param+2;
1172 char *str2 = skip_string(str1,1);
1173 char *netname = skip_string(str2,1);
1174 char *p = skip_string(netname,1);
1175 int uLevel = SVAL(p,0);
1176 int snum = find_service(netname);
1178 if (snum < 0) return False;
1180 /* check it's a supported varient */
1181 if (!prefix_ok(str1,"zWrLh")) return False;
1182 if (!check_share_info(uLevel,str2)) return False;
1184 *rdata = REALLOC(*rdata,mdrcnt);
1186 *rdata_len = fill_share_info(cnum,snum,uLevel,&p,&mdrcnt,0,0,0);
1187 if (*rdata_len < 0) return False;
1190 *rparam = REALLOC(*rparam,*rparam_len);
1191 SSVAL(*rparam,0,NERR_Success);
1192 SSVAL(*rparam,2,0); /* converter word */
1193 SSVAL(*rparam,4,*rdata_len);
1198 /****************************************************************************
1199 view list of shares available
1200 ****************************************************************************/
1201 static BOOL api_RNetShareEnum(int cnum,int uid, char *param,char *data,
1202 int mdrcnt,int mprcnt,
1203 char **rdata,char **rparam,
1204 int *rdata_len,int *rparam_len)
1206 char *str1 = param+2;
1207 char *str2 = skip_string(str1,1);
1208 char *p = skip_string(str2,1);
1209 int uLevel = SVAL(p,0);
1210 int buf_len = SVAL(p,2);
1212 int count=lp_numservices();
1213 int total=0,counted=0;
1215 int data_len, fixed_len, string_len;
1218 if (!prefix_ok(str1,"WrLeh")) return False;
1219 if (!check_share_info(uLevel,str2)) return False;
1221 data_len = fixed_len = string_len = 0;
1222 for (i=0;i<count;i++)
1223 if (lp_browseable(i) && lp_snum_ok(i))
1226 data_len += fill_share_info(cnum,i,uLevel,0,&f_len,0,&s_len,0);
1227 if (data_len <= buf_len)
1231 string_len += s_len;
1234 *rdata_len = fixed_len + string_len;
1235 *rdata = REALLOC(*rdata,*rdata_len);
1236 memset(*rdata,0,*rdata_len);
1238 p2 = (*rdata) + fixed_len; /* auxillery data (strings) will go here */
1242 for (i = 0; i < count;i++)
1243 if (lp_browseable(i) && lp_snum_ok(i))
1244 if (fill_share_info(cnum,i,uLevel,&p,&f_len,&p2,&s_len,*rdata) < 0)
1248 *rparam = REALLOC(*rparam,*rparam_len);
1249 SSVAL(*rparam,0,NERR_Success);
1251 SSVAL(*rparam,4,counted);
1252 SSVAL(*rparam,6,total);
1254 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1255 counted,total,uLevel,
1256 buf_len,*rdata_len,mdrcnt));
1262 /****************************************************************************
1263 get the time of day info
1264 ****************************************************************************/
1265 static BOOL api_NetRemoteTOD(int cnum,int uid, char *param,char *data,
1266 int mdrcnt,int mprcnt,
1267 char **rdata,char **rparam,
1268 int *rdata_len,int *rparam_len)
1272 *rparam = REALLOC(*rparam,*rparam_len);
1275 *rdata = REALLOC(*rdata,*rdata_len);
1277 SSVAL(*rparam,0,NERR_Success);
1278 SSVAL(*rparam,2,0); /* converter word */
1284 time_t unixdate = time(NULL);
1286 put_dos_date3(p,0,unixdate); /* this is the time that is looked at
1287 by NT in a "net time" operation,
1288 it seems to ignore the one below */
1290 /* the client expects to get localtime, not GMT, in this bit
1291 (I think, this needs testing) */
1292 t = LocalTime(&unixdate,GMT_TO_LOCAL);
1294 SIVAL(p,4,0); /* msecs ? */
1295 CVAL(p,8) = t->tm_hour;
1296 CVAL(p,9) = t->tm_min;
1297 CVAL(p,10) = t->tm_sec;
1298 CVAL(p,11) = 0; /* hundredths of seconds */
1299 SSVALS(p,12,TimeDiff(unixdate)/60); /* timezone in minutes from GMT */
1300 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
1301 CVAL(p,16) = t->tm_mday;
1302 CVAL(p,17) = t->tm_mon + 1;
1303 SSVAL(p,18,1900+t->tm_year);
1304 CVAL(p,20) = t->tm_wday;
1311 /****************************************************************************
1312 set the user password
1313 ****************************************************************************/
1314 static BOOL api_SetUserPassword(int cnum,int uid, char *param,char *data,
1315 int mdrcnt,int mprcnt,
1316 char **rdata,char **rparam,
1317 int *rdata_len,int *rparam_len)
1319 char *p = skip_string(param+2,2);
1321 fstring pass1,pass2;
1325 p = skip_string(p,1);
1327 StrnCpy(pass1,p,16);
1328 StrnCpy(pass2,p+16,16);
1331 *rparam = REALLOC(*rparam,*rparam_len);
1335 SSVAL(*rparam,0,NERR_Success);
1336 SSVAL(*rparam,2,0); /* converter word */
1338 DEBUG(3,("Set password for <%s>\n",user));
1340 if (!password_ok(user,pass1,strlen(pass1),NULL,False) ||
1341 !chgpasswd(user,pass1,pass2))
1342 SSVAL(*rparam,0,NERR_badpass);
1344 bzero(pass1,sizeof(fstring));
1345 bzero(pass2,sizeof(fstring));
1350 /****************************************************************************
1353 ****************************************************************************/
1354 static BOOL api_RDosPrintJobDel(int cnum,int uid, char *param,char *data,
1355 int mdrcnt,int mprcnt,
1356 char **rdata,char **rparam,
1357 int *rdata_len,int *rparam_len)
1359 int function = SVAL(param,0);
1360 char *str1 = param+2;
1361 char *str2 = skip_string(str1,1);
1362 char *p = skip_string(str2,1);
1363 int jobid = (SVAL(p,0)&0xFF); /* the snum and jobid are encoded
1364 by the print queue api */
1365 int snum = (SVAL(p,0)>>8);
1369 /* check it's a supported varient */
1370 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
1374 *rparam = REALLOC(*rparam,*rparam_len);
1378 SSVAL(*rparam,0,NERR_Success);
1380 if (snum >= 0 && VALID_SNUM(snum))
1382 print_queue_struct *queue=NULL;
1384 count = get_printqueue(snum,cnum,&queue,NULL);
1386 for (i=0;i<count;i++)
1387 if ((queue[i].job%0xFF) == jobid)
1390 case 81: /* delete */
1391 DEBUG(3,("Deleting queue entry %d\n",queue[i].job));
1392 del_printqueue(cnum,snum,queue[i].job);
1394 case 82: /* pause */
1395 case 83: /* resume */
1396 DEBUG(3,("%s queue entry %d\n",
1397 (function==82?"pausing":"resuming"),queue[i].job));
1398 status_printjob(cnum,snum,queue[i].job,
1399 (function==82?LPQ_PAUSED:LPQ_QUEUED));
1406 SSVAL(*rparam,0,NERR_JobNotFound);
1408 if (queue) free(queue);
1411 SSVAL(*rparam,2,0); /* converter word */
1416 static BOOL api_WPrintQueuePurge(int cnum,int uid, char *param,char *data,
1417 int mdrcnt,int mprcnt,
1418 char **rdata,char **rparam,
1419 int *rdata_len,int *rparam_len)
1421 char *str1 = param+2;
1422 char *str2 = skip_string(str1,1);
1423 char *QueueName = skip_string(str2,1);
1426 /* check it's a supported varient */
1427 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
1431 *rparam = REALLOC(*rparam,*rparam_len);
1435 SSVAL(*rparam,0,NERR_Success);
1436 SSVAL(*rparam,2,0); /* converter word */
1438 snum = lp_servicenumber(QueueName);
1439 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
1440 int pnum = lp_servicenumber(PRINTERS_NAME);
1442 lp_add_printer(QueueName,pnum);
1443 snum = lp_servicenumber(QueueName);
1447 if (snum >= 0 && VALID_SNUM(snum)) {
1448 print_queue_struct *queue=NULL;
1452 count = get_printqueue(snum,cnum,&queue,NULL);
1453 for (i = 0; i < count; i++)
1454 del_printqueue(cnum,snum,queue[i].job);
1456 if (queue) free(queue);
1459 DEBUG(3,("Print queue purge, queue=%s\n",QueueName));
1465 /****************************************************************************
1466 set the property of a print job (undocumented?)
1467 ? function = 0xb -> set name of print job
1468 ? function = 0x6 -> move print job up/down
1469 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
1470 or <WWsTP> <WB21BB16B10zWWzDDz>
1471 ****************************************************************************/
1472 static int check_printjob_info(struct pack_desc* desc,
1473 int uLevel, char* id)
1475 desc->subformat = NULL;
1477 case 0: desc->format = "W"; break;
1478 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
1479 case 2: desc->format = "WWzWWDDzz"; break;
1480 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
1481 default: return False;
1483 if (strcmp(desc->format,id) != 0) return False;
1487 static BOOL api_PrintJobInfo(int cnum,int uid,char *param,char *data,
1488 int mdrcnt,int mprcnt,
1489 char **rdata,char **rparam,
1490 int *rdata_len,int *rparam_len)
1492 struct pack_desc desc;
1493 char *str1 = param+2;
1494 char *str2 = skip_string(str1,1);
1495 char *p = skip_string(str2,1);
1496 int jobid = (SVAL(p,0)&0xFF); /* the snum and jobid are encoded
1497 by the print queue api */
1498 int snum = (SVAL(p,0)>>8);
1499 int uLevel = SVAL(p,2);
1500 int function = SVAL(p,4); /* what is this ?? */
1505 *rparam = REALLOC(*rparam,*rparam_len);
1509 /* check it's a supported varient */
1510 if ((strcmp(str1,"WWsTP")) || (!check_printjob_info(&desc,uLevel,str2)))
1514 case 0x6: /* change job place in the queue, data gives the new place */
1515 if (snum >= 0 && VALID_SNUM(snum))
1517 print_queue_struct *queue=NULL;
1521 count = get_printqueue(snum,cnum,&queue,NULL);
1522 for (i=0;i<count;i++) /* find job */
1523 if ((queue[i].job%0xFF) == jobid) break;
1526 desc.errcode=NERR_JobNotFound;
1527 if (queue) free(queue);
1530 desc.errcode=NERR_Success;
1534 int place= SVAL(data,0);
1535 /* we currently have no way of doing this. Can any unix do it? */
1536 if (i < place) /* move down */;
1537 else if (i > place ) /* move up */;
1540 desc.errcode=NERR_notsupported; /* not yet supported */
1541 if (queue) free(queue);
1544 else desc.errcode=NERR_JobNotFound;
1546 case 0xb: /* change print job name, data gives the name */
1547 /* jobid, snum should be zero */
1554 if (isalnum(*s) || strchr("-._",*s))
1560 DEBUG(3,("Setting print name to %s\n",name));
1562 for (i=0;i<MAX_OPEN_FILES;i++)
1563 if (Files[i].open && Files[i].print_file)
1569 if (!become_user(Files[i].cnum,uid) ||
1570 !become_service(Files[i].cnum,True))
1573 if (sys_rename(Files[i].name,name) == 0)
1574 string_set(&Files[i].name,name);
1578 desc.errcode=NERR_Success;
1581 default: /* not implemented */
1585 SSVALS(*rparam,0,desc.errcode);
1586 SSVAL(*rparam,2,0); /* converter word */
1592 /****************************************************************************
1593 get info about the server
1594 ****************************************************************************/
1595 static BOOL api_RNetServerGetInfo(int cnum,int uid, char *param,char *data,
1596 int mdrcnt,int mprcnt,
1597 char **rdata,char **rparam,
1598 int *rdata_len,int *rparam_len)
1600 char *str1 = param+2;
1601 char *str2 = skip_string(str1,1);
1602 char *p = skip_string(str2,1);
1603 int uLevel = SVAL(p,0);
1607 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
1609 /* check it's a supported varient */
1610 if (!prefix_ok(str1,"WrLh")) return False;
1613 if (strcmp(str2,"B16") != 0) return False;
1617 if (strcmp(str2,"B16BBDz") != 0) return False;
1621 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")
1626 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz")
1631 if (strcmp(str2,"DN") != 0) return False;
1635 if (strcmp(str2,"B16BBDzWWzzz") != 0) return False;
1638 default: return False;
1641 *rdata_len = mdrcnt;
1642 *rdata = REALLOC(*rdata,*rdata_len);
1645 p2 = p + struct_len;
1647 StrnCpy(p,local_machine,16);
1653 struct srv_info_struct *servers=NULL;
1656 uint32 servertype=SV_TYPE_SERVER_UNIX|SV_TYPE_WORKSTATION|
1657 SV_TYPE_SERVER|SV_TYPE_TIME_SOURCE;
1659 strcpy(comment,lp_serverstring());
1661 if ((count=get_server_info(SV_TYPE_ALL,&servers))>0) {
1662 for (i=0;i<count;i++)
1663 if (strequal(servers[i].name,local_machine)) {
1664 servertype = servers[i].type;
1665 strcpy(comment,servers[i].comment);
1668 if (servers) free(servers);
1670 SCVAL(p,0,2); /* version_major */
1671 SCVAL(p,1,0); /* version_minor */
1672 SIVAL(p,2,servertype);
1673 if (mdrcnt == struct_len) {
1676 SIVAL(p,6,PTR_DIFF(p2,*rdata));
1677 standard_sub(cnum,comment);
1678 StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
1679 p2 = skip_string(p2,1);
1684 return False; /* not yet implemented */
1687 *rdata_len = PTR_DIFF(p2,*rdata);
1690 *rparam = REALLOC(*rparam,*rparam_len);
1691 SSVAL(*rparam,0,NERR_Success);
1692 SSVAL(*rparam,2,0); /* converter word */
1693 SSVAL(*rparam,4,*rdata_len);
1699 /****************************************************************************
1700 get info about the server
1701 ****************************************************************************/
1702 static BOOL api_NetWkstaGetInfo(int cnum,int uid, char *param,char *data,
1703 int mdrcnt,int mprcnt,
1704 char **rdata,char **rparam,
1705 int *rdata_len,int *rparam_len)
1707 char *str1 = param+2;
1708 char *str2 = skip_string(str1,1);
1709 char *p = skip_string(str2,1);
1711 extern pstring sesssetup_user;
1712 int level = SVAL(p,0);
1714 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
1717 *rparam = REALLOC(*rparam,*rparam_len);
1719 /* check it's a supported varient */
1720 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz")))
1723 *rdata_len = mdrcnt + 1024;
1724 *rdata = REALLOC(*rdata,*rdata_len);
1726 SSVAL(*rparam,0,NERR_Success);
1727 SSVAL(*rparam,2,0); /* converter word */
1732 SIVAL(p,0,PTR_DIFF(p2,*rdata));
1733 strcpy(p2,local_machine);
1734 p2 = skip_string(p2,1);
1737 SIVAL(p,0,PTR_DIFF(p2,*rdata));
1738 strcpy(p2,sesssetup_user);
1739 p2 = skip_string(p2,1);
1742 SIVAL(p,0,PTR_DIFF(p2,*rdata));
1743 strcpy(p2,my_workgroup());
1744 p2 = skip_string(p2,1);
1747 SCVAL(p,0,2); /* major version?? */
1748 SCVAL(p,1,1); /* minor version?? */
1751 SIVAL(p,0,PTR_DIFF(p2,*rdata));
1752 strcpy(p2,my_workgroup()); /* login domain?? */
1753 p2 = skip_string(p2,1);
1756 SIVAL(p,0,PTR_DIFF(p2,*rdata));
1758 p2 = skip_string(p2,1);
1761 *rdata_len = PTR_DIFF(p2,*rdata);
1763 SSVAL(*rparam,4,*rdata_len);
1769 /****************************************************************************
1770 get info about a user
1771 ****************************************************************************/
1773 #define USER_PRIV_GUEST 0
1774 #define USER_PRIV_USER 1
1775 #define USER_PRIV_ADMIN 2
1777 static BOOL api_RNetUserGetInfo(int cnum,int uid, char *param,char *data,
1778 int mdrcnt,int mprcnt,
1779 char **rdata,char **rparam,
1780 int *rdata_len,int *rparam_len)
1782 char *str1 = param+2;
1783 char *str2 = skip_string(str1,1);
1784 char *UserName = skip_string(str2,1);
1785 char *p = skip_string(UserName,1);
1786 int uLevel = SVAL(p,0);
1790 *rparam = REALLOC(*rparam,*rparam_len);
1792 /* check it's a supported varient */
1793 if (strcmp(str1,"zWrLh") != 0) return False;
1795 case 0: p2 = "B21"; break;
1796 case 1: p2 = "B21BB16DWzzWz"; break;
1797 case 2: p2 = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
1798 case 10: p2 = "B21Bzzz"; break;
1799 case 11: p2 = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
1800 default: return False;
1802 if (strcmp(p2,str2) != 0) return False;
1804 *rdata_len = mdrcnt + 1024;
1805 *rdata = REALLOC(*rdata,*rdata_len);
1807 SSVAL(*rparam,0,NERR_Success);
1808 SSVAL(*rparam,2,0); /* converter word */
1819 SIVAL(p,22,PTR_DIFF(p2,p)); /* comment */
1820 strcpy(p2,"<Comment>");
1821 p2 = skip_string(p2,1);
1822 SIVAL(p,26,PTR_DIFF(p2,p)); /* user_comment */
1823 strcpy(p2,"<UserComment>");
1824 p2 = skip_string(p2,1);
1825 SIVAL(p,30,PTR_DIFF(p2,p)); /* full name */
1826 strcpy(p2,"<FullName>");
1827 p2 = skip_string(p2,1);
1829 if (uLevel == 11) { /* modelled after NTAS 3.51 reply */
1830 SSVAL(p,34,USER_PRIV_USER); /* user privilege */
1831 SIVAL(p,36,0); /* auth flags */
1832 SIVALS(p,40,-1); /* password age */
1833 SIVAL(p,44,PTR_DIFF(p2,p)); /* home dir */
1834 strcpy(p2,"\\\\%L\\HOMES");
1835 standard_sub_basic(p2);
1836 p2 = skip_string(p2,1);
1837 SIVAL(p,48,PTR_DIFF(p2,p)); /* parms */
1839 p2 = skip_string(p2,1);
1840 SIVAL(p,52,0); /* last logon */
1841 SIVAL(p,56,0); /* last logoff */
1842 SSVALS(p,60,-1); /* bad pw counts */
1843 SSVALS(p,62,-1); /* num logons */
1844 SIVAL(p,64,PTR_DIFF(p2,p)); /* logon server */
1846 p2 = skip_string(p2,1);
1847 SSVAL(p,68,0); /* country code */
1849 SIVAL(p,70,PTR_DIFF(p2,p)); /* workstations */
1851 p2 = skip_string(p2,1);
1853 SIVALS(p,74,-1); /* max storage */
1854 SSVAL(p,78,168); /* units per week */
1855 SIVAL(p,80,PTR_DIFF(p2,p)); /* logon hours */
1857 SCVAL(p2,21,0); /* fix zero termination */
1858 p2 = skip_string(p2,1);
1860 SSVAL(p,84,0); /* code page */
1862 if (uLevel == 1 || uLevel == 2) {
1863 memset(p+22,' ',16); /* password */
1864 SIVALS(p,38,-1); /* password age */
1865 SSVAL(p,42,USER_PRIV_ADMIN); /* user privilege */
1866 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
1867 strcpy(p2,"\\\\%L\\HOMES");
1868 standard_sub_basic(p2);
1869 p2 = skip_string(p2,1);
1870 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
1872 SSVAL(p,52,0); /* flags */
1873 SIVAL(p,54,0); /* script_path */
1875 SIVAL(p,60,0); /* auth_flags */
1876 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
1877 strcpy(p2,"<Full Name>");
1878 p2 = skip_string(p2,1);
1879 SIVAL(p,68,0); /* urs_comment */
1880 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
1882 p2 = skip_string(p2,1);
1883 SIVAL(p,76,0); /* workstations */
1884 SIVAL(p,80,0); /* last_logon */
1885 SIVAL(p,84,0); /* last_logoff */
1886 SIVALS(p,88,-1); /* acct_expires */
1887 SIVALS(p,92,-1); /* max_storage */
1888 SSVAL(p,96,168); /* units_per_week */
1889 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
1892 SSVALS(p,102,-1); /* bad_pw_count */
1893 SSVALS(p,104,-1); /* num_logons */
1894 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
1895 strcpy(p2,"\\\\%L");
1896 standard_sub_basic(p2);
1897 p2 = skip_string(p2,1);
1898 SSVAL(p,110,49); /* country_code */
1899 SSVAL(p,112,860); /* code page */
1904 *rdata_len = PTR_DIFF(p2,*rdata);
1906 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
1912 /*******************************************************************
1913 get groups that a user is a member of
1914 ******************************************************************/
1915 static BOOL api_NetUserGetGroups(int cnum,int uid, char *param,char *data,
1916 int mdrcnt,int mprcnt,
1917 char **rdata,char **rparam,
1918 int *rdata_len,int *rparam_len)
1920 char *str1 = param+2;
1921 char *str2 = skip_string(str1,1);
1922 char *UserName = skip_string(str2,1);
1923 char *p = skip_string(UserName,1);
1924 int uLevel = SVAL(p,0);
1929 *rparam = REALLOC(*rparam,*rparam_len);
1931 /* check it's a supported varient */
1932 if (strcmp(str1,"zWrLeh") != 0) return False;
1934 case 0: p2 = "B21"; break;
1935 default: return False;
1937 if (strcmp(p2,str2) != 0) return False;
1939 *rdata_len = mdrcnt + 1024;
1940 *rdata = REALLOC(*rdata,*rdata_len);
1942 SSVAL(*rparam,0,NERR_Success);
1943 SSVAL(*rparam,2,0); /* converter word */
1947 /* XXXX we need a real SAM database some day */
1948 strcpy(p,"Users"); p += 21; count++;
1949 strcpy(p,"Domain Users"); p += 21; count++;
1950 strcpy(p,"Guests"); p += 21; count++;
1951 strcpy(p,"Domain Guests"); p += 21; count++;
1953 *rdata_len = PTR_DIFF(p,*rdata);
1955 SSVAL(*rparam,4,count); /* is this right?? */
1956 SSVAL(*rparam,6,count); /* is this right?? */
1962 static BOOL api_WWkstaUserLogon(int cnum,int uid, char *param,char *data,
1963 int mdrcnt,int mprcnt,
1964 char **rdata,char **rparam,
1965 int *rdata_len,int *rparam_len)
1967 char *str1 = param+2;
1968 char *str2 = skip_string(str1,1);
1969 char *p = skip_string(str2,1);
1971 struct pack_desc desc;
1977 bzero(&desc,sizeof(desc));
1979 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
1981 /* check it's a supported varient */
1982 if (strcmp(str1,"OOWb54WrLh") != 0) return False;
1983 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) return False;
1984 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
1986 desc.buflen = mdrcnt;
1987 desc.subformat = NULL;
1992 if (init_package(&desc,1,0)) {
1993 PACKI(&desc,"W",0); /* code */
1994 PACKS(&desc,"B21",name); /* eff. name */
1995 PACKS(&desc,"B",""); /* pad */
1997 Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
1998 PACKI(&desc,"D",0); /* auth flags XXX */
1999 PACKI(&desc,"W",0); /* num logons */
2000 PACKI(&desc,"W",0); /* bad pw count */
2001 PACKI(&desc,"D",-1); /* last logon */
2002 PACKI(&desc,"D",-1); /* last logoff */
2003 PACKI(&desc,"D",-1); /* logoff time */
2004 PACKI(&desc,"D",-1); /* kickoff time */
2005 PACKI(&desc,"D",0); /* password age */
2006 PACKI(&desc,"D",0); /* password can change */
2007 PACKI(&desc,"D",-1); /* password must change */
2010 strcpy(mypath,"\\\\");
2011 strcat(mypath,local_machine);
2013 PACKS(&desc,"z",mypath); /* computer */
2015 PACKS(&desc,"z",my_workgroup());/* domain */
2016 PACKS(&desc,"z",lp_logon_script()); /* script path */
2017 PACKI(&desc,"D",0); /* reserved */
2020 *rdata_len = desc.usedlen;
2022 *rparam = REALLOC(*rparam,*rparam_len);
2023 SSVALS(*rparam,0,desc.errcode);
2025 SSVAL(*rparam,4,desc.neededlen);
2027 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
2032 /****************************************************************************
2033 api_WAccessGetUserPerms
2034 ****************************************************************************/
2035 static BOOL api_WAccessGetUserPerms(int cnum,int uid, char *param,char *data,
2036 int mdrcnt,int mprcnt,
2037 char **rdata,char **rparam,
2038 int *rdata_len,int *rparam_len)
2040 char *str1 = param+2;
2041 char *str2 = skip_string(str1,1);
2042 char *user = skip_string(str2,1);
2043 char *resource = skip_string(user,1);
2045 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
2047 /* check it's a supported varient */
2048 if (strcmp(str1,"zzh") != 0) return False;
2049 if (strcmp(str2,"") != 0) return False;
2052 *rparam = REALLOC(*rparam,*rparam_len);
2053 SSVALS(*rparam,0,0); /* errorcode */
2054 SSVAL(*rparam,2,0); /* converter word */
2055 SSVAL(*rparam,4,0x7f); /* permission flags */
2060 /****************************************************************************
2061 api_WPrintJobEnumerate
2062 ****************************************************************************/
2063 static BOOL api_WPrintJobGetInfo(int cnum,int uid, char *param,char *data,
2064 int mdrcnt,int mprcnt,
2065 char **rdata,char **rparam,
2066 int *rdata_len,int *rparam_len)
2068 char *str1 = param+2;
2069 char *str2 = skip_string(str1,1);
2070 char *p = skip_string(str2,1);
2071 int uJobId = SVAL(p,0);
2077 struct pack_desc desc;
2078 print_queue_struct *queue=NULL;
2079 print_status_struct status;
2084 bzero(&desc,sizeof(desc));
2085 bzero(&status,sizeof(status));
2087 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,uJobId));
2089 /* check it's a supported varient */
2090 if (strcmp(str1,"WWrLh") != 0) return False;
2091 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2093 snum = (unsigned int)uJobId >> 8; /*## valid serice number??*/
2094 job = uJobId & 0xFF;
2096 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2098 count = get_printqueue(snum,cnum,&queue,&status);
2099 for (i = 0; i < count; i++) {
2100 if ((queue[i].job % 0xFF) == job) break;
2102 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2104 desc.buflen = mdrcnt;
2106 if (init_package(&desc,1,0)) {
2108 fill_printjob_info(cnum,snum,uLevel,&desc,&queue[i],i);
2109 *rdata_len = desc.usedlen;
2112 desc.errcode = NERR_JobNotFound;
2118 *rparam = REALLOC(*rparam,*rparam_len);
2119 SSVALS(*rparam,0,desc.errcode);
2121 SSVAL(*rparam,4,desc.neededlen);
2123 if (queue) free(queue);
2125 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
2129 static BOOL api_WPrintJobEnumerate(int cnum,int uid, char *param,char *data,
2130 int mdrcnt,int mprcnt,
2131 char **rdata,char **rparam,
2132 int *rdata_len,int *rparam_len)
2134 char *str1 = param+2;
2135 char *str2 = skip_string(str1,1);
2136 char *p = skip_string(str2,1);
2142 struct pack_desc desc;
2143 print_queue_struct *queue=NULL;
2144 print_status_struct status;
2146 bzero(&desc,sizeof(desc));
2147 bzero(&status,sizeof(status));
2149 p = skip_string(p,1);
2153 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
2155 /* check it's a supported varient */
2156 if (strcmp(str1,"zWrLeh") != 0) return False;
2157 if (uLevel > 2) return False; /* defined only for uLevel 0,1,2 */
2158 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2160 snum = lp_servicenumber(name);
2161 if (snum < 0 && pcap_printername_ok(name,NULL)) {
2162 int pnum = lp_servicenumber(PRINTERS_NAME);
2164 lp_add_printer(name,pnum);
2165 snum = lp_servicenumber(name);
2169 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2171 count = get_printqueue(snum,cnum,&queue,&status);
2172 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2174 desc.buflen = mdrcnt;
2176 if (init_package(&desc,count,0)) {
2178 for (i = 0; i < count; i++) {
2179 fill_printjob_info(cnum,snum,uLevel,&desc,&queue[i],i);
2180 if (desc.errcode == NERR_Success) succnt = i+1;
2184 *rdata_len = desc.usedlen;
2187 *rparam = REALLOC(*rparam,*rparam_len);
2188 SSVALS(*rparam,0,desc.errcode);
2190 SSVAL(*rparam,4,succnt);
2191 SSVAL(*rparam,6,count);
2193 if (queue) free(queue);
2195 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
2199 static int check_printdest_info(struct pack_desc* desc,
2200 int uLevel, char* id)
2202 desc->subformat = NULL;
2204 case 0: desc->format = "B9"; break;
2205 case 1: desc->format = "B9B21WWzW"; break;
2206 case 2: desc->format = "z"; break;
2207 case 3: desc->format = "zzzWWzzzWW"; break;
2208 default: return False;
2210 if (strcmp(desc->format,id) != 0) return False;
2214 static void fill_printdest_info(int cnum, int snum, int uLevel,
2215 struct pack_desc* desc)
2218 strcpy(buf,SERVICE(snum));
2221 PACKS(desc,"B9",buf); /* szName */
2223 PACKS(desc,"B21",""); /* szUserName */
2224 PACKI(desc,"W",0); /* uJobId */
2225 PACKI(desc,"W",0); /* fsStatus */
2226 PACKS(desc,"z",""); /* pszStatus */
2227 PACKI(desc,"W",0); /* time */
2230 if (uLevel == 2 || uLevel == 3) {
2231 PACKS(desc,"z",buf); /* pszPrinterName */
2233 PACKS(desc,"z",""); /* pszUserName */
2234 PACKS(desc,"z",""); /* pszLogAddr */
2235 PACKI(desc,"W",0); /* uJobId */
2236 PACKI(desc,"W",0); /* fsStatus */
2237 PACKS(desc,"z",""); /* pszStatus */
2238 PACKS(desc,"z",""); /* pszComment */
2239 PACKS(desc,"z","NULL"); /* pszDrivers */
2240 PACKI(desc,"W",0); /* time */
2241 PACKI(desc,"W",0); /* pad1 */
2246 static BOOL api_WPrintDestGetInfo(int cnum,int uid, char *param,char *data,
2247 int mdrcnt,int mprcnt,
2248 char **rdata,char **rparam,
2249 int *rdata_len,int *rparam_len)
2251 char *str1 = param+2;
2252 char *str2 = skip_string(str1,1);
2253 char *p = skip_string(str2,1);
2254 char* PrinterName = p;
2256 struct pack_desc desc;
2259 bzero(&desc,sizeof(desc));
2261 p = skip_string(p,1);
2265 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
2267 /* check it's a supported varient */
2268 if (strcmp(str1,"zWrLh") != 0) return False;
2269 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2271 snum = lp_servicenumber(PrinterName);
2272 if (snum < 0 && pcap_printername_ok(PrinterName,NULL)) {
2273 int pnum = lp_servicenumber(PRINTERS_NAME);
2275 lp_add_printer(PrinterName,pnum);
2276 snum = lp_servicenumber(PrinterName);
2282 desc.errcode = NERR_DestNotFound;
2286 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2288 desc.buflen = mdrcnt;
2289 if (init_package(&desc,1,0)) {
2290 fill_printdest_info(cnum,snum,uLevel,&desc);
2292 *rdata_len = desc.usedlen;
2296 *rparam = REALLOC(*rparam,*rparam_len);
2297 SSVALS(*rparam,0,desc.errcode);
2299 SSVAL(*rparam,4,desc.neededlen);
2301 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
2305 static BOOL api_WPrintDestEnum(int cnum,int uid, char *param,char *data,
2306 int mdrcnt,int mprcnt,
2307 char **rdata,char **rparam,
2308 int *rdata_len,int *rparam_len)
2310 char *str1 = param+2;
2311 char *str2 = skip_string(str1,1);
2312 char *p = skip_string(str2,1);
2316 struct pack_desc desc;
2317 int services = lp_numservices();
2319 bzero(&desc,sizeof(desc));
2324 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
2326 /* check it's a supported varient */
2327 if (strcmp(str1,"WrLeh") != 0) return False;
2328 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2331 for (i = 0; i < services; i++)
2332 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
2335 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2337 desc.buflen = mdrcnt;
2338 if (init_package(&desc,queuecnt,0)) {
2341 for (i = 0; i < services; i++) {
2342 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
2343 fill_printdest_info(cnum,i,uLevel,&desc);
2345 if (desc.errcode == NERR_Success) succnt = n;
2350 *rdata_len = desc.usedlen;
2353 *rparam = REALLOC(*rparam,*rparam_len);
2354 SSVALS(*rparam,0,desc.errcode);
2356 SSVAL(*rparam,4,succnt);
2357 SSVAL(*rparam,6,queuecnt);
2359 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
2363 static BOOL api_WPrintDriverEnum(int cnum,int uid, char *param,char *data,
2364 int mdrcnt,int mprcnt,
2365 char **rdata,char **rparam,
2366 int *rdata_len,int *rparam_len)
2368 char *str1 = param+2;
2369 char *str2 = skip_string(str1,1);
2370 char *p = skip_string(str2,1);
2373 struct pack_desc desc;
2375 bzero(&desc,sizeof(desc));
2380 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
2382 /* check it's a supported varient */
2383 if (strcmp(str1,"WrLeh") != 0) return False;
2384 if (uLevel != 0 || strcmp(str2,"B41") != 0) return False;
2386 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2388 desc.buflen = mdrcnt;
2389 if (init_package(&desc,1,0)) {
2390 PACKS(&desc,"B41","NULL");
2393 succnt = (desc.errcode == NERR_Success ? 1 : 0);
2395 *rdata_len = desc.usedlen;
2398 *rparam = REALLOC(*rparam,*rparam_len);
2399 SSVALS(*rparam,0,desc.errcode);
2401 SSVAL(*rparam,4,succnt);
2404 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
2408 static BOOL api_WPrintQProcEnum(int cnum,int uid, char *param,char *data,
2409 int mdrcnt,int mprcnt,
2410 char **rdata,char **rparam,
2411 int *rdata_len,int *rparam_len)
2413 char *str1 = param+2;
2414 char *str2 = skip_string(str1,1);
2415 char *p = skip_string(str2,1);
2418 struct pack_desc desc;
2420 bzero(&desc,sizeof(desc));
2425 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
2427 /* check it's a supported varient */
2428 if (strcmp(str1,"WrLeh") != 0) return False;
2429 if (uLevel != 0 || strcmp(str2,"B13") != 0) return False;
2431 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2433 desc.buflen = mdrcnt;
2435 if (init_package(&desc,1,0)) {
2436 PACKS(&desc,"B13","lpd");
2439 succnt = (desc.errcode == NERR_Success ? 1 : 0);
2441 *rdata_len = desc.usedlen;
2444 *rparam = REALLOC(*rparam,*rparam_len);
2445 SSVALS(*rparam,0,desc.errcode);
2447 SSVAL(*rparam,4,succnt);
2450 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
2454 static BOOL api_WPrintPortEnum(int cnum,int uid, char *param,char *data,
2455 int mdrcnt,int mprcnt,
2456 char **rdata,char **rparam,
2457 int *rdata_len,int *rparam_len)
2459 char *str1 = param+2;
2460 char *str2 = skip_string(str1,1);
2461 char *p = skip_string(str2,1);
2464 struct pack_desc desc;
2466 bzero(&desc,sizeof(desc));
2471 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
2473 /* check it's a supported varient */
2474 if (strcmp(str1,"WrLeh") != 0) return False;
2475 if (uLevel != 0 || strcmp(str2,"B9") != 0) return False;
2477 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2478 bzero(&desc,sizeof(desc));
2480 desc.buflen = mdrcnt;
2482 if (init_package(&desc,1,0)) {
2483 PACKS(&desc,"B13","lp0");
2486 succnt = (desc.errcode == NERR_Success ? 1 : 0);
2488 *rdata_len = desc.usedlen;
2491 *rparam = REALLOC(*rparam,*rparam_len);
2492 SSVALS(*rparam,0,desc.errcode);
2494 SSVAL(*rparam,4,succnt);
2497 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
2501 /****************************************************************************
2502 the buffer was too small
2503 ****************************************************************************/
2504 static BOOL api_TooSmall(int cnum,int uid, char *param,char *data,
2505 int mdrcnt,int mprcnt,
2506 char **rdata,char **rparam,
2507 int *rdata_len,int *rparam_len)
2509 *rparam_len = MIN(*rparam_len,mprcnt);
2510 *rparam = REALLOC(*rparam,*rparam_len);
2514 SSVAL(*rparam,0,NERR_BufTooSmall);
2516 DEBUG(3,("Supplied buffer too small in API command\n"));
2522 /****************************************************************************
2523 the request is not supported
2524 ****************************************************************************/
2525 static BOOL api_Unsupported(int cnum,int uid, char *param,char *data,
2526 int mdrcnt,int mprcnt,
2527 char **rdata,char **rparam,
2528 int *rdata_len,int *rparam_len)
2531 *rparam = REALLOC(*rparam,*rparam_len);
2535 SSVAL(*rparam,0,NERR_notsupported);
2536 SSVAL(*rparam,2,0); /* converter word */
2538 DEBUG(3,("Unsupported API command\n"));
2552 } api_commands[] = {
2553 {"RNetShareEnum", 0, api_RNetShareEnum,0},
2554 {"RNetShareGetInfo", 1, api_RNetShareGetInfo,0},
2555 {"RNetServerGetInfo", 13, api_RNetServerGetInfo,0},
2556 {"RNetUserGetInfo", 56, api_RNetUserGetInfo,0},
2557 {"NetUserGetGroups", 59, api_NetUserGetGroups,0},
2558 {"NetWkstaGetInfo", 63, api_NetWkstaGetInfo,0},
2559 {"DosPrintQEnum", 69, api_DosPrintQEnum,0},
2560 {"DosPrintQGetInfo", 70, api_DosPrintQGetInfo,0},
2561 {"WPrintJobEnumerate",76, api_WPrintJobEnumerate,0},
2562 {"WPrintJobGetInfo", 77, api_WPrintJobGetInfo,0},
2563 {"RDosPrintJobDel", 81, api_RDosPrintJobDel,0},
2564 {"RDosPrintJobPause", 82, api_RDosPrintJobDel,0},
2565 {"RDosPrintJobResume",83, api_RDosPrintJobDel,0},
2566 {"WPrintDestEnum", 84, api_WPrintDestEnum,0},
2567 {"WPrintDestGetInfo", 85, api_WPrintDestGetInfo,0},
2568 {"NetRemoteTOD", 91, api_NetRemoteTOD,0},
2569 {"WPrintQueuePurge", 103, api_WPrintQueuePurge,0},
2570 {"NetServerEnum", 104, api_RNetServerEnum,0},
2571 {"WAccessGetUserPerms",105, api_WAccessGetUserPerms,0},
2572 {"SetUserPassword", 115, api_SetUserPassword,0},
2573 {"WWkstaUserLogon", 132, api_WWkstaUserLogon,0},
2574 {"PrintJobInfo", 147, api_PrintJobInfo,0},
2575 {"WPrintDriverEnum", 205, api_WPrintDriverEnum,0},
2576 {"WPrintQProcEnum", 206, api_WPrintQProcEnum,0},
2577 {"WPrintPortEnum", 207, api_WPrintPortEnum,0},
2578 {NULL, -1, api_Unsupported,0}};
2581 /****************************************************************************
2582 handle remote api calls
2583 ****************************************************************************/
2584 static int api_reply(int cnum,int uid,char *outbuf,char *data,char *params,
2585 int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
2587 int api_command = SVAL(params,0);
2589 char *rparam = NULL;
2595 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
2596 api_command,params+2,skip_string(params+2,1),
2597 tdscnt,tpscnt,mdrcnt,mprcnt));
2599 for (i=0;api_commands[i].name;i++)
2600 if (api_commands[i].id == api_command && api_commands[i].fn)
2602 DEBUG(3,("Doing %s\n",api_commands[i].name));
2606 rdata = (char *)malloc(1024); if (rdata) bzero(rdata,1024);
2607 rparam = (char *)malloc(1024); if (rparam) bzero(rparam,1024);
2609 reply = api_commands[i].fn(cnum,uid,params,data,mdrcnt,mprcnt,
2610 &rdata,&rparam,&rdata_len,&rparam_len);
2613 if (rdata_len > mdrcnt ||
2614 rparam_len > mprcnt)
2616 reply = api_TooSmall(cnum,uid,params,data,mdrcnt,mprcnt,
2617 &rdata,&rparam,&rdata_len,&rparam_len);
2621 /* if we get False back then it's actually unsupported */
2623 api_Unsupported(cnum,uid,params,data,mdrcnt,mprcnt,
2624 &rdata,&rparam,&rdata_len,&rparam_len);
2628 /* now send the reply */
2629 send_trans_reply(outbuf,rdata,rparam,NULL,rdata_len,rparam_len,0);
2639 /****************************************************************************
2640 handle named pipe commands
2641 ****************************************************************************/
2642 static int named_pipe(int cnum,int uid, char *outbuf,char *name,
2643 uint16 *setup,char *data,char *params,
2644 int suwcnt,int tdscnt,int tpscnt,
2645 int msrcnt,int mdrcnt,int mprcnt)
2648 if (strequal(name,"LANMAN"))
2649 return(api_reply(cnum,uid,outbuf,data,params,tdscnt,tpscnt,mdrcnt,mprcnt));
2651 DEBUG(3,("named pipe command on <%s> 0x%X setup1=%d\n",
2652 name,(int)setup[0],(int)setup[1]));
2658 /****************************************************************************
2660 ****************************************************************************/
2661 int reply_trans(char *inbuf,char *outbuf)
2665 char *data=NULL,*params=NULL;
2669 int cnum = SVAL(inbuf,smb_tid);
2670 int uid = SVAL(inbuf,smb_uid);
2672 int tpscnt = SVAL(inbuf,smb_vwv0);
2673 int tdscnt = SVAL(inbuf,smb_vwv1);
2674 int mprcnt = SVAL(inbuf,smb_vwv2);
2675 int mdrcnt = SVAL(inbuf,smb_vwv3);
2676 int msrcnt = CVAL(inbuf,smb_vwv4);
2677 BOOL close_on_completion = BITSETW(inbuf+smb_vwv5,0);
2678 BOOL one_way = BITSETW(inbuf+smb_vwv5,1);
2679 int pscnt = SVAL(inbuf,smb_vwv9);
2680 int psoff = SVAL(inbuf,smb_vwv10);
2681 int dscnt = SVAL(inbuf,smb_vwv11);
2682 int dsoff = SVAL(inbuf,smb_vwv12);
2683 int suwcnt = CVAL(inbuf,smb_vwv13);
2685 StrnCpy(name,smb_buf(inbuf),sizeof(name)-1);
2689 data = (char *)malloc(tdscnt);
2690 memcpy(data,smb_base(inbuf)+dsoff,dscnt);
2694 params = (char *)malloc(tpscnt);
2695 memcpy(params,smb_base(inbuf)+psoff,pscnt);
2701 setup = (uint16 *)malloc(suwcnt*sizeof(setup[0]));
2702 for (i=0;i<suwcnt;i++)
2703 setup[i] = SVAL(inbuf,smb_vwv14+i*SIZEOFWORD);
2707 if (pscnt < tpscnt || dscnt < tdscnt)
2709 /* We need to send an interim response then receive the rest
2710 of the parameter/data bytes */
2711 outsize = set_message(outbuf,0,0,True);
2713 send_smb(Client,outbuf);
2716 /* receive the rest of the trans packet */
2717 while (pscnt < tpscnt || dscnt < tdscnt)
2719 int pcnt,poff,dcnt,doff,pdisp,ddisp;
2721 receive_smb(Client,inbuf, 0);
2724 /* Ensure this is still a trans packet (sanity check) */
2725 if(CVAL(inbuf, smb_com) != SMBtrans)
2727 DEBUG(2,("Invalid secondary trans2 packet\n"));
2728 if (params) free(params);
2729 if (data) free(data);
2730 if (setup) free(setup);
2731 return(ERROR(ERRSRV,ERRerror));
2734 tpscnt = SVAL(inbuf,smb_vwv0);
2735 tdscnt = SVAL(inbuf,smb_vwv1);
2737 pcnt = SVAL(inbuf,smb_vwv2);
2738 poff = SVAL(inbuf,smb_vwv3);
2739 pdisp = SVAL(inbuf,smb_vwv4);
2741 dcnt = SVAL(inbuf,smb_vwv5);
2742 doff = SVAL(inbuf,smb_vwv6);
2743 ddisp = SVAL(inbuf,smb_vwv7);
2749 memcpy(params+pdisp,smb_base(inbuf)+poff,pcnt);
2751 memcpy(data+ddisp,smb_base(inbuf)+doff,dcnt);
2755 DEBUG(3,("trans <%s> data=%d params=%d setup=%d\n",name,tdscnt,tpscnt,suwcnt));
2758 if (strncmp(name,"\\PIPE\\",strlen("\\PIPE\\")) == 0)
2759 outsize = named_pipe(cnum,uid,outbuf,name+strlen("\\PIPE\\"),setup,data,params,
2760 suwcnt,tdscnt,tpscnt,msrcnt,mdrcnt,mprcnt);
2763 if (data) free(data);
2764 if (params) free(params);
2765 if (setup) free(setup);
2767 if (close_on_completion)
2768 close_cnum(cnum,uid);
2774 return(ERROR(ERRSRV,ERRnosupport));