2 Unix SMB/Netbios implementation.
4 Inter-process communication and named pipe handling
5 Copyright (C) Andrew Tridgell 1992-1997
8 Copyright (C) John H Terpstra 1995-1997
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 This file handles the named pipe and mailslot calls
26 in the SMBtrans protocol
36 extern int DEBUGLEVEL;
38 extern files_struct Files[];
39 extern connection_struct Connections[];
41 extern fstring local_machine;
42 extern fstring myworkgroup;
44 #define NERR_Success 0
45 #define NERR_badpass 86
46 #define NERR_notsupported 50
48 #define NERR_BASE (2100)
49 #define NERR_BufTooSmall (NERR_BASE+23)
50 #define NERR_JobNotFound (NERR_BASE+51)
51 #define NERR_DestNotFound (NERR_BASE+52)
52 #define ERROR_INVALID_LEVEL 124
53 #define ERROR_MORE_DATA 234
55 #define REALLOC(ptr,size) Realloc(ptr,MAX((size),4*1024))
57 #define ACCESS_READ 0x01
58 #define ACCESS_WRITE 0x02
59 #define ACCESS_CREATE 0x04
61 #define SHPWLEN 8 /* share password length */
62 #define NNLEN 12 /* 8.3 net name length */
63 #define SNLEN 15 /* service name length */
64 #define QNLEN 12 /* queue name maximum length */
68 static BOOL api_Unsupported(int cnum,uint16 vuid, char *param,char *data,
69 int mdrcnt,int mprcnt,
70 char **rdata,char **rparam,
71 int *rdata_len,int *rparam_len);
72 static BOOL api_TooSmall(int cnum,uint16 vuid, char *param,char *data,
73 int mdrcnt,int mprcnt,
74 char **rdata,char **rparam,
75 int *rdata_len,int *rparam_len);
78 static int CopyExpanded(int cnum, int snum, char** dst, char* src, int* n)
83 if (!src || !dst || !n || !(*dst)) return(0);
85 StrnCpy(buf,src,sizeof(buf)/2);
86 string_sub(buf,"%S",lp_servicename(snum));
87 standard_sub(cnum,buf);
95 static int CopyAndAdvance(char** dst, char* src, int* n)
98 if (!src || !dst || !n || !(*dst)) return(0);
100 l = strlen(*dst) + 1;
106 static int StrlenExpanded(int cnum, int snum, char* s)
110 StrnCpy(buf,s,sizeof(buf)/2);
111 string_sub(buf,"%S",lp_servicename(snum));
112 standard_sub(cnum,buf);
113 return strlen(buf) + 1;
116 static char* Expand(int cnum, int snum, char* s)
119 if (!s) return(NULL);
120 StrnCpy(buf,s,sizeof(buf)/2);
121 string_sub(buf,"%S",lp_servicename(snum));
122 standard_sub(cnum,buf);
126 /*******************************************************************
127 check a API string for validity when we only need to check the prefix
128 ******************************************************************/
129 static BOOL prefix_ok(char *str,char *prefix)
131 return(strncmp(str,prefix,strlen(prefix)) == 0);
135 /****************************************************************************
137 ****************************************************************************/
138 static void send_trans_reply(char *outbuf,char *data,char *param,uint16 *setup,
139 int ldata,int lparam,int lsetup)
142 int this_ldata,this_lparam;
143 int tot_data=0,tot_param=0;
146 this_lparam = MIN(lparam,max_send - (500+lsetup*SIZEOFWORD)); /* hack */
147 this_ldata = MIN(ldata,max_send - (500+lsetup*SIZEOFWORD+this_lparam));
149 align = (this_lparam%4);
151 set_message(outbuf,10+lsetup,align+this_ldata+this_lparam,True);
153 memcpy(smb_buf(outbuf),param,this_lparam);
155 memcpy(smb_buf(outbuf)+this_lparam+align,data,this_ldata);
157 SSVAL(outbuf,smb_vwv0,lparam);
158 SSVAL(outbuf,smb_vwv1,ldata);
159 SSVAL(outbuf,smb_vwv3,this_lparam);
160 SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf),outbuf));
161 SSVAL(outbuf,smb_vwv5,0);
162 SSVAL(outbuf,smb_vwv6,this_ldata);
163 SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+this_lparam+align,outbuf));
164 SSVAL(outbuf,smb_vwv8,0);
165 SSVAL(outbuf,smb_vwv9,lsetup);
166 for (i=0;i<lsetup;i++)
167 SSVAL(outbuf,smb_vwv10+i*SIZEOFWORD,setup[i]);
170 send_smb(Client,outbuf);
172 tot_data = this_ldata;
173 tot_param = this_lparam;
175 while (tot_data < ldata || tot_param < lparam)
177 this_lparam = MIN(lparam-tot_param,max_send - 500); /* hack */
178 this_ldata = MIN(ldata-tot_data,max_send - (500+this_lparam));
180 align = (this_lparam%4);
182 set_message(outbuf,10,this_ldata+this_lparam+align,False);
184 memcpy(smb_buf(outbuf),param+tot_param,this_lparam);
186 memcpy(smb_buf(outbuf)+this_lparam+align,data+tot_data,this_ldata);
188 SSVAL(outbuf,smb_vwv3,this_lparam);
189 SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf),outbuf));
190 SSVAL(outbuf,smb_vwv5,tot_param);
191 SSVAL(outbuf,smb_vwv6,this_ldata);
192 SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+this_lparam+align,outbuf));
193 SSVAL(outbuf,smb_vwv8,tot_data);
194 SSVAL(outbuf,smb_vwv9,0);
197 send_smb(Client,outbuf);
199 tot_data += this_ldata;
200 tot_param += this_lparam;
205 char* format; /* formatstring for structure */
206 char* subformat; /* subformat for structure */
207 char* base; /* baseaddress of buffer */
208 int buflen; /* remaining size for fixed part; on init: length of base */
209 int subcount; /* count of substructures */
210 char* structbuf; /* pointer into buffer for remaining fixed part */
211 int stringlen; /* remaining size for variable part */
212 char* stringbuf; /* pointer into buffer for remaining variable part */
213 int neededlen; /* total needed size */
214 int usedlen; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
215 char* curpos; /* current position; pointer into format or subformat */
219 static int get_counter(char** p)
222 if (!p || !(*p)) return(1);
223 if (!isdigit(**p)) return 1;
227 n = 10 * n + (i - '0');
234 static int getlen(char* p)
240 case 'W': /* word (2 byte) */
243 case 'N': /* count of substructures (word) at end */
246 case 'D': /* double word (4 byte) */
247 case 'z': /* offset to zero terminated string (4 byte) */
248 case 'l': /* offset to user data (4 byte) */
251 case 'b': /* offset to data (with counter) (4 byte) */
255 case 'B': /* byte (with optional counter) */
256 n += get_counter(&p);
263 static BOOL init_package(struct pack_desc* p, int count, int subcount)
268 if (!p->format || !p->base) return(False);
270 i = count * getlen(p->format);
271 if (p->subformat) i += subcount * getlen(p->subformat);
272 p->structbuf = p->base;
276 p->curpos = p->format;
279 p->errcode = NERR_BufTooSmall;
282 p->errcode = NERR_Success;
285 p->stringbuf = p->base + i;
287 return(p->errcode == NERR_Success);
291 static int package(struct pack_desc* p, ...)
294 static int package(va_alist)
300 int needed=0, stringneeded;
302 int is_string=0, stringused;
309 p = va_arg(args,struct pack_desc *);
314 p->curpos = p->format;
316 p->curpos = p->subformat;
321 str = va_arg(args,char*);
322 if (strncmp(str,p->curpos,strlen(str)) != 0) {
323 DEBUG(2,("type error in package: %s instead of %*s\n",str,
324 strlen(str),p->curpos));
334 if (!p->curpos) return(0);
336 switch( *p->curpos++ ) {
337 case 'W': /* word (2 byte) */
339 temp = va_arg(args,int);
340 if (p->buflen >= needed) SSVAL(p->structbuf,0,temp);
342 case 'N': /* count of substructures (word) at end */
344 p->subcount = va_arg(args,int);
345 if (p->buflen >= needed) SSVAL(p->structbuf,0,p->subcount);
347 case 'D': /* double word (4 byte) */
349 temp = va_arg(args,int);
350 if (p->buflen >= needed) SIVAL(p->structbuf,0,temp);
352 case 'B': /* byte (with optional counter) */
353 needed = get_counter(&p->curpos);
355 char *s = va_arg(args,char*);
356 if (p->buflen >= needed) StrnCpy(p->structbuf,s?s:"",needed);
359 case 'z': /* offset to zero terminated string (4 byte) */
360 str = va_arg(args,char*);
361 stringneeded = (str ? strlen(str)+1 : 0);
364 case 'l': /* offset to user data (4 byte) */
365 str = va_arg(args,char*);
366 stringneeded = va_arg(args,int);
369 case 'b': /* offset to data (with counter) (4 byte) */
370 str = va_arg(args,char*);
371 stringneeded = get_counter(&p->curpos);
376 if (stringneeded >= 0) {
378 if (p->buflen >= needed) {
379 stringused = stringneeded;
380 if (stringused > p->stringlen) {
381 stringused = (is_string ? p->stringlen : 0);
382 if (p->errcode == NERR_Success) p->errcode = ERROR_MORE_DATA;
385 SIVAL(p->structbuf,0,0);
387 SIVAL(p->structbuf,0,PTR_DIFF(p->stringbuf,p->base));
388 memcpy(p->stringbuf,str?str:"",stringused);
389 if (is_string) p->stringbuf[stringused-1] = '\0';
390 p->stringbuf += stringused;
391 p->stringlen -= stringused;
392 p->usedlen += stringused;
395 p->neededlen += stringneeded;
397 p->neededlen += needed;
398 if (p->buflen >= needed) {
399 p->structbuf += needed;
401 p->usedlen += needed;
404 if (p->errcode == NERR_Success) p->errcode = NERR_BufTooSmall;
410 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
411 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
413 #define PACK(desc,t,v) package(desc,v)
414 #define PACKl(desc,t,v,l) package(desc,v,l)
417 static void PACKI(struct pack_desc* desc,char *t,int v)
422 static void PACKS(struct pack_desc* desc,char *t,char *v)
428 /****************************************************************************
430 ****************************************************************************/
432 static void PackDriverData(struct pack_desc* desc)
434 char drivdata[4+4+32];
435 SIVAL(drivdata,0,sizeof drivdata); /* cb */
436 SIVAL(drivdata,4,1000); /* lVersion */
437 memset(drivdata+8,0,32); /* szDeviceName */
438 strcpy(drivdata+8,"NULL");
439 PACKl(desc,"l",drivdata,sizeof drivdata); /* pDriverData */
442 static int check_printq_info(struct pack_desc* desc,
443 int uLevel, char *id1, const char* id2)
445 desc->subformat = NULL;
448 desc->format = "B13";
451 desc->format = "B13BWWWzzzzzWW";
454 desc->format = "B13BWWWzzzzzWN";
455 desc->subformat = "WB21BB16B10zWWzDDz";
458 desc->format = "zWWWWzzzzWWzzl";
461 desc->format = "zWWWWzzzzWNzzl";
462 desc->subformat = "WWzWWDDzz";
467 default: return False;
469 if (strcmp(desc->format,id1) != 0) return False;
470 if (desc->subformat && strcmp(desc->subformat,id2) != 0) return False;
474 static void fill_printjob_info(int cnum, int snum, int uLevel,
475 struct pack_desc* desc,
476 print_queue_struct* queue, int n)
478 time_t t = queue->time;
480 /* the client expects localtime */
483 PACKI(desc,"W",((snum%0xFF)<<8) | (queue->job%0xFF)); /* uJobId */
485 PACKS(desc,"B21",queue->user); /* szUserName */
486 PACKS(desc,"B",""); /* pad */
487 PACKS(desc,"B16",""); /* szNotifyName */
488 PACKS(desc,"B10","PM_Q_RAW"); /* szDataType */
489 PACKS(desc,"z",""); /* pszParms */
490 PACKI(desc,"W",n+1); /* uPosition */
491 PACKI(desc,"W",queue->status); /* fsStatus */
492 PACKS(desc,"z",""); /* pszStatus */
493 PACKI(desc,"D",t); /* ulSubmitted */
494 PACKI(desc,"D",queue->size); /* ulSize */
495 PACKS(desc,"z",queue->file); /* pszComment */
497 if (uLevel == 2 || uLevel == 3) {
498 PACKI(desc,"W",queue->priority); /* uPriority */
499 PACKS(desc,"z",queue->user); /* pszUserName */
500 PACKI(desc,"W",n+1); /* uPosition */
501 PACKI(desc,"W",queue->status); /* fsStatus */
502 PACKI(desc,"D",t); /* ulSubmitted */
503 PACKI(desc,"D",queue->size); /* ulSize */
504 PACKS(desc,"z","Samba"); /* pszComment */
505 PACKS(desc,"z",queue->file); /* pszDocument */
507 PACKS(desc,"z",""); /* pszNotifyName */
508 PACKS(desc,"z","PM_Q_RAW"); /* pszDataType */
509 PACKS(desc,"z",""); /* pszParms */
510 PACKS(desc,"z",""); /* pszStatus */
511 PACKS(desc,"z",SERVICE(snum)); /* pszQueue */
512 PACKS(desc,"z","lpd"); /* pszQProcName */
513 PACKS(desc,"z",""); /* pszQProcParms */
514 PACKS(desc,"z","NULL"); /* pszDriverName */
515 PackDriverData(desc); /* pDriverData */
516 PACKS(desc,"z",""); /* pszPrinterName */
521 static void fill_printq_info(int cnum, int snum, int uLevel,
522 struct pack_desc* desc,
523 int count, print_queue_struct* queue,
524 print_status_struct* status)
527 PACKS(desc,"B13",SERVICE(snum));
529 PACKS(desc,"z",Expand(cnum,snum,SERVICE(snum)));
531 if (uLevel == 1 || uLevel == 2) {
532 PACKS(desc,"B",""); /* alignment */
533 PACKI(desc,"W",5); /* priority */
534 PACKI(desc,"W",0); /* start time */
535 PACKI(desc,"W",0); /* until time */
536 PACKS(desc,"z",""); /* pSepFile */
537 PACKS(desc,"z","lpd"); /* pPrProc */
538 PACKS(desc,"z",SERVICE(snum)); /* pDestinations */
539 PACKS(desc,"z",""); /* pParms */
541 PACKS(desc,"z","UNKNOWN PRINTER");
542 PACKI(desc,"W",LPSTAT_ERROR);
544 else if (!status || !status->message[0]) {
545 PACKS(desc,"z",Expand(cnum,snum,lp_comment(snum)));
546 PACKI(desc,"W",LPSTAT_OK); /* status */
548 PACKS(desc,"z",status->message);
549 PACKI(desc,"W",status->status); /* status */
551 PACKI(desc,(uLevel == 1 ? "W" : "N"),count);
553 if (uLevel == 3 || uLevel == 4) {
554 PACKI(desc,"W",5); /* uPriority */
555 PACKI(desc,"W",0); /* uStarttime */
556 PACKI(desc,"W",0); /* uUntiltime */
557 PACKI(desc,"W",5); /* pad1 */
558 PACKS(desc,"z",""); /* pszSepFile */
559 PACKS(desc,"z","WinPrint"); /* pszPrProc */
560 PACKS(desc,"z",""); /* pszParms */
561 if (!status || !status->message[0]) {
562 PACKS(desc,"z",Expand(cnum,snum,lp_comment(snum))); /* pszComment */
563 PACKI(desc,"W",LPSTAT_OK); /* fsStatus */
565 PACKS(desc,"z",status->message); /* pszComment */
566 PACKI(desc,"W",status->status); /* fsStatus */
568 PACKI(desc,(uLevel == 3 ? "W" : "N"),count); /* cJobs */
569 PACKS(desc,"z",SERVICE(snum)); /* pszPrinters */
570 PACKS(desc,"z",lp_printerdriver(snum)); /* pszDriverName */
571 PackDriverData(desc); /* pDriverData */
573 if (uLevel == 2 || uLevel == 4) {
575 for (i=0;i<count;i++)
576 fill_printjob_info(cnum,snum,uLevel == 2 ? 1 : 2,desc,&queue[i],i);
579 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n",SERVICE(snum),count));
582 static BOOL api_DosPrintQGetInfo(int cnum,uint16 vuid, char *param,char *data,
583 int mdrcnt,int mprcnt,
584 char **rdata,char **rparam,
585 int *rdata_len,int *rparam_len)
587 char *str1 = param+2;
588 char *str2 = skip_string(str1,1);
589 char *p = skip_string(str2,1);
595 struct pack_desc desc;
596 print_queue_struct *queue=NULL;
597 print_status_struct status;
599 bzero(&status,sizeof(status));
600 bzero(&desc,sizeof(desc));
602 p = skip_string(p,1);
607 /* remove any trailing username */
608 if ((p = strchr(QueueName,'%'))) *p = 0;
610 DEBUG(3,("PrintQueue uLevel=%d name=%s\n",uLevel,QueueName));
612 /* check it's a supported varient */
613 if (!prefix_ok(str1,"zWrLh")) return False;
614 if (!check_printq_info(&desc,uLevel,str2,str3)) return False;
616 snum = lp_servicenumber(QueueName);
617 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
618 int pnum = lp_servicenumber(PRINTERS_NAME);
620 lp_add_printer(QueueName,pnum);
621 snum = lp_servicenumber(QueueName);
625 if (snum < 0 || !VALID_SNUM(snum)) return(False);
627 count = get_printqueue(snum,cnum,&queue,&status);
628 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
630 desc.buflen = mdrcnt;
631 if (init_package(&desc,1,count)) {
632 desc.subcount = count;
633 fill_printq_info(cnum,snum,uLevel,&desc,count,queue,&status);
636 *rdata_len = desc.usedlen;
639 *rparam = REALLOC(*rparam,*rparam_len);
640 SSVALS(*rparam,0,desc.errcode);
642 SSVAL(*rparam,4,desc.neededlen);
644 DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode));
646 if (queue) free(queue);
652 /****************************************************************************
653 view list of all print jobs on all queues
654 ****************************************************************************/
655 static BOOL api_DosPrintQEnum(int cnum, uint16 vuid, char* param, char* data,
656 int mdrcnt, int mprcnt,
657 char **rdata, char** rparam,
658 int *rdata_len, int *rparam_len)
660 char *param_format = param+2;
661 char *output_format1 = skip_string(param_format,1);
662 char *p = skip_string(output_format1,1);
663 int uLevel = SVAL(p,0);
664 char *output_format2 = p + 4;
665 int services = lp_numservices();
667 struct pack_desc desc;
668 print_queue_struct **queue = NULL;
669 print_status_struct *status = NULL;
670 int* subcntarr = NULL;
671 int queuecnt, subcnt=0, succnt=0;
673 bzero(&desc,sizeof(desc));
675 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
677 if (!prefix_ok(param_format,"WrLeh")) return False;
678 if (!check_printq_info(&desc,uLevel,output_format1,output_format2))
681 for (i = 0; i < services; i++)
682 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
685 queue = (print_queue_struct**)malloc(queuecnt*sizeof(print_queue_struct*));
686 memset(queue,0,queuecnt*sizeof(print_queue_struct*));
687 status = (print_status_struct*)malloc(queuecnt*sizeof(print_status_struct));
688 memset(status,0,queuecnt*sizeof(print_status_struct));
689 subcntarr = (int*)malloc(queuecnt*sizeof(int));
692 for (i = 0; i < services; i++)
693 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
694 subcntarr[n] = get_printqueue(i,cnum,&queue[n],&status[n]);
695 subcnt += subcntarr[n];
699 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
701 desc.buflen = mdrcnt;
703 if (init_package(&desc,queuecnt,subcnt)) {
706 for (i = 0; i < services; i++)
707 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
708 fill_printq_info(cnum,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]);
710 if (desc.errcode == NERR_Success) succnt = n;
714 if (subcntarr) free(subcntarr);
716 *rdata_len = desc.usedlen;
718 *rparam = REALLOC(*rparam,*rparam_len);
719 SSVALS(*rparam,0,desc.errcode);
721 SSVAL(*rparam,4,succnt);
722 SSVAL(*rparam,6,queuecnt);
724 for (i = 0; i < queuecnt; i++) {
725 if (queue && queue[i]) free(queue[i]);
728 if (queue) free(queue);
729 if (status) free(status);
734 /****************************************************************************
735 get info level for a server list query
736 ****************************************************************************/
737 static BOOL check_server_info(int uLevel, char* id)
741 if (strcmp(id,"B16") != 0) return False;
744 if (strcmp(id,"B16BBDz") != 0) return False;
752 struct srv_info_struct
762 /*******************************************************************
763 get server info lists from the files saved by nmbd. Return the
765 ******************************************************************/
766 static int get_server_info(uint32 servertype,
767 struct srv_info_struct **servers,
775 BOOL local_list_only;
777 strcpy(fname,lp_lockdir());
778 trim_string(fname,NULL,"/");
780 strcat(fname,SERVER_LIST);
782 f = fopen(fname,"r");
785 DEBUG(4,("Can't open %s - %s\n",fname,strerror(errno)));
789 /* request for everything is code for request all servers */
790 if (servertype == SV_TYPE_ALL)
791 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
793 local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY);
795 DEBUG(4,("Servertype search: %8x\n",servertype));
800 struct srv_info_struct *s;
805 fgets(line,sizeof(line)-1,f);
806 if (!*line) continue;
808 if (count == alloced) {
810 (*servers) = (struct srv_info_struct *)
811 Realloc(*servers,sizeof(**servers)*alloced);
812 if (!(*servers)) return(0);
813 bzero((char *)((*servers)+count),sizeof(**servers)*(alloced-count));
815 s = &(*servers)[count];
817 if (!next_token(&ptr,s->name , NULL)) continue;
818 if (!next_token(&ptr,stype , NULL)) continue;
819 if (!next_token(&ptr,s->comment, NULL)) continue;
820 if (!next_token(&ptr,s->domain , NULL)) {
821 /* this allows us to cope with an old nmbd */
822 strcpy(s->domain,myworkgroup);
825 if (sscanf(stype,"%X",&s->type) != 1) {
826 DEBUG(4,("r:host file "));
830 /* Filter the servers/domains we return based on what was asked for. */
832 /* Check to see if we are being asked for a local list only. */
833 if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) {
834 DEBUG(4,("r: local list only"));
838 /* doesn't match up: don't want it */
839 if (!(servertype & s->type)) {
840 DEBUG(4,("r:serv type "));
844 if ((servertype & SV_TYPE_DOMAIN_ENUM) !=
845 (s->type & SV_TYPE_DOMAIN_ENUM))
847 DEBUG(4,("s: dom mismatch "));
851 if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM))
856 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
857 s->type &= ~SV_TYPE_LOCAL_LIST_ONLY;
861 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
862 s->name, s->type, s->comment, s->domain));
864 s->server_added = True;
869 DEBUG(4,("%20s %8x %25s %15s\n",
870 s->name, s->type, s->comment, s->domain));
879 /*******************************************************************
880 fill in a server info structure
881 ******************************************************************/
882 static int fill_srv_info(struct srv_info_struct *service,
883 int uLevel, char **buf, int *buflen,
884 char **stringbuf, int *stringspace, char *baseaddr)
893 case 0: struct_len = 16; break;
894 case 1: struct_len = 26; break;
904 len = strlen(service->comment)+1;
908 if (buflen) *buflen = struct_len;
909 if (stringspace) *stringspace = len;
910 return struct_len + len;
915 if (*buflen < struct_len) return -1;
924 l2 = *buflen - struct_len;
926 if (!baseaddr) baseaddr = p;
931 StrnCpy(p,service->name,15);
935 StrnCpy(p,service->name,15);
936 SIVAL(p,18,service->type);
937 SIVAL(p,22,PTR_DIFF(p2,baseaddr));
938 len += CopyAndAdvance(&p2,service->comment,&l2);
944 *buf = p + struct_len;
945 *buflen -= struct_len;
958 static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
960 return(strcmp(s1->name,s2->name));
963 /****************************************************************************
964 view list of servers available (or possibly domains). The info is
965 extracted from lists saved by nmbd on the local host
966 ****************************************************************************/
967 static BOOL api_RNetServerEnum(int cnum, uint16 vuid, char *param, char *data,
968 int mdrcnt, int mprcnt, char **rdata,
969 char **rparam, int *rdata_len, int *rparam_len)
971 char *str1 = param+2;
972 char *str2 = skip_string(str1,1);
973 char *p = skip_string(str2,1);
974 int uLevel = SVAL(p,0);
975 int buf_len = SVAL(p,2);
976 uint32 servertype = IVAL(p,4);
978 int data_len, fixed_len, string_len;
980 struct srv_info_struct *servers=NULL;
981 int counted=0,total=0;
987 /* If someone sets all the bits they don't really mean to set
988 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
991 if (servertype == SV_TYPE_ALL)
992 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
994 domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
995 local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
999 if (!prefix_ok(str1,"WrLehD")) return False;
1000 if (!check_server_info(uLevel,str2)) return False;
1002 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1003 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1004 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1006 if (strcmp(str1, "WrLehDz") == 0) {
1007 StrnCpy(domain, p, sizeof(fstring)-1);
1009 StrnCpy(domain, myworkgroup, sizeof(fstring)-1);
1012 if (lp_browse_list())
1013 total = get_server_info(servertype,&servers,domain);
1015 data_len = fixed_len = string_len = 0;
1018 qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
1021 char *lastname=NULL;
1023 for (i=0;i<total;i++)
1025 struct srv_info_struct *s = &servers[i];
1026 if (lastname && strequal(lastname,s->name)) continue;
1028 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1029 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1030 s->name, s->type, s->comment, s->domain));
1032 if (data_len <= buf_len) {
1035 string_len += s_len;
1042 *rdata_len = fixed_len + string_len;
1043 *rdata = REALLOC(*rdata,*rdata_len);
1044 bzero(*rdata,*rdata_len);
1046 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1052 char *lastname=NULL;
1053 int count2 = counted;
1054 for (i = 0; i < total && count2;i++)
1056 struct srv_info_struct *s = &servers[i];
1057 if (lastname && strequal(lastname,s->name)) continue;
1059 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1060 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1061 s->name, s->type, s->comment, s->domain));
1067 *rparam = REALLOC(*rparam,*rparam_len);
1068 SSVAL(*rparam,0,NERR_Success);
1070 SSVAL(*rparam,4,counted);
1071 SSVAL(*rparam,6,counted+missed);
1073 if (servers) free(servers);
1075 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1076 domain,uLevel,counted,counted+missed));
1082 /****************************************************************************
1083 get info about a share
1084 ****************************************************************************/
1085 static BOOL check_share_info(int uLevel, char* id)
1089 if (strcmp(id,"B13") != 0) return False;
1092 if (strcmp(id,"B13BWz") != 0) return False;
1095 if (strcmp(id,"B13BWzWWWzB9B") != 0) return False;
1098 if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) return False;
1100 default: return False;
1105 static int fill_share_info(int cnum, int snum, int uLevel,
1106 char** buf, int* buflen,
1107 char** stringbuf, int* stringspace, char* baseaddr)
1116 case 0: struct_len = 13; break;
1117 case 1: struct_len = 20; break;
1118 case 2: struct_len = 40; break;
1119 case 91: struct_len = 68; break;
1127 if (uLevel > 0) len += StrlenExpanded(cnum,snum,lp_comment(snum));
1128 if (uLevel > 1) len += strlen(lp_pathname(snum)) + 1;
1129 if (buflen) *buflen = struct_len;
1130 if (stringspace) *stringspace = len;
1131 return struct_len + len;
1136 if ((*buflen) < struct_len) return -1;
1144 p2 = p + struct_len;
1145 l2 = (*buflen) - struct_len;
1147 if (!baseaddr) baseaddr = p;
1149 StrnCpy(p,lp_servicename(snum),13);
1155 type = STYPE_DISKTREE;
1156 if (lp_print_ok(snum)) type = STYPE_PRINTQ;
1157 if (strequal("IPC$",lp_servicename(snum))) type = STYPE_IPC;
1158 SSVAL(p,14,type); /* device type */
1159 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1160 len += CopyExpanded(cnum,snum,&p2,lp_comment(snum),&l2);
1165 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1166 SSVALS(p,22,-1); /* max uses */
1167 SSVAL(p,24,1); /* current uses */
1168 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1169 len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1170 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1175 memset(p+40,0,SHPWLEN+2);
1187 (*buf) = p + struct_len;
1188 (*buflen) -= struct_len;
1190 (*stringspace) = l2;
1200 static BOOL api_RNetShareGetInfo(int cnum,uint16 vuid, char *param,char *data,
1201 int mdrcnt,int mprcnt,
1202 char **rdata,char **rparam,
1203 int *rdata_len,int *rparam_len)
1205 char *str1 = param+2;
1206 char *str2 = skip_string(str1,1);
1207 char *netname = skip_string(str2,1);
1208 char *p = skip_string(netname,1);
1209 int uLevel = SVAL(p,0);
1210 int snum = find_service(netname);
1212 if (snum < 0) return False;
1214 /* check it's a supported varient */
1215 if (!prefix_ok(str1,"zWrLh")) return False;
1216 if (!check_share_info(uLevel,str2)) return False;
1218 *rdata = REALLOC(*rdata,mdrcnt);
1220 *rdata_len = fill_share_info(cnum,snum,uLevel,&p,&mdrcnt,0,0,0);
1221 if (*rdata_len < 0) return False;
1224 *rparam = REALLOC(*rparam,*rparam_len);
1225 SSVAL(*rparam,0,NERR_Success);
1226 SSVAL(*rparam,2,0); /* converter word */
1227 SSVAL(*rparam,4,*rdata_len);
1232 /****************************************************************************
1233 view list of shares available
1234 ****************************************************************************/
1235 static BOOL api_RNetShareEnum(int cnum,uint16 vuid, char *param,char *data,
1236 int mdrcnt,int mprcnt,
1237 char **rdata,char **rparam,
1238 int *rdata_len,int *rparam_len)
1240 char *str1 = param+2;
1241 char *str2 = skip_string(str1,1);
1242 char *p = skip_string(str2,1);
1243 int uLevel = SVAL(p,0);
1244 int buf_len = SVAL(p,2);
1246 int count=lp_numservices();
1247 int total=0,counted=0;
1249 int data_len, fixed_len, string_len;
1252 if (!prefix_ok(str1,"WrLeh")) return False;
1253 if (!check_share_info(uLevel,str2)) return False;
1255 data_len = fixed_len = string_len = 0;
1256 for (i=0;i<count;i++)
1257 if (lp_browseable(i) && lp_snum_ok(i))
1260 data_len += fill_share_info(cnum,i,uLevel,0,&f_len,0,&s_len,0);
1261 if (data_len <= buf_len)
1265 string_len += s_len;
1268 *rdata_len = fixed_len + string_len;
1269 *rdata = REALLOC(*rdata,*rdata_len);
1270 memset(*rdata,0,*rdata_len);
1272 p2 = (*rdata) + fixed_len; /* auxillery data (strings) will go here */
1276 for (i = 0; i < count;i++)
1277 if (lp_browseable(i) && lp_snum_ok(i))
1278 if (fill_share_info(cnum,i,uLevel,&p,&f_len,&p2,&s_len,*rdata) < 0)
1282 *rparam = REALLOC(*rparam,*rparam_len);
1283 SSVAL(*rparam,0,NERR_Success);
1285 SSVAL(*rparam,4,counted);
1286 SSVAL(*rparam,6,total);
1288 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1289 counted,total,uLevel,
1290 buf_len,*rdata_len,mdrcnt));
1296 /****************************************************************************
1297 get the time of day info
1298 ****************************************************************************/
1299 static BOOL api_NetRemoteTOD(int cnum,uint16 vuid, char *param,char *data,
1300 int mdrcnt,int mprcnt,
1301 char **rdata,char **rparam,
1302 int *rdata_len,int *rparam_len)
1306 *rparam = REALLOC(*rparam,*rparam_len);
1309 *rdata = REALLOC(*rdata,*rdata_len);
1311 SSVAL(*rparam,0,NERR_Success);
1312 SSVAL(*rparam,2,0); /* converter word */
1318 time_t unixdate = time(NULL);
1320 put_dos_date3(p,0,unixdate); /* this is the time that is looked at
1321 by NT in a "net time" operation,
1322 it seems to ignore the one below */
1324 /* the client expects to get localtime, not GMT, in this bit
1325 (I think, this needs testing) */
1326 t = LocalTime(&unixdate);
1328 SIVAL(p,4,0); /* msecs ? */
1329 CVAL(p,8) = t->tm_hour;
1330 CVAL(p,9) = t->tm_min;
1331 CVAL(p,10) = t->tm_sec;
1332 CVAL(p,11) = 0; /* hundredths of seconds */
1333 SSVALS(p,12,TimeDiff(unixdate)/60); /* timezone in minutes from GMT */
1334 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
1335 CVAL(p,16) = t->tm_mday;
1336 CVAL(p,17) = t->tm_mon + 1;
1337 SSVAL(p,18,1900+t->tm_year);
1338 CVAL(p,20) = t->tm_wday;
1345 /****************************************************************************
1346 set the user password
1347 ****************************************************************************/
1348 static BOOL api_SetUserPassword(int cnum,uint16 vuid, char *param,char *data,
1349 int mdrcnt,int mprcnt,
1350 char **rdata,char **rparam,
1351 int *rdata_len,int *rparam_len)
1353 char *p = skip_string(param+2,2);
1355 fstring pass1,pass2;
1359 p = skip_string(p,1);
1361 StrnCpy(pass1,p,16);
1362 StrnCpy(pass2,p+16,16);
1365 *rparam = REALLOC(*rparam,*rparam_len);
1369 SSVAL(*rparam,0,NERR_badpass);
1370 SSVAL(*rparam,2,0); /* converter word */
1372 DEBUG(3,("Set password for <%s>\n",user));
1374 if (password_ok(user,pass1,strlen(pass1),NULL) &&
1375 chgpasswd(user,pass1,pass2))
1377 SSVAL(*rparam,0,NERR_Success);
1380 bzero(pass1,sizeof(fstring));
1381 bzero(pass2,sizeof(fstring));
1386 /****************************************************************************
1389 ****************************************************************************/
1390 static BOOL api_RDosPrintJobDel(int cnum,uint16 vuid, char *param,char *data,
1391 int mdrcnt,int mprcnt,
1392 char **rdata,char **rparam,
1393 int *rdata_len,int *rparam_len)
1395 int function = SVAL(param,0);
1396 char *str1 = param+2;
1397 char *str2 = skip_string(str1,1);
1398 char *p = skip_string(str2,1);
1399 int jobid = (SVAL(p,0)&0xFF); /* the snum and jobid are encoded
1400 by the print queue api */
1401 int snum = (SVAL(p,0)>>8);
1405 /* check it's a supported varient */
1406 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
1410 *rparam = REALLOC(*rparam,*rparam_len);
1414 SSVAL(*rparam,0,NERR_Success);
1416 if (snum >= 0 && VALID_SNUM(snum))
1418 print_queue_struct *queue=NULL;
1420 count = get_printqueue(snum,cnum,&queue,NULL);
1422 for (i=0;i<count;i++)
1423 if ((queue[i].job%0xFF) == jobid)
1426 case 81: /* delete */
1427 DEBUG(3,("Deleting queue entry %d\n",queue[i].job));
1428 del_printqueue(cnum,snum,queue[i].job);
1430 case 82: /* pause */
1431 case 83: /* resume */
1432 DEBUG(3,("%s queue entry %d\n",
1433 (function==82?"pausing":"resuming"),queue[i].job));
1434 status_printjob(cnum,snum,queue[i].job,
1435 (function==82?LPQ_PAUSED:LPQ_QUEUED));
1442 SSVAL(*rparam,0,NERR_JobNotFound);
1444 if (queue) free(queue);
1447 SSVAL(*rparam,2,0); /* converter word */
1452 static BOOL api_WPrintQueuePurge(int cnum,uint16 vuid, char *param,char *data,
1453 int mdrcnt,int mprcnt,
1454 char **rdata,char **rparam,
1455 int *rdata_len,int *rparam_len)
1457 char *str1 = param+2;
1458 char *str2 = skip_string(str1,1);
1459 char *QueueName = skip_string(str2,1);
1462 /* check it's a supported varient */
1463 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
1467 *rparam = REALLOC(*rparam,*rparam_len);
1471 SSVAL(*rparam,0,NERR_Success);
1472 SSVAL(*rparam,2,0); /* converter word */
1474 snum = lp_servicenumber(QueueName);
1475 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
1476 int pnum = lp_servicenumber(PRINTERS_NAME);
1478 lp_add_printer(QueueName,pnum);
1479 snum = lp_servicenumber(QueueName);
1483 if (snum >= 0 && VALID_SNUM(snum)) {
1484 print_queue_struct *queue=NULL;
1488 count = get_printqueue(snum,cnum,&queue,NULL);
1489 for (i = 0; i < count; i++)
1490 del_printqueue(cnum,snum,queue[i].job);
1492 if (queue) free(queue);
1495 DEBUG(3,("Print queue purge, queue=%s\n",QueueName));
1501 /****************************************************************************
1502 set the property of a print job (undocumented?)
1503 ? function = 0xb -> set name of print job
1504 ? function = 0x6 -> move print job up/down
1505 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
1506 or <WWsTP> <WB21BB16B10zWWzDDz>
1507 ****************************************************************************/
1508 static int check_printjob_info(struct pack_desc* desc,
1509 int uLevel, char* id)
1511 desc->subformat = NULL;
1513 case 0: desc->format = "W"; break;
1514 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
1515 case 2: desc->format = "WWzWWDDzz"; break;
1516 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
1517 default: return False;
1519 if (strcmp(desc->format,id) != 0) return False;
1523 static BOOL api_PrintJobInfo(int cnum,uint16 vuid,char *param,char *data,
1524 int mdrcnt,int mprcnt,
1525 char **rdata,char **rparam,
1526 int *rdata_len,int *rparam_len)
1528 struct pack_desc desc;
1529 char *str1 = param+2;
1530 char *str2 = skip_string(str1,1);
1531 char *p = skip_string(str2,1);
1532 int jobid = (SVAL(p,0)&0xFF); /* the snum and jobid are encoded
1533 by the print queue api */
1534 int snum = (SVAL(p,0)>>8);
1535 int uLevel = SVAL(p,2);
1536 int function = SVAL(p,4); /* what is this ?? */
1541 *rparam = REALLOC(*rparam,*rparam_len);
1545 /* check it's a supported varient */
1546 if ((strcmp(str1,"WWsTP")) || (!check_printjob_info(&desc,uLevel,str2)))
1550 case 0x6: /* change job place in the queue, data gives the new place */
1551 if (snum >= 0 && VALID_SNUM(snum))
1553 print_queue_struct *queue=NULL;
1557 count = get_printqueue(snum,cnum,&queue,NULL);
1558 for (i=0;i<count;i++) /* find job */
1559 if ((queue[i].job%0xFF) == jobid) break;
1562 desc.errcode=NERR_JobNotFound;
1563 if (queue) free(queue);
1566 desc.errcode=NERR_Success;
1570 int place= SVAL(data,0);
1571 /* we currently have no way of doing this. Can any unix do it? */
1572 if (i < place) /* move down */;
1573 else if (i > place ) /* move up */;
1576 desc.errcode=NERR_notsupported; /* not yet supported */
1577 if (queue) free(queue);
1580 else desc.errcode=NERR_JobNotFound;
1582 case 0xb: /* change print job name, data gives the name */
1583 /* jobid, snum should be zero */
1590 if (issafe(*s)) name[l++] = *s;
1595 DEBUG(3,("Setting print name to %s\n",name));
1597 for (i=0;i<MAX_OPEN_FILES;i++)
1598 if (Files[i].open && Files[i].print_file)
1604 if (!become_user(Files[i].cnum,vuid) ||
1605 !become_service(Files[i].cnum,True))
1608 if (sys_rename(Files[i].name,name) == 0)
1609 string_set(&Files[i].name,name);
1613 desc.errcode=NERR_Success;
1616 default: /* not implemented */
1620 SSVALS(*rparam,0,desc.errcode);
1621 SSVAL(*rparam,2,0); /* converter word */
1627 /****************************************************************************
1628 get info about the server
1629 ****************************************************************************/
1630 static BOOL api_RNetServerGetInfo(int cnum,uint16 vuid, char *param,char *data,
1631 int mdrcnt,int mprcnt,
1632 char **rdata,char **rparam,
1633 int *rdata_len,int *rparam_len)
1635 char *str1 = param+2;
1636 char *str2 = skip_string(str1,1);
1637 char *p = skip_string(str2,1);
1638 int uLevel = SVAL(p,0);
1642 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
1644 /* check it's a supported varient */
1645 if (!prefix_ok(str1,"WrLh")) return False;
1648 if (strcmp(str2,"B16") != 0) return False;
1652 if (strcmp(str2,"B16BBDz") != 0) return False;
1656 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")
1661 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz")
1666 if (strcmp(str2,"DN") != 0) return False;
1670 if (strcmp(str2,"B16BBDzWWzzz") != 0) return False;
1673 default: return False;
1676 *rdata_len = mdrcnt;
1677 *rdata = REALLOC(*rdata,*rdata_len);
1680 p2 = p + struct_len;
1682 StrnCpy(p,local_machine,16);
1688 struct srv_info_struct *servers=NULL;
1691 uint32 servertype= lp_default_server_announce();
1693 strcpy(comment,lp_serverstring());
1695 if ((count=get_server_info(SV_TYPE_ALL,&servers,myworkgroup))>0) {
1696 for (i=0;i<count;i++)
1697 if (strequal(servers[i].name,local_machine))
1699 servertype = servers[i].type;
1700 strcpy(comment,servers[i].comment);
1703 if (servers) free(servers);
1705 SCVAL(p,0,lp_major_announce_version());
1706 SCVAL(p,1,lp_minor_announce_version());
1707 SIVAL(p,2,servertype);
1709 if (mdrcnt == struct_len) {
1712 SIVAL(p,6,PTR_DIFF(p2,*rdata));
1713 standard_sub(cnum,comment);
1714 StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
1715 p2 = skip_string(p2,1);
1720 return False; /* not yet implemented */
1723 *rdata_len = PTR_DIFF(p2,*rdata);
1726 *rparam = REALLOC(*rparam,*rparam_len);
1727 SSVAL(*rparam,0,NERR_Success);
1728 SSVAL(*rparam,2,0); /* converter word */
1729 SSVAL(*rparam,4,*rdata_len);
1735 /****************************************************************************
1736 get info about the server
1737 ****************************************************************************/
1738 static BOOL api_NetWkstaGetInfo(int cnum,uint16 vuid, char *param,char *data,
1739 int mdrcnt,int mprcnt,
1740 char **rdata,char **rparam,
1741 int *rdata_len,int *rparam_len)
1743 char *str1 = param+2;
1744 char *str2 = skip_string(str1,1);
1745 char *p = skip_string(str2,1);
1747 extern pstring sesssetup_user;
1748 int level = SVAL(p,0);
1750 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
1753 *rparam = REALLOC(*rparam,*rparam_len);
1755 /* check it's a supported varient */
1756 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz")))
1759 *rdata_len = mdrcnt + 1024;
1760 *rdata = REALLOC(*rdata,*rdata_len);
1762 SSVAL(*rparam,0,NERR_Success);
1763 SSVAL(*rparam,2,0); /* converter word */
1769 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
1770 strcpy(p2,local_machine);
1772 p2 = skip_string(p2,1);
1775 SIVAL(p,0,PTR_DIFF(p2,*rdata));
1776 strcpy(p2,sesssetup_user);
1777 p2 = skip_string(p2,1);
1780 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
1781 strcpy(p2,myworkgroup);
1783 p2 = skip_string(p2,1);
1786 SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
1787 SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
1790 SIVAL(p,0,PTR_DIFF(p2,*rdata));
1791 strcpy(p2,myworkgroup); /* don't know. login domain?? */
1792 p2 = skip_string(p2,1);
1795 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
1797 p2 = skip_string(p2,1);
1800 *rdata_len = PTR_DIFF(p2,*rdata);
1802 SSVAL(*rparam,4,*rdata_len);
1807 /****************************************************************************
1808 get info about a user
1810 struct user_info_11 {
1811 char usri11_name[21]; 0-20
1813 char *usri11_comment; 22-25
1814 char *usri11_usr_comment; 26-29
1815 unsigned short usri11_priv; 30-31
1816 unsigned long usri11_auth_flags; 32-35
1817 long usri11_password_age; 36-39
1818 char *usri11_homedir; 40-43
1819 char *usri11_parms; 44-47
1820 long usri11_last_logon; 48-51
1821 long usri11_last_logoff; 52-55
1822 unsigned short usri11_bad_pw_count; 56-57
1823 unsigned short usri11_num_logons; 58-59
1824 char *usri11_logon_server; 60-63
1825 unsigned short usri11_country_code; 64-65
1826 char *usri11_workstations; 66-69
1827 unsigned long usri11_max_storage; 70-73
1828 unsigned short usri11_units_per_week; 74-75
1829 unsigned char *usri11_logon_hours; 76-79
1830 unsigned short usri11_code_page; 80-81
1835 usri11_name specifies the user name for which information is retireved
1837 usri11_pad aligns the next data structure element to a word boundary
1839 usri11_comment is a null terminated ASCII comment
1841 usri11_user_comment is a null terminated ASCII comment about the user
1843 usri11_priv specifies the level of the privilege assigned to the user.
1844 The possible values are:
1846 Name Value Description
1847 USER_PRIV_GUEST 0 Guest privilege
1848 USER_PRIV_USER 1 User privilege
1849 USER_PRV_ADMIN 2 Administrator privilege
1851 usri11_auth_flags specifies the account operator privileges. The
1852 possible values are:
1854 Name Value Description
1855 AF_OP_PRINT 0 Print operator
1858 Leach, Naik [Page 28]
\r\f
1861 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
1864 AF_OP_COMM 1 Communications operator
1865 AF_OP_SERVER 2 Server operator
1866 AF_OP_ACCOUNTS 3 Accounts operator
1869 usri11_password_age specifies how many seconds have elapsed since the
1870 password was last changed.
1872 usri11_home_dir points to a null terminated ASCII string that contains
1873 the path name of the user's home directory.
1875 usri11_parms points to a null terminated ASCII string that is set
1876 aside for use by applications.
1878 usri11_last_logon specifies the time when the user last logged on.
1879 This value is stored as the number of seconds elapsed since
1880 00:00:00, January 1, 1970.
1882 usri11_last_logoff specifies the time when the user last logged off.
1883 This value is stored as the number of seconds elapsed since
1884 00:00:00, January 1, 1970. A value of 0 means the last logoff
1887 usri11_bad_pw_count specifies the number of incorrect passwords
1888 entered since the last successful logon.
1890 usri11_log1_num_logons specifies the number of times this user has
1891 logged on. A value of -1 means the number of logons is unknown.
1893 usri11_logon_server points to a null terminated ASCII string that
1894 contains the name of the server to which logon requests are sent.
1895 A null string indicates logon requests should be sent to the
1898 usri11_country_code specifies the country code for the user's language
1901 usri11_workstations points to a null terminated ASCII string that
1902 contains the names of workstations the user may log on from.
1903 There may be up to 8 workstations, with the names separated by
1904 commas. A null strings indicates there are no restrictions.
1906 usri11_max_storage specifies the maximum amount of disk space the user
1907 can occupy. A value of 0xffffffff indicates there are no
1910 usri11_units_per_week specifies the equal number of time units into
1911 which a week is divided. This value must be equal to 168.
1913 usri11_logon_hours points to a 21 byte (168 bits) string that
1914 specifies the time during which the user can log on. Each bit
1915 represents one unique hour in a week. The first bit (bit 0, word
1916 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
1920 Leach, Naik [Page 29]
\r\f
1923 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
1926 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
1927 are no restrictions.
1929 usri11_code_page specifies the code page for the user's language of
1932 All of the pointers in this data structure need to be treated
1933 specially. The pointer is a 32 bit pointer. The higher 16 bits need
1934 to be ignored. The converter word returned in the parameters section
1935 needs to be subtracted from the lower 16 bits to calculate an offset
1936 into the return buffer where this ASCII string resides.
1938 There is no auxiliary data in the response.
1940 ****************************************************************************/
1942 #define usri11_name 0
1943 #define usri11_pad 21
1944 #define usri11_comment 22
1945 #define usri11_usr_comment 26
1946 #define usri11_full_name 30
1947 #define usri11_priv 34
1948 #define usri11_auth_flags 36
1949 #define usri11_password_age 40
1950 #define usri11_homedir 44
1951 #define usri11_parms 48
1952 #define usri11_last_logon 52
1953 #define usri11_last_logoff 56
1954 #define usri11_bad_pw_count 60
1955 #define usri11_num_logons 62
1956 #define usri11_logon_server 64
1957 #define usri11_country_code 68
1958 #define usri11_workstations 70
1959 #define usri11_max_storage 74
1960 #define usri11_units_per_week 78
1961 #define usri11_logon_hours 80
1962 #define usri11_code_page 84
1963 #define usri11_end 86
1965 #define USER_PRIV_GUEST 0
1966 #define USER_PRIV_USER 1
1967 #define USER_PRIV_ADMIN 2
1969 #define AF_OP_PRINT 0
1970 #define AF_OP_COMM 1
1971 #define AF_OP_SERVER 2
1972 #define AF_OP_ACCOUNTS 3
1975 static BOOL api_RNetUserGetInfo(int cnum,uint16 vuid, char *param,char *data,
1976 int mdrcnt,int mprcnt,
1977 char **rdata,char **rparam,
1978 int *rdata_len,int *rparam_len)
1980 char *str1 = param+2;
1981 char *str2 = skip_string(str1,1);
1982 char *UserName = skip_string(str2,1);
1983 char *p = skip_string(UserName,1);
1984 int uLevel = SVAL(p,0);
1987 /* get NIS home of a previously validated user - simeon */
1988 user_struct *vuser = get_valid_user_struct(vuid);
1989 DEBUG(3,(" Username of UID %d is %s\n", vuser->uid, vuser->name));
1990 #if (defined(NETGROUP) && defined(AUTOMOUNT))
1991 DEBUG(3,(" HOMESHR for %s is %s\n", vuser->name, vuser->home_share));
1995 *rparam = REALLOC(*rparam,*rparam_len);
1997 /* check it's a supported variant */
1998 if (strcmp(str1,"zWrLh") != 0) return False;
2001 case 0: p2 = "B21"; break;
2002 case 1: p2 = "B21BB16DWzzWz"; break;
2003 case 2: p2 = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
2004 case 10: p2 = "B21Bzzz"; break;
2005 case 11: p2 = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
2006 default: return False;
2009 if (strcmp(p2,str2) != 0) return False;
2011 *rdata_len = mdrcnt + 1024;
2012 *rdata = REALLOC(*rdata,*rdata_len);
2014 SSVAL(*rparam,0,NERR_Success);
2015 SSVAL(*rparam,2,0); /* converter word */
2018 p2 = p + usri11_end;
2021 strcpy(p+usri11_name,UserName); /* 21 bytes - user name */
2025 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
2030 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
2031 strcpy(p2,"Comment");
2032 p2 = skip_string(p2,1);
2034 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
2035 strcpy(p2,"UserComment");
2036 p2 = skip_string(p2,1);
2038 /* EEK! the cifsrap.txt doesn't have this in!!!! */
2039 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
2040 strcpy(p2,vuser->real_name); /* simeon */
2041 p2 = skip_string(p2,1);
2044 if (uLevel == 11) /* modelled after NTAS 3.51 reply */
2046 SSVAL(p,usri11_priv,Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2047 SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
2048 SIVALS(p,usri11_password_age,0xffffffff); /* password age */
2049 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
2050 if (*lp_logon_path())
2052 strcpy(p2,lp_logon_path());
2056 #if (defined(NETGROUP) && defined(AUTOMOUNT))
2057 strcpy(p2, vuser->home_share);
2059 strcpy(p2,"\\\\%L\\%U");
2062 standard_sub_basic(p2);
2063 p2 = skip_string(p2,1);
2064 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
2066 p2 = skip_string(p2,1);
2067 SIVAL(p,usri11_last_logon,0); /* last logon */
2068 SIVAL(p,usri11_last_logoff,0); /* last logoff */
2069 SSVALS(p,usri11_bad_pw_count,0xffffffff); /* bad pw counts */
2070 SSVALS(p,usri11_num_logons,0xffffffff); /* num logons */
2071 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
2073 p2 = skip_string(p2,1);
2074 SSVAL(p,usri11_country_code,0); /* country code */
2076 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
2078 p2 = skip_string(p2,1);
2080 SIVALS(p,usri11_max_storage,0xffffffff); /* max storage */
2081 SSVAL(p,usri11_units_per_week,168); /* units per week */
2082 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
2084 /* a simple way to get logon hours at all times. */
2086 SCVAL(p2,21,0); /* fix zero termination */
2087 p2 = skip_string(p2,1);
2089 SSVAL(p,usri11_code_page,0); /* code page */
2091 if (uLevel == 1 || uLevel == 2)
2093 memset(p+22,' ',16); /* password */
2094 SIVALS(p,38,-1); /* password age */
2096 Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2097 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
2098 if (*lp_logon_path())
2100 strcpy(p2,lp_logon_path());
2104 #if (defined(NETGROUP) && defined(AUTOMOUNT))
2105 strcpy(p2, vuser->home_share);
2107 strcpy(p2,"\\\\%L\\%U");
2110 standard_sub_basic(p2);
2111 p2 = skip_string(p2,1);
2112 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
2114 SSVAL(p,52,0); /* flags */
2115 SIVAL(p,54,0); /* script_path */
2118 SIVAL(p,60,0); /* auth_flags */
2119 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
2120 strcpy(p2,vuser->real_name); /* simeon */
2121 p2 = skip_string(p2,1);
2122 SIVAL(p,68,0); /* urs_comment */
2123 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
2125 p2 = skip_string(p2,1);
2126 SIVAL(p,76,0); /* workstations */
2127 SIVAL(p,80,0); /* last_logon */
2128 SIVAL(p,84,0); /* last_logoff */
2129 SIVALS(p,88,-1); /* acct_expires */
2130 SIVALS(p,92,-1); /* max_storage */
2131 SSVAL(p,96,168); /* units_per_week */
2132 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
2135 SSVALS(p,102,-1); /* bad_pw_count */
2136 SSVALS(p,104,-1); /* num_logons */
2137 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
2138 strcpy(p2,"\\\\%L");
2139 standard_sub_basic(p2);
2140 p2 = skip_string(p2,1);
2141 SSVAL(p,110,49); /* country_code */
2142 SSVAL(p,112,860); /* code page */
2146 *rdata_len = PTR_DIFF(p2,*rdata);
2148 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
2153 /*******************************************************************
2154 get groups that a user is a member of
2155 ******************************************************************/
2156 static BOOL api_NetUserGetGroups(int cnum,uint16 vuid, char *param,char *data,
2157 int mdrcnt,int mprcnt,
2158 char **rdata,char **rparam,
2159 int *rdata_len,int *rparam_len)
2161 char *str1 = param+2;
2162 char *str2 = skip_string(str1,1);
2163 char *UserName = skip_string(str2,1);
2164 char *p = skip_string(UserName,1);
2165 int uLevel = SVAL(p,0);
2170 *rparam = REALLOC(*rparam,*rparam_len);
2172 /* check it's a supported varient */
2173 if (strcmp(str1,"zWrLeh") != 0) return False;
2175 case 0: p2 = "B21"; break;
2176 default: return False;
2178 if (strcmp(p2,str2) != 0) return False;
2180 *rdata_len = mdrcnt + 1024;
2181 *rdata = REALLOC(*rdata,*rdata_len);
2183 SSVAL(*rparam,0,NERR_Success);
2184 SSVAL(*rparam,2,0); /* converter word */
2188 /* XXXX we need a real SAM database some day */
2189 strcpy(p,"Users"); p += 21; count++;
2190 strcpy(p,"Domain Users"); p += 21; count++;
2191 strcpy(p,"Guests"); p += 21; count++;
2192 strcpy(p,"Domain Guests"); p += 21; count++;
2194 *rdata_len = PTR_DIFF(p,*rdata);
2196 SSVAL(*rparam,4,count); /* is this right?? */
2197 SSVAL(*rparam,6,count); /* is this right?? */
2203 static BOOL api_WWkstaUserLogon(int cnum,uint16 vuid, char *param,char *data,
2204 int mdrcnt,int mprcnt,
2205 char **rdata,char **rparam,
2206 int *rdata_len,int *rparam_len)
2208 char *str1 = param+2;
2209 char *str2 = skip_string(str1,1);
2210 char *p = skip_string(str2,1);
2212 struct pack_desc desc;
2218 bzero(&desc,sizeof(desc));
2220 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
2222 /* check it's a supported varient */
2223 if (strcmp(str1,"OOWb54WrLh") != 0) return False;
2224 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) return False;
2225 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2227 desc.buflen = mdrcnt;
2228 desc.subformat = NULL;
2231 if (init_package(&desc,1,0))
2233 PACKI(&desc,"W",0); /* code */
2234 PACKS(&desc,"B21",name); /* eff. name */
2235 PACKS(&desc,"B",""); /* pad */
2237 Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2238 PACKI(&desc,"D",0); /* auth flags XXX */
2239 PACKI(&desc,"W",0); /* num logons */
2240 PACKI(&desc,"W",0); /* bad pw count */
2241 PACKI(&desc,"D",0); /* last logon */
2242 PACKI(&desc,"D",-1); /* last logoff */
2243 PACKI(&desc,"D",-1); /* logoff time */
2244 PACKI(&desc,"D",-1); /* kickoff time */
2245 PACKI(&desc,"D",0); /* password age */
2246 PACKI(&desc,"D",0); /* password can change */
2247 PACKI(&desc,"D",-1); /* password must change */
2250 strcpy(mypath,"\\\\");
2251 strcat(mypath,local_machine);
2253 PACKS(&desc,"z",mypath); /* computer */
2255 PACKS(&desc,"z",myworkgroup);/* domain */
2256 PACKS(&desc,"z",lp_logon_script()); /* script path */
2257 PACKI(&desc,"D",0x00000000); /* reserved */
2260 *rdata_len = desc.usedlen;
2262 *rparam = REALLOC(*rparam,*rparam_len);
2263 SSVALS(*rparam,0,desc.errcode);
2265 SSVAL(*rparam,4,desc.neededlen);
2267 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
2272 /****************************************************************************
2273 api_WAccessGetUserPerms
2274 ****************************************************************************/
2275 static BOOL api_WAccessGetUserPerms(int cnum,uint16 vuid, char *param,char *data,
2276 int mdrcnt,int mprcnt,
2277 char **rdata,char **rparam,
2278 int *rdata_len,int *rparam_len)
2280 char *str1 = param+2;
2281 char *str2 = skip_string(str1,1);
2282 char *user = skip_string(str2,1);
2283 char *resource = skip_string(user,1);
2285 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
2287 /* check it's a supported varient */
2288 if (strcmp(str1,"zzh") != 0) return False;
2289 if (strcmp(str2,"") != 0) return False;
2292 *rparam = REALLOC(*rparam,*rparam_len);
2293 SSVALS(*rparam,0,0); /* errorcode */
2294 SSVAL(*rparam,2,0); /* converter word */
2295 SSVAL(*rparam,4,0x7f); /* permission flags */
2300 /****************************************************************************
2301 api_WPrintJobEnumerate
2302 ****************************************************************************/
2303 static BOOL api_WPrintJobGetInfo(int cnum,uint16 vuid, char *param,char *data,
2304 int mdrcnt,int mprcnt,
2305 char **rdata,char **rparam,
2306 int *rdata_len,int *rparam_len)
2308 char *str1 = param+2;
2309 char *str2 = skip_string(str1,1);
2310 char *p = skip_string(str2,1);
2311 int uJobId = SVAL(p,0);
2317 struct pack_desc desc;
2318 print_queue_struct *queue=NULL;
2319 print_status_struct status;
2324 bzero(&desc,sizeof(desc));
2325 bzero(&status,sizeof(status));
2327 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,uJobId));
2329 /* check it's a supported varient */
2330 if (strcmp(str1,"WWrLh") != 0) return False;
2331 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2333 snum = (unsigned int)uJobId >> 8; /*## valid serice number??*/
2334 job = uJobId & 0xFF;
2336 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2338 count = get_printqueue(snum,cnum,&queue,&status);
2339 for (i = 0; i < count; i++) {
2340 if ((queue[i].job % 0xFF) == job) break;
2342 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2344 desc.buflen = mdrcnt;
2346 if (init_package(&desc,1,0)) {
2348 fill_printjob_info(cnum,snum,uLevel,&desc,&queue[i],i);
2349 *rdata_len = desc.usedlen;
2352 desc.errcode = NERR_JobNotFound;
2358 *rparam = REALLOC(*rparam,*rparam_len);
2359 SSVALS(*rparam,0,desc.errcode);
2361 SSVAL(*rparam,4,desc.neededlen);
2363 if (queue) free(queue);
2365 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
2369 static BOOL api_WPrintJobEnumerate(int cnum,uint16 vuid, char *param,char *data,
2370 int mdrcnt,int mprcnt,
2371 char **rdata,char **rparam,
2372 int *rdata_len,int *rparam_len)
2374 char *str1 = param+2;
2375 char *str2 = skip_string(str1,1);
2376 char *p = skip_string(str2,1);
2382 struct pack_desc desc;
2383 print_queue_struct *queue=NULL;
2384 print_status_struct status;
2386 bzero(&desc,sizeof(desc));
2387 bzero(&status,sizeof(status));
2389 p = skip_string(p,1);
2393 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
2395 /* check it's a supported varient */
2396 if (strcmp(str1,"zWrLeh") != 0) return False;
2397 if (uLevel > 2) return False; /* defined only for uLevel 0,1,2 */
2398 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2400 snum = lp_servicenumber(name);
2401 if (snum < 0 && pcap_printername_ok(name,NULL)) {
2402 int pnum = lp_servicenumber(PRINTERS_NAME);
2404 lp_add_printer(name,pnum);
2405 snum = lp_servicenumber(name);
2409 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2411 count = get_printqueue(snum,cnum,&queue,&status);
2412 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2414 desc.buflen = mdrcnt;
2416 if (init_package(&desc,count,0)) {
2418 for (i = 0; i < count; i++) {
2419 fill_printjob_info(cnum,snum,uLevel,&desc,&queue[i],i);
2420 if (desc.errcode == NERR_Success) succnt = i+1;
2424 *rdata_len = desc.usedlen;
2427 *rparam = REALLOC(*rparam,*rparam_len);
2428 SSVALS(*rparam,0,desc.errcode);
2430 SSVAL(*rparam,4,succnt);
2431 SSVAL(*rparam,6,count);
2433 if (queue) free(queue);
2435 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
2439 static int check_printdest_info(struct pack_desc* desc,
2440 int uLevel, char* id)
2442 desc->subformat = NULL;
2444 case 0: desc->format = "B9"; break;
2445 case 1: desc->format = "B9B21WWzW"; break;
2446 case 2: desc->format = "z"; break;
2447 case 3: desc->format = "zzzWWzzzWW"; break;
2448 default: return False;
2450 if (strcmp(desc->format,id) != 0) return False;
2454 static void fill_printdest_info(int cnum, int snum, int uLevel,
2455 struct pack_desc* desc)
2458 strcpy(buf,SERVICE(snum));
2461 PACKS(desc,"B9",buf); /* szName */
2463 PACKS(desc,"B21",""); /* szUserName */
2464 PACKI(desc,"W",0); /* uJobId */
2465 PACKI(desc,"W",0); /* fsStatus */
2466 PACKS(desc,"z",""); /* pszStatus */
2467 PACKI(desc,"W",0); /* time */
2470 if (uLevel == 2 || uLevel == 3) {
2471 PACKS(desc,"z",buf); /* pszPrinterName */
2473 PACKS(desc,"z",""); /* pszUserName */
2474 PACKS(desc,"z",""); /* pszLogAddr */
2475 PACKI(desc,"W",0); /* uJobId */
2476 PACKI(desc,"W",0); /* fsStatus */
2477 PACKS(desc,"z",""); /* pszStatus */
2478 PACKS(desc,"z",""); /* pszComment */
2479 PACKS(desc,"z","NULL"); /* pszDrivers */
2480 PACKI(desc,"W",0); /* time */
2481 PACKI(desc,"W",0); /* pad1 */
2486 static BOOL api_WPrintDestGetInfo(int cnum,uint16 vuid, char *param,char *data,
2487 int mdrcnt,int mprcnt,
2488 char **rdata,char **rparam,
2489 int *rdata_len,int *rparam_len)
2491 char *str1 = param+2;
2492 char *str2 = skip_string(str1,1);
2493 char *p = skip_string(str2,1);
2494 char* PrinterName = p;
2496 struct pack_desc desc;
2499 bzero(&desc,sizeof(desc));
2501 p = skip_string(p,1);
2505 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
2507 /* check it's a supported varient */
2508 if (strcmp(str1,"zWrLh") != 0) return False;
2509 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2511 snum = lp_servicenumber(PrinterName);
2512 if (snum < 0 && pcap_printername_ok(PrinterName,NULL)) {
2513 int pnum = lp_servicenumber(PRINTERS_NAME);
2515 lp_add_printer(PrinterName,pnum);
2516 snum = lp_servicenumber(PrinterName);
2522 desc.errcode = NERR_DestNotFound;
2526 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2528 desc.buflen = mdrcnt;
2529 if (init_package(&desc,1,0)) {
2530 fill_printdest_info(cnum,snum,uLevel,&desc);
2532 *rdata_len = desc.usedlen;
2536 *rparam = REALLOC(*rparam,*rparam_len);
2537 SSVALS(*rparam,0,desc.errcode);
2539 SSVAL(*rparam,4,desc.neededlen);
2541 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
2545 static BOOL api_WPrintDestEnum(int cnum,uint16 vuid, char *param,char *data,
2546 int mdrcnt,int mprcnt,
2547 char **rdata,char **rparam,
2548 int *rdata_len,int *rparam_len)
2550 char *str1 = param+2;
2551 char *str2 = skip_string(str1,1);
2552 char *p = skip_string(str2,1);
2556 struct pack_desc desc;
2557 int services = lp_numservices();
2559 bzero(&desc,sizeof(desc));
2564 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
2566 /* check it's a supported varient */
2567 if (strcmp(str1,"WrLeh") != 0) return False;
2568 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2571 for (i = 0; i < services; i++)
2572 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
2575 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2577 desc.buflen = mdrcnt;
2578 if (init_package(&desc,queuecnt,0)) {
2581 for (i = 0; i < services; i++) {
2582 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
2583 fill_printdest_info(cnum,i,uLevel,&desc);
2585 if (desc.errcode == NERR_Success) succnt = n;
2590 *rdata_len = desc.usedlen;
2593 *rparam = REALLOC(*rparam,*rparam_len);
2594 SSVALS(*rparam,0,desc.errcode);
2596 SSVAL(*rparam,4,succnt);
2597 SSVAL(*rparam,6,queuecnt);
2599 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
2603 static BOOL api_WPrintDriverEnum(int cnum,uint16 vuid, char *param,char *data,
2604 int mdrcnt,int mprcnt,
2605 char **rdata,char **rparam,
2606 int *rdata_len,int *rparam_len)
2608 char *str1 = param+2;
2609 char *str2 = skip_string(str1,1);
2610 char *p = skip_string(str2,1);
2613 struct pack_desc desc;
2615 bzero(&desc,sizeof(desc));
2620 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
2622 /* check it's a supported varient */
2623 if (strcmp(str1,"WrLeh") != 0) return False;
2624 if (uLevel != 0 || strcmp(str2,"B41") != 0) return False;
2626 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2628 desc.buflen = mdrcnt;
2629 if (init_package(&desc,1,0)) {
2630 PACKS(&desc,"B41","NULL");
2633 succnt = (desc.errcode == NERR_Success ? 1 : 0);
2635 *rdata_len = desc.usedlen;
2638 *rparam = REALLOC(*rparam,*rparam_len);
2639 SSVALS(*rparam,0,desc.errcode);
2641 SSVAL(*rparam,4,succnt);
2644 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
2648 static BOOL api_WPrintQProcEnum(int cnum,uint16 vuid, char *param,char *data,
2649 int mdrcnt,int mprcnt,
2650 char **rdata,char **rparam,
2651 int *rdata_len,int *rparam_len)
2653 char *str1 = param+2;
2654 char *str2 = skip_string(str1,1);
2655 char *p = skip_string(str2,1);
2658 struct pack_desc desc;
2660 bzero(&desc,sizeof(desc));
2665 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
2667 /* check it's a supported varient */
2668 if (strcmp(str1,"WrLeh") != 0) return False;
2669 if (uLevel != 0 || strcmp(str2,"B13") != 0) return False;
2671 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2673 desc.buflen = mdrcnt;
2675 if (init_package(&desc,1,0)) {
2676 PACKS(&desc,"B13","lpd");
2679 succnt = (desc.errcode == NERR_Success ? 1 : 0);
2681 *rdata_len = desc.usedlen;
2684 *rparam = REALLOC(*rparam,*rparam_len);
2685 SSVALS(*rparam,0,desc.errcode);
2687 SSVAL(*rparam,4,succnt);
2690 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
2694 static BOOL api_WPrintPortEnum(int cnum,uint16 vuid, char *param,char *data,
2695 int mdrcnt,int mprcnt,
2696 char **rdata,char **rparam,
2697 int *rdata_len,int *rparam_len)
2699 char *str1 = param+2;
2700 char *str2 = skip_string(str1,1);
2701 char *p = skip_string(str2,1);
2704 struct pack_desc desc;
2706 bzero(&desc,sizeof(desc));
2711 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
2713 /* check it's a supported varient */
2714 if (strcmp(str1,"WrLeh") != 0) return False;
2715 if (uLevel != 0 || strcmp(str2,"B9") != 0) return False;
2717 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2718 bzero(&desc,sizeof(desc));
2720 desc.buflen = mdrcnt;
2722 if (init_package(&desc,1,0)) {
2723 PACKS(&desc,"B13","lp0");
2726 succnt = (desc.errcode == NERR_Success ? 1 : 0);
2728 *rdata_len = desc.usedlen;
2731 *rparam = REALLOC(*rparam,*rparam_len);
2732 SSVALS(*rparam,0,desc.errcode);
2734 SSVAL(*rparam,4,succnt);
2737 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
2748 } api_fd_commands [] =
2750 { "SetNmdPpHndState", "lsarpc", 1, api_LsarpcSNPHS },
2751 { "TransactNmPipe", "lsarpc", 0x26, api_LsarpcTNP },
2752 { NULL, NULL, -1, (BOOL (*)())api_Unsupported }
2755 /****************************************************************************
2756 handle remote api calls delivered to a named pipe already opened.
2757 ****************************************************************************/
2758 static int api_fd_reply(int cnum,uint16 vuid,char *outbuf,
2759 uint16 *setup,char *data,char *params,
2760 int suwcnt,int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
2763 char *rparam = NULL;
2771 /* First find out the name of this file. */
2774 DEBUG(0,("Unexpected named pipe transaction.\n"));
2778 /* Get the file handle and hence the file name. */
2780 subcommand = setup[0];
2782 DEBUG(3,("Got API command %d on pipe %s ",subcommand,Files[fd].name));
2783 DEBUG(3,("(tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
2784 tdscnt,tpscnt,mdrcnt,mprcnt));
2786 for (i=0;api_fd_commands[i].name;i++)
2787 if (strequal(api_fd_commands[i].pipename, Files[fd].name) &&
2788 api_fd_commands[i].subcommand == subcommand &&
2789 api_fd_commands[i].fn)
2791 DEBUG(3,("Doing %s\n",api_fd_commands[i].name));
2795 rdata = (char *)malloc(1024); if (rdata) bzero(rdata,1024);
2796 rparam = (char *)malloc(1024); if (rparam) bzero(rparam,1024);
2798 reply = api_fd_commands[i].fn(cnum,vuid,params,data,mdrcnt,mprcnt,
2799 &rdata,&rparam,&rdata_len,&rparam_len);
2801 if (rdata_len > mdrcnt ||
2802 rparam_len > mprcnt)
2804 reply = api_TooSmall(cnum,vuid,params,data,mdrcnt,mprcnt,
2805 &rdata,&rparam,&rdata_len,&rparam_len);
2809 /* if we get False back then it's actually unsupported */
2811 api_Unsupported(cnum,vuid,params,data,mdrcnt,mprcnt,
2812 &rdata,&rparam,&rdata_len,&rparam_len);
2814 /* now send the reply */
2815 send_trans_reply(outbuf,rdata,rparam,NULL,rdata_len,rparam_len,0);
2827 /****************************************************************************
2828 the buffer was too small
2829 ****************************************************************************/
2830 static BOOL api_TooSmall(int cnum,uint16 vuid, char *param,char *data,
2831 int mdrcnt,int mprcnt,
2832 char **rdata,char **rparam,
2833 int *rdata_len,int *rparam_len)
2835 *rparam_len = MIN(*rparam_len,mprcnt);
2836 *rparam = REALLOC(*rparam,*rparam_len);
2840 SSVAL(*rparam,0,NERR_BufTooSmall);
2842 DEBUG(3,("Supplied buffer too small in API command\n"));
2848 /****************************************************************************
2849 the request is not supported
2850 ****************************************************************************/
2851 static BOOL api_Unsupported(int cnum,uint16 vuid, char *param,char *data,
2852 int mdrcnt,int mprcnt,
2853 char **rdata,char **rparam,
2854 int *rdata_len,int *rparam_len)
2857 *rparam = REALLOC(*rparam,*rparam_len);
2861 SSVAL(*rparam,0,NERR_notsupported);
2862 SSVAL(*rparam,2,0); /* converter word */
2864 DEBUG(3,("Unsupported API command\n"));
2878 } api_commands[] = {
2879 {"RNetShareEnum", 0, (BOOL (*)())api_RNetShareEnum,0},
2880 {"RNetShareGetInfo", 1, (BOOL (*)())api_RNetShareGetInfo,0},
2881 {"RNetServerGetInfo", 13, (BOOL (*)())api_RNetServerGetInfo,0},
2882 {"RNetUserGetInfo", 56, (BOOL (*)())api_RNetUserGetInfo,0},
2883 {"NetUserGetGroups", 59, (BOOL (*)())api_NetUserGetGroups,0},
2884 {"NetWkstaGetInfo", 63, (BOOL (*)())api_NetWkstaGetInfo,0},
2885 {"DosPrintQEnum", 69, (BOOL (*)())api_DosPrintQEnum,0},
2886 {"DosPrintQGetInfo", 70, (BOOL (*)())api_DosPrintQGetInfo,0},
2887 {"WPrintJobEnumerate",76, (BOOL (*)())api_WPrintJobEnumerate,0},
2888 {"WPrintJobGetInfo", 77, (BOOL (*)())api_WPrintJobGetInfo,0},
2889 {"RDosPrintJobDel", 81, (BOOL (*)())api_RDosPrintJobDel,0},
2890 {"RDosPrintJobPause", 82, (BOOL (*)())api_RDosPrintJobDel,0},
2891 {"RDosPrintJobResume",83, (BOOL (*)())api_RDosPrintJobDel,0},
2892 {"WPrintDestEnum", 84, (BOOL (*)())api_WPrintDestEnum,0},
2893 {"WPrintDestGetInfo", 85, (BOOL (*)())api_WPrintDestGetInfo,0},
2894 {"NetRemoteTOD", 91, (BOOL (*)())api_NetRemoteTOD,0},
2895 {"WPrintQueuePurge", 103, (BOOL (*)())api_WPrintQueuePurge,0},
2896 {"NetServerEnum", 104, (BOOL (*)())api_RNetServerEnum,0},
2897 {"WAccessGetUserPerms",105, (BOOL (*)())api_WAccessGetUserPerms,0},
2898 {"SetUserPassword", 115, (BOOL (*)())api_SetUserPassword,0},
2899 {"WWkstaUserLogon", 132, (BOOL (*)())api_WWkstaUserLogon,0},
2900 {"PrintJobInfo", 147, (BOOL (*)())api_PrintJobInfo,0},
2901 {"WPrintDriverEnum", 205, (BOOL (*)())api_WPrintDriverEnum,0},
2902 {"WPrintQProcEnum", 206, (BOOL (*)())api_WPrintQProcEnum,0},
2903 {"WPrintPortEnum", 207, (BOOL (*)())api_WPrintPortEnum,0},
2904 {NULL, -1, (BOOL (*)())api_Unsupported,0}};
2907 /****************************************************************************
2908 handle remote api calls
2909 ****************************************************************************/
2910 static int api_reply(int cnum,uint16 vuid,char *outbuf,char *data,char *params,
2911 int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
2913 int api_command = SVAL(params,0);
2915 char *rparam = NULL;
2921 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
2922 api_command,params+2,skip_string(params+2,1),
2923 tdscnt,tpscnt,mdrcnt,mprcnt));
2925 for (i=0;api_commands[i].name;i++)
2926 if (api_commands[i].id == api_command && api_commands[i].fn)
2928 DEBUG(3,("Doing %s\n",api_commands[i].name));
2932 rdata = (char *)malloc(1024); if (rdata) bzero(rdata,1024);
2933 rparam = (char *)malloc(1024); if (rparam) bzero(rparam,1024);
2935 reply = api_commands[i].fn(cnum,vuid,params,data,mdrcnt,mprcnt,
2936 &rdata,&rparam,&rdata_len,&rparam_len);
2939 if (rdata_len > mdrcnt ||
2940 rparam_len > mprcnt)
2942 reply = api_TooSmall(cnum,vuid,params,data,mdrcnt,mprcnt,
2943 &rdata,&rparam,&rdata_len,&rparam_len);
2947 /* if we get False back then it's actually unsupported */
2949 api_Unsupported(cnum,vuid,params,data,mdrcnt,mprcnt,
2950 &rdata,&rparam,&rdata_len,&rparam_len);
2954 /* now send the reply */
2955 send_trans_reply(outbuf,rdata,rparam,NULL,rdata_len,rparam_len,0);
2965 /****************************************************************************
2966 handle named pipe commands
2967 ****************************************************************************/
2968 static int named_pipe(int cnum,uint16 vuid, char *outbuf,char *name,
2969 uint16 *setup,char *data,char *params,
2970 int suwcnt,int tdscnt,int tpscnt,
2971 int msrcnt,int mdrcnt,int mprcnt)
2974 if (strequal(name,"LANMAN"))
2975 return(api_reply(cnum,vuid,outbuf,data,params,tdscnt,tpscnt,mdrcnt,mprcnt));
2977 if (strlen(name) < 1)
2978 return(api_fd_reply(cnum,vuid,outbuf,setup,data,params,suwcnt,tdscnt,tpscnt,mdrcnt,mprcnt));
2981 DEBUG(3,("named pipe command on <%s> 0x%X setup1=%d\n",
2982 name,(int)setup[0],(int)setup[1]));
2988 /****************************************************************************
2990 ****************************************************************************/
2991 int reply_trans(char *inbuf,char *outbuf)
2995 char *data=NULL,*params=NULL;
2999 int cnum = SVAL(inbuf,smb_tid);
3000 uint16 vuid = SVAL(inbuf,smb_uid);
3002 int tpscnt = SVAL(inbuf,smb_vwv0);
3003 int tdscnt = SVAL(inbuf,smb_vwv1);
3004 int mprcnt = SVAL(inbuf,smb_vwv2);
3005 int mdrcnt = SVAL(inbuf,smb_vwv3);
3006 int msrcnt = CVAL(inbuf,smb_vwv4);
3007 BOOL close_on_completion = BITSETW(inbuf+smb_vwv5,0);
3008 BOOL one_way = BITSETW(inbuf+smb_vwv5,1);
3009 int pscnt = SVAL(inbuf,smb_vwv9);
3010 int psoff = SVAL(inbuf,smb_vwv10);
3011 int dscnt = SVAL(inbuf,smb_vwv11);
3012 int dsoff = SVAL(inbuf,smb_vwv12);
3013 int suwcnt = CVAL(inbuf,smb_vwv13);
3015 StrnCpy(name,smb_buf(inbuf),sizeof(name)-1);
3019 data = (char *)malloc(tdscnt);
3020 memcpy(data,smb_base(inbuf)+dsoff,dscnt);
3024 params = (char *)malloc(tpscnt);
3025 memcpy(params,smb_base(inbuf)+psoff,pscnt);
3031 setup = (uint16 *)malloc(suwcnt*sizeof(setup[0]));
3032 for (i=0;i<suwcnt;i++)
3033 setup[i] = SVAL(inbuf,smb_vwv14+i*SIZEOFWORD);
3037 if (pscnt < tpscnt || dscnt < tdscnt)
3039 /* We need to send an interim response then receive the rest
3040 of the parameter/data bytes */
3041 outsize = set_message(outbuf,0,0,True);
3043 send_smb(Client,outbuf);
3046 /* receive the rest of the trans packet */
3047 while (pscnt < tpscnt || dscnt < tdscnt)
3049 int pcnt,poff,dcnt,doff,pdisp,ddisp;
3051 if (!receive_smb(Client,inbuf, SMB_SECONDARY_WAIT) ||
3052 CVAL(inbuf, smb_com) != SMBtrans)
3054 DEBUG(2,("Invalid secondary trans2 packet\n"));
3055 if (params) free(params);
3056 if (data) free(data);
3057 if (setup) free(setup);
3058 return(ERROR(ERRSRV,ERRerror));
3063 tpscnt = SVAL(inbuf,smb_vwv0);
3064 tdscnt = SVAL(inbuf,smb_vwv1);
3066 pcnt = SVAL(inbuf,smb_vwv2);
3067 poff = SVAL(inbuf,smb_vwv3);
3068 pdisp = SVAL(inbuf,smb_vwv4);
3070 dcnt = SVAL(inbuf,smb_vwv5);
3071 doff = SVAL(inbuf,smb_vwv6);
3072 ddisp = SVAL(inbuf,smb_vwv7);
3078 memcpy(params+pdisp,smb_base(inbuf)+poff,pcnt);
3080 memcpy(data+ddisp,smb_base(inbuf)+doff,dcnt);
3084 DEBUG(3,("trans <%s> data=%d params=%d setup=%d\n",name,tdscnt,tpscnt,suwcnt));
3087 if (strncmp(name,"\\PIPE\\",strlen("\\PIPE\\")) == 0)
3088 outsize = named_pipe(cnum,vuid,outbuf,name+strlen("\\PIPE\\"),setup,data,params,
3089 suwcnt,tdscnt,tpscnt,msrcnt,mdrcnt,mprcnt);
3092 if (data) free(data);
3093 if (params) free(params);
3094 if (setup) free(setup);
3096 if (close_on_completion)
3097 close_cnum(cnum,vuid);
3103 return(ERROR(ERRSRV,ERRnosupport));