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, 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",printjob_encode(snum, queue->job)); /* 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 pstrcpy(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 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
995 any other bit (they may just set this bit on it's own) they
996 want all the locally seen servers. However this bit can be
997 set on its own so set the requested servers to be
998 ALL - DOMAIN_ENUM. */
1000 if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM))
1001 servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
1003 domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
1004 local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
1008 if (!prefix_ok(str1,"WrLehD")) return False;
1009 if (!check_server_info(uLevel,str2)) return False;
1011 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1012 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1013 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1015 if (strcmp(str1, "WrLehDz") == 0) {
1016 StrnCpy(domain, p, sizeof(fstring)-1);
1018 StrnCpy(domain, myworkgroup, sizeof(fstring)-1);
1021 if (lp_browse_list())
1022 total = get_server_info(servertype,&servers,domain);
1024 data_len = fixed_len = string_len = 0;
1027 qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
1030 char *lastname=NULL;
1032 for (i=0;i<total;i++)
1034 struct srv_info_struct *s = &servers[i];
1035 if (lastname && strequal(lastname,s->name)) continue;
1037 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1038 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1039 s->name, s->type, s->comment, s->domain));
1041 if (data_len <= buf_len) {
1044 string_len += s_len;
1051 *rdata_len = fixed_len + string_len;
1052 *rdata = REALLOC(*rdata,*rdata_len);
1053 bzero(*rdata,*rdata_len);
1055 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1061 char *lastname=NULL;
1062 int count2 = counted;
1063 for (i = 0; i < total && count2;i++)
1065 struct srv_info_struct *s = &servers[i];
1066 if (lastname && strequal(lastname,s->name)) continue;
1068 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1069 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1070 s->name, s->type, s->comment, s->domain));
1076 *rparam = REALLOC(*rparam,*rparam_len);
1077 SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERROR_MORE_DATA));
1079 SSVAL(*rparam,4,counted);
1080 SSVAL(*rparam,6,counted+missed);
1082 if (servers) free(servers);
1084 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1085 domain,uLevel,counted,counted+missed));
1091 /****************************************************************************
1092 get info about a share
1093 ****************************************************************************/
1094 static BOOL check_share_info(int uLevel, char* id)
1098 if (strcmp(id,"B13") != 0) return False;
1101 if (strcmp(id,"B13BWz") != 0) return False;
1104 if (strcmp(id,"B13BWzWWWzB9B") != 0) return False;
1107 if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) return False;
1109 default: return False;
1114 static int fill_share_info(int cnum, int snum, int uLevel,
1115 char** buf, int* buflen,
1116 char** stringbuf, int* stringspace, char* baseaddr)
1125 case 0: struct_len = 13; break;
1126 case 1: struct_len = 20; break;
1127 case 2: struct_len = 40; break;
1128 case 91: struct_len = 68; break;
1136 if (uLevel > 0) len += StrlenExpanded(cnum,snum,lp_comment(snum));
1137 if (uLevel > 1) len += strlen(lp_pathname(snum)) + 1;
1138 if (buflen) *buflen = struct_len;
1139 if (stringspace) *stringspace = len;
1140 return struct_len + len;
1145 if ((*buflen) < struct_len) return -1;
1153 p2 = p + struct_len;
1154 l2 = (*buflen) - struct_len;
1156 if (!baseaddr) baseaddr = p;
1158 StrnCpy(p,lp_servicename(snum),13);
1164 type = STYPE_DISKTREE;
1165 if (lp_print_ok(snum)) type = STYPE_PRINTQ;
1166 if (strequal("IPC$",lp_servicename(snum))) type = STYPE_IPC;
1167 SSVAL(p,14,type); /* device type */
1168 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1169 len += CopyExpanded(cnum,snum,&p2,lp_comment(snum),&l2);
1174 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1175 SSVALS(p,22,-1); /* max uses */
1176 SSVAL(p,24,1); /* current uses */
1177 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1178 len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1179 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1184 memset(p+40,0,SHPWLEN+2);
1196 (*buf) = p + struct_len;
1197 (*buflen) -= struct_len;
1199 (*stringspace) = l2;
1209 static BOOL api_RNetShareGetInfo(int cnum,uint16 vuid, char *param,char *data,
1210 int mdrcnt,int mprcnt,
1211 char **rdata,char **rparam,
1212 int *rdata_len,int *rparam_len)
1214 char *str1 = param+2;
1215 char *str2 = skip_string(str1,1);
1216 char *netname = skip_string(str2,1);
1217 char *p = skip_string(netname,1);
1218 int uLevel = SVAL(p,0);
1219 int snum = find_service(netname);
1221 if (snum < 0) return False;
1223 /* check it's a supported varient */
1224 if (!prefix_ok(str1,"zWrLh")) return False;
1225 if (!check_share_info(uLevel,str2)) return False;
1227 *rdata = REALLOC(*rdata,mdrcnt);
1229 *rdata_len = fill_share_info(cnum,snum,uLevel,&p,&mdrcnt,0,0,0);
1230 if (*rdata_len < 0) return False;
1233 *rparam = REALLOC(*rparam,*rparam_len);
1234 SSVAL(*rparam,0,NERR_Success);
1235 SSVAL(*rparam,2,0); /* converter word */
1236 SSVAL(*rparam,4,*rdata_len);
1241 /****************************************************************************
1242 view list of shares available
1243 ****************************************************************************/
1244 static BOOL api_RNetShareEnum(int cnum,uint16 vuid, char *param,char *data,
1245 int mdrcnt,int mprcnt,
1246 char **rdata,char **rparam,
1247 int *rdata_len,int *rparam_len)
1249 char *str1 = param+2;
1250 char *str2 = skip_string(str1,1);
1251 char *p = skip_string(str2,1);
1252 int uLevel = SVAL(p,0);
1253 int buf_len = SVAL(p,2);
1255 int count=lp_numservices();
1256 int total=0,counted=0;
1258 int data_len, fixed_len, string_len;
1261 if (!prefix_ok(str1,"WrLeh")) return False;
1262 if (!check_share_info(uLevel,str2)) return False;
1264 data_len = fixed_len = string_len = 0;
1265 for (i=0;i<count;i++)
1266 if (lp_browseable(i) && lp_snum_ok(i))
1269 data_len += fill_share_info(cnum,i,uLevel,0,&f_len,0,&s_len,0);
1270 if (data_len <= buf_len)
1274 string_len += s_len;
1277 *rdata_len = fixed_len + string_len;
1278 *rdata = REALLOC(*rdata,*rdata_len);
1279 memset(*rdata,0,*rdata_len);
1281 p2 = (*rdata) + fixed_len; /* auxillery data (strings) will go here */
1285 for (i = 0; i < count;i++)
1286 if (lp_browseable(i) && lp_snum_ok(i))
1287 if (fill_share_info(cnum,i,uLevel,&p,&f_len,&p2,&s_len,*rdata) < 0)
1291 *rparam = REALLOC(*rparam,*rparam_len);
1292 SSVAL(*rparam,0,NERR_Success);
1294 SSVAL(*rparam,4,counted);
1295 SSVAL(*rparam,6,total);
1297 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1298 counted,total,uLevel,
1299 buf_len,*rdata_len,mdrcnt));
1305 /****************************************************************************
1306 get the time of day info
1307 ****************************************************************************/
1308 static BOOL api_NetRemoteTOD(int cnum,uint16 vuid, char *param,char *data,
1309 int mdrcnt,int mprcnt,
1310 char **rdata,char **rparam,
1311 int *rdata_len,int *rparam_len)
1315 *rparam = REALLOC(*rparam,*rparam_len);
1318 *rdata = REALLOC(*rdata,*rdata_len);
1320 SSVAL(*rparam,0,NERR_Success);
1321 SSVAL(*rparam,2,0); /* converter word */
1327 time_t unixdate = time(NULL);
1329 put_dos_date3(p,0,unixdate); /* this is the time that is looked at
1330 by NT in a "net time" operation,
1331 it seems to ignore the one below */
1333 /* the client expects to get localtime, not GMT, in this bit
1334 (I think, this needs testing) */
1335 t = LocalTime(&unixdate);
1337 SIVAL(p,4,0); /* msecs ? */
1338 CVAL(p,8) = t->tm_hour;
1339 CVAL(p,9) = t->tm_min;
1340 CVAL(p,10) = t->tm_sec;
1341 CVAL(p,11) = 0; /* hundredths of seconds */
1342 SSVALS(p,12,TimeDiff(unixdate)/60); /* timezone in minutes from GMT */
1343 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
1344 CVAL(p,16) = t->tm_mday;
1345 CVAL(p,17) = t->tm_mon + 1;
1346 SSVAL(p,18,1900+t->tm_year);
1347 CVAL(p,20) = t->tm_wday;
1354 /****************************************************************************
1355 set the user password
1356 ****************************************************************************/
1357 static BOOL api_SetUserPassword(int cnum,uint16 vuid, char *param,char *data,
1358 int mdrcnt,int mprcnt,
1359 char **rdata,char **rparam,
1360 int *rdata_len,int *rparam_len)
1362 char *p = skip_string(param+2,2);
1364 fstring pass1,pass2;
1368 p = skip_string(p,1);
1370 StrnCpy(pass1,p,16);
1371 StrnCpy(pass2,p+16,16);
1374 *rparam = REALLOC(*rparam,*rparam_len);
1378 SSVAL(*rparam,0,NERR_badpass);
1379 SSVAL(*rparam,2,0); /* converter word */
1381 DEBUG(3,("Set password for <%s>\n",user));
1383 if (password_ok(user,pass1,strlen(pass1),NULL) &&
1384 chgpasswd(user,pass1,pass2))
1386 SSVAL(*rparam,0,NERR_Success);
1389 bzero(pass1,sizeof(fstring));
1390 bzero(pass2,sizeof(fstring));
1395 /****************************************************************************
1398 ****************************************************************************/
1399 static BOOL api_RDosPrintJobDel(int cnum,uint16 vuid, char *param,char *data,
1400 int mdrcnt,int mprcnt,
1401 char **rdata,char **rparam,
1402 int *rdata_len,int *rparam_len)
1404 int function = SVAL(param,0);
1405 char *str1 = param+2;
1406 char *str2 = skip_string(str1,1);
1407 char *p = skip_string(str2,1);
1411 printjob_decode(SVAL(p,0), &snum, &jobid);
1413 /* check it's a supported varient */
1414 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
1418 *rparam = REALLOC(*rparam,*rparam_len);
1422 SSVAL(*rparam,0,NERR_Success);
1424 if (snum >= 0 && VALID_SNUM(snum))
1426 print_queue_struct *queue=NULL;
1428 count = get_printqueue(snum,cnum,&queue,NULL);
1430 for (i=0;i<count;i++)
1431 if ((queue[i].job&0xFF) == jobid)
1434 case 81: /* delete */
1435 DEBUG(3,("Deleting queue entry %d\n",queue[i].job));
1436 del_printqueue(cnum,snum,queue[i].job);
1438 case 82: /* pause */
1439 case 83: /* resume */
1440 DEBUG(3,("%s queue entry %d\n",
1441 (function==82?"pausing":"resuming"),queue[i].job));
1442 status_printjob(cnum,snum,queue[i].job,
1443 (function==82?LPQ_PAUSED:LPQ_QUEUED));
1450 SSVAL(*rparam,0,NERR_JobNotFound);
1452 if (queue) free(queue);
1455 SSVAL(*rparam,2,0); /* converter word */
1460 static BOOL api_WPrintQueuePurge(int cnum,uint16 vuid, char *param,char *data,
1461 int mdrcnt,int mprcnt,
1462 char **rdata,char **rparam,
1463 int *rdata_len,int *rparam_len)
1465 char *str1 = param+2;
1466 char *str2 = skip_string(str1,1);
1467 char *QueueName = skip_string(str2,1);
1470 /* check it's a supported varient */
1471 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
1475 *rparam = REALLOC(*rparam,*rparam_len);
1479 SSVAL(*rparam,0,NERR_Success);
1480 SSVAL(*rparam,2,0); /* converter word */
1482 snum = lp_servicenumber(QueueName);
1483 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
1484 int pnum = lp_servicenumber(PRINTERS_NAME);
1486 lp_add_printer(QueueName,pnum);
1487 snum = lp_servicenumber(QueueName);
1491 if (snum >= 0 && VALID_SNUM(snum)) {
1492 print_queue_struct *queue=NULL;
1496 count = get_printqueue(snum,cnum,&queue,NULL);
1497 for (i = 0; i < count; i++)
1498 del_printqueue(cnum,snum,queue[i].job);
1500 if (queue) free(queue);
1503 DEBUG(3,("Print queue purge, queue=%s\n",QueueName));
1509 /****************************************************************************
1510 set the property of a print job (undocumented?)
1511 ? function = 0xb -> set name of print job
1512 ? function = 0x6 -> move print job up/down
1513 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
1514 or <WWsTP> <WB21BB16B10zWWzDDz>
1515 ****************************************************************************/
1516 static int check_printjob_info(struct pack_desc* desc,
1517 int uLevel, char* id)
1519 desc->subformat = NULL;
1521 case 0: desc->format = "W"; break;
1522 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
1523 case 2: desc->format = "WWzWWDDzz"; break;
1524 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
1525 default: return False;
1527 if (strcmp(desc->format,id) != 0) return False;
1531 static BOOL api_PrintJobInfo(int cnum,uint16 vuid,char *param,char *data,
1532 int mdrcnt,int mprcnt,
1533 char **rdata,char **rparam,
1534 int *rdata_len,int *rparam_len)
1536 struct pack_desc desc;
1537 char *str1 = param+2;
1538 char *str2 = skip_string(str1,1);
1539 char *p = skip_string(str2,1);
1541 int uLevel = SVAL(p,2);
1542 int function = SVAL(p,4); /* what is this ?? */
1546 printjob_decode(SVAL(p,0), &snum, &jobid);
1549 *rparam = REALLOC(*rparam,*rparam_len);
1553 /* check it's a supported varient */
1554 if ((strcmp(str1,"WWsTP")) || (!check_printjob_info(&desc,uLevel,str2)))
1558 case 0x6: /* change job place in the queue, data gives the new place */
1559 if (snum >= 0 && VALID_SNUM(snum))
1561 print_queue_struct *queue=NULL;
1565 count = get_printqueue(snum,cnum,&queue,NULL);
1566 for (i=0;i<count;i++) /* find job */
1567 if ((queue[i].job&0xFF) == jobid) break;
1570 desc.errcode=NERR_JobNotFound;
1571 if (queue) free(queue);
1574 desc.errcode=NERR_Success;
1578 int place= SVAL(data,0);
1579 /* we currently have no way of doing this. Can any unix do it? */
1580 if (i < place) /* move down */;
1581 else if (i > place ) /* move up */;
1584 desc.errcode=NERR_notsupported; /* not yet supported */
1585 if (queue) free(queue);
1588 else desc.errcode=NERR_JobNotFound;
1590 case 0xb: /* change print job name, data gives the name */
1591 /* jobid, snum should be zero */
1598 if (issafe(*s)) name[l++] = *s;
1603 DEBUG(3,("Setting print name to %s\n",name));
1607 for (i=0;i<MAX_OPEN_FILES;i++)
1608 if (Files[i].open && Files[i].print_file)
1614 if (!become_user(Files[i].cnum,vuid) ||
1615 !become_service(Files[i].cnum,True))
1618 if (sys_rename(Files[i].name,name) == 0)
1619 string_set(&Files[i].name,name);
1623 unbecome_root(True);
1625 desc.errcode=NERR_Success;
1628 default: /* not implemented */
1632 SSVALS(*rparam,0,desc.errcode);
1633 SSVAL(*rparam,2,0); /* converter word */
1639 /****************************************************************************
1640 get info about the server
1641 ****************************************************************************/
1642 static BOOL api_RNetServerGetInfo(int cnum,uint16 vuid, char *param,char *data,
1643 int mdrcnt,int mprcnt,
1644 char **rdata,char **rparam,
1645 int *rdata_len,int *rparam_len)
1647 char *str1 = param+2;
1648 char *str2 = skip_string(str1,1);
1649 char *p = skip_string(str2,1);
1650 int uLevel = SVAL(p,0);
1654 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
1656 /* check it's a supported varient */
1657 if (!prefix_ok(str1,"WrLh")) return False;
1660 if (strcmp(str2,"B16") != 0) return False;
1664 if (strcmp(str2,"B16BBDz") != 0) return False;
1668 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")
1673 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz")
1678 if (strcmp(str2,"DN") != 0) return False;
1682 if (strcmp(str2,"B16BBDzWWzzz") != 0) return False;
1685 default: return False;
1688 *rdata_len = mdrcnt;
1689 *rdata = REALLOC(*rdata,*rdata_len);
1692 p2 = p + struct_len;
1694 StrnCpy(p,local_machine,16);
1700 struct srv_info_struct *servers=NULL;
1703 uint32 servertype= lp_default_server_announce();
1705 pstrcpy(comment,lp_serverstring());
1707 if ((count=get_server_info(SV_TYPE_ALL,&servers,myworkgroup))>0) {
1708 for (i=0;i<count;i++)
1709 if (strequal(servers[i].name,local_machine))
1711 servertype = servers[i].type;
1712 pstrcpy(comment,servers[i].comment);
1715 if (servers) free(servers);
1717 SCVAL(p,0,lp_major_announce_version());
1718 SCVAL(p,1,lp_minor_announce_version());
1719 SIVAL(p,2,servertype);
1721 if (mdrcnt == struct_len) {
1724 SIVAL(p,6,PTR_DIFF(p2,*rdata));
1725 standard_sub(cnum,comment);
1726 StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
1727 p2 = skip_string(p2,1);
1732 return False; /* not yet implemented */
1735 *rdata_len = PTR_DIFF(p2,*rdata);
1738 *rparam = REALLOC(*rparam,*rparam_len);
1739 SSVAL(*rparam,0,NERR_Success);
1740 SSVAL(*rparam,2,0); /* converter word */
1741 SSVAL(*rparam,4,*rdata_len);
1747 /****************************************************************************
1748 get info about the server
1749 ****************************************************************************/
1750 static BOOL api_NetWkstaGetInfo(int cnum,uint16 vuid, char *param,char *data,
1751 int mdrcnt,int mprcnt,
1752 char **rdata,char **rparam,
1753 int *rdata_len,int *rparam_len)
1755 char *str1 = param+2;
1756 char *str2 = skip_string(str1,1);
1757 char *p = skip_string(str2,1);
1759 extern pstring sesssetup_user;
1760 int level = SVAL(p,0);
1762 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
1765 *rparam = REALLOC(*rparam,*rparam_len);
1767 /* check it's a supported varient */
1768 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz")))
1771 *rdata_len = mdrcnt + 1024;
1772 *rdata = REALLOC(*rdata,*rdata_len);
1774 SSVAL(*rparam,0,NERR_Success);
1775 SSVAL(*rparam,2,0); /* converter word */
1781 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
1782 strcpy(p2,local_machine);
1784 p2 = skip_string(p2,1);
1787 SIVAL(p,0,PTR_DIFF(p2,*rdata));
1788 strcpy(p2,sesssetup_user);
1789 p2 = skip_string(p2,1);
1792 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
1793 strcpy(p2,myworkgroup);
1795 p2 = skip_string(p2,1);
1798 SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
1799 SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
1802 SIVAL(p,0,PTR_DIFF(p2,*rdata));
1803 strcpy(p2,myworkgroup); /* don't know. login domain?? */
1804 p2 = skip_string(p2,1);
1807 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
1809 p2 = skip_string(p2,1);
1812 *rdata_len = PTR_DIFF(p2,*rdata);
1814 SSVAL(*rparam,4,*rdata_len);
1819 /****************************************************************************
1820 get info about a user
1822 struct user_info_11 {
1823 char usri11_name[21]; 0-20
1825 char *usri11_comment; 22-25
1826 char *usri11_usr_comment; 26-29
1827 unsigned short usri11_priv; 30-31
1828 unsigned long usri11_auth_flags; 32-35
1829 long usri11_password_age; 36-39
1830 char *usri11_homedir; 40-43
1831 char *usri11_parms; 44-47
1832 long usri11_last_logon; 48-51
1833 long usri11_last_logoff; 52-55
1834 unsigned short usri11_bad_pw_count; 56-57
1835 unsigned short usri11_num_logons; 58-59
1836 char *usri11_logon_server; 60-63
1837 unsigned short usri11_country_code; 64-65
1838 char *usri11_workstations; 66-69
1839 unsigned long usri11_max_storage; 70-73
1840 unsigned short usri11_units_per_week; 74-75
1841 unsigned char *usri11_logon_hours; 76-79
1842 unsigned short usri11_code_page; 80-81
1847 usri11_name specifies the user name for which information is retireved
1849 usri11_pad aligns the next data structure element to a word boundary
1851 usri11_comment is a null terminated ASCII comment
1853 usri11_user_comment is a null terminated ASCII comment about the user
1855 usri11_priv specifies the level of the privilege assigned to the user.
1856 The possible values are:
1858 Name Value Description
1859 USER_PRIV_GUEST 0 Guest privilege
1860 USER_PRIV_USER 1 User privilege
1861 USER_PRV_ADMIN 2 Administrator privilege
1863 usri11_auth_flags specifies the account operator privileges. The
1864 possible values are:
1866 Name Value Description
1867 AF_OP_PRINT 0 Print operator
1870 Leach, Naik [Page 28]
\r\f
1873 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
1876 AF_OP_COMM 1 Communications operator
1877 AF_OP_SERVER 2 Server operator
1878 AF_OP_ACCOUNTS 3 Accounts operator
1881 usri11_password_age specifies how many seconds have elapsed since the
1882 password was last changed.
1884 usri11_home_dir points to a null terminated ASCII string that contains
1885 the path name of the user's home directory.
1887 usri11_parms points to a null terminated ASCII string that is set
1888 aside for use by applications.
1890 usri11_last_logon specifies the time when the user last logged on.
1891 This value is stored as the number of seconds elapsed since
1892 00:00:00, January 1, 1970.
1894 usri11_last_logoff specifies the time when the user last logged off.
1895 This value is stored as the number of seconds elapsed since
1896 00:00:00, January 1, 1970. A value of 0 means the last logoff
1899 usri11_bad_pw_count specifies the number of incorrect passwords
1900 entered since the last successful logon.
1902 usri11_log1_num_logons specifies the number of times this user has
1903 logged on. A value of -1 means the number of logons is unknown.
1905 usri11_logon_server points to a null terminated ASCII string that
1906 contains the name of the server to which logon requests are sent.
1907 A null string indicates logon requests should be sent to the
1910 usri11_country_code specifies the country code for the user's language
1913 usri11_workstations points to a null terminated ASCII string that
1914 contains the names of workstations the user may log on from.
1915 There may be up to 8 workstations, with the names separated by
1916 commas. A null strings indicates there are no restrictions.
1918 usri11_max_storage specifies the maximum amount of disk space the user
1919 can occupy. A value of 0xffffffff indicates there are no
1922 usri11_units_per_week specifies the equal number of time units into
1923 which a week is divided. This value must be equal to 168.
1925 usri11_logon_hours points to a 21 byte (168 bits) string that
1926 specifies the time during which the user can log on. Each bit
1927 represents one unique hour in a week. The first bit (bit 0, word
1928 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
1932 Leach, Naik [Page 29]
\r\f
1935 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
1938 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
1939 are no restrictions.
1941 usri11_code_page specifies the code page for the user's language of
1944 All of the pointers in this data structure need to be treated
1945 specially. The pointer is a 32 bit pointer. The higher 16 bits need
1946 to be ignored. The converter word returned in the parameters section
1947 needs to be subtracted from the lower 16 bits to calculate an offset
1948 into the return buffer where this ASCII string resides.
1950 There is no auxiliary data in the response.
1952 ****************************************************************************/
1954 #define usri11_name 0
1955 #define usri11_pad 21
1956 #define usri11_comment 22
1957 #define usri11_usr_comment 26
1958 #define usri11_full_name 30
1959 #define usri11_priv 34
1960 #define usri11_auth_flags 36
1961 #define usri11_password_age 40
1962 #define usri11_homedir 44
1963 #define usri11_parms 48
1964 #define usri11_last_logon 52
1965 #define usri11_last_logoff 56
1966 #define usri11_bad_pw_count 60
1967 #define usri11_num_logons 62
1968 #define usri11_logon_server 64
1969 #define usri11_country_code 68
1970 #define usri11_workstations 70
1971 #define usri11_max_storage 74
1972 #define usri11_units_per_week 78
1973 #define usri11_logon_hours 80
1974 #define usri11_code_page 84
1975 #define usri11_end 86
1977 #define USER_PRIV_GUEST 0
1978 #define USER_PRIV_USER 1
1979 #define USER_PRIV_ADMIN 2
1981 #define AF_OP_PRINT 0
1982 #define AF_OP_COMM 1
1983 #define AF_OP_SERVER 2
1984 #define AF_OP_ACCOUNTS 3
1987 static BOOL api_RNetUserGetInfo(int cnum,uint16 vuid, char *param,char *data,
1988 int mdrcnt,int mprcnt,
1989 char **rdata,char **rparam,
1990 int *rdata_len,int *rparam_len)
1992 char *str1 = param+2;
1993 char *str2 = skip_string(str1,1);
1994 char *UserName = skip_string(str2,1);
1995 char *p = skip_string(UserName,1);
1996 int uLevel = SVAL(p,0);
1999 /* get NIS home of a previously validated user - simeon */
2000 user_struct *vuser = get_valid_user_struct(vuid);
2001 DEBUG(3,(" Username of UID %d is %s\n", vuser->uid, vuser->name));
2002 #if (defined(NETGROUP) && defined(AUTOMOUNT))
2003 DEBUG(3,(" HOMESHR for %s is %s\n", vuser->name, vuser->home_share));
2007 *rparam = REALLOC(*rparam,*rparam_len);
2009 /* check it's a supported variant */
2010 if (strcmp(str1,"zWrLh") != 0) return False;
2013 case 0: p2 = "B21"; break;
2014 case 1: p2 = "B21BB16DWzzWz"; break;
2015 case 2: p2 = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
2016 case 10: p2 = "B21Bzzz"; break;
2017 case 11: p2 = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
2018 default: return False;
2021 if (strcmp(p2,str2) != 0) return False;
2023 *rdata_len = mdrcnt + 1024;
2024 *rdata = REALLOC(*rdata,*rdata_len);
2026 SSVAL(*rparam,0,NERR_Success);
2027 SSVAL(*rparam,2,0); /* converter word */
2030 p2 = p + usri11_end;
2033 fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
2037 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
2042 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
2043 strcpy(p2,"Comment");
2044 p2 = skip_string(p2,1);
2046 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
2047 strcpy(p2,"UserComment");
2048 p2 = skip_string(p2,1);
2050 /* EEK! the cifsrap.txt doesn't have this in!!!! */
2051 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
2052 strcpy(p2,vuser->real_name); /* simeon */
2053 p2 = skip_string(p2,1);
2056 if (uLevel == 11) /* modelled after NTAS 3.51 reply */
2058 SSVAL(p,usri11_priv,Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2059 SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
2060 SIVALS(p,usri11_password_age,0xffffffff); /* password age */
2061 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
2062 if (*lp_logon_path())
2064 strcpy(p2,lp_logon_path());
2068 #if (defined(NETGROUP) && defined(AUTOMOUNT))
2069 strcpy(p2, vuser->home_share);
2071 strcpy(p2,"\\\\%L\\%U");
2074 standard_sub_basic(p2);
2075 p2 = skip_string(p2,1);
2076 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
2078 p2 = skip_string(p2,1);
2079 SIVAL(p,usri11_last_logon,0); /* last logon */
2080 SIVAL(p,usri11_last_logoff,0); /* last logoff */
2081 SSVALS(p,usri11_bad_pw_count,0xffffffff); /* bad pw counts */
2082 SSVALS(p,usri11_num_logons,0xffffffff); /* num logons */
2083 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
2085 p2 = skip_string(p2,1);
2086 SSVAL(p,usri11_country_code,0); /* country code */
2088 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
2090 p2 = skip_string(p2,1);
2092 SIVALS(p,usri11_max_storage,0xffffffff); /* max storage */
2093 SSVAL(p,usri11_units_per_week,168); /* units per week */
2094 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
2096 /* a simple way to get logon hours at all times. */
2098 SCVAL(p2,21,0); /* fix zero termination */
2099 p2 = skip_string(p2,1);
2101 SSVAL(p,usri11_code_page,0); /* code page */
2103 if (uLevel == 1 || uLevel == 2)
2105 memset(p+22,' ',16); /* password */
2106 SIVALS(p,38,-1); /* password age */
2108 Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2109 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
2110 if (*lp_logon_path())
2112 strcpy(p2,lp_logon_path());
2116 #if (defined(NETGROUP) && defined(AUTOMOUNT))
2117 strcpy(p2, vuser->home_share);
2119 strcpy(p2,"\\\\%L\\%U");
2122 standard_sub_basic(p2);
2123 p2 = skip_string(p2,1);
2124 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
2126 SSVAL(p,52,0); /* flags */
2127 SIVAL(p,54,0); /* script_path */
2130 SIVAL(p,60,0); /* auth_flags */
2131 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
2132 strcpy(p2,vuser->real_name); /* simeon */
2133 p2 = skip_string(p2,1);
2134 SIVAL(p,68,0); /* urs_comment */
2135 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
2137 p2 = skip_string(p2,1);
2138 SIVAL(p,76,0); /* workstations */
2139 SIVAL(p,80,0); /* last_logon */
2140 SIVAL(p,84,0); /* last_logoff */
2141 SIVALS(p,88,-1); /* acct_expires */
2142 SIVALS(p,92,-1); /* max_storage */
2143 SSVAL(p,96,168); /* units_per_week */
2144 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
2147 SSVALS(p,102,-1); /* bad_pw_count */
2148 SSVALS(p,104,-1); /* num_logons */
2149 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
2150 strcpy(p2,"\\\\%L");
2151 standard_sub_basic(p2);
2152 p2 = skip_string(p2,1);
2153 SSVAL(p,110,49); /* country_code */
2154 SSVAL(p,112,860); /* code page */
2158 *rdata_len = PTR_DIFF(p2,*rdata);
2160 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
2165 /*******************************************************************
2166 get groups that a user is a member of
2167 ******************************************************************/
2168 static BOOL api_NetUserGetGroups(int cnum,uint16 vuid, char *param,char *data,
2169 int mdrcnt,int mprcnt,
2170 char **rdata,char **rparam,
2171 int *rdata_len,int *rparam_len)
2173 char *str1 = param+2;
2174 char *str2 = skip_string(str1,1);
2175 char *UserName = skip_string(str2,1);
2176 char *p = skip_string(UserName,1);
2177 int uLevel = SVAL(p,0);
2182 *rparam = REALLOC(*rparam,*rparam_len);
2184 /* check it's a supported varient */
2185 if (strcmp(str1,"zWrLeh") != 0) return False;
2187 case 0: p2 = "B21"; break;
2188 default: return False;
2190 if (strcmp(p2,str2) != 0) return False;
2192 *rdata_len = mdrcnt + 1024;
2193 *rdata = REALLOC(*rdata,*rdata_len);
2195 SSVAL(*rparam,0,NERR_Success);
2196 SSVAL(*rparam,2,0); /* converter word */
2200 /* XXXX we need a real SAM database some day */
2201 strcpy(p,"Users"); p += 21; count++;
2202 strcpy(p,"Domain Users"); p += 21; count++;
2203 strcpy(p,"Guests"); p += 21; count++;
2204 strcpy(p,"Domain Guests"); p += 21; count++;
2206 *rdata_len = PTR_DIFF(p,*rdata);
2208 SSVAL(*rparam,4,count); /* is this right?? */
2209 SSVAL(*rparam,6,count); /* is this right?? */
2215 static BOOL api_WWkstaUserLogon(int cnum,uint16 vuid, char *param,char *data,
2216 int mdrcnt,int mprcnt,
2217 char **rdata,char **rparam,
2218 int *rdata_len,int *rparam_len)
2220 char *str1 = param+2;
2221 char *str2 = skip_string(str1,1);
2222 char *p = skip_string(str2,1);
2224 struct pack_desc desc;
2231 bzero(&desc,sizeof(desc));
2233 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
2235 /* check it's a supported varient */
2236 if (strcmp(str1,"OOWb54WrLh") != 0) return False;
2237 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) return False;
2238 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2240 desc.buflen = mdrcnt;
2241 desc.subformat = NULL;
2244 if (init_package(&desc,1,0))
2246 PACKI(&desc,"W",0); /* code */
2247 PACKS(&desc,"B21",name); /* eff. name */
2248 PACKS(&desc,"B",""); /* pad */
2250 Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2251 PACKI(&desc,"D",0); /* auth flags XXX */
2252 PACKI(&desc,"W",0); /* num logons */
2253 PACKI(&desc,"W",0); /* bad pw count */
2254 PACKI(&desc,"D",0); /* last logon */
2255 PACKI(&desc,"D",-1); /* last logoff */
2256 PACKI(&desc,"D",-1); /* logoff time */
2257 PACKI(&desc,"D",-1); /* kickoff time */
2258 PACKI(&desc,"D",0); /* password age */
2259 PACKI(&desc,"D",0); /* password can change */
2260 PACKI(&desc,"D",-1); /* password must change */
2263 strcpy(mypath,"\\\\");
2264 strcat(mypath,local_machine);
2266 PACKS(&desc,"z",mypath); /* computer */
2268 PACKS(&desc,"z",myworkgroup);/* domain */
2270 /* JHT - By calling lp_logon_script() and standard_sub() we have */
2271 /* made sure all macros are fully substituted and available */
2272 logon_script = lp_logon_script();
2273 standard_sub( cnum, logon_script );
2274 PACKS(&desc,"z", logon_script); /* script path */
2275 /* End of JHT mods */
2277 PACKI(&desc,"D",0x00000000); /* reserved */
2280 *rdata_len = desc.usedlen;
2282 *rparam = REALLOC(*rparam,*rparam_len);
2283 SSVALS(*rparam,0,desc.errcode);
2285 SSVAL(*rparam,4,desc.neededlen);
2287 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
2292 /****************************************************************************
2293 api_WAccessGetUserPerms
2294 ****************************************************************************/
2295 static BOOL api_WAccessGetUserPerms(int cnum,uint16 vuid, char *param,char *data,
2296 int mdrcnt,int mprcnt,
2297 char **rdata,char **rparam,
2298 int *rdata_len,int *rparam_len)
2300 char *str1 = param+2;
2301 char *str2 = skip_string(str1,1);
2302 char *user = skip_string(str2,1);
2303 char *resource = skip_string(user,1);
2305 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
2307 /* check it's a supported varient */
2308 if (strcmp(str1,"zzh") != 0) return False;
2309 if (strcmp(str2,"") != 0) return False;
2312 *rparam = REALLOC(*rparam,*rparam_len);
2313 SSVALS(*rparam,0,0); /* errorcode */
2314 SSVAL(*rparam,2,0); /* converter word */
2315 SSVAL(*rparam,4,0x7f); /* permission flags */
2320 /****************************************************************************
2321 api_WPrintJobEnumerate
2322 ****************************************************************************/
2323 static BOOL api_WPrintJobGetInfo(int cnum,uint16 vuid, char *param,char *data,
2324 int mdrcnt,int mprcnt,
2325 char **rdata,char **rparam,
2326 int *rdata_len,int *rparam_len)
2328 char *str1 = param+2;
2329 char *str2 = skip_string(str1,1);
2330 char *p = skip_string(str2,1);
2336 struct pack_desc desc;
2337 print_queue_struct *queue=NULL;
2338 print_status_struct status;
2343 bzero(&desc,sizeof(desc));
2344 bzero(&status,sizeof(status));
2346 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
2348 /* check it's a supported varient */
2349 if (strcmp(str1,"WWrLh") != 0) return False;
2350 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2352 printjob_decode(SVAL(p,0), &snum, &job);
2354 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2356 count = get_printqueue(snum,cnum,&queue,&status);
2357 for (i = 0; i < count; i++) {
2358 if ((queue[i].job & 0xFF) == job) break;
2360 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2362 desc.buflen = mdrcnt;
2364 if (init_package(&desc,1,0)) {
2366 fill_printjob_info(cnum,snum,uLevel,&desc,&queue[i],i);
2367 *rdata_len = desc.usedlen;
2370 desc.errcode = NERR_JobNotFound;
2376 *rparam = REALLOC(*rparam,*rparam_len);
2377 SSVALS(*rparam,0,desc.errcode);
2379 SSVAL(*rparam,4,desc.neededlen);
2381 if (queue) free(queue);
2383 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
2387 static BOOL api_WPrintJobEnumerate(int cnum,uint16 vuid, char *param,char *data,
2388 int mdrcnt,int mprcnt,
2389 char **rdata,char **rparam,
2390 int *rdata_len,int *rparam_len)
2392 char *str1 = param+2;
2393 char *str2 = skip_string(str1,1);
2394 char *p = skip_string(str2,1);
2400 struct pack_desc desc;
2401 print_queue_struct *queue=NULL;
2402 print_status_struct status;
2404 bzero(&desc,sizeof(desc));
2405 bzero(&status,sizeof(status));
2407 p = skip_string(p,1);
2411 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
2413 /* check it's a supported varient */
2414 if (strcmp(str1,"zWrLeh") != 0) return False;
2415 if (uLevel > 2) return False; /* defined only for uLevel 0,1,2 */
2416 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2418 snum = lp_servicenumber(name);
2419 if (snum < 0 && pcap_printername_ok(name,NULL)) {
2420 int pnum = lp_servicenumber(PRINTERS_NAME);
2422 lp_add_printer(name,pnum);
2423 snum = lp_servicenumber(name);
2427 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2429 count = get_printqueue(snum,cnum,&queue,&status);
2430 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2432 desc.buflen = mdrcnt;
2434 if (init_package(&desc,count,0)) {
2436 for (i = 0; i < count; i++) {
2437 fill_printjob_info(cnum,snum,uLevel,&desc,&queue[i],i);
2438 if (desc.errcode == NERR_Success) succnt = i+1;
2442 *rdata_len = desc.usedlen;
2445 *rparam = REALLOC(*rparam,*rparam_len);
2446 SSVALS(*rparam,0,desc.errcode);
2448 SSVAL(*rparam,4,succnt);
2449 SSVAL(*rparam,6,count);
2451 if (queue) free(queue);
2453 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
2457 static int check_printdest_info(struct pack_desc* desc,
2458 int uLevel, char* id)
2460 desc->subformat = NULL;
2462 case 0: desc->format = "B9"; break;
2463 case 1: desc->format = "B9B21WWzW"; break;
2464 case 2: desc->format = "z"; break;
2465 case 3: desc->format = "zzzWWzzzWW"; break;
2466 default: return False;
2468 if (strcmp(desc->format,id) != 0) return False;
2472 static void fill_printdest_info(int cnum, int snum, int uLevel,
2473 struct pack_desc* desc)
2476 strncpy(buf,SERVICE(snum),sizeof(buf)-1);
2477 buf[sizeof(buf)-1] = 0;
2480 PACKS(desc,"B9",buf); /* szName */
2482 PACKS(desc,"B21",""); /* szUserName */
2483 PACKI(desc,"W",0); /* uJobId */
2484 PACKI(desc,"W",0); /* fsStatus */
2485 PACKS(desc,"z",""); /* pszStatus */
2486 PACKI(desc,"W",0); /* time */
2489 if (uLevel == 2 || uLevel == 3) {
2490 PACKS(desc,"z",buf); /* pszPrinterName */
2492 PACKS(desc,"z",""); /* pszUserName */
2493 PACKS(desc,"z",""); /* pszLogAddr */
2494 PACKI(desc,"W",0); /* uJobId */
2495 PACKI(desc,"W",0); /* fsStatus */
2496 PACKS(desc,"z",""); /* pszStatus */
2497 PACKS(desc,"z",""); /* pszComment */
2498 PACKS(desc,"z","NULL"); /* pszDrivers */
2499 PACKI(desc,"W",0); /* time */
2500 PACKI(desc,"W",0); /* pad1 */
2505 static BOOL api_WPrintDestGetInfo(int cnum,uint16 vuid, char *param,char *data,
2506 int mdrcnt,int mprcnt,
2507 char **rdata,char **rparam,
2508 int *rdata_len,int *rparam_len)
2510 char *str1 = param+2;
2511 char *str2 = skip_string(str1,1);
2512 char *p = skip_string(str2,1);
2513 char* PrinterName = p;
2515 struct pack_desc desc;
2518 bzero(&desc,sizeof(desc));
2520 p = skip_string(p,1);
2524 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
2526 /* check it's a supported varient */
2527 if (strcmp(str1,"zWrLh") != 0) return False;
2528 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2530 snum = lp_servicenumber(PrinterName);
2531 if (snum < 0 && pcap_printername_ok(PrinterName,NULL)) {
2532 int pnum = lp_servicenumber(PRINTERS_NAME);
2534 lp_add_printer(PrinterName,pnum);
2535 snum = lp_servicenumber(PrinterName);
2541 desc.errcode = NERR_DestNotFound;
2545 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2547 desc.buflen = mdrcnt;
2548 if (init_package(&desc,1,0)) {
2549 fill_printdest_info(cnum,snum,uLevel,&desc);
2551 *rdata_len = desc.usedlen;
2555 *rparam = REALLOC(*rparam,*rparam_len);
2556 SSVALS(*rparam,0,desc.errcode);
2558 SSVAL(*rparam,4,desc.neededlen);
2560 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
2564 static BOOL api_WPrintDestEnum(int cnum,uint16 vuid, char *param,char *data,
2565 int mdrcnt,int mprcnt,
2566 char **rdata,char **rparam,
2567 int *rdata_len,int *rparam_len)
2569 char *str1 = param+2;
2570 char *str2 = skip_string(str1,1);
2571 char *p = skip_string(str2,1);
2575 struct pack_desc desc;
2576 int services = lp_numservices();
2578 bzero(&desc,sizeof(desc));
2583 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
2585 /* check it's a supported varient */
2586 if (strcmp(str1,"WrLeh") != 0) return False;
2587 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2590 for (i = 0; i < services; i++)
2591 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
2594 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2596 desc.buflen = mdrcnt;
2597 if (init_package(&desc,queuecnt,0)) {
2600 for (i = 0; i < services; i++) {
2601 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
2602 fill_printdest_info(cnum,i,uLevel,&desc);
2604 if (desc.errcode == NERR_Success) succnt = n;
2609 *rdata_len = desc.usedlen;
2612 *rparam = REALLOC(*rparam,*rparam_len);
2613 SSVALS(*rparam,0,desc.errcode);
2615 SSVAL(*rparam,4,succnt);
2616 SSVAL(*rparam,6,queuecnt);
2618 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
2622 static BOOL api_WPrintDriverEnum(int cnum,uint16 vuid, char *param,char *data,
2623 int mdrcnt,int mprcnt,
2624 char **rdata,char **rparam,
2625 int *rdata_len,int *rparam_len)
2627 char *str1 = param+2;
2628 char *str2 = skip_string(str1,1);
2629 char *p = skip_string(str2,1);
2632 struct pack_desc desc;
2634 bzero(&desc,sizeof(desc));
2639 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
2641 /* check it's a supported varient */
2642 if (strcmp(str1,"WrLeh") != 0) return False;
2643 if (uLevel != 0 || strcmp(str2,"B41") != 0) return False;
2645 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2647 desc.buflen = mdrcnt;
2648 if (init_package(&desc,1,0)) {
2649 PACKS(&desc,"B41","NULL");
2652 succnt = (desc.errcode == NERR_Success ? 1 : 0);
2654 *rdata_len = desc.usedlen;
2657 *rparam = REALLOC(*rparam,*rparam_len);
2658 SSVALS(*rparam,0,desc.errcode);
2660 SSVAL(*rparam,4,succnt);
2663 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
2667 static BOOL api_WPrintQProcEnum(int cnum,uint16 vuid, char *param,char *data,
2668 int mdrcnt,int mprcnt,
2669 char **rdata,char **rparam,
2670 int *rdata_len,int *rparam_len)
2672 char *str1 = param+2;
2673 char *str2 = skip_string(str1,1);
2674 char *p = skip_string(str2,1);
2677 struct pack_desc desc;
2679 bzero(&desc,sizeof(desc));
2684 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
2686 /* check it's a supported varient */
2687 if (strcmp(str1,"WrLeh") != 0) return False;
2688 if (uLevel != 0 || strcmp(str2,"B13") != 0) return False;
2690 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2692 desc.buflen = mdrcnt;
2694 if (init_package(&desc,1,0)) {
2695 PACKS(&desc,"B13","lpd");
2698 succnt = (desc.errcode == NERR_Success ? 1 : 0);
2700 *rdata_len = desc.usedlen;
2703 *rparam = REALLOC(*rparam,*rparam_len);
2704 SSVALS(*rparam,0,desc.errcode);
2706 SSVAL(*rparam,4,succnt);
2709 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
2713 static BOOL api_WPrintPortEnum(int cnum,uint16 vuid, char *param,char *data,
2714 int mdrcnt,int mprcnt,
2715 char **rdata,char **rparam,
2716 int *rdata_len,int *rparam_len)
2718 char *str1 = param+2;
2719 char *str2 = skip_string(str1,1);
2720 char *p = skip_string(str2,1);
2723 struct pack_desc desc;
2725 bzero(&desc,sizeof(desc));
2730 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
2732 /* check it's a supported varient */
2733 if (strcmp(str1,"WrLeh") != 0) return False;
2734 if (uLevel != 0 || strcmp(str2,"B9") != 0) return False;
2736 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2737 bzero(&desc,sizeof(desc));
2739 desc.buflen = mdrcnt;
2741 if (init_package(&desc,1,0)) {
2742 PACKS(&desc,"B13","lp0");
2745 succnt = (desc.errcode == NERR_Success ? 1 : 0);
2747 *rdata_len = desc.usedlen;
2750 *rparam = REALLOC(*rparam,*rparam_len);
2751 SSVALS(*rparam,0,desc.errcode);
2753 SSVAL(*rparam,4,succnt);
2756 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
2767 } api_fd_commands [] =
2770 { "SetNmdPpHndState", "lsarpc", 1, api_LsarpcSNPHS },
2771 { "SetNmdPpHndState", "srvsvc", 1, api_LsarpcSNPHS },
2772 { "SetNmdPpHndState", "NETLOGON", 1, api_LsarpcSNPHS },
2773 { "TransactNmPipe", "lsarpc", 0x26, api_ntLsarpcTNP },
2774 { "TransactNmPipe", "srvsvc", 0x26, api_srvsvcTNP },
2775 { "TransactNmPipe", "NETLOGON", 0x26, api_netlogrpcTNP },
2777 { "SetNmdPpHndState", "lsarpc", 1, api_LsarpcSNPHS },
2778 { "TransactNmPipe" , "lsarpc", 0x26, api_LsarpcTNP },
2780 { NULL, NULL, -1, (BOOL (*)())api_Unsupported }
2783 /****************************************************************************
2784 handle remote api calls delivered to a named pipe already opened.
2785 ****************************************************************************/
2786 static int api_fd_reply(int cnum,uint16 vuid,char *outbuf,
2787 uint16 *setup,char *data,char *params,
2788 int suwcnt,int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
2791 char *rparam = NULL;
2799 /* First find out the name of this file. */
2802 DEBUG(0,("Unexpected named pipe transaction.\n"));
2806 /* Get the file handle and hence the file name. */
2808 subcommand = setup[0];
2810 DEBUG(3,("Got API command %d on pipe %s ",subcommand,Files[fd].name));
2811 DEBUG(3,("(tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d,cnum=%d,vuid=%d)\n",
2812 tdscnt,tpscnt,mdrcnt,mprcnt,cnum,vuid));
2814 for (i=0;api_fd_commands[i].name;i++)
2816 if (strequal(api_fd_commands[i].pipename, Files[fd].name) &&
2817 api_fd_commands[i].subcommand == subcommand &&
2818 api_fd_commands[i].fn)
2820 DEBUG(3,("Doing %s\n",api_fd_commands[i].name));
2825 rdata = (char *)malloc(1024); if (rdata ) bzero(rdata ,1024);
2826 rparam = (char *)malloc(1024); if (rparam) bzero(rparam,1024);
2828 DEBUG(10,("calling api_fd_command\n"));
2830 reply = api_fd_commands[i].fn(cnum,vuid,params,data,mdrcnt,mprcnt,
2831 &rdata,&rparam,&rdata_len,&rparam_len);
2833 DEBUG(10,("called api_fd_command\n"));
2835 if (rdata_len > mdrcnt || rparam_len > mprcnt)
2837 reply = api_TooSmall(cnum,vuid,params,data,mdrcnt,mprcnt,
2838 &rdata,&rparam,&rdata_len,&rparam_len);
2842 /* if we get False back then it's actually unsupported */
2844 api_Unsupported(cnum,vuid,params,data,mdrcnt,mprcnt,
2845 &rdata,&rparam,&rdata_len,&rparam_len);
2847 /* now send the reply */
2848 send_trans_reply(outbuf,rdata,rparam,NULL,rdata_len,rparam_len,0);
2860 /****************************************************************************
2861 the buffer was too small
2862 ****************************************************************************/
2863 static BOOL api_TooSmall(int cnum,uint16 vuid, char *param,char *data,
2864 int mdrcnt,int mprcnt,
2865 char **rdata,char **rparam,
2866 int *rdata_len,int *rparam_len)
2868 *rparam_len = MIN(*rparam_len,mprcnt);
2869 *rparam = REALLOC(*rparam,*rparam_len);
2873 SSVAL(*rparam,0,NERR_BufTooSmall);
2875 DEBUG(3,("Supplied buffer too small in API command\n"));
2881 /****************************************************************************
2882 the request is not supported
2883 ****************************************************************************/
2884 static BOOL api_Unsupported(int cnum,uint16 vuid, char *param,char *data,
2885 int mdrcnt,int mprcnt,
2886 char **rdata,char **rparam,
2887 int *rdata_len,int *rparam_len)
2890 *rparam = REALLOC(*rparam,*rparam_len);
2894 SSVAL(*rparam,0,NERR_notsupported);
2895 SSVAL(*rparam,2,0); /* converter word */
2897 DEBUG(3,("Unsupported API command\n"));
2911 } api_commands[] = {
2912 {"RNetShareEnum", 0, (BOOL (*)())api_RNetShareEnum,0},
2913 {"RNetShareGetInfo", 1, (BOOL (*)())api_RNetShareGetInfo,0},
2914 {"RNetServerGetInfo", 13, (BOOL (*)())api_RNetServerGetInfo,0},
2915 {"RNetUserGetInfo", 56, (BOOL (*)())api_RNetUserGetInfo,0},
2916 {"NetUserGetGroups", 59, (BOOL (*)())api_NetUserGetGroups,0},
2917 {"NetWkstaGetInfo", 63, (BOOL (*)())api_NetWkstaGetInfo,0},
2918 {"DosPrintQEnum", 69, (BOOL (*)())api_DosPrintQEnum,0},
2919 {"DosPrintQGetInfo", 70, (BOOL (*)())api_DosPrintQGetInfo,0},
2920 {"WPrintJobEnumerate",76, (BOOL (*)())api_WPrintJobEnumerate,0},
2921 {"WPrintJobGetInfo", 77, (BOOL (*)())api_WPrintJobGetInfo,0},
2922 {"RDosPrintJobDel", 81, (BOOL (*)())api_RDosPrintJobDel,0},
2923 {"RDosPrintJobPause", 82, (BOOL (*)())api_RDosPrintJobDel,0},
2924 {"RDosPrintJobResume",83, (BOOL (*)())api_RDosPrintJobDel,0},
2925 {"WPrintDestEnum", 84, (BOOL (*)())api_WPrintDestEnum,0},
2926 {"WPrintDestGetInfo", 85, (BOOL (*)())api_WPrintDestGetInfo,0},
2927 {"NetRemoteTOD", 91, (BOOL (*)())api_NetRemoteTOD,0},
2928 {"WPrintQueuePurge", 103, (BOOL (*)())api_WPrintQueuePurge,0},
2929 {"NetServerEnum", 104, (BOOL (*)())api_RNetServerEnum,0},
2930 {"WAccessGetUserPerms",105, (BOOL (*)())api_WAccessGetUserPerms,0},
2931 {"SetUserPassword", 115, (BOOL (*)())api_SetUserPassword,0},
2932 {"WWkstaUserLogon", 132, (BOOL (*)())api_WWkstaUserLogon,0},
2933 {"PrintJobInfo", 147, (BOOL (*)())api_PrintJobInfo,0},
2934 {"WPrintDriverEnum", 205, (BOOL (*)())api_WPrintDriverEnum,0},
2935 {"WPrintQProcEnum", 206, (BOOL (*)())api_WPrintQProcEnum,0},
2936 {"WPrintPortEnum", 207, (BOOL (*)())api_WPrintPortEnum,0},
2937 {NULL, -1, (BOOL (*)())api_Unsupported,0}};
2940 /****************************************************************************
2941 handle remote api calls
2942 ****************************************************************************/
2943 static int api_reply(int cnum,uint16 vuid,char *outbuf,char *data,char *params,
2944 int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
2946 int api_command = SVAL(params,0);
2948 char *rparam = NULL;
2954 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
2955 api_command,params+2,skip_string(params+2,1),
2956 tdscnt,tpscnt,mdrcnt,mprcnt));
2958 for (i=0;api_commands[i].name;i++)
2959 if (api_commands[i].id == api_command && api_commands[i].fn)
2961 DEBUG(3,("Doing %s\n",api_commands[i].name));
2965 rdata = (char *)malloc(1024); if (rdata) bzero(rdata,1024);
2966 rparam = (char *)malloc(1024); if (rparam) bzero(rparam,1024);
2968 reply = api_commands[i].fn(cnum,vuid,params,data,mdrcnt,mprcnt,
2969 &rdata,&rparam,&rdata_len,&rparam_len);
2972 if (rdata_len > mdrcnt ||
2973 rparam_len > mprcnt)
2975 reply = api_TooSmall(cnum,vuid,params,data,mdrcnt,mprcnt,
2976 &rdata,&rparam,&rdata_len,&rparam_len);
2980 /* if we get False back then it's actually unsupported */
2982 api_Unsupported(cnum,vuid,params,data,mdrcnt,mprcnt,
2983 &rdata,&rparam,&rdata_len,&rparam_len);
2987 /* now send the reply */
2988 send_trans_reply(outbuf,rdata,rparam,NULL,rdata_len,rparam_len,0);
2998 /****************************************************************************
2999 handle named pipe commands
3000 ****************************************************************************/
3001 static int named_pipe(int cnum,uint16 vuid, char *outbuf,char *name,
3002 uint16 *setup,char *data,char *params,
3003 int suwcnt,int tdscnt,int tpscnt,
3004 int msrcnt,int mdrcnt,int mprcnt)
3007 if (strequal(name,"LANMAN"))
3008 return(api_reply(cnum,vuid,outbuf,data,params,tdscnt,tpscnt,mdrcnt,mprcnt));
3010 if (strlen(name) < 1)
3011 return(api_fd_reply(cnum,vuid,outbuf,setup,data,params,suwcnt,tdscnt,tpscnt,mdrcnt,mprcnt));
3014 DEBUG(3,("named pipe command on <%s> 0x%X setup1=%d\n",
3015 name,(int)setup[0],(int)setup[1]));
3021 /****************************************************************************
3023 ****************************************************************************/
3024 int reply_trans(char *inbuf,char *outbuf)
3028 char *data=NULL,*params=NULL;
3032 int cnum = SVAL(inbuf,smb_tid);
3033 uint16 vuid = SVAL(inbuf,smb_uid);
3035 int tpscnt = SVAL(inbuf,smb_vwv0);
3036 int tdscnt = SVAL(inbuf,smb_vwv1);
3037 int mprcnt = SVAL(inbuf,smb_vwv2);
3038 int mdrcnt = SVAL(inbuf,smb_vwv3);
3039 int msrcnt = CVAL(inbuf,smb_vwv4);
3040 BOOL close_on_completion = BITSETW(inbuf+smb_vwv5,0);
3041 BOOL one_way = BITSETW(inbuf+smb_vwv5,1);
3042 int pscnt = SVAL(inbuf,smb_vwv9);
3043 int psoff = SVAL(inbuf,smb_vwv10);
3044 int dscnt = SVAL(inbuf,smb_vwv11);
3045 int dsoff = SVAL(inbuf,smb_vwv12);
3046 int suwcnt = CVAL(inbuf,smb_vwv13);
3048 fstrcpy(name,smb_buf(inbuf));
3050 if (dscnt > tdscnt || pscnt > tpscnt) {
3051 exit_server("invalid trans parameters\n");
3056 data = (char *)malloc(tdscnt);
3057 memcpy(data,smb_base(inbuf)+dsoff,dscnt);
3061 params = (char *)malloc(tpscnt);
3062 memcpy(params,smb_base(inbuf)+psoff,pscnt);
3068 setup = (uint16 *)malloc(suwcnt*sizeof(setup[0]));
3069 for (i=0;i<suwcnt;i++)
3070 setup[i] = SVAL(inbuf,smb_vwv14+i*SIZEOFWORD);
3074 if (pscnt < tpscnt || dscnt < tdscnt)
3076 /* We need to send an interim response then receive the rest
3077 of the parameter/data bytes */
3078 outsize = set_message(outbuf,0,0,True);
3080 send_smb(Client,outbuf);
3083 /* receive the rest of the trans packet */
3084 while (pscnt < tpscnt || dscnt < tdscnt)
3086 int pcnt,poff,dcnt,doff,pdisp,ddisp;
3088 if (!receive_smb(Client,inbuf, SMB_SECONDARY_WAIT) ||
3089 CVAL(inbuf, smb_com) != SMBtrans)
3091 DEBUG(2,("Invalid secondary trans2 packet\n"));
3092 if (params) free(params);
3093 if (data) free(data);
3094 if (setup) free(setup);
3095 return(ERROR(ERRSRV,ERRerror));
3100 tpscnt = SVAL(inbuf,smb_vwv0);
3101 tdscnt = SVAL(inbuf,smb_vwv1);
3103 pcnt = SVAL(inbuf,smb_vwv2);
3104 poff = SVAL(inbuf,smb_vwv3);
3105 pdisp = SVAL(inbuf,smb_vwv4);
3107 dcnt = SVAL(inbuf,smb_vwv5);
3108 doff = SVAL(inbuf,smb_vwv6);
3109 ddisp = SVAL(inbuf,smb_vwv7);
3114 if (dscnt > tdscnt || pscnt > tpscnt) {
3115 exit_server("invalid trans parameters\n");
3119 memcpy(params+pdisp,smb_base(inbuf)+poff,pcnt);
3121 memcpy(data+ddisp,smb_base(inbuf)+doff,dcnt);
3125 DEBUG(3,("trans <%s> data=%d params=%d setup=%d\n",name,tdscnt,tpscnt,suwcnt));
3128 if (strncmp(name,"\\PIPE\\",strlen("\\PIPE\\")) == 0)
3129 outsize = named_pipe(cnum,vuid,outbuf,name+strlen("\\PIPE\\"),setup,data,params,
3130 suwcnt,tdscnt,tpscnt,msrcnt,mdrcnt,mprcnt);
3133 if (data) free(data);
3134 if (params) free(params);
3135 if (setup) free(setup);
3137 if (close_on_completion)
3138 close_cnum(cnum,vuid);
3144 return(ERROR(ERRSRV,ERRnosupport));