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;
985 BOOL local_request = servertype & SV_TYPE_LOCAL_LIST_ONLY;
987 if (servertype == SV_TYPE_ALL) servertype &= ~SV_TYPE_DOMAIN_ENUM;
989 domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
993 if (!prefix_ok(str1,"WrLehD")) return False;
994 if (!check_server_info(uLevel,str2)) return False;
996 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
997 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
998 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1000 if (strcmp(str1, "WrLehDz") == 0) {
1001 StrnCpy(domain, p, sizeof(fstring)-1);
1003 StrnCpy(domain, myworkgroup, sizeof(fstring)-1);
1006 if (lp_browse_list())
1007 total = get_server_info(servertype,&servers,domain);
1009 data_len = fixed_len = string_len = 0;
1012 qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
1015 char *lastname=NULL;
1017 for (i=0;i<total;i++)
1019 struct srv_info_struct *s = &servers[i];
1020 if (lastname && strequal(lastname,s->name)) continue;
1022 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1023 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1024 s->name, s->type, s->comment, s->domain));
1026 if (data_len <= buf_len) {
1029 string_len += s_len;
1036 *rdata_len = fixed_len + string_len;
1037 *rdata = REALLOC(*rdata,*rdata_len);
1038 bzero(*rdata,*rdata_len);
1040 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1046 char *lastname=NULL;
1047 int count2 = counted;
1048 for (i = 0; i < total && count2;i++)
1050 struct srv_info_struct *s = &servers[i];
1051 if (lastname && strequal(lastname,s->name)) continue;
1053 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1054 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1055 s->name, s->type, s->comment, s->domain));
1061 *rparam = REALLOC(*rparam,*rparam_len);
1062 SSVAL(*rparam,0,NERR_Success);
1064 SSVAL(*rparam,4,counted);
1065 SSVAL(*rparam,6,counted+missed);
1067 if (servers) free(servers);
1069 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1070 domain,uLevel,counted,counted+missed));
1076 /****************************************************************************
1077 get info about a share
1078 ****************************************************************************/
1079 static BOOL check_share_info(int uLevel, char* id)
1083 if (strcmp(id,"B13") != 0) return False;
1086 if (strcmp(id,"B13BWz") != 0) return False;
1089 if (strcmp(id,"B13BWzWWWzB9B") != 0) return False;
1092 if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) return False;
1094 default: return False;
1099 static int fill_share_info(int cnum, int snum, int uLevel,
1100 char** buf, int* buflen,
1101 char** stringbuf, int* stringspace, char* baseaddr)
1110 case 0: struct_len = 13; break;
1111 case 1: struct_len = 20; break;
1112 case 2: struct_len = 40; break;
1113 case 91: struct_len = 68; break;
1121 if (uLevel > 0) len += StrlenExpanded(cnum,snum,lp_comment(snum));
1122 if (uLevel > 1) len += strlen(lp_pathname(snum)) + 1;
1123 if (buflen) *buflen = struct_len;
1124 if (stringspace) *stringspace = len;
1125 return struct_len + len;
1130 if ((*buflen) < struct_len) return -1;
1138 p2 = p + struct_len;
1139 l2 = (*buflen) - struct_len;
1141 if (!baseaddr) baseaddr = p;
1143 StrnCpy(p,lp_servicename(snum),13);
1149 type = STYPE_DISKTREE;
1150 if (lp_print_ok(snum)) type = STYPE_PRINTQ;
1151 if (strequal("IPC$",lp_servicename(snum))) type = STYPE_IPC;
1152 SSVAL(p,14,type); /* device type */
1153 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1154 len += CopyExpanded(cnum,snum,&p2,lp_comment(snum),&l2);
1159 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1160 SSVALS(p,22,-1); /* max uses */
1161 SSVAL(p,24,1); /* current uses */
1162 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1163 len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1164 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1169 memset(p+40,0,SHPWLEN+2);
1181 (*buf) = p + struct_len;
1182 (*buflen) -= struct_len;
1184 (*stringspace) = l2;
1194 static BOOL api_RNetShareGetInfo(int cnum,uint16 vuid, char *param,char *data,
1195 int mdrcnt,int mprcnt,
1196 char **rdata,char **rparam,
1197 int *rdata_len,int *rparam_len)
1199 char *str1 = param+2;
1200 char *str2 = skip_string(str1,1);
1201 char *netname = skip_string(str2,1);
1202 char *p = skip_string(netname,1);
1203 int uLevel = SVAL(p,0);
1204 int snum = find_service(netname);
1206 if (snum < 0) return False;
1208 /* check it's a supported varient */
1209 if (!prefix_ok(str1,"zWrLh")) return False;
1210 if (!check_share_info(uLevel,str2)) return False;
1212 *rdata = REALLOC(*rdata,mdrcnt);
1214 *rdata_len = fill_share_info(cnum,snum,uLevel,&p,&mdrcnt,0,0,0);
1215 if (*rdata_len < 0) return False;
1218 *rparam = REALLOC(*rparam,*rparam_len);
1219 SSVAL(*rparam,0,NERR_Success);
1220 SSVAL(*rparam,2,0); /* converter word */
1221 SSVAL(*rparam,4,*rdata_len);
1226 /****************************************************************************
1227 view list of shares available
1228 ****************************************************************************/
1229 static BOOL api_RNetShareEnum(int cnum,uint16 vuid, char *param,char *data,
1230 int mdrcnt,int mprcnt,
1231 char **rdata,char **rparam,
1232 int *rdata_len,int *rparam_len)
1234 char *str1 = param+2;
1235 char *str2 = skip_string(str1,1);
1236 char *p = skip_string(str2,1);
1237 int uLevel = SVAL(p,0);
1238 int buf_len = SVAL(p,2);
1240 int count=lp_numservices();
1241 int total=0,counted=0;
1243 int data_len, fixed_len, string_len;
1246 if (!prefix_ok(str1,"WrLeh")) return False;
1247 if (!check_share_info(uLevel,str2)) return False;
1249 data_len = fixed_len = string_len = 0;
1250 for (i=0;i<count;i++)
1251 if (lp_browseable(i) && lp_snum_ok(i))
1254 data_len += fill_share_info(cnum,i,uLevel,0,&f_len,0,&s_len,0);
1255 if (data_len <= buf_len)
1259 string_len += s_len;
1262 *rdata_len = fixed_len + string_len;
1263 *rdata = REALLOC(*rdata,*rdata_len);
1264 memset(*rdata,0,*rdata_len);
1266 p2 = (*rdata) + fixed_len; /* auxillery data (strings) will go here */
1270 for (i = 0; i < count;i++)
1271 if (lp_browseable(i) && lp_snum_ok(i))
1272 if (fill_share_info(cnum,i,uLevel,&p,&f_len,&p2,&s_len,*rdata) < 0)
1276 *rparam = REALLOC(*rparam,*rparam_len);
1277 SSVAL(*rparam,0,NERR_Success);
1279 SSVAL(*rparam,4,counted);
1280 SSVAL(*rparam,6,total);
1282 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1283 counted,total,uLevel,
1284 buf_len,*rdata_len,mdrcnt));
1290 /****************************************************************************
1291 get the time of day info
1292 ****************************************************************************/
1293 static BOOL api_NetRemoteTOD(int cnum,uint16 vuid, char *param,char *data,
1294 int mdrcnt,int mprcnt,
1295 char **rdata,char **rparam,
1296 int *rdata_len,int *rparam_len)
1300 *rparam = REALLOC(*rparam,*rparam_len);
1303 *rdata = REALLOC(*rdata,*rdata_len);
1305 SSVAL(*rparam,0,NERR_Success);
1306 SSVAL(*rparam,2,0); /* converter word */
1312 time_t unixdate = time(NULL);
1314 put_dos_date3(p,0,unixdate); /* this is the time that is looked at
1315 by NT in a "net time" operation,
1316 it seems to ignore the one below */
1318 /* the client expects to get localtime, not GMT, in this bit
1319 (I think, this needs testing) */
1320 t = LocalTime(&unixdate);
1322 SIVAL(p,4,0); /* msecs ? */
1323 CVAL(p,8) = t->tm_hour;
1324 CVAL(p,9) = t->tm_min;
1325 CVAL(p,10) = t->tm_sec;
1326 CVAL(p,11) = 0; /* hundredths of seconds */
1327 SSVALS(p,12,TimeDiff(unixdate)/60); /* timezone in minutes from GMT */
1328 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
1329 CVAL(p,16) = t->tm_mday;
1330 CVAL(p,17) = t->tm_mon + 1;
1331 SSVAL(p,18,1900+t->tm_year);
1332 CVAL(p,20) = t->tm_wday;
1339 /****************************************************************************
1340 set the user password
1341 ****************************************************************************/
1342 static BOOL api_SetUserPassword(int cnum,uint16 vuid, char *param,char *data,
1343 int mdrcnt,int mprcnt,
1344 char **rdata,char **rparam,
1345 int *rdata_len,int *rparam_len)
1347 char *p = skip_string(param+2,2);
1349 fstring pass1,pass2;
1353 p = skip_string(p,1);
1355 StrnCpy(pass1,p,16);
1356 StrnCpy(pass2,p+16,16);
1359 *rparam = REALLOC(*rparam,*rparam_len);
1363 SSVAL(*rparam,0,NERR_badpass);
1364 SSVAL(*rparam,2,0); /* converter word */
1366 DEBUG(3,("Set password for <%s>\n",user));
1368 if (password_ok(user,pass1,strlen(pass1),NULL) &&
1369 chgpasswd(user,pass1,pass2))
1371 SSVAL(*rparam,0,NERR_Success);
1374 bzero(pass1,sizeof(fstring));
1375 bzero(pass2,sizeof(fstring));
1380 /****************************************************************************
1383 ****************************************************************************/
1384 static BOOL api_RDosPrintJobDel(int cnum,uint16 vuid, char *param,char *data,
1385 int mdrcnt,int mprcnt,
1386 char **rdata,char **rparam,
1387 int *rdata_len,int *rparam_len)
1389 int function = SVAL(param,0);
1390 char *str1 = param+2;
1391 char *str2 = skip_string(str1,1);
1392 char *p = skip_string(str2,1);
1393 int jobid = (SVAL(p,0)&0xFF); /* the snum and jobid are encoded
1394 by the print queue api */
1395 int snum = (SVAL(p,0)>>8);
1399 /* check it's a supported varient */
1400 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
1404 *rparam = REALLOC(*rparam,*rparam_len);
1408 SSVAL(*rparam,0,NERR_Success);
1410 if (snum >= 0 && VALID_SNUM(snum))
1412 print_queue_struct *queue=NULL;
1414 count = get_printqueue(snum,cnum,&queue,NULL);
1416 for (i=0;i<count;i++)
1417 if ((queue[i].job%0xFF) == jobid)
1420 case 81: /* delete */
1421 DEBUG(3,("Deleting queue entry %d\n",queue[i].job));
1422 del_printqueue(cnum,snum,queue[i].job);
1424 case 82: /* pause */
1425 case 83: /* resume */
1426 DEBUG(3,("%s queue entry %d\n",
1427 (function==82?"pausing":"resuming"),queue[i].job));
1428 status_printjob(cnum,snum,queue[i].job,
1429 (function==82?LPQ_PAUSED:LPQ_QUEUED));
1436 SSVAL(*rparam,0,NERR_JobNotFound);
1438 if (queue) free(queue);
1441 SSVAL(*rparam,2,0); /* converter word */
1446 static BOOL api_WPrintQueuePurge(int cnum,uint16 vuid, char *param,char *data,
1447 int mdrcnt,int mprcnt,
1448 char **rdata,char **rparam,
1449 int *rdata_len,int *rparam_len)
1451 char *str1 = param+2;
1452 char *str2 = skip_string(str1,1);
1453 char *QueueName = skip_string(str2,1);
1456 /* check it's a supported varient */
1457 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
1461 *rparam = REALLOC(*rparam,*rparam_len);
1465 SSVAL(*rparam,0,NERR_Success);
1466 SSVAL(*rparam,2,0); /* converter word */
1468 snum = lp_servicenumber(QueueName);
1469 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
1470 int pnum = lp_servicenumber(PRINTERS_NAME);
1472 lp_add_printer(QueueName,pnum);
1473 snum = lp_servicenumber(QueueName);
1477 if (snum >= 0 && VALID_SNUM(snum)) {
1478 print_queue_struct *queue=NULL;
1482 count = get_printqueue(snum,cnum,&queue,NULL);
1483 for (i = 0; i < count; i++)
1484 del_printqueue(cnum,snum,queue[i].job);
1486 if (queue) free(queue);
1489 DEBUG(3,("Print queue purge, queue=%s\n",QueueName));
1495 /****************************************************************************
1496 set the property of a print job (undocumented?)
1497 ? function = 0xb -> set name of print job
1498 ? function = 0x6 -> move print job up/down
1499 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
1500 or <WWsTP> <WB21BB16B10zWWzDDz>
1501 ****************************************************************************/
1502 static int check_printjob_info(struct pack_desc* desc,
1503 int uLevel, char* id)
1505 desc->subformat = NULL;
1507 case 0: desc->format = "W"; break;
1508 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
1509 case 2: desc->format = "WWzWWDDzz"; break;
1510 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
1511 default: return False;
1513 if (strcmp(desc->format,id) != 0) return False;
1517 static BOOL api_PrintJobInfo(int cnum,uint16 vuid,char *param,char *data,
1518 int mdrcnt,int mprcnt,
1519 char **rdata,char **rparam,
1520 int *rdata_len,int *rparam_len)
1522 struct pack_desc desc;
1523 char *str1 = param+2;
1524 char *str2 = skip_string(str1,1);
1525 char *p = skip_string(str2,1);
1526 int jobid = (SVAL(p,0)&0xFF); /* the snum and jobid are encoded
1527 by the print queue api */
1528 int snum = (SVAL(p,0)>>8);
1529 int uLevel = SVAL(p,2);
1530 int function = SVAL(p,4); /* what is this ?? */
1535 *rparam = REALLOC(*rparam,*rparam_len);
1539 /* check it's a supported varient */
1540 if ((strcmp(str1,"WWsTP")) || (!check_printjob_info(&desc,uLevel,str2)))
1544 case 0x6: /* change job place in the queue, data gives the new place */
1545 if (snum >= 0 && VALID_SNUM(snum))
1547 print_queue_struct *queue=NULL;
1551 count = get_printqueue(snum,cnum,&queue,NULL);
1552 for (i=0;i<count;i++) /* find job */
1553 if ((queue[i].job%0xFF) == jobid) break;
1556 desc.errcode=NERR_JobNotFound;
1557 if (queue) free(queue);
1560 desc.errcode=NERR_Success;
1564 int place= SVAL(data,0);
1565 /* we currently have no way of doing this. Can any unix do it? */
1566 if (i < place) /* move down */;
1567 else if (i > place ) /* move up */;
1570 desc.errcode=NERR_notsupported; /* not yet supported */
1571 if (queue) free(queue);
1574 else desc.errcode=NERR_JobNotFound;
1576 case 0xb: /* change print job name, data gives the name */
1577 /* jobid, snum should be zero */
1584 if (issafe(*s)) name[l++] = *s;
1589 DEBUG(3,("Setting print name to %s\n",name));
1591 for (i=0;i<MAX_OPEN_FILES;i++)
1592 if (Files[i].open && Files[i].print_file)
1598 if (!become_user(Files[i].cnum,vuid) ||
1599 !become_service(Files[i].cnum,True))
1602 if (sys_rename(Files[i].name,name) == 0)
1603 string_set(&Files[i].name,name);
1607 desc.errcode=NERR_Success;
1610 default: /* not implemented */
1614 SSVALS(*rparam,0,desc.errcode);
1615 SSVAL(*rparam,2,0); /* converter word */
1621 /****************************************************************************
1622 get info about the server
1623 ****************************************************************************/
1624 static BOOL api_RNetServerGetInfo(int cnum,uint16 vuid, char *param,char *data,
1625 int mdrcnt,int mprcnt,
1626 char **rdata,char **rparam,
1627 int *rdata_len,int *rparam_len)
1629 char *str1 = param+2;
1630 char *str2 = skip_string(str1,1);
1631 char *p = skip_string(str2,1);
1632 int uLevel = SVAL(p,0);
1636 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
1638 /* check it's a supported varient */
1639 if (!prefix_ok(str1,"WrLh")) return False;
1642 if (strcmp(str2,"B16") != 0) return False;
1646 if (strcmp(str2,"B16BBDz") != 0) return False;
1650 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")
1655 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz")
1660 if (strcmp(str2,"DN") != 0) return False;
1664 if (strcmp(str2,"B16BBDzWWzzz") != 0) return False;
1667 default: return False;
1670 *rdata_len = mdrcnt;
1671 *rdata = REALLOC(*rdata,*rdata_len);
1674 p2 = p + struct_len;
1676 StrnCpy(p,local_machine,16);
1682 struct srv_info_struct *servers=NULL;
1685 uint32 servertype=DFLT_SERVER_TYPE;
1687 strcpy(comment,lp_serverstring());
1689 if ((count=get_server_info(SV_TYPE_ALL,&servers,myworkgroup))>0) {
1690 for (i=0;i<count;i++)
1691 if (strequal(servers[i].name,local_machine))
1693 servertype = servers[i].type;
1694 strcpy(comment,servers[i].comment);
1697 if (servers) free(servers);
1699 SCVAL(p,0,MAJOR_VERSION);
1700 SCVAL(p,1,MINOR_VERSION);
1701 SIVAL(p,2,servertype);
1703 if (mdrcnt == struct_len) {
1706 SIVAL(p,6,PTR_DIFF(p2,*rdata));
1707 standard_sub(cnum,comment);
1708 StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
1709 p2 = skip_string(p2,1);
1714 return False; /* not yet implemented */
1717 *rdata_len = PTR_DIFF(p2,*rdata);
1720 *rparam = REALLOC(*rparam,*rparam_len);
1721 SSVAL(*rparam,0,NERR_Success);
1722 SSVAL(*rparam,2,0); /* converter word */
1723 SSVAL(*rparam,4,*rdata_len);
1729 /****************************************************************************
1730 get info about the server
1731 ****************************************************************************/
1732 static BOOL api_NetWkstaGetInfo(int cnum,uint16 vuid, char *param,char *data,
1733 int mdrcnt,int mprcnt,
1734 char **rdata,char **rparam,
1735 int *rdata_len,int *rparam_len)
1737 char *str1 = param+2;
1738 char *str2 = skip_string(str1,1);
1739 char *p = skip_string(str2,1);
1741 extern pstring sesssetup_user;
1742 int level = SVAL(p,0);
1744 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
1747 *rparam = REALLOC(*rparam,*rparam_len);
1749 /* check it's a supported varient */
1750 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz")))
1753 *rdata_len = mdrcnt + 1024;
1754 *rdata = REALLOC(*rdata,*rdata_len);
1756 SSVAL(*rparam,0,NERR_Success);
1757 SSVAL(*rparam,2,0); /* converter word */
1763 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
1764 strcpy(p2,local_machine);
1766 p2 = skip_string(p2,1);
1769 SIVAL(p,0,PTR_DIFF(p2,*rdata));
1770 strcpy(p2,sesssetup_user);
1771 p2 = skip_string(p2,1);
1774 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
1775 strcpy(p2,myworkgroup);
1777 p2 = skip_string(p2,1);
1780 SCVAL(p,0,MAJOR_VERSION); /* system version - e.g 4 in 4.1 */
1781 SCVAL(p,1,MINOR_VERSION); /* system version - e.g .1 in 4.1 */
1784 SIVAL(p,0,PTR_DIFF(p2,*rdata));
1785 strcpy(p2,myworkgroup); /* don't know. login domain?? */
1786 p2 = skip_string(p2,1);
1789 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
1791 p2 = skip_string(p2,1);
1794 *rdata_len = PTR_DIFF(p2,*rdata);
1796 SSVAL(*rparam,4,*rdata_len);
1801 /****************************************************************************
1802 get info about a user
1804 struct user_info_11 {
1805 char usri11_name[21]; 0-20
1807 char *usri11_comment; 22-25
1808 char *usri11_usr_comment; 26-29
1809 unsigned short usri11_priv; 30-31
1810 unsigned long usri11_auth_flags; 32-35
1811 long usri11_password_age; 36-39
1812 char *usri11_homedir; 40-43
1813 char *usri11_parms; 44-47
1814 long usri11_last_logon; 48-51
1815 long usri11_last_logoff; 52-55
1816 unsigned short usri11_bad_pw_count; 56-57
1817 unsigned short usri11_num_logons; 58-59
1818 char *usri11_logon_server; 60-63
1819 unsigned short usri11_country_code; 64-65
1820 char *usri11_workstations; 66-69
1821 unsigned long usri11_max_storage; 70-73
1822 unsigned short usri11_units_per_week; 74-75
1823 unsigned char *usri11_logon_hours; 76-79
1824 unsigned short usri11_code_page; 80-81
1829 usri11_name specifies the user name for which information is retireved
1831 usri11_pad aligns the next data structure element to a word boundary
1833 usri11_comment is a null terminated ASCII comment
1835 usri11_user_comment is a null terminated ASCII comment about the user
1837 usri11_priv specifies the level of the privilege assigned to the user.
1838 The possible values are:
1840 Name Value Description
1841 USER_PRIV_GUEST 0 Guest privilege
1842 USER_PRIV_USER 1 User privilege
1843 USER_PRV_ADMIN 2 Administrator privilege
1845 usri11_auth_flags specifies the account operator privileges. The
1846 possible values are:
1848 Name Value Description
1849 AF_OP_PRINT 0 Print operator
1852 Leach, Naik [Page 28]
\r\f
1855 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
1858 AF_OP_COMM 1 Communications operator
1859 AF_OP_SERVER 2 Server operator
1860 AF_OP_ACCOUNTS 3 Accounts operator
1863 usri11_password_age specifies how many seconds have elapsed since the
1864 password was last changed.
1866 usri11_home_dir points to a null terminated ASCII string that contains
1867 the path name of the user's home directory.
1869 usri11_parms points to a null terminated ASCII string that is set
1870 aside for use by applications.
1872 usri11_last_logon specifies the time when the user last logged on.
1873 This value is stored as the number of seconds elapsed since
1874 00:00:00, January 1, 1970.
1876 usri11_last_logoff specifies the time when the user last logged off.
1877 This value is stored as the number of seconds elapsed since
1878 00:00:00, January 1, 1970. A value of 0 means the last logoff
1881 usri11_bad_pw_count specifies the number of incorrect passwords
1882 entered since the last successful logon.
1884 usri11_log1_num_logons specifies the number of times this user has
1885 logged on. A value of -1 means the number of logons is unknown.
1887 usri11_logon_server points to a null terminated ASCII string that
1888 contains the name of the server to which logon requests are sent.
1889 A null string indicates logon requests should be sent to the
1892 usri11_country_code specifies the country code for the user's language
1895 usri11_workstations points to a null terminated ASCII string that
1896 contains the names of workstations the user may log on from.
1897 There may be up to 8 workstations, with the names separated by
1898 commas. A null strings indicates there are no restrictions.
1900 usri11_max_storage specifies the maximum amount of disk space the user
1901 can occupy. A value of 0xffffffff indicates there are no
1904 usri11_units_per_week specifies the equal number of time units into
1905 which a week is divided. This value must be equal to 168.
1907 usri11_logon_hours points to a 21 byte (168 bits) string that
1908 specifies the time during which the user can log on. Each bit
1909 represents one unique hour in a week. The first bit (bit 0, word
1910 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
1914 Leach, Naik [Page 29]
\r\f
1917 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
1920 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
1921 are no restrictions.
1923 usri11_code_page specifies the code page for the user's language of
1926 All of the pointers in this data structure need to be treated
1927 specially. The pointer is a 32 bit pointer. The higher 16 bits need
1928 to be ignored. The converter word returned in the parameters section
1929 needs to be subtracted from the lower 16 bits to calculate an offset
1930 into the return buffer where this ASCII string resides.
1932 There is no auxiliary data in the response.
1934 ****************************************************************************/
1936 #define usri11_name 0
1937 #define usri11_pad 21
1938 #define usri11_comment 22
1939 #define usri11_usr_comment 26
1940 #define usri11_full_name 30
1941 #define usri11_priv 34
1942 #define usri11_auth_flags 36
1943 #define usri11_password_age 40
1944 #define usri11_homedir 44
1945 #define usri11_parms 48
1946 #define usri11_last_logon 52
1947 #define usri11_last_logoff 56
1948 #define usri11_bad_pw_count 60
1949 #define usri11_num_logons 62
1950 #define usri11_logon_server 64
1951 #define usri11_country_code 68
1952 #define usri11_workstations 70
1953 #define usri11_max_storage 74
1954 #define usri11_units_per_week 78
1955 #define usri11_logon_hours 80
1956 #define usri11_code_page 84
1957 #define usri11_end 86
1959 #define USER_PRIV_GUEST 0
1960 #define USER_PRIV_USER 1
1961 #define USER_PRIV_ADMIN 2
1963 #define AF_OP_PRINT 0
1964 #define AF_OP_COMM 1
1965 #define AF_OP_SERVER 2
1966 #define AF_OP_ACCOUNTS 3
1969 static BOOL api_RNetUserGetInfo(int cnum,uint16 vuid, char *param,char *data,
1970 int mdrcnt,int mprcnt,
1971 char **rdata,char **rparam,
1972 int *rdata_len,int *rparam_len)
1974 char *str1 = param+2;
1975 char *str2 = skip_string(str1,1);
1976 char *UserName = skip_string(str2,1);
1977 char *p = skip_string(UserName,1);
1978 int uLevel = SVAL(p,0);
1981 /* get NIS home of a previously validated user - simeon */
1982 user_struct *vuser = get_valid_user_struct(vuid);
1983 DEBUG(3,(" Username of UID %d is %s\n", vuser->uid, vuser->name));
1984 #if (defined(NETGROUP) && defined(AUTOMOUNT))
1985 DEBUG(3,(" HOMESHR for %s is %s\n", vuser->name, vuser->home_share));
1989 *rparam = REALLOC(*rparam,*rparam_len);
1991 /* check it's a supported variant */
1992 if (strcmp(str1,"zWrLh") != 0) return False;
1995 case 0: p2 = "B21"; break;
1996 case 1: p2 = "B21BB16DWzzWz"; break;
1997 case 2: p2 = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
1998 case 10: p2 = "B21Bzzz"; break;
1999 case 11: p2 = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
2000 default: return False;
2003 if (strcmp(p2,str2) != 0) return False;
2005 *rdata_len = mdrcnt + 1024;
2006 *rdata = REALLOC(*rdata,*rdata_len);
2008 SSVAL(*rparam,0,NERR_Success);
2009 SSVAL(*rparam,2,0); /* converter word */
2012 p2 = p + usri11_end;
2015 strcpy(p+usri11_name,UserName); /* 21 bytes - user name */
2019 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
2024 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
2025 strcpy(p2,"Comment");
2026 p2 = skip_string(p2,1);
2028 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
2029 strcpy(p2,"UserComment");
2030 p2 = skip_string(p2,1);
2032 /* EEK! the cifsrap.txt doesn't have this in!!!! */
2033 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
2034 strcpy(p2,vuser->real_name); /* simeon */
2035 p2 = skip_string(p2,1);
2038 if (uLevel == 11) /* modelled after NTAS 3.51 reply */
2040 SSVAL(p,usri11_priv,Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2041 SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
2042 SIVALS(p,usri11_password_age,0xffffffff); /* password age */
2043 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
2044 if (*lp_logon_path())
2046 strcpy(p2,lp_logon_path());
2050 #if (defined(NETGROUP) && defined(AUTOMOUNT))
2051 strcpy(p2, vuser->home_share);
2053 strcpy(p2,"\\\\%L\\%U");
2056 standard_sub_basic(p2);
2057 p2 = skip_string(p2,1);
2058 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
2060 p2 = skip_string(p2,1);
2061 SIVAL(p,usri11_last_logon,0); /* last logon */
2062 SIVAL(p,usri11_last_logoff,0); /* last logoff */
2063 SSVALS(p,usri11_bad_pw_count,0xffffffff); /* bad pw counts */
2064 SSVALS(p,usri11_num_logons,0xffffffff); /* num logons */
2065 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
2067 p2 = skip_string(p2,1);
2068 SSVAL(p,usri11_country_code,0); /* country code */
2070 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
2072 p2 = skip_string(p2,1);
2074 SIVALS(p,usri11_max_storage,0xffffffff); /* max storage */
2075 SSVAL(p,usri11_units_per_week,168); /* units per week */
2076 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
2078 /* a simple way to get logon hours at all times. */
2080 SCVAL(p2,21,0); /* fix zero termination */
2081 p2 = skip_string(p2,1);
2083 SSVAL(p,usri11_code_page,0); /* code page */
2085 if (uLevel == 1 || uLevel == 2)
2087 memset(p+22,' ',16); /* password */
2088 SIVALS(p,38,-1); /* password age */
2090 Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2091 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
2092 if (*lp_logon_path())
2094 strcpy(p2,lp_logon_path());
2098 #if (defined(NETGROUP) && defined(AUTOMOUNT))
2099 strcpy(p2, vuser->home_share);
2101 strcpy(p2,"\\\\%L\\%U");
2104 standard_sub_basic(p2);
2105 p2 = skip_string(p2,1);
2106 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
2108 SSVAL(p,52,0); /* flags */
2109 SIVAL(p,54,0); /* script_path */
2112 SIVAL(p,60,0); /* auth_flags */
2113 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
2114 strcpy(p2,vuser->real_name); /* simeon */
2115 p2 = skip_string(p2,1);
2116 SIVAL(p,68,0); /* urs_comment */
2117 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
2119 p2 = skip_string(p2,1);
2120 SIVAL(p,76,0); /* workstations */
2121 SIVAL(p,80,0); /* last_logon */
2122 SIVAL(p,84,0); /* last_logoff */
2123 SIVALS(p,88,-1); /* acct_expires */
2124 SIVALS(p,92,-1); /* max_storage */
2125 SSVAL(p,96,168); /* units_per_week */
2126 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
2129 SSVALS(p,102,-1); /* bad_pw_count */
2130 SSVALS(p,104,-1); /* num_logons */
2131 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
2132 strcpy(p2,"\\\\%L");
2133 standard_sub_basic(p2);
2134 p2 = skip_string(p2,1);
2135 SSVAL(p,110,49); /* country_code */
2136 SSVAL(p,112,860); /* code page */
2140 *rdata_len = PTR_DIFF(p2,*rdata);
2142 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
2147 /*******************************************************************
2148 get groups that a user is a member of
2149 ******************************************************************/
2150 static BOOL api_NetUserGetGroups(int cnum,uint16 vuid, char *param,char *data,
2151 int mdrcnt,int mprcnt,
2152 char **rdata,char **rparam,
2153 int *rdata_len,int *rparam_len)
2155 char *str1 = param+2;
2156 char *str2 = skip_string(str1,1);
2157 char *UserName = skip_string(str2,1);
2158 char *p = skip_string(UserName,1);
2159 int uLevel = SVAL(p,0);
2164 *rparam = REALLOC(*rparam,*rparam_len);
2166 /* check it's a supported varient */
2167 if (strcmp(str1,"zWrLeh") != 0) return False;
2169 case 0: p2 = "B21"; break;
2170 default: return False;
2172 if (strcmp(p2,str2) != 0) return False;
2174 *rdata_len = mdrcnt + 1024;
2175 *rdata = REALLOC(*rdata,*rdata_len);
2177 SSVAL(*rparam,0,NERR_Success);
2178 SSVAL(*rparam,2,0); /* converter word */
2182 /* XXXX we need a real SAM database some day */
2183 strcpy(p,"Users"); p += 21; count++;
2184 strcpy(p,"Domain Users"); p += 21; count++;
2185 strcpy(p,"Guests"); p += 21; count++;
2186 strcpy(p,"Domain Guests"); p += 21; count++;
2188 *rdata_len = PTR_DIFF(p,*rdata);
2190 SSVAL(*rparam,4,count); /* is this right?? */
2191 SSVAL(*rparam,6,count); /* is this right?? */
2197 static BOOL api_WWkstaUserLogon(int cnum,uint16 vuid, char *param,char *data,
2198 int mdrcnt,int mprcnt,
2199 char **rdata,char **rparam,
2200 int *rdata_len,int *rparam_len)
2202 char *str1 = param+2;
2203 char *str2 = skip_string(str1,1);
2204 char *p = skip_string(str2,1);
2206 struct pack_desc desc;
2212 bzero(&desc,sizeof(desc));
2214 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
2216 /* check it's a supported varient */
2217 if (strcmp(str1,"OOWb54WrLh") != 0) return False;
2218 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) return False;
2219 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2221 desc.buflen = mdrcnt;
2222 desc.subformat = NULL;
2225 if (init_package(&desc,1,0))
2227 PACKI(&desc,"W",0); /* code */
2228 PACKS(&desc,"B21",name); /* eff. name */
2229 PACKS(&desc,"B",""); /* pad */
2231 Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2232 PACKI(&desc,"D",0); /* auth flags XXX */
2233 PACKI(&desc,"W",0); /* num logons */
2234 PACKI(&desc,"W",0); /* bad pw count */
2235 PACKI(&desc,"D",0); /* last logon */
2236 PACKI(&desc,"D",-1); /* last logoff */
2237 PACKI(&desc,"D",-1); /* logoff time */
2238 PACKI(&desc,"D",-1); /* kickoff time */
2239 PACKI(&desc,"D",0); /* password age */
2240 PACKI(&desc,"D",0); /* password can change */
2241 PACKI(&desc,"D",-1); /* password must change */
2244 strcpy(mypath,"\\\\");
2245 strcat(mypath,local_machine);
2247 PACKS(&desc,"z",mypath); /* computer */
2249 PACKS(&desc,"z",myworkgroup);/* domain */
2250 PACKS(&desc,"z",lp_logon_script()); /* script path */
2251 PACKI(&desc,"D",0x00000000); /* reserved */
2254 *rdata_len = desc.usedlen;
2256 *rparam = REALLOC(*rparam,*rparam_len);
2257 SSVALS(*rparam,0,desc.errcode);
2259 SSVAL(*rparam,4,desc.neededlen);
2261 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
2266 /****************************************************************************
2267 api_WAccessGetUserPerms
2268 ****************************************************************************/
2269 static BOOL api_WAccessGetUserPerms(int cnum,uint16 vuid, char *param,char *data,
2270 int mdrcnt,int mprcnt,
2271 char **rdata,char **rparam,
2272 int *rdata_len,int *rparam_len)
2274 char *str1 = param+2;
2275 char *str2 = skip_string(str1,1);
2276 char *user = skip_string(str2,1);
2277 char *resource = skip_string(user,1);
2279 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
2281 /* check it's a supported varient */
2282 if (strcmp(str1,"zzh") != 0) return False;
2283 if (strcmp(str2,"") != 0) return False;
2286 *rparam = REALLOC(*rparam,*rparam_len);
2287 SSVALS(*rparam,0,0); /* errorcode */
2288 SSVAL(*rparam,2,0); /* converter word */
2289 SSVAL(*rparam,4,0x7f); /* permission flags */
2294 /****************************************************************************
2295 api_WPrintJobEnumerate
2296 ****************************************************************************/
2297 static BOOL api_WPrintJobGetInfo(int cnum,uint16 vuid, char *param,char *data,
2298 int mdrcnt,int mprcnt,
2299 char **rdata,char **rparam,
2300 int *rdata_len,int *rparam_len)
2302 char *str1 = param+2;
2303 char *str2 = skip_string(str1,1);
2304 char *p = skip_string(str2,1);
2305 int uJobId = SVAL(p,0);
2311 struct pack_desc desc;
2312 print_queue_struct *queue=NULL;
2313 print_status_struct status;
2318 bzero(&desc,sizeof(desc));
2319 bzero(&status,sizeof(status));
2321 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,uJobId));
2323 /* check it's a supported varient */
2324 if (strcmp(str1,"WWrLh") != 0) return False;
2325 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2327 snum = (unsigned int)uJobId >> 8; /*## valid serice number??*/
2328 job = uJobId & 0xFF;
2330 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2332 count = get_printqueue(snum,cnum,&queue,&status);
2333 for (i = 0; i < count; i++) {
2334 if ((queue[i].job % 0xFF) == job) break;
2336 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2338 desc.buflen = mdrcnt;
2340 if (init_package(&desc,1,0)) {
2342 fill_printjob_info(cnum,snum,uLevel,&desc,&queue[i],i);
2343 *rdata_len = desc.usedlen;
2346 desc.errcode = NERR_JobNotFound;
2352 *rparam = REALLOC(*rparam,*rparam_len);
2353 SSVALS(*rparam,0,desc.errcode);
2355 SSVAL(*rparam,4,desc.neededlen);
2357 if (queue) free(queue);
2359 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
2363 static BOOL api_WPrintJobEnumerate(int cnum,uint16 vuid, char *param,char *data,
2364 int mdrcnt,int mprcnt,
2365 char **rdata,char **rparam,
2366 int *rdata_len,int *rparam_len)
2368 char *str1 = param+2;
2369 char *str2 = skip_string(str1,1);
2370 char *p = skip_string(str2,1);
2376 struct pack_desc desc;
2377 print_queue_struct *queue=NULL;
2378 print_status_struct status;
2380 bzero(&desc,sizeof(desc));
2381 bzero(&status,sizeof(status));
2383 p = skip_string(p,1);
2387 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
2389 /* check it's a supported varient */
2390 if (strcmp(str1,"zWrLeh") != 0) return False;
2391 if (uLevel > 2) return False; /* defined only for uLevel 0,1,2 */
2392 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2394 snum = lp_servicenumber(name);
2395 if (snum < 0 && pcap_printername_ok(name,NULL)) {
2396 int pnum = lp_servicenumber(PRINTERS_NAME);
2398 lp_add_printer(name,pnum);
2399 snum = lp_servicenumber(name);
2403 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2405 count = get_printqueue(snum,cnum,&queue,&status);
2406 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2408 desc.buflen = mdrcnt;
2410 if (init_package(&desc,count,0)) {
2412 for (i = 0; i < count; i++) {
2413 fill_printjob_info(cnum,snum,uLevel,&desc,&queue[i],i);
2414 if (desc.errcode == NERR_Success) succnt = i+1;
2418 *rdata_len = desc.usedlen;
2421 *rparam = REALLOC(*rparam,*rparam_len);
2422 SSVALS(*rparam,0,desc.errcode);
2424 SSVAL(*rparam,4,succnt);
2425 SSVAL(*rparam,6,count);
2427 if (queue) free(queue);
2429 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
2433 static int check_printdest_info(struct pack_desc* desc,
2434 int uLevel, char* id)
2436 desc->subformat = NULL;
2438 case 0: desc->format = "B9"; break;
2439 case 1: desc->format = "B9B21WWzW"; break;
2440 case 2: desc->format = "z"; break;
2441 case 3: desc->format = "zzzWWzzzWW"; break;
2442 default: return False;
2444 if (strcmp(desc->format,id) != 0) return False;
2448 static void fill_printdest_info(int cnum, int snum, int uLevel,
2449 struct pack_desc* desc)
2452 strcpy(buf,SERVICE(snum));
2455 PACKS(desc,"B9",buf); /* szName */
2457 PACKS(desc,"B21",""); /* szUserName */
2458 PACKI(desc,"W",0); /* uJobId */
2459 PACKI(desc,"W",0); /* fsStatus */
2460 PACKS(desc,"z",""); /* pszStatus */
2461 PACKI(desc,"W",0); /* time */
2464 if (uLevel == 2 || uLevel == 3) {
2465 PACKS(desc,"z",buf); /* pszPrinterName */
2467 PACKS(desc,"z",""); /* pszUserName */
2468 PACKS(desc,"z",""); /* pszLogAddr */
2469 PACKI(desc,"W",0); /* uJobId */
2470 PACKI(desc,"W",0); /* fsStatus */
2471 PACKS(desc,"z",""); /* pszStatus */
2472 PACKS(desc,"z",""); /* pszComment */
2473 PACKS(desc,"z","NULL"); /* pszDrivers */
2474 PACKI(desc,"W",0); /* time */
2475 PACKI(desc,"W",0); /* pad1 */
2480 static BOOL api_WPrintDestGetInfo(int cnum,uint16 vuid, char *param,char *data,
2481 int mdrcnt,int mprcnt,
2482 char **rdata,char **rparam,
2483 int *rdata_len,int *rparam_len)
2485 char *str1 = param+2;
2486 char *str2 = skip_string(str1,1);
2487 char *p = skip_string(str2,1);
2488 char* PrinterName = p;
2490 struct pack_desc desc;
2493 bzero(&desc,sizeof(desc));
2495 p = skip_string(p,1);
2499 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
2501 /* check it's a supported varient */
2502 if (strcmp(str1,"zWrLh") != 0) return False;
2503 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2505 snum = lp_servicenumber(PrinterName);
2506 if (snum < 0 && pcap_printername_ok(PrinterName,NULL)) {
2507 int pnum = lp_servicenumber(PRINTERS_NAME);
2509 lp_add_printer(PrinterName,pnum);
2510 snum = lp_servicenumber(PrinterName);
2516 desc.errcode = NERR_DestNotFound;
2520 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2522 desc.buflen = mdrcnt;
2523 if (init_package(&desc,1,0)) {
2524 fill_printdest_info(cnum,snum,uLevel,&desc);
2526 *rdata_len = desc.usedlen;
2530 *rparam = REALLOC(*rparam,*rparam_len);
2531 SSVALS(*rparam,0,desc.errcode);
2533 SSVAL(*rparam,4,desc.neededlen);
2535 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
2539 static BOOL api_WPrintDestEnum(int cnum,uint16 vuid, char *param,char *data,
2540 int mdrcnt,int mprcnt,
2541 char **rdata,char **rparam,
2542 int *rdata_len,int *rparam_len)
2544 char *str1 = param+2;
2545 char *str2 = skip_string(str1,1);
2546 char *p = skip_string(str2,1);
2550 struct pack_desc desc;
2551 int services = lp_numservices();
2553 bzero(&desc,sizeof(desc));
2558 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
2560 /* check it's a supported varient */
2561 if (strcmp(str1,"WrLeh") != 0) return False;
2562 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2565 for (i = 0; i < services; i++)
2566 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
2569 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2571 desc.buflen = mdrcnt;
2572 if (init_package(&desc,queuecnt,0)) {
2575 for (i = 0; i < services; i++) {
2576 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
2577 fill_printdest_info(cnum,i,uLevel,&desc);
2579 if (desc.errcode == NERR_Success) succnt = n;
2584 *rdata_len = desc.usedlen;
2587 *rparam = REALLOC(*rparam,*rparam_len);
2588 SSVALS(*rparam,0,desc.errcode);
2590 SSVAL(*rparam,4,succnt);
2591 SSVAL(*rparam,6,queuecnt);
2593 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
2597 static BOOL api_WPrintDriverEnum(int cnum,uint16 vuid, char *param,char *data,
2598 int mdrcnt,int mprcnt,
2599 char **rdata,char **rparam,
2600 int *rdata_len,int *rparam_len)
2602 char *str1 = param+2;
2603 char *str2 = skip_string(str1,1);
2604 char *p = skip_string(str2,1);
2607 struct pack_desc desc;
2609 bzero(&desc,sizeof(desc));
2614 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
2616 /* check it's a supported varient */
2617 if (strcmp(str1,"WrLeh") != 0) return False;
2618 if (uLevel != 0 || strcmp(str2,"B41") != 0) return False;
2620 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2622 desc.buflen = mdrcnt;
2623 if (init_package(&desc,1,0)) {
2624 PACKS(&desc,"B41","NULL");
2627 succnt = (desc.errcode == NERR_Success ? 1 : 0);
2629 *rdata_len = desc.usedlen;
2632 *rparam = REALLOC(*rparam,*rparam_len);
2633 SSVALS(*rparam,0,desc.errcode);
2635 SSVAL(*rparam,4,succnt);
2638 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
2642 static BOOL api_WPrintQProcEnum(int cnum,uint16 vuid, char *param,char *data,
2643 int mdrcnt,int mprcnt,
2644 char **rdata,char **rparam,
2645 int *rdata_len,int *rparam_len)
2647 char *str1 = param+2;
2648 char *str2 = skip_string(str1,1);
2649 char *p = skip_string(str2,1);
2652 struct pack_desc desc;
2654 bzero(&desc,sizeof(desc));
2659 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
2661 /* check it's a supported varient */
2662 if (strcmp(str1,"WrLeh") != 0) return False;
2663 if (uLevel != 0 || strcmp(str2,"B13") != 0) return False;
2665 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2667 desc.buflen = mdrcnt;
2669 if (init_package(&desc,1,0)) {
2670 PACKS(&desc,"B13","lpd");
2673 succnt = (desc.errcode == NERR_Success ? 1 : 0);
2675 *rdata_len = desc.usedlen;
2678 *rparam = REALLOC(*rparam,*rparam_len);
2679 SSVALS(*rparam,0,desc.errcode);
2681 SSVAL(*rparam,4,succnt);
2684 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
2688 static BOOL api_WPrintPortEnum(int cnum,uint16 vuid, char *param,char *data,
2689 int mdrcnt,int mprcnt,
2690 char **rdata,char **rparam,
2691 int *rdata_len,int *rparam_len)
2693 char *str1 = param+2;
2694 char *str2 = skip_string(str1,1);
2695 char *p = skip_string(str2,1);
2698 struct pack_desc desc;
2700 bzero(&desc,sizeof(desc));
2705 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
2707 /* check it's a supported varient */
2708 if (strcmp(str1,"WrLeh") != 0) return False;
2709 if (uLevel != 0 || strcmp(str2,"B9") != 0) return False;
2711 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2712 bzero(&desc,sizeof(desc));
2714 desc.buflen = mdrcnt;
2716 if (init_package(&desc,1,0)) {
2717 PACKS(&desc,"B13","lp0");
2720 succnt = (desc.errcode == NERR_Success ? 1 : 0);
2722 *rdata_len = desc.usedlen;
2725 *rparam = REALLOC(*rparam,*rparam_len);
2726 SSVALS(*rparam,0,desc.errcode);
2728 SSVAL(*rparam,4,succnt);
2731 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
2742 } api_fd_commands [] =
2744 { "SetNmdPpHndState", "lsarpc", 1, api_LsarpcSNPHS },
2745 { "TransactNmPipe", "lsarpc", 0x26, api_LsarpcTNP },
2746 { NULL, NULL, -1, (BOOL (*)())api_Unsupported }
2749 /****************************************************************************
2750 handle remote api calls delivered to a named pipe already opened.
2751 ****************************************************************************/
2752 static int api_fd_reply(int cnum,uint16 vuid,char *outbuf,
2753 uint16 *setup,char *data,char *params,
2754 int suwcnt,int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
2757 char *rparam = NULL;
2765 /* First find out the name of this file. */
2768 DEBUG(0,("Unexpected named pipe transaction.\n"));
2772 /* Get the file handle and hence the file name. */
2774 subcommand = setup[0];
2776 DEBUG(3,("Got API command %d on pipe %s ",subcommand,Files[fd].name));
2777 DEBUG(3,("(tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
2778 tdscnt,tpscnt,mdrcnt,mprcnt));
2780 for (i=0;api_fd_commands[i].name;i++)
2781 if (strequal(api_fd_commands[i].pipename, Files[fd].name) &&
2782 api_fd_commands[i].subcommand == subcommand &&
2783 api_fd_commands[i].fn)
2785 DEBUG(3,("Doing %s\n",api_fd_commands[i].name));
2789 rdata = (char *)malloc(1024); if (rdata) bzero(rdata,1024);
2790 rparam = (char *)malloc(1024); if (rparam) bzero(rparam,1024);
2792 reply = api_fd_commands[i].fn(cnum,vuid,params,data,mdrcnt,mprcnt,
2793 &rdata,&rparam,&rdata_len,&rparam_len);
2795 if (rdata_len > mdrcnt ||
2796 rparam_len > mprcnt)
2798 reply = api_TooSmall(cnum,vuid,params,data,mdrcnt,mprcnt,
2799 &rdata,&rparam,&rdata_len,&rparam_len);
2803 /* if we get False back then it's actually unsupported */
2805 api_Unsupported(cnum,vuid,params,data,mdrcnt,mprcnt,
2806 &rdata,&rparam,&rdata_len,&rparam_len);
2808 /* now send the reply */
2809 send_trans_reply(outbuf,rdata,rparam,NULL,rdata_len,rparam_len,0);
2821 /****************************************************************************
2822 the buffer was too small
2823 ****************************************************************************/
2824 static BOOL api_TooSmall(int cnum,uint16 vuid, char *param,char *data,
2825 int mdrcnt,int mprcnt,
2826 char **rdata,char **rparam,
2827 int *rdata_len,int *rparam_len)
2829 *rparam_len = MIN(*rparam_len,mprcnt);
2830 *rparam = REALLOC(*rparam,*rparam_len);
2834 SSVAL(*rparam,0,NERR_BufTooSmall);
2836 DEBUG(3,("Supplied buffer too small in API command\n"));
2842 /****************************************************************************
2843 the request is not supported
2844 ****************************************************************************/
2845 static BOOL api_Unsupported(int cnum,uint16 vuid, char *param,char *data,
2846 int mdrcnt,int mprcnt,
2847 char **rdata,char **rparam,
2848 int *rdata_len,int *rparam_len)
2851 *rparam = REALLOC(*rparam,*rparam_len);
2855 SSVAL(*rparam,0,NERR_notsupported);
2856 SSVAL(*rparam,2,0); /* converter word */
2858 DEBUG(3,("Unsupported API command\n"));
2872 } api_commands[] = {
2873 {"RNetShareEnum", 0, (BOOL (*)())api_RNetShareEnum,0},
2874 {"RNetShareGetInfo", 1, (BOOL (*)())api_RNetShareGetInfo,0},
2875 {"RNetServerGetInfo", 13, (BOOL (*)())api_RNetServerGetInfo,0},
2876 {"RNetUserGetInfo", 56, (BOOL (*)())api_RNetUserGetInfo,0},
2877 {"NetUserGetGroups", 59, (BOOL (*)())api_NetUserGetGroups,0},
2878 {"NetWkstaGetInfo", 63, (BOOL (*)())api_NetWkstaGetInfo,0},
2879 {"DosPrintQEnum", 69, (BOOL (*)())api_DosPrintQEnum,0},
2880 {"DosPrintQGetInfo", 70, (BOOL (*)())api_DosPrintQGetInfo,0},
2881 {"WPrintJobEnumerate",76, (BOOL (*)())api_WPrintJobEnumerate,0},
2882 {"WPrintJobGetInfo", 77, (BOOL (*)())api_WPrintJobGetInfo,0},
2883 {"RDosPrintJobDel", 81, (BOOL (*)())api_RDosPrintJobDel,0},
2884 {"RDosPrintJobPause", 82, (BOOL (*)())api_RDosPrintJobDel,0},
2885 {"RDosPrintJobResume",83, (BOOL (*)())api_RDosPrintJobDel,0},
2886 {"WPrintDestEnum", 84, (BOOL (*)())api_WPrintDestEnum,0},
2887 {"WPrintDestGetInfo", 85, (BOOL (*)())api_WPrintDestGetInfo,0},
2888 {"NetRemoteTOD", 91, (BOOL (*)())api_NetRemoteTOD,0},
2889 {"WPrintQueuePurge", 103, (BOOL (*)())api_WPrintQueuePurge,0},
2890 {"NetServerEnum", 104, (BOOL (*)())api_RNetServerEnum,0},
2891 {"WAccessGetUserPerms",105, (BOOL (*)())api_WAccessGetUserPerms,0},
2892 {"SetUserPassword", 115, (BOOL (*)())api_SetUserPassword,0},
2893 {"WWkstaUserLogon", 132, (BOOL (*)())api_WWkstaUserLogon,0},
2894 {"PrintJobInfo", 147, (BOOL (*)())api_PrintJobInfo,0},
2895 {"WPrintDriverEnum", 205, (BOOL (*)())api_WPrintDriverEnum,0},
2896 {"WPrintQProcEnum", 206, (BOOL (*)())api_WPrintQProcEnum,0},
2897 {"WPrintPortEnum", 207, (BOOL (*)())api_WPrintPortEnum,0},
2898 {NULL, -1, (BOOL (*)())api_Unsupported,0}};
2901 /****************************************************************************
2902 handle remote api calls
2903 ****************************************************************************/
2904 static int api_reply(int cnum,uint16 vuid,char *outbuf,char *data,char *params,
2905 int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
2907 int api_command = SVAL(params,0);
2909 char *rparam = NULL;
2915 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
2916 api_command,params+2,skip_string(params+2,1),
2917 tdscnt,tpscnt,mdrcnt,mprcnt));
2919 for (i=0;api_commands[i].name;i++)
2920 if (api_commands[i].id == api_command && api_commands[i].fn)
2922 DEBUG(3,("Doing %s\n",api_commands[i].name));
2926 rdata = (char *)malloc(1024); if (rdata) bzero(rdata,1024);
2927 rparam = (char *)malloc(1024); if (rparam) bzero(rparam,1024);
2929 reply = api_commands[i].fn(cnum,vuid,params,data,mdrcnt,mprcnt,
2930 &rdata,&rparam,&rdata_len,&rparam_len);
2933 if (rdata_len > mdrcnt ||
2934 rparam_len > mprcnt)
2936 reply = api_TooSmall(cnum,vuid,params,data,mdrcnt,mprcnt,
2937 &rdata,&rparam,&rdata_len,&rparam_len);
2941 /* if we get False back then it's actually unsupported */
2943 api_Unsupported(cnum,vuid,params,data,mdrcnt,mprcnt,
2944 &rdata,&rparam,&rdata_len,&rparam_len);
2948 /* now send the reply */
2949 send_trans_reply(outbuf,rdata,rparam,NULL,rdata_len,rparam_len,0);
2959 /****************************************************************************
2960 handle named pipe commands
2961 ****************************************************************************/
2962 static int named_pipe(int cnum,uint16 vuid, char *outbuf,char *name,
2963 uint16 *setup,char *data,char *params,
2964 int suwcnt,int tdscnt,int tpscnt,
2965 int msrcnt,int mdrcnt,int mprcnt)
2968 if (strequal(name,"LANMAN"))
2969 return(api_reply(cnum,vuid,outbuf,data,params,tdscnt,tpscnt,mdrcnt,mprcnt));
2971 if (strlen(name) < 1)
2972 return(api_fd_reply(cnum,vuid,outbuf,setup,data,params,suwcnt,tdscnt,tpscnt,mdrcnt,mprcnt));
2975 DEBUG(3,("named pipe command on <%s> 0x%X setup1=%d\n",
2976 name,(int)setup[0],(int)setup[1]));
2982 /****************************************************************************
2984 ****************************************************************************/
2985 int reply_trans(char *inbuf,char *outbuf)
2989 char *data=NULL,*params=NULL;
2993 int cnum = SVAL(inbuf,smb_tid);
2994 uint16 vuid = SVAL(inbuf,smb_uid);
2996 int tpscnt = SVAL(inbuf,smb_vwv0);
2997 int tdscnt = SVAL(inbuf,smb_vwv1);
2998 int mprcnt = SVAL(inbuf,smb_vwv2);
2999 int mdrcnt = SVAL(inbuf,smb_vwv3);
3000 int msrcnt = CVAL(inbuf,smb_vwv4);
3001 BOOL close_on_completion = BITSETW(inbuf+smb_vwv5,0);
3002 BOOL one_way = BITSETW(inbuf+smb_vwv5,1);
3003 int pscnt = SVAL(inbuf,smb_vwv9);
3004 int psoff = SVAL(inbuf,smb_vwv10);
3005 int dscnt = SVAL(inbuf,smb_vwv11);
3006 int dsoff = SVAL(inbuf,smb_vwv12);
3007 int suwcnt = CVAL(inbuf,smb_vwv13);
3009 StrnCpy(name,smb_buf(inbuf),sizeof(name)-1);
3013 data = (char *)malloc(tdscnt);
3014 memcpy(data,smb_base(inbuf)+dsoff,dscnt);
3018 params = (char *)malloc(tpscnt);
3019 memcpy(params,smb_base(inbuf)+psoff,pscnt);
3025 setup = (uint16 *)malloc(suwcnt*sizeof(setup[0]));
3026 for (i=0;i<suwcnt;i++)
3027 setup[i] = SVAL(inbuf,smb_vwv14+i*SIZEOFWORD);
3031 if (pscnt < tpscnt || dscnt < tdscnt)
3033 /* We need to send an interim response then receive the rest
3034 of the parameter/data bytes */
3035 outsize = set_message(outbuf,0,0,True);
3037 send_smb(Client,outbuf);
3040 /* receive the rest of the trans packet */
3041 while (pscnt < tpscnt || dscnt < tdscnt)
3043 int pcnt,poff,dcnt,doff,pdisp,ddisp;
3045 if (!receive_smb(Client,inbuf, SMB_SECONDARY_WAIT) ||
3046 CVAL(inbuf, smb_com) != SMBtrans)
3048 DEBUG(2,("Invalid secondary trans2 packet\n"));
3049 if (params) free(params);
3050 if (data) free(data);
3051 if (setup) free(setup);
3052 return(ERROR(ERRSRV,ERRerror));
3057 tpscnt = SVAL(inbuf,smb_vwv0);
3058 tdscnt = SVAL(inbuf,smb_vwv1);
3060 pcnt = SVAL(inbuf,smb_vwv2);
3061 poff = SVAL(inbuf,smb_vwv3);
3062 pdisp = SVAL(inbuf,smb_vwv4);
3064 dcnt = SVAL(inbuf,smb_vwv5);
3065 doff = SVAL(inbuf,smb_vwv6);
3066 ddisp = SVAL(inbuf,smb_vwv7);
3072 memcpy(params+pdisp,smb_base(inbuf)+poff,pcnt);
3074 memcpy(data+ddisp,smb_base(inbuf)+doff,dcnt);
3078 DEBUG(3,("trans <%s> data=%d params=%d setup=%d\n",name,tdscnt,tpscnt,suwcnt));
3081 if (strncmp(name,"\\PIPE\\",strlen("\\PIPE\\")) == 0)
3082 outsize = named_pipe(cnum,vuid,outbuf,name+strlen("\\PIPE\\"),setup,data,params,
3083 suwcnt,tdscnt,tpscnt,msrcnt,mdrcnt,mprcnt);
3086 if (data) free(data);
3087 if (params) free(params);
3088 if (setup) free(setup);
3090 if (close_on_completion)
3091 close_cnum(cnum,vuid);
3097 return(ERROR(ERRSRV,ERRnosupport));