3 Unix SMB/Netbios implementation.
5 Inter-process communication and named pipe handling
6 Copyright (C) Andrew Tridgell 1992-1995
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 This file handles the named pipe and mailslot calls
24 in the SMBtrans protocol
34 extern int DEBUGLEVEL;
36 extern files_struct Files[];
37 extern connection_struct Connections[];
39 extern fstring local_machine;
41 #define NERR_Success 0
42 #define NERR_badpass 86
43 #define NERR_notsupported 50
45 #define NERR_BASE (2100)
46 #define NERR_BufTooSmall (NERR_BASE+23)
47 #define NERR_JobNotFound (NERR_BASE+51)
48 #define NERR_DestNotFound (NERR_BASE+52)
49 #define ERROR_INVALID_LEVEL 124
50 #define ERROR_MORE_DATA 234
52 #define REALLOC(ptr,size) Realloc(ptr,MAX((size),4*1024))
54 #define ACCESS_READ 0x01
55 #define ACCESS_WRITE 0x02
56 #define ACCESS_CREATE 0x04
58 #define SHPWLEN 8 /* share password length */
59 #define NNLEN 12 /* 8.3 net name length */
60 #define SNLEN 15 /* service name length */
61 #define QNLEN 12 /* queue name maximum length */
63 #define MAJOR_VERSION 4
64 #define MINOR_VERSION 1
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,
776 strcpy(fname,lp_lockdir());
777 trim_string(fname,NULL,"/");
779 strcat(fname,SERVER_LIST);
781 f = fopen(fname,"r");
784 DEBUG(4,("Can't open %s - %s\n",fname,strerror(errno)));
788 /* request for everything is code for request all servers */
789 if (servertype == SV_TYPE_ALL) servertype &= ~SV_TYPE_DOMAIN_ENUM;
791 DEBUG(4,("Servertype search: %8x\n",servertype));
796 struct srv_info_struct *s;
801 fgets(line,sizeof(line)-1,f);
802 if (!*line) continue;
804 if (count == alloced) {
806 (*servers) = (struct srv_info_struct *)
807 Realloc(*servers,sizeof(**servers)*alloced);
808 if (!(*servers)) return(0);
809 bzero((char *)((*servers)+count),sizeof(**servers)*(alloced-count));
811 s = &(*servers)[count];
813 if (!next_token(&ptr,s->name , NULL)) continue;
814 if (!next_token(&ptr,stype , NULL)) continue;
815 if (!next_token(&ptr,s->comment, NULL)) continue;
816 if (!next_token(&ptr,s->domain , NULL)) {
817 /* this allows us to cope with an old nmbd */
818 strcpy(s->domain,lp_workgroup());
821 if (sscanf(stype,"%X",&s->type) != 1) {
822 DEBUG(4,("r:host file "));
826 /* doesn't match up: don't want it */
827 if (!(servertype & s->type)) {
828 DEBUG(4,("r:serv type "));
832 if ((servertype & SV_TYPE_DOMAIN_ENUM) !=
833 (s->type & SV_TYPE_DOMAIN_ENUM))
835 DEBUG(4,("s: dom mismatch "));
839 if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM))
846 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
847 s->name, s->type, s->comment, s->domain));
849 s->server_added = True;
854 DEBUG(4,("%20s %8x %25s %15s\n",
855 s->name, s->type, s->comment, s->domain));
864 /*******************************************************************
865 fill in a server info structure
866 ******************************************************************/
867 static int fill_srv_info(struct srv_info_struct *service,
868 int uLevel, char **buf, int *buflen,
869 char **stringbuf, int *stringspace, char *baseaddr)
878 case 0: struct_len = 16; break;
879 case 1: struct_len = 26; break;
889 len = strlen(service->comment)+1;
893 if (buflen) *buflen = struct_len;
894 if (stringspace) *stringspace = len;
895 return struct_len + len;
900 if (*buflen < struct_len) return -1;
909 l2 = *buflen - struct_len;
911 if (!baseaddr) baseaddr = p;
916 StrnCpy(p,service->name,15);
920 StrnCpy(p,service->name,15);
921 SIVAL(p,18,service->type);
922 SIVAL(p,22,PTR_DIFF(p2,baseaddr));
923 len += CopyAndAdvance(&p2,service->comment,&l2);
929 *buf = p + struct_len;
930 *buflen -= struct_len;
943 static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
945 return(strcmp(s1->name,s2->name));
948 /****************************************************************************
949 view list of servers available (or possibly domains). The info is
950 extracted from lists saved by nmbd on the local host
951 ****************************************************************************/
952 static BOOL api_RNetServerEnum(int cnum, uint16 vuid, char *param, char *data,
953 int mdrcnt, int mprcnt, char **rdata,
954 char **rparam, int *rdata_len, int *rparam_len)
956 char *str1 = param+2;
957 char *str2 = skip_string(str1,1);
958 char *p = skip_string(str2,1);
959 int uLevel = SVAL(p,0);
960 int buf_len = SVAL(p,2);
961 uint32 servertype = IVAL(p,4);
963 int data_len, fixed_len, string_len;
965 struct srv_info_struct *servers=NULL;
966 int counted=0,total=0;
970 BOOL local_request = servertype & SV_TYPE_LOCAL_LIST_ONLY;
972 if (servertype == SV_TYPE_ALL) servertype &= ~SV_TYPE_DOMAIN_ENUM;
974 domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
978 if (!prefix_ok(str1,"WrLehD")) return False;
979 if (!check_server_info(uLevel,str2)) return False;
981 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
982 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
983 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
985 if (strcmp(str1, "WrLehDz") == 0) {
986 StrnCpy(domain, p, sizeof(fstring)-1);
988 StrnCpy(domain, lp_workgroup(), sizeof(fstring)-1);
991 if (lp_browse_list())
992 total = get_server_info(servertype,&servers,domain);
994 data_len = fixed_len = string_len = 0;
997 qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
1000 char *lastname=NULL;
1002 for (i=0;i<total;i++)
1004 struct srv_info_struct *s = &servers[i];
1005 if (lastname && strequal(lastname,s->name)) continue;
1007 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1008 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1009 s->name, s->type, s->comment, s->domain));
1011 if (data_len <= buf_len) {
1014 string_len += s_len;
1021 *rdata_len = fixed_len + string_len;
1022 *rdata = REALLOC(*rdata,*rdata_len);
1023 bzero(*rdata,*rdata_len);
1025 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1031 char *lastname=NULL;
1032 int count2 = counted;
1033 for (i = 0; i < total && count2;i++)
1035 struct srv_info_struct *s = &servers[i];
1036 if (lastname && strequal(lastname,s->name)) continue;
1038 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1039 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1040 s->name, s->type, s->comment, s->domain));
1046 *rparam = REALLOC(*rparam,*rparam_len);
1047 SSVAL(*rparam,0,NERR_Success);
1049 SSVAL(*rparam,4,counted);
1050 SSVAL(*rparam,6,counted+missed);
1052 if (servers) free(servers);
1054 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1055 domain,uLevel,counted,counted+missed));
1061 /****************************************************************************
1062 get info about a share
1063 ****************************************************************************/
1064 static BOOL check_share_info(int uLevel, char* id)
1068 if (strcmp(id,"B13") != 0) return False;
1071 if (strcmp(id,"B13BWz") != 0) return False;
1074 if (strcmp(id,"B13BWzWWWzB9B") != 0) return False;
1077 if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) return False;
1079 default: return False;
1084 static int fill_share_info(int cnum, int snum, int uLevel,
1085 char** buf, int* buflen,
1086 char** stringbuf, int* stringspace, char* baseaddr)
1095 case 0: struct_len = 13; break;
1096 case 1: struct_len = 20; break;
1097 case 2: struct_len = 40; break;
1098 case 91: struct_len = 68; break;
1106 if (uLevel > 0) len += StrlenExpanded(cnum,snum,lp_comment(snum));
1107 if (uLevel > 1) len += strlen(lp_pathname(snum)) + 1;
1108 if (buflen) *buflen = struct_len;
1109 if (stringspace) *stringspace = len;
1110 return struct_len + len;
1115 if ((*buflen) < struct_len) return -1;
1123 p2 = p + struct_len;
1124 l2 = (*buflen) - struct_len;
1126 if (!baseaddr) baseaddr = p;
1128 StrnCpy(p,lp_servicename(snum),13);
1134 type = STYPE_DISKTREE;
1135 if (lp_print_ok(snum)) type = STYPE_PRINTQ;
1136 if (strequal("IPC$",lp_servicename(snum))) type = STYPE_IPC;
1137 SSVAL(p,14,type); /* device type */
1138 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1139 len += CopyExpanded(cnum,snum,&p2,lp_comment(snum),&l2);
1144 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1145 SSVALS(p,22,-1); /* max uses */
1146 SSVAL(p,24,1); /* current uses */
1147 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1148 len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1149 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1154 memset(p+40,0,SHPWLEN+2);
1166 (*buf) = p + struct_len;
1167 (*buflen) -= struct_len;
1169 (*stringspace) = l2;
1179 static BOOL api_RNetShareGetInfo(int cnum,uint16 vuid, char *param,char *data,
1180 int mdrcnt,int mprcnt,
1181 char **rdata,char **rparam,
1182 int *rdata_len,int *rparam_len)
1184 char *str1 = param+2;
1185 char *str2 = skip_string(str1,1);
1186 char *netname = skip_string(str2,1);
1187 char *p = skip_string(netname,1);
1188 int uLevel = SVAL(p,0);
1189 int snum = find_service(netname);
1191 if (snum < 0) return False;
1193 /* check it's a supported varient */
1194 if (!prefix_ok(str1,"zWrLh")) return False;
1195 if (!check_share_info(uLevel,str2)) return False;
1197 *rdata = REALLOC(*rdata,mdrcnt);
1199 *rdata_len = fill_share_info(cnum,snum,uLevel,&p,&mdrcnt,0,0,0);
1200 if (*rdata_len < 0) return False;
1203 *rparam = REALLOC(*rparam,*rparam_len);
1204 SSVAL(*rparam,0,NERR_Success);
1205 SSVAL(*rparam,2,0); /* converter word */
1206 SSVAL(*rparam,4,*rdata_len);
1211 /****************************************************************************
1212 view list of shares available
1213 ****************************************************************************/
1214 static BOOL api_RNetShareEnum(int cnum,uint16 vuid, char *param,char *data,
1215 int mdrcnt,int mprcnt,
1216 char **rdata,char **rparam,
1217 int *rdata_len,int *rparam_len)
1219 char *str1 = param+2;
1220 char *str2 = skip_string(str1,1);
1221 char *p = skip_string(str2,1);
1222 int uLevel = SVAL(p,0);
1223 int buf_len = SVAL(p,2);
1225 int count=lp_numservices();
1226 int total=0,counted=0;
1228 int data_len, fixed_len, string_len;
1231 if (!prefix_ok(str1,"WrLeh")) return False;
1232 if (!check_share_info(uLevel,str2)) return False;
1234 data_len = fixed_len = string_len = 0;
1235 for (i=0;i<count;i++)
1236 if (lp_browseable(i) && lp_snum_ok(i))
1239 data_len += fill_share_info(cnum,i,uLevel,0,&f_len,0,&s_len,0);
1240 if (data_len <= buf_len)
1244 string_len += s_len;
1247 *rdata_len = fixed_len + string_len;
1248 *rdata = REALLOC(*rdata,*rdata_len);
1249 memset(*rdata,0,*rdata_len);
1251 p2 = (*rdata) + fixed_len; /* auxillery data (strings) will go here */
1255 for (i = 0; i < count;i++)
1256 if (lp_browseable(i) && lp_snum_ok(i))
1257 if (fill_share_info(cnum,i,uLevel,&p,&f_len,&p2,&s_len,*rdata) < 0)
1261 *rparam = REALLOC(*rparam,*rparam_len);
1262 SSVAL(*rparam,0,NERR_Success);
1264 SSVAL(*rparam,4,counted);
1265 SSVAL(*rparam,6,total);
1267 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1268 counted,total,uLevel,
1269 buf_len,*rdata_len,mdrcnt));
1275 /****************************************************************************
1276 get the time of day info
1277 ****************************************************************************/
1278 static BOOL api_NetRemoteTOD(int cnum,uint16 vuid, char *param,char *data,
1279 int mdrcnt,int mprcnt,
1280 char **rdata,char **rparam,
1281 int *rdata_len,int *rparam_len)
1285 *rparam = REALLOC(*rparam,*rparam_len);
1288 *rdata = REALLOC(*rdata,*rdata_len);
1290 SSVAL(*rparam,0,NERR_Success);
1291 SSVAL(*rparam,2,0); /* converter word */
1297 time_t unixdate = time(NULL);
1299 put_dos_date3(p,0,unixdate); /* this is the time that is looked at
1300 by NT in a "net time" operation,
1301 it seems to ignore the one below */
1303 /* the client expects to get localtime, not GMT, in this bit
1304 (I think, this needs testing) */
1305 t = LocalTime(&unixdate);
1307 SIVAL(p,4,0); /* msecs ? */
1308 CVAL(p,8) = t->tm_hour;
1309 CVAL(p,9) = t->tm_min;
1310 CVAL(p,10) = t->tm_sec;
1311 CVAL(p,11) = 0; /* hundredths of seconds */
1312 SSVALS(p,12,TimeDiff(unixdate)/60); /* timezone in minutes from GMT */
1313 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
1314 CVAL(p,16) = t->tm_mday;
1315 CVAL(p,17) = t->tm_mon + 1;
1316 SSVAL(p,18,1900+t->tm_year);
1317 CVAL(p,20) = t->tm_wday;
1324 /****************************************************************************
1325 set the user password
1326 ****************************************************************************/
1327 static BOOL api_SetUserPassword(int cnum,uint16 vuid, char *param,char *data,
1328 int mdrcnt,int mprcnt,
1329 char **rdata,char **rparam,
1330 int *rdata_len,int *rparam_len)
1332 char *p = skip_string(param+2,2);
1334 fstring pass1,pass2;
1338 p = skip_string(p,1);
1340 StrnCpy(pass1,p,16);
1341 StrnCpy(pass2,p+16,16);
1344 *rparam = REALLOC(*rparam,*rparam_len);
1348 SSVAL(*rparam,0,NERR_badpass);
1349 SSVAL(*rparam,2,0); /* converter word */
1351 DEBUG(3,("Set password for <%s>\n",user));
1353 if (password_ok(user,pass1,strlen(pass1),NULL) &&
1354 chgpasswd(user,pass1,pass2))
1356 SSVAL(*rparam,0,NERR_Success);
1359 bzero(pass1,sizeof(fstring));
1360 bzero(pass2,sizeof(fstring));
1365 /****************************************************************************
1368 ****************************************************************************/
1369 static BOOL api_RDosPrintJobDel(int cnum,uint16 vuid, char *param,char *data,
1370 int mdrcnt,int mprcnt,
1371 char **rdata,char **rparam,
1372 int *rdata_len,int *rparam_len)
1374 int function = SVAL(param,0);
1375 char *str1 = param+2;
1376 char *str2 = skip_string(str1,1);
1377 char *p = skip_string(str2,1);
1378 int jobid = (SVAL(p,0)&0xFF); /* the snum and jobid are encoded
1379 by the print queue api */
1380 int snum = (SVAL(p,0)>>8);
1384 /* check it's a supported varient */
1385 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
1389 *rparam = REALLOC(*rparam,*rparam_len);
1393 SSVAL(*rparam,0,NERR_Success);
1395 if (snum >= 0 && VALID_SNUM(snum))
1397 print_queue_struct *queue=NULL;
1399 count = get_printqueue(snum,cnum,&queue,NULL);
1401 for (i=0;i<count;i++)
1402 if ((queue[i].job%0xFF) == jobid)
1405 case 81: /* delete */
1406 DEBUG(3,("Deleting queue entry %d\n",queue[i].job));
1407 del_printqueue(cnum,snum,queue[i].job);
1409 case 82: /* pause */
1410 case 83: /* resume */
1411 DEBUG(3,("%s queue entry %d\n",
1412 (function==82?"pausing":"resuming"),queue[i].job));
1413 status_printjob(cnum,snum,queue[i].job,
1414 (function==82?LPQ_PAUSED:LPQ_QUEUED));
1421 SSVAL(*rparam,0,NERR_JobNotFound);
1423 if (queue) free(queue);
1426 SSVAL(*rparam,2,0); /* converter word */
1431 static BOOL api_WPrintQueuePurge(int cnum,uint16 vuid, char *param,char *data,
1432 int mdrcnt,int mprcnt,
1433 char **rdata,char **rparam,
1434 int *rdata_len,int *rparam_len)
1436 char *str1 = param+2;
1437 char *str2 = skip_string(str1,1);
1438 char *QueueName = skip_string(str2,1);
1441 /* check it's a supported varient */
1442 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
1446 *rparam = REALLOC(*rparam,*rparam_len);
1450 SSVAL(*rparam,0,NERR_Success);
1451 SSVAL(*rparam,2,0); /* converter word */
1453 snum = lp_servicenumber(QueueName);
1454 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
1455 int pnum = lp_servicenumber(PRINTERS_NAME);
1457 lp_add_printer(QueueName,pnum);
1458 snum = lp_servicenumber(QueueName);
1462 if (snum >= 0 && VALID_SNUM(snum)) {
1463 print_queue_struct *queue=NULL;
1467 count = get_printqueue(snum,cnum,&queue,NULL);
1468 for (i = 0; i < count; i++)
1469 del_printqueue(cnum,snum,queue[i].job);
1471 if (queue) free(queue);
1474 DEBUG(3,("Print queue purge, queue=%s\n",QueueName));
1480 /****************************************************************************
1481 set the property of a print job (undocumented?)
1482 ? function = 0xb -> set name of print job
1483 ? function = 0x6 -> move print job up/down
1484 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
1485 or <WWsTP> <WB21BB16B10zWWzDDz>
1486 ****************************************************************************/
1487 static int check_printjob_info(struct pack_desc* desc,
1488 int uLevel, char* id)
1490 desc->subformat = NULL;
1492 case 0: desc->format = "W"; break;
1493 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
1494 case 2: desc->format = "WWzWWDDzz"; break;
1495 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
1496 default: return False;
1498 if (strcmp(desc->format,id) != 0) return False;
1502 static BOOL api_PrintJobInfo(int cnum,uint16 vuid,char *param,char *data,
1503 int mdrcnt,int mprcnt,
1504 char **rdata,char **rparam,
1505 int *rdata_len,int *rparam_len)
1507 struct pack_desc desc;
1508 char *str1 = param+2;
1509 char *str2 = skip_string(str1,1);
1510 char *p = skip_string(str2,1);
1511 int jobid = (SVAL(p,0)&0xFF); /* the snum and jobid are encoded
1512 by the print queue api */
1513 int snum = (SVAL(p,0)>>8);
1514 int uLevel = SVAL(p,2);
1515 int function = SVAL(p,4); /* what is this ?? */
1520 *rparam = REALLOC(*rparam,*rparam_len);
1524 /* check it's a supported varient */
1525 if ((strcmp(str1,"WWsTP")) || (!check_printjob_info(&desc,uLevel,str2)))
1529 case 0x6: /* change job place in the queue, data gives the new place */
1530 if (snum >= 0 && VALID_SNUM(snum))
1532 print_queue_struct *queue=NULL;
1536 count = get_printqueue(snum,cnum,&queue,NULL);
1537 for (i=0;i<count;i++) /* find job */
1538 if ((queue[i].job%0xFF) == jobid) break;
1541 desc.errcode=NERR_JobNotFound;
1542 if (queue) free(queue);
1545 desc.errcode=NERR_Success;
1549 int place= SVAL(data,0);
1550 /* we currently have no way of doing this. Can any unix do it? */
1551 if (i < place) /* move down */;
1552 else if (i > place ) /* move up */;
1555 desc.errcode=NERR_notsupported; /* not yet supported */
1556 if (queue) free(queue);
1559 else desc.errcode=NERR_JobNotFound;
1561 case 0xb: /* change print job name, data gives the name */
1562 /* jobid, snum should be zero */
1569 if (issafe(*s)) name[l++] = *s;
1574 DEBUG(3,("Setting print name to %s\n",name));
1576 for (i=0;i<MAX_OPEN_FILES;i++)
1577 if (Files[i].open && Files[i].print_file)
1583 if (!become_user(Files[i].cnum,vuid) ||
1584 !become_service(Files[i].cnum,True))
1587 if (sys_rename(Files[i].name,name) == 0)
1588 string_set(&Files[i].name,name);
1592 desc.errcode=NERR_Success;
1595 default: /* not implemented */
1599 SSVALS(*rparam,0,desc.errcode);
1600 SSVAL(*rparam,2,0); /* converter word */
1606 /****************************************************************************
1607 get info about the server
1608 ****************************************************************************/
1609 static BOOL api_RNetServerGetInfo(int cnum,uint16 vuid, char *param,char *data,
1610 int mdrcnt,int mprcnt,
1611 char **rdata,char **rparam,
1612 int *rdata_len,int *rparam_len)
1614 char *str1 = param+2;
1615 char *str2 = skip_string(str1,1);
1616 char *p = skip_string(str2,1);
1617 int uLevel = SVAL(p,0);
1621 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
1623 /* check it's a supported varient */
1624 if (!prefix_ok(str1,"WrLh")) return False;
1627 if (strcmp(str2,"B16") != 0) return False;
1631 if (strcmp(str2,"B16BBDz") != 0) return False;
1635 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")
1640 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz")
1645 if (strcmp(str2,"DN") != 0) return False;
1649 if (strcmp(str2,"B16BBDzWWzzz") != 0) return False;
1652 default: return False;
1655 *rdata_len = mdrcnt;
1656 *rdata = REALLOC(*rdata,*rdata_len);
1659 p2 = p + struct_len;
1661 StrnCpy(p,local_machine,16);
1667 struct srv_info_struct *servers=NULL;
1670 uint32 servertype=DFLT_SERVER_TYPE;
1672 strcpy(comment,lp_serverstring());
1674 if ((count=get_server_info(SV_TYPE_ALL,&servers,lp_workgroup()))>0) {
1675 for (i=0;i<count;i++)
1676 if (strequal(servers[i].name,local_machine))
1678 servertype = servers[i].type;
1679 strcpy(comment,servers[i].comment);
1682 if (servers) free(servers);
1684 SCVAL(p,0,MAJOR_VERSION);
1685 SCVAL(p,1,MINOR_VERSION);
1686 SIVAL(p,2,servertype);
1688 if (mdrcnt == struct_len) {
1691 SIVAL(p,6,PTR_DIFF(p2,*rdata));
1692 standard_sub(cnum,comment);
1693 StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
1694 p2 = skip_string(p2,1);
1699 return False; /* not yet implemented */
1702 *rdata_len = PTR_DIFF(p2,*rdata);
1705 *rparam = REALLOC(*rparam,*rparam_len);
1706 SSVAL(*rparam,0,NERR_Success);
1707 SSVAL(*rparam,2,0); /* converter word */
1708 SSVAL(*rparam,4,*rdata_len);
1714 /****************************************************************************
1715 get info about the server
1716 ****************************************************************************/
1717 static BOOL api_NetWkstaGetInfo(int cnum,uint16 vuid, char *param,char *data,
1718 int mdrcnt,int mprcnt,
1719 char **rdata,char **rparam,
1720 int *rdata_len,int *rparam_len)
1722 char *str1 = param+2;
1723 char *str2 = skip_string(str1,1);
1724 char *p = skip_string(str2,1);
1726 extern pstring sesssetup_user;
1727 int level = SVAL(p,0);
1729 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
1732 *rparam = REALLOC(*rparam,*rparam_len);
1734 /* check it's a supported varient */
1735 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz")))
1738 *rdata_len = mdrcnt + 1024;
1739 *rdata = REALLOC(*rdata,*rdata_len);
1741 SSVAL(*rparam,0,NERR_Success);
1742 SSVAL(*rparam,2,0); /* converter word */
1748 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
1749 strcpy(p2,local_machine);
1751 p2 = skip_string(p2,1);
1754 SIVAL(p,0,PTR_DIFF(p2,*rdata));
1755 strcpy(p2,sesssetup_user);
1756 p2 = skip_string(p2,1);
1759 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
1760 strcpy(p2,lp_workgroup());
1762 p2 = skip_string(p2,1);
1765 SCVAL(p,0,MAJOR_VERSION); /* system version - e.g 4 in 4.1 */
1766 SCVAL(p,1,MINOR_VERSION); /* system version - e.g .1 in 4.1 */
1769 SIVAL(p,0,PTR_DIFF(p2,*rdata));
1770 strcpy(p2,lp_workgroup()); /* don't know. login domain?? */
1771 p2 = skip_string(p2,1);
1774 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
1776 p2 = skip_string(p2,1);
1779 *rdata_len = PTR_DIFF(p2,*rdata);
1781 SSVAL(*rparam,4,*rdata_len);
1786 /****************************************************************************
1787 get info about a user
1789 struct user_info_11 {
1790 char usri11_name[21]; 0-20
1792 char *usri11_comment; 22-25
1793 char *usri11_usr_comment; 26-29
1794 unsigned short usri11_priv; 30-31
1795 unsigned long usri11_auth_flags; 32-35
1796 long usri11_password_age; 36-39
1797 char *usri11_homedir; 40-43
1798 char *usri11_parms; 44-47
1799 long usri11_last_logon; 48-51
1800 long usri11_last_logoff; 52-55
1801 unsigned short usri11_bad_pw_count; 56-57
1802 unsigned short usri11_num_logons; 58-59
1803 char *usri11_logon_server; 60-63
1804 unsigned short usri11_country_code; 64-65
1805 char *usri11_workstations; 66-69
1806 unsigned long usri11_max_storage; 70-73
1807 unsigned short usri11_units_per_week; 74-75
1808 unsigned char *usri11_logon_hours; 76-79
1809 unsigned short usri11_code_page; 80-81
1814 usri11_name specifies the user name for which information is retireved
1816 usri11_pad aligns the next data structure element to a word boundary
1818 usri11_comment is a null terminated ASCII comment
1820 usri11_user_comment is a null terminated ASCII comment about the user
1822 usri11_priv specifies the level of the privilege assigned to the user.
1823 The possible values are:
1825 Name Value Description
1826 USER_PRIV_GUEST 0 Guest privilege
1827 USER_PRIV_USER 1 User privilege
1828 USER_PRV_ADMIN 2 Administrator privilege
1830 usri11_auth_flags specifies the account operator privileges. The
1831 possible values are:
1833 Name Value Description
1834 AF_OP_PRINT 0 Print operator
1837 Leach, Naik [Page 28]
\r\f
1840 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
1843 AF_OP_COMM 1 Communications operator
1844 AF_OP_SERVER 2 Server operator
1845 AF_OP_ACCOUNTS 3 Accounts operator
1848 usri11_password_age specifies how many seconds have elapsed since the
1849 password was last changed.
1851 usri11_home_dir points to a null terminated ASCII string that contains
1852 the path name of the user's home directory.
1854 usri11_parms points to a null terminated ASCII string that is set
1855 aside for use by applications.
1857 usri11_last_logon specifies the time when the user last logged on.
1858 This value is stored as the number of seconds elapsed since
1859 00:00:00, January 1, 1970.
1861 usri11_last_logoff specifies the time when the user last logged off.
1862 This value is stored as the number of seconds elapsed since
1863 00:00:00, January 1, 1970. A value of 0 means the last logoff
1866 usri11_bad_pw_count specifies the number of incorrect passwords
1867 entered since the last successful logon.
1869 usri11_log1_num_logons specifies the number of times this user has
1870 logged on. A value of -1 means the number of logons is unknown.
1872 usri11_logon_server points to a null terminated ASCII string that
1873 contains the name of the server to which logon requests are sent.
1874 A null string indicates logon requests should be sent to the
1877 usri11_country_code specifies the country code for the user's language
1880 usri11_workstations points to a null terminated ASCII string that
1881 contains the names of workstations the user may log on from.
1882 There may be up to 8 workstations, with the names separated by
1883 commas. A null strings indicates there are no restrictions.
1885 usri11_max_storage specifies the maximum amount of disk space the user
1886 can occupy. A value of 0xffffffff indicates there are no
1889 usri11_units_per_week specifies the equal number of time units into
1890 which a week is divided. This value must be equal to 168.
1892 usri11_logon_hours points to a 21 byte (168 bits) string that
1893 specifies the time during which the user can log on. Each bit
1894 represents one unique hour in a week. The first bit (bit 0, word
1895 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
1899 Leach, Naik [Page 29]
\r\f
1902 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
1905 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
1906 are no restrictions.
1908 usri11_code_page specifies the code page for the user's language of
1911 All of the pointers in this data structure need to be treated
1912 specially. The pointer is a 32 bit pointer. The higher 16 bits need
1913 to be ignored. The converter word returned in the parameters section
1914 needs to be subtracted from the lower 16 bits to calculate an offset
1915 into the return buffer where this ASCII string resides.
1917 There is no auxiliary data in the response.
1919 ****************************************************************************/
1921 #define usri11_name 0
1922 #define usri11_pad 21
1923 #define usri11_comment 22
1924 #define usri11_usr_comment 26
1925 #define usri11_full_name 30
1926 #define usri11_priv 34
1927 #define usri11_auth_flags 36
1928 #define usri11_password_age 40
1929 #define usri11_homedir 44
1930 #define usri11_parms 48
1931 #define usri11_last_logon 52
1932 #define usri11_last_logoff 56
1933 #define usri11_bad_pw_count 60
1934 #define usri11_num_logons 62
1935 #define usri11_logon_server 64
1936 #define usri11_country_code 68
1937 #define usri11_workstations 70
1938 #define usri11_max_storage 74
1939 #define usri11_units_per_week 78
1940 #define usri11_logon_hours 80
1941 #define usri11_code_page 84
1942 #define usri11_end 86
1944 #define USER_PRIV_GUEST 0
1945 #define USER_PRIV_USER 1
1946 #define USER_PRIV_ADMIN 2
1948 #define AF_OP_PRINT 0
1949 #define AF_OP_COMM 1
1950 #define AF_OP_SERVER 2
1951 #define AF_OP_ACCOUNTS 3
1953 static BOOL api_RNetUserGetInfo(int cnum,uint16 vuid, char *param,char *data,
1954 int mdrcnt,int mprcnt,
1955 char **rdata,char **rparam,
1956 int *rdata_len,int *rparam_len)
1958 char *str1 = param+2;
1959 char *str2 = skip_string(str1,1);
1960 char *UserName = skip_string(str2,1);
1961 char *p = skip_string(UserName,1);
1962 int uLevel = SVAL(p,0);
1966 *rparam = REALLOC(*rparam,*rparam_len);
1968 /* check it's a supported varient */
1969 if (strcmp(str1,"zWrLh") != 0) return False;
1972 case 0: p2 = "B21"; break;
1973 case 1: p2 = "B21BB16DWzzWz"; break;
1974 case 2: p2 = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
1975 case 10: p2 = "B21Bzzz"; break;
1976 case 11: p2 = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
1977 default: return False;
1980 if (strcmp(p2,str2) != 0) return False;
1982 *rdata_len = mdrcnt + 1024;
1983 *rdata = REALLOC(*rdata,*rdata_len);
1985 SSVAL(*rparam,0,NERR_Success);
1986 SSVAL(*rparam,2,0); /* converter word */
1989 p2 = p + usri11_end;
1992 strcpy(p+usri11_name,UserName); /* 21 bytes - user name */
1996 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
2001 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
2002 strcpy(p2,"Comment");
2003 p2 = skip_string(p2,1);
2005 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
2006 strcpy(p2,"UserComment");
2007 p2 = skip_string(p2,1);
2009 /* EEK! the cifsrap.txt doesn't have this in!!!! */
2010 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
2012 strcpy(p2,"FullName");
2014 strcpy(p2,UserName); /* suggest copying the user name, for now... */
2015 p2 = skip_string(p2,1);
2017 if (uLevel == 11) /* modelled after NTAS 3.51 reply */
2019 SSVAL(p,usri11_priv,Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2020 SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
2021 SIVALS(p,usri11_password_age,0xffffffff); /* password age */
2022 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
2023 if (*lp_logon_path())
2025 strcpy(p2,lp_logon_path());
2029 strcpy(p2,"\\\\%L\\%U");
2031 standard_sub_basic(p2);
2032 p2 = skip_string(p2,1);
2033 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
2035 p2 = skip_string(p2,1);
2036 SIVAL(p,usri11_last_logon,0); /* last logon */
2037 SIVAL(p,usri11_last_logoff,0); /* last logoff */
2038 SSVALS(p,usri11_bad_pw_count,0xffffffff); /* bad pw counts */
2039 SSVALS(p,usri11_num_logons,0xffffffff); /* num logons */
2040 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
2042 p2 = skip_string(p2,1);
2043 SSVAL(p,usri11_country_code,0); /* country code */
2045 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
2047 p2 = skip_string(p2,1);
2049 SIVALS(p,usri11_max_storage,0xffffffff); /* max storage */
2050 SSVAL(p,usri11_units_per_week,168); /* units per week */
2051 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
2053 /* a simple way to get logon hours at all times. */
2055 SCVAL(p2,21,0); /* fix zero termination */
2056 p2 = skip_string(p2,1);
2058 SSVAL(p,usri11_code_page,0); /* code page */
2060 if (uLevel == 1 || uLevel == 2)
2062 memset(p+22,' ',16); /* password */
2063 SIVALS(p,38,-1); /* password age */
2065 Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2066 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
2067 if (*lp_logon_path())
2069 strcpy(p2,lp_logon_path());
2073 strcpy(p2,"\\\\%L\\%U");
2075 standard_sub_basic(p2);
2076 p2 = skip_string(p2,1);
2077 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
2079 SSVAL(p,52,0); /* flags */
2080 SIVAL(p,54,0); /* script_path */
2083 SIVAL(p,60,0); /* auth_flags */
2084 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
2085 strcpy(p2,"<Full Name>");
2086 p2 = skip_string(p2,1);
2087 SIVAL(p,68,0); /* urs_comment */
2088 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
2090 p2 = skip_string(p2,1);
2091 SIVAL(p,76,0); /* workstations */
2092 SIVAL(p,80,0); /* last_logon */
2093 SIVAL(p,84,0); /* last_logoff */
2094 SIVALS(p,88,-1); /* acct_expires */
2095 SIVALS(p,92,-1); /* max_storage */
2096 SSVAL(p,96,168); /* units_per_week */
2097 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
2100 SSVALS(p,102,-1); /* bad_pw_count */
2101 SSVALS(p,104,-1); /* num_logons */
2102 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
2103 strcpy(p2,"\\\\%L");
2104 standard_sub_basic(p2);
2105 p2 = skip_string(p2,1);
2106 SSVAL(p,110,49); /* country_code */
2107 SSVAL(p,112,860); /* code page */
2111 *rdata_len = PTR_DIFF(p2,*rdata);
2113 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
2118 /*******************************************************************
2119 get groups that a user is a member of
2120 ******************************************************************/
2121 static BOOL api_NetUserGetGroups(int cnum,uint16 vuid, char *param,char *data,
2122 int mdrcnt,int mprcnt,
2123 char **rdata,char **rparam,
2124 int *rdata_len,int *rparam_len)
2126 char *str1 = param+2;
2127 char *str2 = skip_string(str1,1);
2128 char *UserName = skip_string(str2,1);
2129 char *p = skip_string(UserName,1);
2130 int uLevel = SVAL(p,0);
2135 *rparam = REALLOC(*rparam,*rparam_len);
2137 /* check it's a supported varient */
2138 if (strcmp(str1,"zWrLeh") != 0) return False;
2140 case 0: p2 = "B21"; break;
2141 default: return False;
2143 if (strcmp(p2,str2) != 0) return False;
2145 *rdata_len = mdrcnt + 1024;
2146 *rdata = REALLOC(*rdata,*rdata_len);
2148 SSVAL(*rparam,0,NERR_Success);
2149 SSVAL(*rparam,2,0); /* converter word */
2153 /* XXXX we need a real SAM database some day */
2154 strcpy(p,"Users"); p += 21; count++;
2155 strcpy(p,"Domain Users"); p += 21; count++;
2156 strcpy(p,"Guests"); p += 21; count++;
2157 strcpy(p,"Domain Guests"); p += 21; count++;
2159 *rdata_len = PTR_DIFF(p,*rdata);
2161 SSVAL(*rparam,4,count); /* is this right?? */
2162 SSVAL(*rparam,6,count); /* is this right?? */
2168 static BOOL api_WWkstaUserLogon(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 *p = skip_string(str2,1);
2177 struct pack_desc desc;
2183 bzero(&desc,sizeof(desc));
2185 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
2187 /* check it's a supported varient */
2188 if (strcmp(str1,"OOWb54WrLh") != 0) return False;
2189 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) return False;
2190 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2192 desc.buflen = mdrcnt;
2193 desc.subformat = NULL;
2196 if (init_package(&desc,1,0))
2198 PACKI(&desc,"W",0); /* code */
2199 PACKS(&desc,"B21",name); /* eff. name */
2200 PACKS(&desc,"B",""); /* pad */
2202 Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2203 PACKI(&desc,"D",0); /* auth flags XXX */
2204 PACKI(&desc,"W",0); /* num logons */
2205 PACKI(&desc,"W",0); /* bad pw count */
2206 PACKI(&desc,"D",0); /* last logon */
2207 PACKI(&desc,"D",-1); /* last logoff */
2208 PACKI(&desc,"D",-1); /* logoff time */
2209 PACKI(&desc,"D",-1); /* kickoff time */
2210 PACKI(&desc,"D",0); /* password age */
2211 PACKI(&desc,"D",0); /* password can change */
2212 PACKI(&desc,"D",-1); /* password must change */
2215 strcpy(mypath,"\\\\");
2216 strcat(mypath,local_machine);
2218 PACKS(&desc,"z",mypath); /* computer */
2220 PACKS(&desc,"z",lp_workgroup());/* domain */
2221 PACKS(&desc,"z",lp_logon_script()); /* script path */
2222 PACKI(&desc,"D",0x00000000); /* reserved */
2225 *rdata_len = desc.usedlen;
2227 *rparam = REALLOC(*rparam,*rparam_len);
2228 SSVALS(*rparam,0,desc.errcode);
2230 SSVAL(*rparam,4,desc.neededlen);
2232 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
2237 /****************************************************************************
2238 api_WAccessGetUserPerms
2239 ****************************************************************************/
2240 static BOOL api_WAccessGetUserPerms(int cnum,uint16 vuid, char *param,char *data,
2241 int mdrcnt,int mprcnt,
2242 char **rdata,char **rparam,
2243 int *rdata_len,int *rparam_len)
2245 char *str1 = param+2;
2246 char *str2 = skip_string(str1,1);
2247 char *user = skip_string(str2,1);
2248 char *resource = skip_string(user,1);
2250 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
2252 /* check it's a supported varient */
2253 if (strcmp(str1,"zzh") != 0) return False;
2254 if (strcmp(str2,"") != 0) return False;
2257 *rparam = REALLOC(*rparam,*rparam_len);
2258 SSVALS(*rparam,0,0); /* errorcode */
2259 SSVAL(*rparam,2,0); /* converter word */
2260 SSVAL(*rparam,4,0x7f); /* permission flags */
2265 /****************************************************************************
2266 api_WPrintJobEnumerate
2267 ****************************************************************************/
2268 static BOOL api_WPrintJobGetInfo(int cnum,uint16 vuid, char *param,char *data,
2269 int mdrcnt,int mprcnt,
2270 char **rdata,char **rparam,
2271 int *rdata_len,int *rparam_len)
2273 char *str1 = param+2;
2274 char *str2 = skip_string(str1,1);
2275 char *p = skip_string(str2,1);
2276 int uJobId = SVAL(p,0);
2282 struct pack_desc desc;
2283 print_queue_struct *queue=NULL;
2284 print_status_struct status;
2289 bzero(&desc,sizeof(desc));
2290 bzero(&status,sizeof(status));
2292 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,uJobId));
2294 /* check it's a supported varient */
2295 if (strcmp(str1,"WWrLh") != 0) return False;
2296 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2298 snum = (unsigned int)uJobId >> 8; /*## valid serice number??*/
2299 job = uJobId & 0xFF;
2301 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2303 count = get_printqueue(snum,cnum,&queue,&status);
2304 for (i = 0; i < count; i++) {
2305 if ((queue[i].job % 0xFF) == job) break;
2307 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2309 desc.buflen = mdrcnt;
2311 if (init_package(&desc,1,0)) {
2313 fill_printjob_info(cnum,snum,uLevel,&desc,&queue[i],i);
2314 *rdata_len = desc.usedlen;
2317 desc.errcode = NERR_JobNotFound;
2323 *rparam = REALLOC(*rparam,*rparam_len);
2324 SSVALS(*rparam,0,desc.errcode);
2326 SSVAL(*rparam,4,desc.neededlen);
2328 if (queue) free(queue);
2330 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
2334 static BOOL api_WPrintJobEnumerate(int cnum,uint16 vuid, char *param,char *data,
2335 int mdrcnt,int mprcnt,
2336 char **rdata,char **rparam,
2337 int *rdata_len,int *rparam_len)
2339 char *str1 = param+2;
2340 char *str2 = skip_string(str1,1);
2341 char *p = skip_string(str2,1);
2347 struct pack_desc desc;
2348 print_queue_struct *queue=NULL;
2349 print_status_struct status;
2351 bzero(&desc,sizeof(desc));
2352 bzero(&status,sizeof(status));
2354 p = skip_string(p,1);
2358 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
2360 /* check it's a supported varient */
2361 if (strcmp(str1,"zWrLeh") != 0) return False;
2362 if (uLevel > 2) return False; /* defined only for uLevel 0,1,2 */
2363 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2365 snum = lp_servicenumber(name);
2366 if (snum < 0 && pcap_printername_ok(name,NULL)) {
2367 int pnum = lp_servicenumber(PRINTERS_NAME);
2369 lp_add_printer(name,pnum);
2370 snum = lp_servicenumber(name);
2374 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2376 count = get_printqueue(snum,cnum,&queue,&status);
2377 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2379 desc.buflen = mdrcnt;
2381 if (init_package(&desc,count,0)) {
2383 for (i = 0; i < count; i++) {
2384 fill_printjob_info(cnum,snum,uLevel,&desc,&queue[i],i);
2385 if (desc.errcode == NERR_Success) succnt = i+1;
2389 *rdata_len = desc.usedlen;
2392 *rparam = REALLOC(*rparam,*rparam_len);
2393 SSVALS(*rparam,0,desc.errcode);
2395 SSVAL(*rparam,4,succnt);
2396 SSVAL(*rparam,6,count);
2398 if (queue) free(queue);
2400 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
2404 static int check_printdest_info(struct pack_desc* desc,
2405 int uLevel, char* id)
2407 desc->subformat = NULL;
2409 case 0: desc->format = "B9"; break;
2410 case 1: desc->format = "B9B21WWzW"; break;
2411 case 2: desc->format = "z"; break;
2412 case 3: desc->format = "zzzWWzzzWW"; break;
2413 default: return False;
2415 if (strcmp(desc->format,id) != 0) return False;
2419 static void fill_printdest_info(int cnum, int snum, int uLevel,
2420 struct pack_desc* desc)
2423 strcpy(buf,SERVICE(snum));
2426 PACKS(desc,"B9",buf); /* szName */
2428 PACKS(desc,"B21",""); /* szUserName */
2429 PACKI(desc,"W",0); /* uJobId */
2430 PACKI(desc,"W",0); /* fsStatus */
2431 PACKS(desc,"z",""); /* pszStatus */
2432 PACKI(desc,"W",0); /* time */
2435 if (uLevel == 2 || uLevel == 3) {
2436 PACKS(desc,"z",buf); /* pszPrinterName */
2438 PACKS(desc,"z",""); /* pszUserName */
2439 PACKS(desc,"z",""); /* pszLogAddr */
2440 PACKI(desc,"W",0); /* uJobId */
2441 PACKI(desc,"W",0); /* fsStatus */
2442 PACKS(desc,"z",""); /* pszStatus */
2443 PACKS(desc,"z",""); /* pszComment */
2444 PACKS(desc,"z","NULL"); /* pszDrivers */
2445 PACKI(desc,"W",0); /* time */
2446 PACKI(desc,"W",0); /* pad1 */
2451 static BOOL api_WPrintDestGetInfo(int cnum,uint16 vuid, char *param,char *data,
2452 int mdrcnt,int mprcnt,
2453 char **rdata,char **rparam,
2454 int *rdata_len,int *rparam_len)
2456 char *str1 = param+2;
2457 char *str2 = skip_string(str1,1);
2458 char *p = skip_string(str2,1);
2459 char* PrinterName = p;
2461 struct pack_desc desc;
2464 bzero(&desc,sizeof(desc));
2466 p = skip_string(p,1);
2470 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
2472 /* check it's a supported varient */
2473 if (strcmp(str1,"zWrLh") != 0) return False;
2474 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2476 snum = lp_servicenumber(PrinterName);
2477 if (snum < 0 && pcap_printername_ok(PrinterName,NULL)) {
2478 int pnum = lp_servicenumber(PRINTERS_NAME);
2480 lp_add_printer(PrinterName,pnum);
2481 snum = lp_servicenumber(PrinterName);
2487 desc.errcode = NERR_DestNotFound;
2491 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2493 desc.buflen = mdrcnt;
2494 if (init_package(&desc,1,0)) {
2495 fill_printdest_info(cnum,snum,uLevel,&desc);
2497 *rdata_len = desc.usedlen;
2501 *rparam = REALLOC(*rparam,*rparam_len);
2502 SSVALS(*rparam,0,desc.errcode);
2504 SSVAL(*rparam,4,desc.neededlen);
2506 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
2510 static BOOL api_WPrintDestEnum(int cnum,uint16 vuid, char *param,char *data,
2511 int mdrcnt,int mprcnt,
2512 char **rdata,char **rparam,
2513 int *rdata_len,int *rparam_len)
2515 char *str1 = param+2;
2516 char *str2 = skip_string(str1,1);
2517 char *p = skip_string(str2,1);
2521 struct pack_desc desc;
2522 int services = lp_numservices();
2524 bzero(&desc,sizeof(desc));
2529 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
2531 /* check it's a supported varient */
2532 if (strcmp(str1,"WrLeh") != 0) return False;
2533 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2536 for (i = 0; i < services; i++)
2537 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
2540 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2542 desc.buflen = mdrcnt;
2543 if (init_package(&desc,queuecnt,0)) {
2546 for (i = 0; i < services; i++) {
2547 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
2548 fill_printdest_info(cnum,i,uLevel,&desc);
2550 if (desc.errcode == NERR_Success) succnt = n;
2555 *rdata_len = desc.usedlen;
2558 *rparam = REALLOC(*rparam,*rparam_len);
2559 SSVALS(*rparam,0,desc.errcode);
2561 SSVAL(*rparam,4,succnt);
2562 SSVAL(*rparam,6,queuecnt);
2564 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
2568 static BOOL api_WPrintDriverEnum(int cnum,uint16 vuid, char *param,char *data,
2569 int mdrcnt,int mprcnt,
2570 char **rdata,char **rparam,
2571 int *rdata_len,int *rparam_len)
2573 char *str1 = param+2;
2574 char *str2 = skip_string(str1,1);
2575 char *p = skip_string(str2,1);
2578 struct pack_desc desc;
2580 bzero(&desc,sizeof(desc));
2585 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
2587 /* check it's a supported varient */
2588 if (strcmp(str1,"WrLeh") != 0) return False;
2589 if (uLevel != 0 || strcmp(str2,"B41") != 0) return False;
2591 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2593 desc.buflen = mdrcnt;
2594 if (init_package(&desc,1,0)) {
2595 PACKS(&desc,"B41","NULL");
2598 succnt = (desc.errcode == NERR_Success ? 1 : 0);
2600 *rdata_len = desc.usedlen;
2603 *rparam = REALLOC(*rparam,*rparam_len);
2604 SSVALS(*rparam,0,desc.errcode);
2606 SSVAL(*rparam,4,succnt);
2609 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
2613 static BOOL api_WPrintQProcEnum(int cnum,uint16 vuid, char *param,char *data,
2614 int mdrcnt,int mprcnt,
2615 char **rdata,char **rparam,
2616 int *rdata_len,int *rparam_len)
2618 char *str1 = param+2;
2619 char *str2 = skip_string(str1,1);
2620 char *p = skip_string(str2,1);
2623 struct pack_desc desc;
2625 bzero(&desc,sizeof(desc));
2630 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
2632 /* check it's a supported varient */
2633 if (strcmp(str1,"WrLeh") != 0) return False;
2634 if (uLevel != 0 || strcmp(str2,"B13") != 0) return False;
2636 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2638 desc.buflen = mdrcnt;
2640 if (init_package(&desc,1,0)) {
2641 PACKS(&desc,"B13","lpd");
2644 succnt = (desc.errcode == NERR_Success ? 1 : 0);
2646 *rdata_len = desc.usedlen;
2649 *rparam = REALLOC(*rparam,*rparam_len);
2650 SSVALS(*rparam,0,desc.errcode);
2652 SSVAL(*rparam,4,succnt);
2655 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
2659 static BOOL api_WPrintPortEnum(int cnum,uint16 vuid, char *param,char *data,
2660 int mdrcnt,int mprcnt,
2661 char **rdata,char **rparam,
2662 int *rdata_len,int *rparam_len)
2664 char *str1 = param+2;
2665 char *str2 = skip_string(str1,1);
2666 char *p = skip_string(str2,1);
2669 struct pack_desc desc;
2671 bzero(&desc,sizeof(desc));
2676 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
2678 /* check it's a supported varient */
2679 if (strcmp(str1,"WrLeh") != 0) return False;
2680 if (uLevel != 0 || strcmp(str2,"B9") != 0) return False;
2682 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2683 bzero(&desc,sizeof(desc));
2685 desc.buflen = mdrcnt;
2687 if (init_package(&desc,1,0)) {
2688 PACKS(&desc,"B13","lp0");
2691 succnt = (desc.errcode == NERR_Success ? 1 : 0);
2693 *rdata_len = desc.usedlen;
2696 *rparam = REALLOC(*rparam,*rparam_len);
2697 SSVALS(*rparam,0,desc.errcode);
2699 SSVAL(*rparam,4,succnt);
2702 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
2713 } api_fd_commands [] =
2715 { "SetNmdPpHndState", "lsarpc", 1, api_LsarpcSNPHS },
2716 { "TransactNmPipe", "lsarpc", 0x26, api_LsarpcTNP },
2717 { NULL, NULL, -1, (BOOL (*)())api_Unsupported }
2720 /****************************************************************************
2721 handle remote api calls delivered to a named pipe already opened.
2722 ****************************************************************************/
2723 static int api_fd_reply(int cnum,uint16 vuid,char *outbuf,
2724 uint16 *setup,char *data,char *params,
2725 int suwcnt,int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
2728 char *rparam = NULL;
2736 /* First find out the name of this file. */
2739 DEBUG(0,("Unexpected named pipe transaction.\n"));
2743 /* Get the file handle and hence the file name. */
2745 subcommand = setup[0];
2747 DEBUG(3,("Got API command %d on pipe %s ",subcommand,Files[fd].name));
2748 DEBUG(3,("(tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
2749 tdscnt,tpscnt,mdrcnt,mprcnt));
2751 for (i=0;api_fd_commands[i].name;i++)
2752 if (strequal(api_fd_commands[i].pipename, Files[fd].name) &&
2753 api_fd_commands[i].subcommand == subcommand &&
2754 api_fd_commands[i].fn)
2756 DEBUG(3,("Doing %s\n",api_fd_commands[i].name));
2760 rdata = (char *)malloc(1024); if (rdata) bzero(rdata,1024);
2761 rparam = (char *)malloc(1024); if (rparam) bzero(rparam,1024);
2763 reply = api_fd_commands[i].fn(cnum,vuid,params,data,mdrcnt,mprcnt,
2764 &rdata,&rparam,&rdata_len,&rparam_len);
2766 if (rdata_len > mdrcnt ||
2767 rparam_len > mprcnt)
2769 reply = api_TooSmall(cnum,vuid,params,data,mdrcnt,mprcnt,
2770 &rdata,&rparam,&rdata_len,&rparam_len);
2774 /* if we get False back then it's actually unsupported */
2776 api_Unsupported(cnum,vuid,params,data,mdrcnt,mprcnt,
2777 &rdata,&rparam,&rdata_len,&rparam_len);
2779 /* now send the reply */
2780 send_trans_reply(outbuf,rdata,rparam,NULL,rdata_len,rparam_len,0);
2792 /****************************************************************************
2793 the buffer was too small
2794 ****************************************************************************/
2795 static BOOL api_TooSmall(int cnum,uint16 vuid, char *param,char *data,
2796 int mdrcnt,int mprcnt,
2797 char **rdata,char **rparam,
2798 int *rdata_len,int *rparam_len)
2800 *rparam_len = MIN(*rparam_len,mprcnt);
2801 *rparam = REALLOC(*rparam,*rparam_len);
2805 SSVAL(*rparam,0,NERR_BufTooSmall);
2807 DEBUG(3,("Supplied buffer too small in API command\n"));
2813 /****************************************************************************
2814 the request is not supported
2815 ****************************************************************************/
2816 static BOOL api_Unsupported(int cnum,uint16 vuid, char *param,char *data,
2817 int mdrcnt,int mprcnt,
2818 char **rdata,char **rparam,
2819 int *rdata_len,int *rparam_len)
2822 *rparam = REALLOC(*rparam,*rparam_len);
2826 SSVAL(*rparam,0,NERR_notsupported);
2827 SSVAL(*rparam,2,0); /* converter word */
2829 DEBUG(3,("Unsupported API command\n"));
2843 } api_commands[] = {
2844 {"RNetShareEnum", 0, (BOOL (*)())api_RNetShareEnum,0},
2845 {"RNetShareGetInfo", 1, (BOOL (*)())api_RNetShareGetInfo,0},
2846 {"RNetServerGetInfo", 13, (BOOL (*)())api_RNetServerGetInfo,0},
2847 {"RNetUserGetInfo", 56, (BOOL (*)())api_RNetUserGetInfo,0},
2848 {"NetUserGetGroups", 59, (BOOL (*)())api_NetUserGetGroups,0},
2849 {"NetWkstaGetInfo", 63, (BOOL (*)())api_NetWkstaGetInfo,0},
2850 {"DosPrintQEnum", 69, (BOOL (*)())api_DosPrintQEnum,0},
2851 {"DosPrintQGetInfo", 70, (BOOL (*)())api_DosPrintQGetInfo,0},
2852 {"WPrintJobEnumerate",76, (BOOL (*)())api_WPrintJobEnumerate,0},
2853 {"WPrintJobGetInfo", 77, (BOOL (*)())api_WPrintJobGetInfo,0},
2854 {"RDosPrintJobDel", 81, (BOOL (*)())api_RDosPrintJobDel,0},
2855 {"RDosPrintJobPause", 82, (BOOL (*)())api_RDosPrintJobDel,0},
2856 {"RDosPrintJobResume",83, (BOOL (*)())api_RDosPrintJobDel,0},
2857 {"WPrintDestEnum", 84, (BOOL (*)())api_WPrintDestEnum,0},
2858 {"WPrintDestGetInfo", 85, (BOOL (*)())api_WPrintDestGetInfo,0},
2859 {"NetRemoteTOD", 91, (BOOL (*)())api_NetRemoteTOD,0},
2860 {"WPrintQueuePurge", 103, (BOOL (*)())api_WPrintQueuePurge,0},
2861 {"NetServerEnum", 104, (BOOL (*)())api_RNetServerEnum,0},
2862 {"WAccessGetUserPerms",105, (BOOL (*)())api_WAccessGetUserPerms,0},
2863 {"SetUserPassword", 115, (BOOL (*)())api_SetUserPassword,0},
2864 {"WWkstaUserLogon", 132, (BOOL (*)())api_WWkstaUserLogon,0},
2865 {"PrintJobInfo", 147, (BOOL (*)())api_PrintJobInfo,0},
2866 {"WPrintDriverEnum", 205, (BOOL (*)())api_WPrintDriverEnum,0},
2867 {"WPrintQProcEnum", 206, (BOOL (*)())api_WPrintQProcEnum,0},
2868 {"WPrintPortEnum", 207, (BOOL (*)())api_WPrintPortEnum,0},
2869 {NULL, -1, (BOOL (*)())api_Unsupported,0}};
2872 /****************************************************************************
2873 handle remote api calls
2874 ****************************************************************************/
2875 static int api_reply(int cnum,uint16 vuid,char *outbuf,char *data,char *params,
2876 int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
2878 int api_command = SVAL(params,0);
2880 char *rparam = NULL;
2886 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
2887 api_command,params+2,skip_string(params+2,1),
2888 tdscnt,tpscnt,mdrcnt,mprcnt));
2890 for (i=0;api_commands[i].name;i++)
2891 if (api_commands[i].id == api_command && api_commands[i].fn)
2893 DEBUG(3,("Doing %s\n",api_commands[i].name));
2897 rdata = (char *)malloc(1024); if (rdata) bzero(rdata,1024);
2898 rparam = (char *)malloc(1024); if (rparam) bzero(rparam,1024);
2900 reply = api_commands[i].fn(cnum,vuid,params,data,mdrcnt,mprcnt,
2901 &rdata,&rparam,&rdata_len,&rparam_len);
2904 if (rdata_len > mdrcnt ||
2905 rparam_len > mprcnt)
2907 reply = api_TooSmall(cnum,vuid,params,data,mdrcnt,mprcnt,
2908 &rdata,&rparam,&rdata_len,&rparam_len);
2912 /* if we get False back then it's actually unsupported */
2914 api_Unsupported(cnum,vuid,params,data,mdrcnt,mprcnt,
2915 &rdata,&rparam,&rdata_len,&rparam_len);
2919 /* now send the reply */
2920 send_trans_reply(outbuf,rdata,rparam,NULL,rdata_len,rparam_len,0);
2930 /****************************************************************************
2931 handle named pipe commands
2932 ****************************************************************************/
2933 static int named_pipe(int cnum,uint16 vuid, char *outbuf,char *name,
2934 uint16 *setup,char *data,char *params,
2935 int suwcnt,int tdscnt,int tpscnt,
2936 int msrcnt,int mdrcnt,int mprcnt)
2939 if (strequal(name,"LANMAN"))
2940 return(api_reply(cnum,vuid,outbuf,data,params,tdscnt,tpscnt,mdrcnt,mprcnt));
2942 if (strlen(name) < 1)
2943 return(api_fd_reply(cnum,vuid,outbuf,setup,data,params,suwcnt,tdscnt,tpscnt,mdrcnt,mprcnt));
2946 DEBUG(3,("named pipe command on <%s> 0x%X setup1=%d\n",
2947 name,(int)setup[0],(int)setup[1]));
2953 /****************************************************************************
2955 ****************************************************************************/
2956 int reply_trans(char *inbuf,char *outbuf)
2960 char *data=NULL,*params=NULL;
2964 int cnum = SVAL(inbuf,smb_tid);
2965 uint16 vuid = SVAL(inbuf,smb_uid);
2967 int tpscnt = SVAL(inbuf,smb_vwv0);
2968 int tdscnt = SVAL(inbuf,smb_vwv1);
2969 int mprcnt = SVAL(inbuf,smb_vwv2);
2970 int mdrcnt = SVAL(inbuf,smb_vwv3);
2971 int msrcnt = CVAL(inbuf,smb_vwv4);
2972 BOOL close_on_completion = BITSETW(inbuf+smb_vwv5,0);
2973 BOOL one_way = BITSETW(inbuf+smb_vwv5,1);
2974 int pscnt = SVAL(inbuf,smb_vwv9);
2975 int psoff = SVAL(inbuf,smb_vwv10);
2976 int dscnt = SVAL(inbuf,smb_vwv11);
2977 int dsoff = SVAL(inbuf,smb_vwv12);
2978 int suwcnt = CVAL(inbuf,smb_vwv13);
2980 StrnCpy(name,smb_buf(inbuf),sizeof(name)-1);
2984 data = (char *)malloc(tdscnt);
2985 memcpy(data,smb_base(inbuf)+dsoff,dscnt);
2989 params = (char *)malloc(tpscnt);
2990 memcpy(params,smb_base(inbuf)+psoff,pscnt);
2996 setup = (uint16 *)malloc(suwcnt*sizeof(setup[0]));
2997 for (i=0;i<suwcnt;i++)
2998 setup[i] = SVAL(inbuf,smb_vwv14+i*SIZEOFWORD);
3002 if (pscnt < tpscnt || dscnt < tdscnt)
3004 /* We need to send an interim response then receive the rest
3005 of the parameter/data bytes */
3006 outsize = set_message(outbuf,0,0,True);
3008 send_smb(Client,outbuf);
3011 /* receive the rest of the trans packet */
3012 while (pscnt < tpscnt || dscnt < tdscnt)
3014 int pcnt,poff,dcnt,doff,pdisp,ddisp;
3016 if (!receive_smb(Client,inbuf, SMB_SECONDARY_WAIT) ||
3017 CVAL(inbuf, smb_com) != SMBtrans)
3019 DEBUG(2,("Invalid secondary trans2 packet\n"));
3020 if (params) free(params);
3021 if (data) free(data);
3022 if (setup) free(setup);
3023 return(ERROR(ERRSRV,ERRerror));
3028 tpscnt = SVAL(inbuf,smb_vwv0);
3029 tdscnt = SVAL(inbuf,smb_vwv1);
3031 pcnt = SVAL(inbuf,smb_vwv2);
3032 poff = SVAL(inbuf,smb_vwv3);
3033 pdisp = SVAL(inbuf,smb_vwv4);
3035 dcnt = SVAL(inbuf,smb_vwv5);
3036 doff = SVAL(inbuf,smb_vwv6);
3037 ddisp = SVAL(inbuf,smb_vwv7);
3043 memcpy(params+pdisp,smb_base(inbuf)+poff,pcnt);
3045 memcpy(data+ddisp,smb_base(inbuf)+doff,dcnt);
3049 DEBUG(3,("trans <%s> data=%d params=%d setup=%d\n",name,tdscnt,tpscnt,suwcnt));
3052 if (strncmp(name,"\\PIPE\\",strlen("\\PIPE\\")) == 0)
3053 outsize = named_pipe(cnum,vuid,outbuf,name+strlen("\\PIPE\\"),setup,data,params,
3054 suwcnt,tdscnt,tpscnt,msrcnt,mdrcnt,mprcnt);
3057 if (data) free(data);
3058 if (params) free(params);
3059 if (setup) free(setup);
3061 if (close_on_completion)
3062 close_cnum(cnum,vuid);
3068 return(ERROR(ERRSRV,ERRnosupport));