3 Unix SMB/Netbios implementation.
5 Inter-process communication and named pipe handling
6 Copyright (C) Andrew Tridgell 1992-1997
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;
40 extern fstring myworkgroup;
42 #define NERR_Success 0
43 #define NERR_badpass 86
44 #define NERR_notsupported 50
46 #define NERR_BASE (2100)
47 #define NERR_BufTooSmall (NERR_BASE+23)
48 #define NERR_JobNotFound (NERR_BASE+51)
49 #define NERR_DestNotFound (NERR_BASE+52)
50 #define ERROR_INVALID_LEVEL 124
51 #define ERROR_MORE_DATA 234
53 #define REALLOC(ptr,size) Realloc(ptr,MAX((size),4*1024))
55 #define ACCESS_READ 0x01
56 #define ACCESS_WRITE 0x02
57 #define ACCESS_CREATE 0x04
59 #define SHPWLEN 8 /* share password length */
60 #define NNLEN 12 /* 8.3 net name length */
61 #define SNLEN 15 /* service name length */
62 #define QNLEN 12 /* queue name maximum length */
66 static BOOL api_Unsupported(int cnum,uint16 vuid, char *param,char *data,
67 int mdrcnt,int mprcnt,
68 char **rdata,char **rparam,
69 int *rdata_len,int *rparam_len);
70 static BOOL api_TooSmall(int cnum,uint16 vuid, char *param,char *data,
71 int mdrcnt,int mprcnt,
72 char **rdata,char **rparam,
73 int *rdata_len,int *rparam_len);
76 static int CopyExpanded(int cnum, int snum, char** dst, char* src, int* n)
81 if (!src || !dst || !n || !(*dst)) return(0);
83 StrnCpy(buf,src,sizeof(buf)/2);
84 string_sub(buf,"%S",lp_servicename(snum));
85 standard_sub(cnum,buf);
93 static int CopyAndAdvance(char** dst, char* src, int* n)
96 if (!src || !dst || !n || !(*dst)) return(0);
104 static int StrlenExpanded(int cnum, int snum, char* s)
108 StrnCpy(buf,s,sizeof(buf)/2);
109 string_sub(buf,"%S",lp_servicename(snum));
110 standard_sub(cnum,buf);
111 return strlen(buf) + 1;
114 static char* Expand(int cnum, int snum, char* s)
117 if (!s) return(NULL);
118 StrnCpy(buf,s,sizeof(buf)/2);
119 string_sub(buf,"%S",lp_servicename(snum));
120 standard_sub(cnum,buf);
124 /*******************************************************************
125 check a API string for validity when we only need to check the prefix
126 ******************************************************************/
127 static BOOL prefix_ok(char *str,char *prefix)
129 return(strncmp(str,prefix,strlen(prefix)) == 0);
133 /****************************************************************************
135 ****************************************************************************/
136 static void send_trans_reply(char *outbuf,char *data,char *param,uint16 *setup,
137 int ldata,int lparam,int lsetup)
140 int this_ldata,this_lparam;
141 int tot_data=0,tot_param=0;
144 this_lparam = MIN(lparam,max_send - (500+lsetup*SIZEOFWORD)); /* hack */
145 this_ldata = MIN(ldata,max_send - (500+lsetup*SIZEOFWORD+this_lparam));
147 align = (this_lparam%4);
149 set_message(outbuf,10+lsetup,align+this_ldata+this_lparam,True);
151 memcpy(smb_buf(outbuf),param,this_lparam);
153 memcpy(smb_buf(outbuf)+this_lparam+align,data,this_ldata);
155 SSVAL(outbuf,smb_vwv0,lparam);
156 SSVAL(outbuf,smb_vwv1,ldata);
157 SSVAL(outbuf,smb_vwv3,this_lparam);
158 SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf),outbuf));
159 SSVAL(outbuf,smb_vwv5,0);
160 SSVAL(outbuf,smb_vwv6,this_ldata);
161 SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+this_lparam+align,outbuf));
162 SSVAL(outbuf,smb_vwv8,0);
163 SSVAL(outbuf,smb_vwv9,lsetup);
164 for (i=0;i<lsetup;i++)
165 SSVAL(outbuf,smb_vwv10+i*SIZEOFWORD,setup[i]);
168 send_smb(Client,outbuf);
170 tot_data = this_ldata;
171 tot_param = this_lparam;
173 while (tot_data < ldata || tot_param < lparam)
175 this_lparam = MIN(lparam-tot_param,max_send - 500); /* hack */
176 this_ldata = MIN(ldata-tot_data,max_send - (500+this_lparam));
178 align = (this_lparam%4);
180 set_message(outbuf,10,this_ldata+this_lparam+align,False);
182 memcpy(smb_buf(outbuf),param+tot_param,this_lparam);
184 memcpy(smb_buf(outbuf)+this_lparam+align,data+tot_data,this_ldata);
186 SSVAL(outbuf,smb_vwv3,this_lparam);
187 SSVAL(outbuf,smb_vwv4,smb_offset(smb_buf(outbuf),outbuf));
188 SSVAL(outbuf,smb_vwv5,tot_param);
189 SSVAL(outbuf,smb_vwv6,this_ldata);
190 SSVAL(outbuf,smb_vwv7,smb_offset(smb_buf(outbuf)+this_lparam+align,outbuf));
191 SSVAL(outbuf,smb_vwv8,tot_data);
192 SSVAL(outbuf,smb_vwv9,0);
195 send_smb(Client,outbuf);
197 tot_data += this_ldata;
198 tot_param += this_lparam;
203 char* format; /* formatstring for structure */
204 char* subformat; /* subformat for structure */
205 char* base; /* baseaddress of buffer */
206 int buflen; /* remaining size for fixed part; on init: length of base */
207 int subcount; /* count of substructures */
208 char* structbuf; /* pointer into buffer for remaining fixed part */
209 int stringlen; /* remaining size for variable part */
210 char* stringbuf; /* pointer into buffer for remaining variable part */
211 int neededlen; /* total needed size */
212 int usedlen; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
213 char* curpos; /* current position; pointer into format or subformat */
217 static int get_counter(char** p)
220 if (!p || !(*p)) return(1);
221 if (!isdigit(**p)) return 1;
225 n = 10 * n + (i - '0');
232 static int getlen(char* p)
238 case 'W': /* word (2 byte) */
241 case 'N': /* count of substructures (word) at end */
244 case 'D': /* double word (4 byte) */
245 case 'z': /* offset to zero terminated string (4 byte) */
246 case 'l': /* offset to user data (4 byte) */
249 case 'b': /* offset to data (with counter) (4 byte) */
253 case 'B': /* byte (with optional counter) */
254 n += get_counter(&p);
261 static BOOL init_package(struct pack_desc* p, int count, int subcount)
266 if (!p->format || !p->base) return(False);
268 i = count * getlen(p->format);
269 if (p->subformat) i += subcount * getlen(p->subformat);
270 p->structbuf = p->base;
274 p->curpos = p->format;
277 p->errcode = NERR_BufTooSmall;
280 p->errcode = NERR_Success;
283 p->stringbuf = p->base + i;
285 return(p->errcode == NERR_Success);
289 static int package(struct pack_desc* p, ...)
292 static int package(va_alist)
298 int needed=0, stringneeded;
300 int is_string=0, stringused;
307 p = va_arg(args,struct pack_desc *);
312 p->curpos = p->format;
314 p->curpos = p->subformat;
319 str = va_arg(args,char*);
320 if (strncmp(str,p->curpos,strlen(str)) != 0) {
321 DEBUG(2,("type error in package: %s instead of %*s\n",str,
322 strlen(str),p->curpos));
332 if (!p->curpos) return(0);
334 switch( *p->curpos++ ) {
335 case 'W': /* word (2 byte) */
337 temp = va_arg(args,int);
338 if (p->buflen >= needed) SSVAL(p->structbuf,0,temp);
340 case 'N': /* count of substructures (word) at end */
342 p->subcount = va_arg(args,int);
343 if (p->buflen >= needed) SSVAL(p->structbuf,0,p->subcount);
345 case 'D': /* double word (4 byte) */
347 temp = va_arg(args,int);
348 if (p->buflen >= needed) SIVAL(p->structbuf,0,temp);
350 case 'B': /* byte (with optional counter) */
351 needed = get_counter(&p->curpos);
353 char *s = va_arg(args,char*);
354 if (p->buflen >= needed) StrnCpy(p->structbuf,s?s:"",needed);
357 case 'z': /* offset to zero terminated string (4 byte) */
358 str = va_arg(args,char*);
359 stringneeded = (str ? strlen(str)+1 : 0);
362 case 'l': /* offset to user data (4 byte) */
363 str = va_arg(args,char*);
364 stringneeded = va_arg(args,int);
367 case 'b': /* offset to data (with counter) (4 byte) */
368 str = va_arg(args,char*);
369 stringneeded = get_counter(&p->curpos);
374 if (stringneeded >= 0) {
376 if (p->buflen >= needed) {
377 stringused = stringneeded;
378 if (stringused > p->stringlen) {
379 stringused = (is_string ? p->stringlen : 0);
380 if (p->errcode == NERR_Success) p->errcode = ERROR_MORE_DATA;
383 SIVAL(p->structbuf,0,0);
385 SIVAL(p->structbuf,0,PTR_DIFF(p->stringbuf,p->base));
386 memcpy(p->stringbuf,str?str:"",stringused);
387 if (is_string) p->stringbuf[stringused-1] = '\0';
388 p->stringbuf += stringused;
389 p->stringlen -= stringused;
390 p->usedlen += stringused;
393 p->neededlen += stringneeded;
395 p->neededlen += needed;
396 if (p->buflen >= needed) {
397 p->structbuf += needed;
399 p->usedlen += needed;
402 if (p->errcode == NERR_Success) p->errcode = NERR_BufTooSmall;
408 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
409 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
411 #define PACK(desc,t,v) package(desc,v)
412 #define PACKl(desc,t,v,l) package(desc,v,l)
415 static void PACKI(struct pack_desc* desc,char *t,int v)
420 static void PACKS(struct pack_desc* desc,char *t,char *v)
426 /****************************************************************************
428 ****************************************************************************/
430 static void PackDriverData(struct pack_desc* desc)
432 char drivdata[4+4+32];
433 SIVAL(drivdata,0,sizeof drivdata); /* cb */
434 SIVAL(drivdata,4,1000); /* lVersion */
435 memset(drivdata+8,0,32); /* szDeviceName */
436 strcpy(drivdata+8,"NULL");
437 PACKl(desc,"l",drivdata,sizeof drivdata); /* pDriverData */
440 static int check_printq_info(struct pack_desc* desc,
441 int uLevel, char *id1, const char* id2)
443 desc->subformat = NULL;
446 desc->format = "B13";
449 desc->format = "B13BWWWzzzzzWW";
452 desc->format = "B13BWWWzzzzzWN";
453 desc->subformat = "WB21BB16B10zWWzDDz";
456 desc->format = "zWWWWzzzzWWzzl";
459 desc->format = "zWWWWzzzzWNzzl";
460 desc->subformat = "WWzWWDDzz";
465 default: return False;
467 if (strcmp(desc->format,id1) != 0) return False;
468 if (desc->subformat && strcmp(desc->subformat,id2) != 0) return False;
472 static void fill_printjob_info(int cnum, int snum, int uLevel,
473 struct pack_desc* desc,
474 print_queue_struct* queue, int n)
476 time_t t = queue->time;
478 /* the client expects localtime */
481 PACKI(desc,"W",((snum%0xFF)<<8) | (queue->job%0xFF)); /* uJobId */
483 PACKS(desc,"B21",queue->user); /* szUserName */
484 PACKS(desc,"B",""); /* pad */
485 PACKS(desc,"B16",""); /* szNotifyName */
486 PACKS(desc,"B10","PM_Q_RAW"); /* szDataType */
487 PACKS(desc,"z",""); /* pszParms */
488 PACKI(desc,"W",n+1); /* uPosition */
489 PACKI(desc,"W",queue->status); /* fsStatus */
490 PACKS(desc,"z",""); /* pszStatus */
491 PACKI(desc,"D",t); /* ulSubmitted */
492 PACKI(desc,"D",queue->size); /* ulSize */
493 PACKS(desc,"z",queue->file); /* pszComment */
495 if (uLevel == 2 || uLevel == 3) {
496 PACKI(desc,"W",queue->priority); /* uPriority */
497 PACKS(desc,"z",queue->user); /* pszUserName */
498 PACKI(desc,"W",n+1); /* uPosition */
499 PACKI(desc,"W",queue->status); /* fsStatus */
500 PACKI(desc,"D",t); /* ulSubmitted */
501 PACKI(desc,"D",queue->size); /* ulSize */
502 PACKS(desc,"z","Samba"); /* pszComment */
503 PACKS(desc,"z",queue->file); /* pszDocument */
505 PACKS(desc,"z",""); /* pszNotifyName */
506 PACKS(desc,"z","PM_Q_RAW"); /* pszDataType */
507 PACKS(desc,"z",""); /* pszParms */
508 PACKS(desc,"z",""); /* pszStatus */
509 PACKS(desc,"z",SERVICE(snum)); /* pszQueue */
510 PACKS(desc,"z","lpd"); /* pszQProcName */
511 PACKS(desc,"z",""); /* pszQProcParms */
512 PACKS(desc,"z","NULL"); /* pszDriverName */
513 PackDriverData(desc); /* pDriverData */
514 PACKS(desc,"z",""); /* pszPrinterName */
519 static void fill_printq_info(int cnum, int snum, int uLevel,
520 struct pack_desc* desc,
521 int count, print_queue_struct* queue,
522 print_status_struct* status)
525 PACKS(desc,"B13",SERVICE(snum));
527 PACKS(desc,"z",Expand(cnum,snum,SERVICE(snum)));
529 if (uLevel == 1 || uLevel == 2) {
530 PACKS(desc,"B",""); /* alignment */
531 PACKI(desc,"W",5); /* priority */
532 PACKI(desc,"W",0); /* start time */
533 PACKI(desc,"W",0); /* until time */
534 PACKS(desc,"z",""); /* pSepFile */
535 PACKS(desc,"z","lpd"); /* pPrProc */
536 PACKS(desc,"z",SERVICE(snum)); /* pDestinations */
537 PACKS(desc,"z",""); /* pParms */
539 PACKS(desc,"z","UNKNOWN PRINTER");
540 PACKI(desc,"W",LPSTAT_ERROR);
542 else if (!status || !status->message[0]) {
543 PACKS(desc,"z",Expand(cnum,snum,lp_comment(snum)));
544 PACKI(desc,"W",LPSTAT_OK); /* status */
546 PACKS(desc,"z",status->message);
547 PACKI(desc,"W",status->status); /* status */
549 PACKI(desc,(uLevel == 1 ? "W" : "N"),count);
551 if (uLevel == 3 || uLevel == 4) {
552 PACKI(desc,"W",5); /* uPriority */
553 PACKI(desc,"W",0); /* uStarttime */
554 PACKI(desc,"W",0); /* uUntiltime */
555 PACKI(desc,"W",5); /* pad1 */
556 PACKS(desc,"z",""); /* pszSepFile */
557 PACKS(desc,"z","WinPrint"); /* pszPrProc */
558 PACKS(desc,"z",""); /* pszParms */
559 if (!status || !status->message[0]) {
560 PACKS(desc,"z",Expand(cnum,snum,lp_comment(snum))); /* pszComment */
561 PACKI(desc,"W",LPSTAT_OK); /* fsStatus */
563 PACKS(desc,"z",status->message); /* pszComment */
564 PACKI(desc,"W",status->status); /* fsStatus */
566 PACKI(desc,(uLevel == 3 ? "W" : "N"),count); /* cJobs */
567 PACKS(desc,"z",SERVICE(snum)); /* pszPrinters */
568 PACKS(desc,"z",lp_printerdriver(snum)); /* pszDriverName */
569 PackDriverData(desc); /* pDriverData */
571 if (uLevel == 2 || uLevel == 4) {
573 for (i=0;i<count;i++)
574 fill_printjob_info(cnum,snum,uLevel == 2 ? 1 : 2,desc,&queue[i],i);
577 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n",SERVICE(snum),count));
580 static BOOL api_DosPrintQGetInfo(int cnum,uint16 vuid, char *param,char *data,
581 int mdrcnt,int mprcnt,
582 char **rdata,char **rparam,
583 int *rdata_len,int *rparam_len)
585 char *str1 = param+2;
586 char *str2 = skip_string(str1,1);
587 char *p = skip_string(str2,1);
593 struct pack_desc desc;
594 print_queue_struct *queue=NULL;
595 print_status_struct status;
597 bzero(&status,sizeof(status));
598 bzero(&desc,sizeof(desc));
600 p = skip_string(p,1);
605 /* remove any trailing username */
606 if ((p = strchr(QueueName,'%'))) *p = 0;
608 DEBUG(3,("PrintQueue uLevel=%d name=%s\n",uLevel,QueueName));
610 /* check it's a supported varient */
611 if (!prefix_ok(str1,"zWrLh")) return False;
612 if (!check_printq_info(&desc,uLevel,str2,str3)) return False;
614 snum = lp_servicenumber(QueueName);
615 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
616 int pnum = lp_servicenumber(PRINTERS_NAME);
618 lp_add_printer(QueueName,pnum);
619 snum = lp_servicenumber(QueueName);
623 if (snum < 0 || !VALID_SNUM(snum)) return(False);
625 count = get_printqueue(snum,cnum,&queue,&status);
626 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
628 desc.buflen = mdrcnt;
629 if (init_package(&desc,1,count)) {
630 desc.subcount = count;
631 fill_printq_info(cnum,snum,uLevel,&desc,count,queue,&status);
634 *rdata_len = desc.usedlen;
637 *rparam = REALLOC(*rparam,*rparam_len);
638 SSVALS(*rparam,0,desc.errcode);
640 SSVAL(*rparam,4,desc.neededlen);
642 DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode));
644 if (queue) free(queue);
650 /****************************************************************************
651 view list of all print jobs on all queues
652 ****************************************************************************/
653 static BOOL api_DosPrintQEnum(int cnum, uint16 vuid, char* param, char* data,
654 int mdrcnt, int mprcnt,
655 char **rdata, char** rparam,
656 int *rdata_len, int *rparam_len)
658 char *param_format = param+2;
659 char *output_format1 = skip_string(param_format,1);
660 char *p = skip_string(output_format1,1);
661 int uLevel = SVAL(p,0);
662 char *output_format2 = p + 4;
663 int services = lp_numservices();
665 struct pack_desc desc;
666 print_queue_struct **queue = NULL;
667 print_status_struct *status = NULL;
668 int* subcntarr = NULL;
669 int queuecnt, subcnt=0, succnt=0;
671 bzero(&desc,sizeof(desc));
673 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
675 if (!prefix_ok(param_format,"WrLeh")) return False;
676 if (!check_printq_info(&desc,uLevel,output_format1,output_format2))
679 for (i = 0; i < services; i++)
680 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
683 queue = (print_queue_struct**)malloc(queuecnt*sizeof(print_queue_struct*));
684 memset(queue,0,queuecnt*sizeof(print_queue_struct*));
685 status = (print_status_struct*)malloc(queuecnt*sizeof(print_status_struct));
686 memset(status,0,queuecnt*sizeof(print_status_struct));
687 subcntarr = (int*)malloc(queuecnt*sizeof(int));
690 for (i = 0; i < services; i++)
691 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
692 subcntarr[n] = get_printqueue(i,cnum,&queue[n],&status[n]);
693 subcnt += subcntarr[n];
697 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
699 desc.buflen = mdrcnt;
701 if (init_package(&desc,queuecnt,subcnt)) {
704 for (i = 0; i < services; i++)
705 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
706 fill_printq_info(cnum,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]);
708 if (desc.errcode == NERR_Success) succnt = n;
712 if (subcntarr) free(subcntarr);
714 *rdata_len = desc.usedlen;
716 *rparam = REALLOC(*rparam,*rparam_len);
717 SSVALS(*rparam,0,desc.errcode);
719 SSVAL(*rparam,4,succnt);
720 SSVAL(*rparam,6,queuecnt);
722 for (i = 0; i < queuecnt; i++) {
723 if (queue && queue[i]) free(queue[i]);
726 if (queue) free(queue);
727 if (status) free(status);
732 /****************************************************************************
733 get info level for a server list query
734 ****************************************************************************/
735 static BOOL check_server_info(int uLevel, char* id)
739 if (strcmp(id,"B16") != 0) return False;
742 if (strcmp(id,"B16BBDz") != 0) return False;
750 struct srv_info_struct
760 /*******************************************************************
761 get server info lists from the files saved by nmbd. Return the
763 ******************************************************************/
764 static int get_server_info(uint32 servertype,
765 struct srv_info_struct **servers,
774 strcpy(fname,lp_lockdir());
775 trim_string(fname,NULL,"/");
777 strcat(fname,SERVER_LIST);
779 f = fopen(fname,"r");
782 DEBUG(4,("Can't open %s - %s\n",fname,strerror(errno)));
786 /* request for everything is code for request all servers */
787 if (servertype == SV_TYPE_ALL) servertype &= ~SV_TYPE_DOMAIN_ENUM;
789 DEBUG(4,("Servertype search: %8x\n",servertype));
794 struct srv_info_struct *s;
799 fgets(line,sizeof(line)-1,f);
800 if (!*line) continue;
802 if (count == alloced) {
804 (*servers) = (struct srv_info_struct *)
805 Realloc(*servers,sizeof(**servers)*alloced);
806 if (!(*servers)) return(0);
807 bzero((char *)((*servers)+count),sizeof(**servers)*(alloced-count));
809 s = &(*servers)[count];
811 if (!next_token(&ptr,s->name , NULL)) continue;
812 if (!next_token(&ptr,stype , NULL)) continue;
813 if (!next_token(&ptr,s->comment, NULL)) continue;
814 if (!next_token(&ptr,s->domain , NULL)) {
815 /* this allows us to cope with an old nmbd */
816 strcpy(s->domain,myworkgroup);
819 if (sscanf(stype,"%X",&s->type) != 1) {
820 DEBUG(4,("r:host file "));
824 /* doesn't match up: don't want it */
825 if (!(servertype & s->type)) {
826 DEBUG(4,("r:serv type "));
830 if ((servertype & SV_TYPE_DOMAIN_ENUM) !=
831 (s->type & SV_TYPE_DOMAIN_ENUM))
833 DEBUG(4,("s: dom mismatch "));
837 if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM))
844 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
845 s->name, s->type, s->comment, s->domain));
847 s->server_added = True;
852 DEBUG(4,("%20s %8x %25s %15s\n",
853 s->name, s->type, s->comment, s->domain));
862 /*******************************************************************
863 fill in a server info structure
864 ******************************************************************/
865 static int fill_srv_info(struct srv_info_struct *service,
866 int uLevel, char **buf, int *buflen,
867 char **stringbuf, int *stringspace, char *baseaddr)
876 case 0: struct_len = 16; break;
877 case 1: struct_len = 26; break;
887 len = strlen(service->comment)+1;
891 if (buflen) *buflen = struct_len;
892 if (stringspace) *stringspace = len;
893 return struct_len + len;
898 if (*buflen < struct_len) return -1;
907 l2 = *buflen - struct_len;
909 if (!baseaddr) baseaddr = p;
914 StrnCpy(p,service->name,15);
918 StrnCpy(p,service->name,15);
919 SIVAL(p,18,service->type);
920 SIVAL(p,22,PTR_DIFF(p2,baseaddr));
921 len += CopyAndAdvance(&p2,service->comment,&l2);
927 *buf = p + struct_len;
928 *buflen -= struct_len;
941 static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
943 return(strcmp(s1->name,s2->name));
946 /****************************************************************************
947 view list of servers available (or possibly domains). The info is
948 extracted from lists saved by nmbd on the local host
949 ****************************************************************************/
950 static BOOL api_RNetServerEnum(int cnum, uint16 vuid, char *param, char *data,
951 int mdrcnt, int mprcnt, char **rdata,
952 char **rparam, int *rdata_len, int *rparam_len)
954 char *str1 = param+2;
955 char *str2 = skip_string(str1,1);
956 char *p = skip_string(str2,1);
957 int uLevel = SVAL(p,0);
958 int buf_len = SVAL(p,2);
959 uint32 servertype = IVAL(p,4);
961 int data_len, fixed_len, string_len;
963 struct srv_info_struct *servers=NULL;
964 int counted=0,total=0;
968 BOOL local_request = servertype & SV_TYPE_LOCAL_LIST_ONLY;
970 if (servertype == SV_TYPE_ALL) servertype &= ~SV_TYPE_DOMAIN_ENUM;
972 domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
976 if (!prefix_ok(str1,"WrLehD")) return False;
977 if (!check_server_info(uLevel,str2)) return False;
979 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
980 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
981 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
983 if (strcmp(str1, "WrLehDz") == 0) {
984 StrnCpy(domain, p, sizeof(fstring)-1);
986 StrnCpy(domain, myworkgroup, sizeof(fstring)-1);
989 if (lp_browse_list())
990 total = get_server_info(servertype,&servers,domain);
992 data_len = fixed_len = string_len = 0;
995 qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
1000 for (i=0;i<total;i++)
1002 struct srv_info_struct *s = &servers[i];
1003 if (lastname && strequal(lastname,s->name)) continue;
1005 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1006 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1007 s->name, s->type, s->comment, s->domain));
1009 if (data_len <= buf_len) {
1012 string_len += s_len;
1019 *rdata_len = fixed_len + string_len;
1020 *rdata = REALLOC(*rdata,*rdata_len);
1021 bzero(*rdata,*rdata_len);
1023 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1029 char *lastname=NULL;
1030 int count2 = counted;
1031 for (i = 0; i < total && count2;i++)
1033 struct srv_info_struct *s = &servers[i];
1034 if (lastname && strequal(lastname,s->name)) continue;
1036 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1037 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1038 s->name, s->type, s->comment, s->domain));
1044 *rparam = REALLOC(*rparam,*rparam_len);
1045 SSVAL(*rparam,0,NERR_Success);
1047 SSVAL(*rparam,4,counted);
1048 SSVAL(*rparam,6,counted+missed);
1050 if (servers) free(servers);
1052 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1053 domain,uLevel,counted,counted+missed));
1059 /****************************************************************************
1060 get info about a share
1061 ****************************************************************************/
1062 static BOOL check_share_info(int uLevel, char* id)
1066 if (strcmp(id,"B13") != 0) return False;
1069 if (strcmp(id,"B13BWz") != 0) return False;
1072 if (strcmp(id,"B13BWzWWWzB9B") != 0) return False;
1075 if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) return False;
1077 default: return False;
1082 static int fill_share_info(int cnum, int snum, int uLevel,
1083 char** buf, int* buflen,
1084 char** stringbuf, int* stringspace, char* baseaddr)
1093 case 0: struct_len = 13; break;
1094 case 1: struct_len = 20; break;
1095 case 2: struct_len = 40; break;
1096 case 91: struct_len = 68; break;
1104 if (uLevel > 0) len += StrlenExpanded(cnum,snum,lp_comment(snum));
1105 if (uLevel > 1) len += strlen(lp_pathname(snum)) + 1;
1106 if (buflen) *buflen = struct_len;
1107 if (stringspace) *stringspace = len;
1108 return struct_len + len;
1113 if ((*buflen) < struct_len) return -1;
1121 p2 = p + struct_len;
1122 l2 = (*buflen) - struct_len;
1124 if (!baseaddr) baseaddr = p;
1126 StrnCpy(p,lp_servicename(snum),13);
1132 type = STYPE_DISKTREE;
1133 if (lp_print_ok(snum)) type = STYPE_PRINTQ;
1134 if (strequal("IPC$",lp_servicename(snum))) type = STYPE_IPC;
1135 SSVAL(p,14,type); /* device type */
1136 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1137 len += CopyExpanded(cnum,snum,&p2,lp_comment(snum),&l2);
1142 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1143 SSVALS(p,22,-1); /* max uses */
1144 SSVAL(p,24,1); /* current uses */
1145 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1146 len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1147 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1152 memset(p+40,0,SHPWLEN+2);
1164 (*buf) = p + struct_len;
1165 (*buflen) -= struct_len;
1167 (*stringspace) = l2;
1177 static BOOL api_RNetShareGetInfo(int cnum,uint16 vuid, char *param,char *data,
1178 int mdrcnt,int mprcnt,
1179 char **rdata,char **rparam,
1180 int *rdata_len,int *rparam_len)
1182 char *str1 = param+2;
1183 char *str2 = skip_string(str1,1);
1184 char *netname = skip_string(str2,1);
1185 char *p = skip_string(netname,1);
1186 int uLevel = SVAL(p,0);
1187 int snum = find_service(netname);
1189 if (snum < 0) return False;
1191 /* check it's a supported varient */
1192 if (!prefix_ok(str1,"zWrLh")) return False;
1193 if (!check_share_info(uLevel,str2)) return False;
1195 *rdata = REALLOC(*rdata,mdrcnt);
1197 *rdata_len = fill_share_info(cnum,snum,uLevel,&p,&mdrcnt,0,0,0);
1198 if (*rdata_len < 0) return False;
1201 *rparam = REALLOC(*rparam,*rparam_len);
1202 SSVAL(*rparam,0,NERR_Success);
1203 SSVAL(*rparam,2,0); /* converter word */
1204 SSVAL(*rparam,4,*rdata_len);
1209 /****************************************************************************
1210 view list of shares available
1211 ****************************************************************************/
1212 static BOOL api_RNetShareEnum(int cnum,uint16 vuid, char *param,char *data,
1213 int mdrcnt,int mprcnt,
1214 char **rdata,char **rparam,
1215 int *rdata_len,int *rparam_len)
1217 char *str1 = param+2;
1218 char *str2 = skip_string(str1,1);
1219 char *p = skip_string(str2,1);
1220 int uLevel = SVAL(p,0);
1221 int buf_len = SVAL(p,2);
1223 int count=lp_numservices();
1224 int total=0,counted=0;
1226 int data_len, fixed_len, string_len;
1229 if (!prefix_ok(str1,"WrLeh")) return False;
1230 if (!check_share_info(uLevel,str2)) return False;
1232 data_len = fixed_len = string_len = 0;
1233 for (i=0;i<count;i++)
1234 if (lp_browseable(i) && lp_snum_ok(i))
1237 data_len += fill_share_info(cnum,i,uLevel,0,&f_len,0,&s_len,0);
1238 if (data_len <= buf_len)
1242 string_len += s_len;
1245 *rdata_len = fixed_len + string_len;
1246 *rdata = REALLOC(*rdata,*rdata_len);
1247 memset(*rdata,0,*rdata_len);
1249 p2 = (*rdata) + fixed_len; /* auxillery data (strings) will go here */
1253 for (i = 0; i < count;i++)
1254 if (lp_browseable(i) && lp_snum_ok(i))
1255 if (fill_share_info(cnum,i,uLevel,&p,&f_len,&p2,&s_len,*rdata) < 0)
1259 *rparam = REALLOC(*rparam,*rparam_len);
1260 SSVAL(*rparam,0,NERR_Success);
1262 SSVAL(*rparam,4,counted);
1263 SSVAL(*rparam,6,total);
1265 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1266 counted,total,uLevel,
1267 buf_len,*rdata_len,mdrcnt));
1273 /****************************************************************************
1274 get the time of day info
1275 ****************************************************************************/
1276 static BOOL api_NetRemoteTOD(int cnum,uint16 vuid, char *param,char *data,
1277 int mdrcnt,int mprcnt,
1278 char **rdata,char **rparam,
1279 int *rdata_len,int *rparam_len)
1283 *rparam = REALLOC(*rparam,*rparam_len);
1286 *rdata = REALLOC(*rdata,*rdata_len);
1288 SSVAL(*rparam,0,NERR_Success);
1289 SSVAL(*rparam,2,0); /* converter word */
1295 time_t unixdate = time(NULL);
1297 put_dos_date3(p,0,unixdate); /* this is the time that is looked at
1298 by NT in a "net time" operation,
1299 it seems to ignore the one below */
1301 /* the client expects to get localtime, not GMT, in this bit
1302 (I think, this needs testing) */
1303 t = LocalTime(&unixdate);
1305 SIVAL(p,4,0); /* msecs ? */
1306 CVAL(p,8) = t->tm_hour;
1307 CVAL(p,9) = t->tm_min;
1308 CVAL(p,10) = t->tm_sec;
1309 CVAL(p,11) = 0; /* hundredths of seconds */
1310 SSVALS(p,12,TimeDiff(unixdate)/60); /* timezone in minutes from GMT */
1311 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
1312 CVAL(p,16) = t->tm_mday;
1313 CVAL(p,17) = t->tm_mon + 1;
1314 SSVAL(p,18,1900+t->tm_year);
1315 CVAL(p,20) = t->tm_wday;
1322 /****************************************************************************
1323 set the user password
1324 ****************************************************************************/
1325 static BOOL api_SetUserPassword(int cnum,uint16 vuid, char *param,char *data,
1326 int mdrcnt,int mprcnt,
1327 char **rdata,char **rparam,
1328 int *rdata_len,int *rparam_len)
1330 char *p = skip_string(param+2,2);
1332 fstring pass1,pass2;
1336 p = skip_string(p,1);
1338 StrnCpy(pass1,p,16);
1339 StrnCpy(pass2,p+16,16);
1342 *rparam = REALLOC(*rparam,*rparam_len);
1346 SSVAL(*rparam,0,NERR_badpass);
1347 SSVAL(*rparam,2,0); /* converter word */
1349 DEBUG(3,("Set password for <%s>\n",user));
1351 if (password_ok(user,pass1,strlen(pass1),NULL) &&
1352 chgpasswd(user,pass1,pass2))
1354 SSVAL(*rparam,0,NERR_Success);
1357 bzero(pass1,sizeof(fstring));
1358 bzero(pass2,sizeof(fstring));
1363 /****************************************************************************
1366 ****************************************************************************/
1367 static BOOL api_RDosPrintJobDel(int cnum,uint16 vuid, char *param,char *data,
1368 int mdrcnt,int mprcnt,
1369 char **rdata,char **rparam,
1370 int *rdata_len,int *rparam_len)
1372 int function = SVAL(param,0);
1373 char *str1 = param+2;
1374 char *str2 = skip_string(str1,1);
1375 char *p = skip_string(str2,1);
1376 int jobid = (SVAL(p,0)&0xFF); /* the snum and jobid are encoded
1377 by the print queue api */
1378 int snum = (SVAL(p,0)>>8);
1382 /* check it's a supported varient */
1383 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
1387 *rparam = REALLOC(*rparam,*rparam_len);
1391 SSVAL(*rparam,0,NERR_Success);
1393 if (snum >= 0 && VALID_SNUM(snum))
1395 print_queue_struct *queue=NULL;
1397 count = get_printqueue(snum,cnum,&queue,NULL);
1399 for (i=0;i<count;i++)
1400 if ((queue[i].job%0xFF) == jobid)
1403 case 81: /* delete */
1404 DEBUG(3,("Deleting queue entry %d\n",queue[i].job));
1405 del_printqueue(cnum,snum,queue[i].job);
1407 case 82: /* pause */
1408 case 83: /* resume */
1409 DEBUG(3,("%s queue entry %d\n",
1410 (function==82?"pausing":"resuming"),queue[i].job));
1411 status_printjob(cnum,snum,queue[i].job,
1412 (function==82?LPQ_PAUSED:LPQ_QUEUED));
1419 SSVAL(*rparam,0,NERR_JobNotFound);
1421 if (queue) free(queue);
1424 SSVAL(*rparam,2,0); /* converter word */
1429 static BOOL api_WPrintQueuePurge(int cnum,uint16 vuid, char *param,char *data,
1430 int mdrcnt,int mprcnt,
1431 char **rdata,char **rparam,
1432 int *rdata_len,int *rparam_len)
1434 char *str1 = param+2;
1435 char *str2 = skip_string(str1,1);
1436 char *QueueName = skip_string(str2,1);
1439 /* check it's a supported varient */
1440 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
1444 *rparam = REALLOC(*rparam,*rparam_len);
1448 SSVAL(*rparam,0,NERR_Success);
1449 SSVAL(*rparam,2,0); /* converter word */
1451 snum = lp_servicenumber(QueueName);
1452 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
1453 int pnum = lp_servicenumber(PRINTERS_NAME);
1455 lp_add_printer(QueueName,pnum);
1456 snum = lp_servicenumber(QueueName);
1460 if (snum >= 0 && VALID_SNUM(snum)) {
1461 print_queue_struct *queue=NULL;
1465 count = get_printqueue(snum,cnum,&queue,NULL);
1466 for (i = 0; i < count; i++)
1467 del_printqueue(cnum,snum,queue[i].job);
1469 if (queue) free(queue);
1472 DEBUG(3,("Print queue purge, queue=%s\n",QueueName));
1478 /****************************************************************************
1479 set the property of a print job (undocumented?)
1480 ? function = 0xb -> set name of print job
1481 ? function = 0x6 -> move print job up/down
1482 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
1483 or <WWsTP> <WB21BB16B10zWWzDDz>
1484 ****************************************************************************/
1485 static int check_printjob_info(struct pack_desc* desc,
1486 int uLevel, char* id)
1488 desc->subformat = NULL;
1490 case 0: desc->format = "W"; break;
1491 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
1492 case 2: desc->format = "WWzWWDDzz"; break;
1493 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
1494 default: return False;
1496 if (strcmp(desc->format,id) != 0) return False;
1500 static BOOL api_PrintJobInfo(int cnum,uint16 vuid,char *param,char *data,
1501 int mdrcnt,int mprcnt,
1502 char **rdata,char **rparam,
1503 int *rdata_len,int *rparam_len)
1505 struct pack_desc desc;
1506 char *str1 = param+2;
1507 char *str2 = skip_string(str1,1);
1508 char *p = skip_string(str2,1);
1509 int jobid = (SVAL(p,0)&0xFF); /* the snum and jobid are encoded
1510 by the print queue api */
1511 int snum = (SVAL(p,0)>>8);
1512 int uLevel = SVAL(p,2);
1513 int function = SVAL(p,4); /* what is this ?? */
1518 *rparam = REALLOC(*rparam,*rparam_len);
1522 /* check it's a supported varient */
1523 if ((strcmp(str1,"WWsTP")) || (!check_printjob_info(&desc,uLevel,str2)))
1527 case 0x6: /* change job place in the queue, data gives the new place */
1528 if (snum >= 0 && VALID_SNUM(snum))
1530 print_queue_struct *queue=NULL;
1534 count = get_printqueue(snum,cnum,&queue,NULL);
1535 for (i=0;i<count;i++) /* find job */
1536 if ((queue[i].job%0xFF) == jobid) break;
1539 desc.errcode=NERR_JobNotFound;
1540 if (queue) free(queue);
1543 desc.errcode=NERR_Success;
1547 int place= SVAL(data,0);
1548 /* we currently have no way of doing this. Can any unix do it? */
1549 if (i < place) /* move down */;
1550 else if (i > place ) /* move up */;
1553 desc.errcode=NERR_notsupported; /* not yet supported */
1554 if (queue) free(queue);
1557 else desc.errcode=NERR_JobNotFound;
1559 case 0xb: /* change print job name, data gives the name */
1560 /* jobid, snum should be zero */
1567 if (issafe(*s)) name[l++] = *s;
1572 DEBUG(3,("Setting print name to %s\n",name));
1574 for (i=0;i<MAX_OPEN_FILES;i++)
1575 if (Files[i].open && Files[i].print_file)
1581 if (!become_user(Files[i].cnum,vuid) ||
1582 !become_service(Files[i].cnum,True))
1585 if (sys_rename(Files[i].name,name) == 0)
1586 string_set(&Files[i].name,name);
1590 desc.errcode=NERR_Success;
1593 default: /* not implemented */
1597 SSVALS(*rparam,0,desc.errcode);
1598 SSVAL(*rparam,2,0); /* converter word */
1604 /****************************************************************************
1605 get info about the server
1606 ****************************************************************************/
1607 static BOOL api_RNetServerGetInfo(int cnum,uint16 vuid, char *param,char *data,
1608 int mdrcnt,int mprcnt,
1609 char **rdata,char **rparam,
1610 int *rdata_len,int *rparam_len)
1612 char *str1 = param+2;
1613 char *str2 = skip_string(str1,1);
1614 char *p = skip_string(str2,1);
1615 int uLevel = SVAL(p,0);
1619 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
1621 /* check it's a supported varient */
1622 if (!prefix_ok(str1,"WrLh")) return False;
1625 if (strcmp(str2,"B16") != 0) return False;
1629 if (strcmp(str2,"B16BBDz") != 0) return False;
1633 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")
1638 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz")
1643 if (strcmp(str2,"DN") != 0) return False;
1647 if (strcmp(str2,"B16BBDzWWzzz") != 0) return False;
1650 default: return False;
1653 *rdata_len = mdrcnt;
1654 *rdata = REALLOC(*rdata,*rdata_len);
1657 p2 = p + struct_len;
1659 StrnCpy(p,local_machine,16);
1665 struct srv_info_struct *servers=NULL;
1668 uint32 servertype=DFLT_SERVER_TYPE;
1670 strcpy(comment,lp_serverstring());
1672 if ((count=get_server_info(SV_TYPE_ALL,&servers,myworkgroup))>0) {
1673 for (i=0;i<count;i++)
1674 if (strequal(servers[i].name,local_machine))
1676 servertype = servers[i].type;
1677 strcpy(comment,servers[i].comment);
1680 if (servers) free(servers);
1682 SCVAL(p,0,MAJOR_VERSION);
1683 SCVAL(p,1,MINOR_VERSION);
1684 SIVAL(p,2,servertype);
1686 if (mdrcnt == struct_len) {
1689 SIVAL(p,6,PTR_DIFF(p2,*rdata));
1690 standard_sub(cnum,comment);
1691 StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
1692 p2 = skip_string(p2,1);
1697 return False; /* not yet implemented */
1700 *rdata_len = PTR_DIFF(p2,*rdata);
1703 *rparam = REALLOC(*rparam,*rparam_len);
1704 SSVAL(*rparam,0,NERR_Success);
1705 SSVAL(*rparam,2,0); /* converter word */
1706 SSVAL(*rparam,4,*rdata_len);
1712 /****************************************************************************
1713 get info about the server
1714 ****************************************************************************/
1715 static BOOL api_NetWkstaGetInfo(int cnum,uint16 vuid, char *param,char *data,
1716 int mdrcnt,int mprcnt,
1717 char **rdata,char **rparam,
1718 int *rdata_len,int *rparam_len)
1720 char *str1 = param+2;
1721 char *str2 = skip_string(str1,1);
1722 char *p = skip_string(str2,1);
1724 extern pstring sesssetup_user;
1725 int level = SVAL(p,0);
1727 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
1730 *rparam = REALLOC(*rparam,*rparam_len);
1732 /* check it's a supported varient */
1733 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz")))
1736 *rdata_len = mdrcnt + 1024;
1737 *rdata = REALLOC(*rdata,*rdata_len);
1739 SSVAL(*rparam,0,NERR_Success);
1740 SSVAL(*rparam,2,0); /* converter word */
1746 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
1747 strcpy(p2,local_machine);
1749 p2 = skip_string(p2,1);
1752 SIVAL(p,0,PTR_DIFF(p2,*rdata));
1753 strcpy(p2,sesssetup_user);
1754 p2 = skip_string(p2,1);
1757 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
1758 strcpy(p2,myworkgroup);
1760 p2 = skip_string(p2,1);
1763 SCVAL(p,0,MAJOR_VERSION); /* system version - e.g 4 in 4.1 */
1764 SCVAL(p,1,MINOR_VERSION); /* system version - e.g .1 in 4.1 */
1767 SIVAL(p,0,PTR_DIFF(p2,*rdata));
1768 strcpy(p2,myworkgroup); /* don't know. login domain?? */
1769 p2 = skip_string(p2,1);
1772 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
1774 p2 = skip_string(p2,1);
1777 *rdata_len = PTR_DIFF(p2,*rdata);
1779 SSVAL(*rparam,4,*rdata_len);
1784 /****************************************************************************
1785 get info about a user
1787 struct user_info_11 {
1788 char usri11_name[21]; 0-20
1790 char *usri11_comment; 22-25
1791 char *usri11_usr_comment; 26-29
1792 unsigned short usri11_priv; 30-31
1793 unsigned long usri11_auth_flags; 32-35
1794 long usri11_password_age; 36-39
1795 char *usri11_homedir; 40-43
1796 char *usri11_parms; 44-47
1797 long usri11_last_logon; 48-51
1798 long usri11_last_logoff; 52-55
1799 unsigned short usri11_bad_pw_count; 56-57
1800 unsigned short usri11_num_logons; 58-59
1801 char *usri11_logon_server; 60-63
1802 unsigned short usri11_country_code; 64-65
1803 char *usri11_workstations; 66-69
1804 unsigned long usri11_max_storage; 70-73
1805 unsigned short usri11_units_per_week; 74-75
1806 unsigned char *usri11_logon_hours; 76-79
1807 unsigned short usri11_code_page; 80-81
1812 usri11_name specifies the user name for which information is retireved
1814 usri11_pad aligns the next data structure element to a word boundary
1816 usri11_comment is a null terminated ASCII comment
1818 usri11_user_comment is a null terminated ASCII comment about the user
1820 usri11_priv specifies the level of the privilege assigned to the user.
1821 The possible values are:
1823 Name Value Description
1824 USER_PRIV_GUEST 0 Guest privilege
1825 USER_PRIV_USER 1 User privilege
1826 USER_PRV_ADMIN 2 Administrator privilege
1828 usri11_auth_flags specifies the account operator privileges. The
1829 possible values are:
1831 Name Value Description
1832 AF_OP_PRINT 0 Print operator
1835 Leach, Naik [Page 28]
\r\f
1838 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
1841 AF_OP_COMM 1 Communications operator
1842 AF_OP_SERVER 2 Server operator
1843 AF_OP_ACCOUNTS 3 Accounts operator
1846 usri11_password_age specifies how many seconds have elapsed since the
1847 password was last changed.
1849 usri11_home_dir points to a null terminated ASCII string that contains
1850 the path name of the user's home directory.
1852 usri11_parms points to a null terminated ASCII string that is set
1853 aside for use by applications.
1855 usri11_last_logon specifies the time when the user last logged on.
1856 This value is stored as the number of seconds elapsed since
1857 00:00:00, January 1, 1970.
1859 usri11_last_logoff specifies the time when the user last logged off.
1860 This value is stored as the number of seconds elapsed since
1861 00:00:00, January 1, 1970. A value of 0 means the last logoff
1864 usri11_bad_pw_count specifies the number of incorrect passwords
1865 entered since the last successful logon.
1867 usri11_log1_num_logons specifies the number of times this user has
1868 logged on. A value of -1 means the number of logons is unknown.
1870 usri11_logon_server points to a null terminated ASCII string that
1871 contains the name of the server to which logon requests are sent.
1872 A null string indicates logon requests should be sent to the
1875 usri11_country_code specifies the country code for the user's language
1878 usri11_workstations points to a null terminated ASCII string that
1879 contains the names of workstations the user may log on from.
1880 There may be up to 8 workstations, with the names separated by
1881 commas. A null strings indicates there are no restrictions.
1883 usri11_max_storage specifies the maximum amount of disk space the user
1884 can occupy. A value of 0xffffffff indicates there are no
1887 usri11_units_per_week specifies the equal number of time units into
1888 which a week is divided. This value must be equal to 168.
1890 usri11_logon_hours points to a 21 byte (168 bits) string that
1891 specifies the time during which the user can log on. Each bit
1892 represents one unique hour in a week. The first bit (bit 0, word
1893 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
1897 Leach, Naik [Page 29]
\r\f
1900 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
1903 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
1904 are no restrictions.
1906 usri11_code_page specifies the code page for the user's language of
1909 All of the pointers in this data structure need to be treated
1910 specially. The pointer is a 32 bit pointer. The higher 16 bits need
1911 to be ignored. The converter word returned in the parameters section
1912 needs to be subtracted from the lower 16 bits to calculate an offset
1913 into the return buffer where this ASCII string resides.
1915 There is no auxiliary data in the response.
1917 ****************************************************************************/
1919 #define usri11_name 0
1920 #define usri11_pad 21
1921 #define usri11_comment 22
1922 #define usri11_usr_comment 26
1923 #define usri11_full_name 30
1924 #define usri11_priv 34
1925 #define usri11_auth_flags 36
1926 #define usri11_password_age 40
1927 #define usri11_homedir 44
1928 #define usri11_parms 48
1929 #define usri11_last_logon 52
1930 #define usri11_last_logoff 56
1931 #define usri11_bad_pw_count 60
1932 #define usri11_num_logons 62
1933 #define usri11_logon_server 64
1934 #define usri11_country_code 68
1935 #define usri11_workstations 70
1936 #define usri11_max_storage 74
1937 #define usri11_units_per_week 78
1938 #define usri11_logon_hours 80
1939 #define usri11_code_page 84
1940 #define usri11_end 86
1942 #define USER_PRIV_GUEST 0
1943 #define USER_PRIV_USER 1
1944 #define USER_PRIV_ADMIN 2
1946 #define AF_OP_PRINT 0
1947 #define AF_OP_COMM 1
1948 #define AF_OP_SERVER 2
1949 #define AF_OP_ACCOUNTS 3
1952 static BOOL api_RNetUserGetInfo(int cnum,uint16 vuid, char *param,char *data,
1953 int mdrcnt,int mprcnt,
1954 char **rdata,char **rparam,
1955 int *rdata_len,int *rparam_len)
1957 char *str1 = param+2;
1958 char *str2 = skip_string(str1,1);
1959 char *UserName = skip_string(str2,1);
1960 char *p = skip_string(UserName,1);
1961 int uLevel = SVAL(p,0);
1964 /* get NIS home of a previously validated user - simeon */
1965 user_struct *vuser = get_valid_user_struct(vuid);
1966 DEBUG(3,(" Username of UID %d is %s\n", vuser->uid, vuser->name));
1967 #if (defined(NETGROUP) && defined(AUTOMOUNT))
1968 DEBUG(3,(" HOMESHR for %s is %s\n", vuser->name, vuser->home_share));
1972 *rparam = REALLOC(*rparam,*rparam_len);
1974 /* check it's a supported variant */
1975 if (strcmp(str1,"zWrLh") != 0) return False;
1978 case 0: p2 = "B21"; break;
1979 case 1: p2 = "B21BB16DWzzWz"; break;
1980 case 2: p2 = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
1981 case 10: p2 = "B21Bzzz"; break;
1982 case 11: p2 = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
1983 default: return False;
1986 if (strcmp(p2,str2) != 0) return False;
1988 *rdata_len = mdrcnt + 1024;
1989 *rdata = REALLOC(*rdata,*rdata_len);
1991 SSVAL(*rparam,0,NERR_Success);
1992 SSVAL(*rparam,2,0); /* converter word */
1995 p2 = p + usri11_end;
1998 strcpy(p+usri11_name,UserName); /* 21 bytes - user name */
2002 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
2007 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
2008 strcpy(p2,"Comment");
2009 p2 = skip_string(p2,1);
2011 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
2012 strcpy(p2,"UserComment");
2013 p2 = skip_string(p2,1);
2015 /* EEK! the cifsrap.txt doesn't have this in!!!! */
2016 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
2017 strcpy(p2,vuser->real_name); /* simeon */
2018 p2 = skip_string(p2,1);
2021 if (uLevel == 11) /* modelled after NTAS 3.51 reply */
2023 SSVAL(p,usri11_priv,Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2024 SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
2025 SIVALS(p,usri11_password_age,0xffffffff); /* password age */
2026 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
2027 if (*lp_logon_path())
2029 strcpy(p2,lp_logon_path());
2033 #if (defined(NETGROUP) && defined(AUTOMOUNT))
2034 strcpy(p2, vuser->home_share);
2036 strcpy(p2,"\\\\%L\\%U");
2039 standard_sub_basic(p2);
2040 p2 = skip_string(p2,1);
2041 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
2043 p2 = skip_string(p2,1);
2044 SIVAL(p,usri11_last_logon,0); /* last logon */
2045 SIVAL(p,usri11_last_logoff,0); /* last logoff */
2046 SSVALS(p,usri11_bad_pw_count,0xffffffff); /* bad pw counts */
2047 SSVALS(p,usri11_num_logons,0xffffffff); /* num logons */
2048 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
2050 p2 = skip_string(p2,1);
2051 SSVAL(p,usri11_country_code,0); /* country code */
2053 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
2055 p2 = skip_string(p2,1);
2057 SIVALS(p,usri11_max_storage,0xffffffff); /* max storage */
2058 SSVAL(p,usri11_units_per_week,168); /* units per week */
2059 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
2061 /* a simple way to get logon hours at all times. */
2063 SCVAL(p2,21,0); /* fix zero termination */
2064 p2 = skip_string(p2,1);
2066 SSVAL(p,usri11_code_page,0); /* code page */
2068 if (uLevel == 1 || uLevel == 2)
2070 memset(p+22,' ',16); /* password */
2071 SIVALS(p,38,-1); /* password age */
2073 Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2074 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
2075 if (*lp_logon_path())
2077 strcpy(p2,lp_logon_path());
2081 #if (defined(NETGROUP) && defined(AUTOMOUNT))
2082 strcpy(p2, vuser->home_share);
2084 strcpy(p2,"\\\\%L\\%U");
2087 standard_sub_basic(p2);
2088 p2 = skip_string(p2,1);
2089 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
2091 SSVAL(p,52,0); /* flags */
2092 SIVAL(p,54,0); /* script_path */
2095 SIVAL(p,60,0); /* auth_flags */
2096 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
2097 strcpy(p2,vuser->real_name); /* simeon */
2098 p2 = skip_string(p2,1);
2099 SIVAL(p,68,0); /* urs_comment */
2100 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
2102 p2 = skip_string(p2,1);
2103 SIVAL(p,76,0); /* workstations */
2104 SIVAL(p,80,0); /* last_logon */
2105 SIVAL(p,84,0); /* last_logoff */
2106 SIVALS(p,88,-1); /* acct_expires */
2107 SIVALS(p,92,-1); /* max_storage */
2108 SSVAL(p,96,168); /* units_per_week */
2109 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
2112 SSVALS(p,102,-1); /* bad_pw_count */
2113 SSVALS(p,104,-1); /* num_logons */
2114 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
2115 strcpy(p2,"\\\\%L");
2116 standard_sub_basic(p2);
2117 p2 = skip_string(p2,1);
2118 SSVAL(p,110,49); /* country_code */
2119 SSVAL(p,112,860); /* code page */
2123 *rdata_len = PTR_DIFF(p2,*rdata);
2125 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
2130 /*******************************************************************
2131 get groups that a user is a member of
2132 ******************************************************************/
2133 static BOOL api_NetUserGetGroups(int cnum,uint16 vuid, char *param,char *data,
2134 int mdrcnt,int mprcnt,
2135 char **rdata,char **rparam,
2136 int *rdata_len,int *rparam_len)
2138 char *str1 = param+2;
2139 char *str2 = skip_string(str1,1);
2140 char *UserName = skip_string(str2,1);
2141 char *p = skip_string(UserName,1);
2142 int uLevel = SVAL(p,0);
2147 *rparam = REALLOC(*rparam,*rparam_len);
2149 /* check it's a supported varient */
2150 if (strcmp(str1,"zWrLeh") != 0) return False;
2152 case 0: p2 = "B21"; break;
2153 default: return False;
2155 if (strcmp(p2,str2) != 0) return False;
2157 *rdata_len = mdrcnt + 1024;
2158 *rdata = REALLOC(*rdata,*rdata_len);
2160 SSVAL(*rparam,0,NERR_Success);
2161 SSVAL(*rparam,2,0); /* converter word */
2165 /* XXXX we need a real SAM database some day */
2166 strcpy(p,"Users"); p += 21; count++;
2167 strcpy(p,"Domain Users"); p += 21; count++;
2168 strcpy(p,"Guests"); p += 21; count++;
2169 strcpy(p,"Domain Guests"); p += 21; count++;
2171 *rdata_len = PTR_DIFF(p,*rdata);
2173 SSVAL(*rparam,4,count); /* is this right?? */
2174 SSVAL(*rparam,6,count); /* is this right?? */
2180 static BOOL api_WWkstaUserLogon(int cnum,uint16 vuid, char *param,char *data,
2181 int mdrcnt,int mprcnt,
2182 char **rdata,char **rparam,
2183 int *rdata_len,int *rparam_len)
2185 char *str1 = param+2;
2186 char *str2 = skip_string(str1,1);
2187 char *p = skip_string(str2,1);
2189 struct pack_desc desc;
2195 bzero(&desc,sizeof(desc));
2197 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
2199 /* check it's a supported varient */
2200 if (strcmp(str1,"OOWb54WrLh") != 0) return False;
2201 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) return False;
2202 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2204 desc.buflen = mdrcnt;
2205 desc.subformat = NULL;
2208 if (init_package(&desc,1,0))
2210 PACKI(&desc,"W",0); /* code */
2211 PACKS(&desc,"B21",name); /* eff. name */
2212 PACKS(&desc,"B",""); /* pad */
2214 Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2215 PACKI(&desc,"D",0); /* auth flags XXX */
2216 PACKI(&desc,"W",0); /* num logons */
2217 PACKI(&desc,"W",0); /* bad pw count */
2218 PACKI(&desc,"D",0); /* last logon */
2219 PACKI(&desc,"D",-1); /* last logoff */
2220 PACKI(&desc,"D",-1); /* logoff time */
2221 PACKI(&desc,"D",-1); /* kickoff time */
2222 PACKI(&desc,"D",0); /* password age */
2223 PACKI(&desc,"D",0); /* password can change */
2224 PACKI(&desc,"D",-1); /* password must change */
2227 strcpy(mypath,"\\\\");
2228 strcat(mypath,local_machine);
2230 PACKS(&desc,"z",mypath); /* computer */
2232 PACKS(&desc,"z",myworkgroup);/* domain */
2233 PACKS(&desc,"z",lp_logon_script()); /* script path */
2234 PACKI(&desc,"D",0x00000000); /* reserved */
2237 *rdata_len = desc.usedlen;
2239 *rparam = REALLOC(*rparam,*rparam_len);
2240 SSVALS(*rparam,0,desc.errcode);
2242 SSVAL(*rparam,4,desc.neededlen);
2244 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
2249 /****************************************************************************
2250 api_WAccessGetUserPerms
2251 ****************************************************************************/
2252 static BOOL api_WAccessGetUserPerms(int cnum,uint16 vuid, char *param,char *data,
2253 int mdrcnt,int mprcnt,
2254 char **rdata,char **rparam,
2255 int *rdata_len,int *rparam_len)
2257 char *str1 = param+2;
2258 char *str2 = skip_string(str1,1);
2259 char *user = skip_string(str2,1);
2260 char *resource = skip_string(user,1);
2262 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
2264 /* check it's a supported varient */
2265 if (strcmp(str1,"zzh") != 0) return False;
2266 if (strcmp(str2,"") != 0) return False;
2269 *rparam = REALLOC(*rparam,*rparam_len);
2270 SSVALS(*rparam,0,0); /* errorcode */
2271 SSVAL(*rparam,2,0); /* converter word */
2272 SSVAL(*rparam,4,0x7f); /* permission flags */
2277 /****************************************************************************
2278 api_WPrintJobEnumerate
2279 ****************************************************************************/
2280 static BOOL api_WPrintJobGetInfo(int cnum,uint16 vuid, char *param,char *data,
2281 int mdrcnt,int mprcnt,
2282 char **rdata,char **rparam,
2283 int *rdata_len,int *rparam_len)
2285 char *str1 = param+2;
2286 char *str2 = skip_string(str1,1);
2287 char *p = skip_string(str2,1);
2288 int uJobId = SVAL(p,0);
2294 struct pack_desc desc;
2295 print_queue_struct *queue=NULL;
2296 print_status_struct status;
2301 bzero(&desc,sizeof(desc));
2302 bzero(&status,sizeof(status));
2304 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,uJobId));
2306 /* check it's a supported varient */
2307 if (strcmp(str1,"WWrLh") != 0) return False;
2308 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2310 snum = (unsigned int)uJobId >> 8; /*## valid serice number??*/
2311 job = uJobId & 0xFF;
2313 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2315 count = get_printqueue(snum,cnum,&queue,&status);
2316 for (i = 0; i < count; i++) {
2317 if ((queue[i].job % 0xFF) == job) break;
2319 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2321 desc.buflen = mdrcnt;
2323 if (init_package(&desc,1,0)) {
2325 fill_printjob_info(cnum,snum,uLevel,&desc,&queue[i],i);
2326 *rdata_len = desc.usedlen;
2329 desc.errcode = NERR_JobNotFound;
2335 *rparam = REALLOC(*rparam,*rparam_len);
2336 SSVALS(*rparam,0,desc.errcode);
2338 SSVAL(*rparam,4,desc.neededlen);
2340 if (queue) free(queue);
2342 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
2346 static BOOL api_WPrintJobEnumerate(int cnum,uint16 vuid, char *param,char *data,
2347 int mdrcnt,int mprcnt,
2348 char **rdata,char **rparam,
2349 int *rdata_len,int *rparam_len)
2351 char *str1 = param+2;
2352 char *str2 = skip_string(str1,1);
2353 char *p = skip_string(str2,1);
2359 struct pack_desc desc;
2360 print_queue_struct *queue=NULL;
2361 print_status_struct status;
2363 bzero(&desc,sizeof(desc));
2364 bzero(&status,sizeof(status));
2366 p = skip_string(p,1);
2370 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
2372 /* check it's a supported varient */
2373 if (strcmp(str1,"zWrLeh") != 0) return False;
2374 if (uLevel > 2) return False; /* defined only for uLevel 0,1,2 */
2375 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2377 snum = lp_servicenumber(name);
2378 if (snum < 0 && pcap_printername_ok(name,NULL)) {
2379 int pnum = lp_servicenumber(PRINTERS_NAME);
2381 lp_add_printer(name,pnum);
2382 snum = lp_servicenumber(name);
2386 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2388 count = get_printqueue(snum,cnum,&queue,&status);
2389 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2391 desc.buflen = mdrcnt;
2393 if (init_package(&desc,count,0)) {
2395 for (i = 0; i < count; i++) {
2396 fill_printjob_info(cnum,snum,uLevel,&desc,&queue[i],i);
2397 if (desc.errcode == NERR_Success) succnt = i+1;
2401 *rdata_len = desc.usedlen;
2404 *rparam = REALLOC(*rparam,*rparam_len);
2405 SSVALS(*rparam,0,desc.errcode);
2407 SSVAL(*rparam,4,succnt);
2408 SSVAL(*rparam,6,count);
2410 if (queue) free(queue);
2412 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
2416 static int check_printdest_info(struct pack_desc* desc,
2417 int uLevel, char* id)
2419 desc->subformat = NULL;
2421 case 0: desc->format = "B9"; break;
2422 case 1: desc->format = "B9B21WWzW"; break;
2423 case 2: desc->format = "z"; break;
2424 case 3: desc->format = "zzzWWzzzWW"; break;
2425 default: return False;
2427 if (strcmp(desc->format,id) != 0) return False;
2431 static void fill_printdest_info(int cnum, int snum, int uLevel,
2432 struct pack_desc* desc)
2435 strcpy(buf,SERVICE(snum));
2438 PACKS(desc,"B9",buf); /* szName */
2440 PACKS(desc,"B21",""); /* szUserName */
2441 PACKI(desc,"W",0); /* uJobId */
2442 PACKI(desc,"W",0); /* fsStatus */
2443 PACKS(desc,"z",""); /* pszStatus */
2444 PACKI(desc,"W",0); /* time */
2447 if (uLevel == 2 || uLevel == 3) {
2448 PACKS(desc,"z",buf); /* pszPrinterName */
2450 PACKS(desc,"z",""); /* pszUserName */
2451 PACKS(desc,"z",""); /* pszLogAddr */
2452 PACKI(desc,"W",0); /* uJobId */
2453 PACKI(desc,"W",0); /* fsStatus */
2454 PACKS(desc,"z",""); /* pszStatus */
2455 PACKS(desc,"z",""); /* pszComment */
2456 PACKS(desc,"z","NULL"); /* pszDrivers */
2457 PACKI(desc,"W",0); /* time */
2458 PACKI(desc,"W",0); /* pad1 */
2463 static BOOL api_WPrintDestGetInfo(int cnum,uint16 vuid, char *param,char *data,
2464 int mdrcnt,int mprcnt,
2465 char **rdata,char **rparam,
2466 int *rdata_len,int *rparam_len)
2468 char *str1 = param+2;
2469 char *str2 = skip_string(str1,1);
2470 char *p = skip_string(str2,1);
2471 char* PrinterName = p;
2473 struct pack_desc desc;
2476 bzero(&desc,sizeof(desc));
2478 p = skip_string(p,1);
2482 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
2484 /* check it's a supported varient */
2485 if (strcmp(str1,"zWrLh") != 0) return False;
2486 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2488 snum = lp_servicenumber(PrinterName);
2489 if (snum < 0 && pcap_printername_ok(PrinterName,NULL)) {
2490 int pnum = lp_servicenumber(PRINTERS_NAME);
2492 lp_add_printer(PrinterName,pnum);
2493 snum = lp_servicenumber(PrinterName);
2499 desc.errcode = NERR_DestNotFound;
2503 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2505 desc.buflen = mdrcnt;
2506 if (init_package(&desc,1,0)) {
2507 fill_printdest_info(cnum,snum,uLevel,&desc);
2509 *rdata_len = desc.usedlen;
2513 *rparam = REALLOC(*rparam,*rparam_len);
2514 SSVALS(*rparam,0,desc.errcode);
2516 SSVAL(*rparam,4,desc.neededlen);
2518 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
2522 static BOOL api_WPrintDestEnum(int cnum,uint16 vuid, char *param,char *data,
2523 int mdrcnt,int mprcnt,
2524 char **rdata,char **rparam,
2525 int *rdata_len,int *rparam_len)
2527 char *str1 = param+2;
2528 char *str2 = skip_string(str1,1);
2529 char *p = skip_string(str2,1);
2533 struct pack_desc desc;
2534 int services = lp_numservices();
2536 bzero(&desc,sizeof(desc));
2541 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
2543 /* check it's a supported varient */
2544 if (strcmp(str1,"WrLeh") != 0) return False;
2545 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2548 for (i = 0; i < services; i++)
2549 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
2552 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2554 desc.buflen = mdrcnt;
2555 if (init_package(&desc,queuecnt,0)) {
2558 for (i = 0; i < services; i++) {
2559 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
2560 fill_printdest_info(cnum,i,uLevel,&desc);
2562 if (desc.errcode == NERR_Success) succnt = n;
2567 *rdata_len = desc.usedlen;
2570 *rparam = REALLOC(*rparam,*rparam_len);
2571 SSVALS(*rparam,0,desc.errcode);
2573 SSVAL(*rparam,4,succnt);
2574 SSVAL(*rparam,6,queuecnt);
2576 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
2580 static BOOL api_WPrintDriverEnum(int cnum,uint16 vuid, char *param,char *data,
2581 int mdrcnt,int mprcnt,
2582 char **rdata,char **rparam,
2583 int *rdata_len,int *rparam_len)
2585 char *str1 = param+2;
2586 char *str2 = skip_string(str1,1);
2587 char *p = skip_string(str2,1);
2590 struct pack_desc desc;
2592 bzero(&desc,sizeof(desc));
2597 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
2599 /* check it's a supported varient */
2600 if (strcmp(str1,"WrLeh") != 0) return False;
2601 if (uLevel != 0 || strcmp(str2,"B41") != 0) return False;
2603 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2605 desc.buflen = mdrcnt;
2606 if (init_package(&desc,1,0)) {
2607 PACKS(&desc,"B41","NULL");
2610 succnt = (desc.errcode == NERR_Success ? 1 : 0);
2612 *rdata_len = desc.usedlen;
2615 *rparam = REALLOC(*rparam,*rparam_len);
2616 SSVALS(*rparam,0,desc.errcode);
2618 SSVAL(*rparam,4,succnt);
2621 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
2625 static BOOL api_WPrintQProcEnum(int cnum,uint16 vuid, char *param,char *data,
2626 int mdrcnt,int mprcnt,
2627 char **rdata,char **rparam,
2628 int *rdata_len,int *rparam_len)
2630 char *str1 = param+2;
2631 char *str2 = skip_string(str1,1);
2632 char *p = skip_string(str2,1);
2635 struct pack_desc desc;
2637 bzero(&desc,sizeof(desc));
2642 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
2644 /* check it's a supported varient */
2645 if (strcmp(str1,"WrLeh") != 0) return False;
2646 if (uLevel != 0 || strcmp(str2,"B13") != 0) return False;
2648 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2650 desc.buflen = mdrcnt;
2652 if (init_package(&desc,1,0)) {
2653 PACKS(&desc,"B13","lpd");
2656 succnt = (desc.errcode == NERR_Success ? 1 : 0);
2658 *rdata_len = desc.usedlen;
2661 *rparam = REALLOC(*rparam,*rparam_len);
2662 SSVALS(*rparam,0,desc.errcode);
2664 SSVAL(*rparam,4,succnt);
2667 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
2671 static BOOL api_WPrintPortEnum(int cnum,uint16 vuid, char *param,char *data,
2672 int mdrcnt,int mprcnt,
2673 char **rdata,char **rparam,
2674 int *rdata_len,int *rparam_len)
2676 char *str1 = param+2;
2677 char *str2 = skip_string(str1,1);
2678 char *p = skip_string(str2,1);
2681 struct pack_desc desc;
2683 bzero(&desc,sizeof(desc));
2688 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
2690 /* check it's a supported varient */
2691 if (strcmp(str1,"WrLeh") != 0) return False;
2692 if (uLevel != 0 || strcmp(str2,"B9") != 0) return False;
2694 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2695 bzero(&desc,sizeof(desc));
2697 desc.buflen = mdrcnt;
2699 if (init_package(&desc,1,0)) {
2700 PACKS(&desc,"B13","lp0");
2703 succnt = (desc.errcode == NERR_Success ? 1 : 0);
2705 *rdata_len = desc.usedlen;
2708 *rparam = REALLOC(*rparam,*rparam_len);
2709 SSVALS(*rparam,0,desc.errcode);
2711 SSVAL(*rparam,4,succnt);
2714 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
2725 } api_fd_commands [] =
2727 { "SetNmdPpHndState", "lsarpc", 1, api_LsarpcSNPHS },
2728 { "TransactNmPipe", "lsarpc", 0x26, api_LsarpcTNP },
2729 { NULL, NULL, -1, (BOOL (*)())api_Unsupported }
2732 /****************************************************************************
2733 handle remote api calls delivered to a named pipe already opened.
2734 ****************************************************************************/
2735 static int api_fd_reply(int cnum,uint16 vuid,char *outbuf,
2736 uint16 *setup,char *data,char *params,
2737 int suwcnt,int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
2740 char *rparam = NULL;
2748 /* First find out the name of this file. */
2751 DEBUG(0,("Unexpected named pipe transaction.\n"));
2755 /* Get the file handle and hence the file name. */
2757 subcommand = setup[0];
2759 DEBUG(3,("Got API command %d on pipe %s ",subcommand,Files[fd].name));
2760 DEBUG(3,("(tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
2761 tdscnt,tpscnt,mdrcnt,mprcnt));
2763 for (i=0;api_fd_commands[i].name;i++)
2764 if (strequal(api_fd_commands[i].pipename, Files[fd].name) &&
2765 api_fd_commands[i].subcommand == subcommand &&
2766 api_fd_commands[i].fn)
2768 DEBUG(3,("Doing %s\n",api_fd_commands[i].name));
2772 rdata = (char *)malloc(1024); if (rdata) bzero(rdata,1024);
2773 rparam = (char *)malloc(1024); if (rparam) bzero(rparam,1024);
2775 reply = api_fd_commands[i].fn(cnum,vuid,params,data,mdrcnt,mprcnt,
2776 &rdata,&rparam,&rdata_len,&rparam_len);
2778 if (rdata_len > mdrcnt ||
2779 rparam_len > mprcnt)
2781 reply = api_TooSmall(cnum,vuid,params,data,mdrcnt,mprcnt,
2782 &rdata,&rparam,&rdata_len,&rparam_len);
2786 /* if we get False back then it's actually unsupported */
2788 api_Unsupported(cnum,vuid,params,data,mdrcnt,mprcnt,
2789 &rdata,&rparam,&rdata_len,&rparam_len);
2791 /* now send the reply */
2792 send_trans_reply(outbuf,rdata,rparam,NULL,rdata_len,rparam_len,0);
2804 /****************************************************************************
2805 the buffer was too small
2806 ****************************************************************************/
2807 static BOOL api_TooSmall(int cnum,uint16 vuid, char *param,char *data,
2808 int mdrcnt,int mprcnt,
2809 char **rdata,char **rparam,
2810 int *rdata_len,int *rparam_len)
2812 *rparam_len = MIN(*rparam_len,mprcnt);
2813 *rparam = REALLOC(*rparam,*rparam_len);
2817 SSVAL(*rparam,0,NERR_BufTooSmall);
2819 DEBUG(3,("Supplied buffer too small in API command\n"));
2825 /****************************************************************************
2826 the request is not supported
2827 ****************************************************************************/
2828 static BOOL api_Unsupported(int cnum,uint16 vuid, char *param,char *data,
2829 int mdrcnt,int mprcnt,
2830 char **rdata,char **rparam,
2831 int *rdata_len,int *rparam_len)
2834 *rparam = REALLOC(*rparam,*rparam_len);
2838 SSVAL(*rparam,0,NERR_notsupported);
2839 SSVAL(*rparam,2,0); /* converter word */
2841 DEBUG(3,("Unsupported API command\n"));
2855 } api_commands[] = {
2856 {"RNetShareEnum", 0, (BOOL (*)())api_RNetShareEnum,0},
2857 {"RNetShareGetInfo", 1, (BOOL (*)())api_RNetShareGetInfo,0},
2858 {"RNetServerGetInfo", 13, (BOOL (*)())api_RNetServerGetInfo,0},
2859 {"RNetUserGetInfo", 56, (BOOL (*)())api_RNetUserGetInfo,0},
2860 {"NetUserGetGroups", 59, (BOOL (*)())api_NetUserGetGroups,0},
2861 {"NetWkstaGetInfo", 63, (BOOL (*)())api_NetWkstaGetInfo,0},
2862 {"DosPrintQEnum", 69, (BOOL (*)())api_DosPrintQEnum,0},
2863 {"DosPrintQGetInfo", 70, (BOOL (*)())api_DosPrintQGetInfo,0},
2864 {"WPrintJobEnumerate",76, (BOOL (*)())api_WPrintJobEnumerate,0},
2865 {"WPrintJobGetInfo", 77, (BOOL (*)())api_WPrintJobGetInfo,0},
2866 {"RDosPrintJobDel", 81, (BOOL (*)())api_RDosPrintJobDel,0},
2867 {"RDosPrintJobPause", 82, (BOOL (*)())api_RDosPrintJobDel,0},
2868 {"RDosPrintJobResume",83, (BOOL (*)())api_RDosPrintJobDel,0},
2869 {"WPrintDestEnum", 84, (BOOL (*)())api_WPrintDestEnum,0},
2870 {"WPrintDestGetInfo", 85, (BOOL (*)())api_WPrintDestGetInfo,0},
2871 {"NetRemoteTOD", 91, (BOOL (*)())api_NetRemoteTOD,0},
2872 {"WPrintQueuePurge", 103, (BOOL (*)())api_WPrintQueuePurge,0},
2873 {"NetServerEnum", 104, (BOOL (*)())api_RNetServerEnum,0},
2874 {"WAccessGetUserPerms",105, (BOOL (*)())api_WAccessGetUserPerms,0},
2875 {"SetUserPassword", 115, (BOOL (*)())api_SetUserPassword,0},
2876 {"WWkstaUserLogon", 132, (BOOL (*)())api_WWkstaUserLogon,0},
2877 {"PrintJobInfo", 147, (BOOL (*)())api_PrintJobInfo,0},
2878 {"WPrintDriverEnum", 205, (BOOL (*)())api_WPrintDriverEnum,0},
2879 {"WPrintQProcEnum", 206, (BOOL (*)())api_WPrintQProcEnum,0},
2880 {"WPrintPortEnum", 207, (BOOL (*)())api_WPrintPortEnum,0},
2881 {NULL, -1, (BOOL (*)())api_Unsupported,0}};
2884 /****************************************************************************
2885 handle remote api calls
2886 ****************************************************************************/
2887 static int api_reply(int cnum,uint16 vuid,char *outbuf,char *data,char *params,
2888 int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
2890 int api_command = SVAL(params,0);
2892 char *rparam = NULL;
2898 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
2899 api_command,params+2,skip_string(params+2,1),
2900 tdscnt,tpscnt,mdrcnt,mprcnt));
2902 for (i=0;api_commands[i].name;i++)
2903 if (api_commands[i].id == api_command && api_commands[i].fn)
2905 DEBUG(3,("Doing %s\n",api_commands[i].name));
2909 rdata = (char *)malloc(1024); if (rdata) bzero(rdata,1024);
2910 rparam = (char *)malloc(1024); if (rparam) bzero(rparam,1024);
2912 reply = api_commands[i].fn(cnum,vuid,params,data,mdrcnt,mprcnt,
2913 &rdata,&rparam,&rdata_len,&rparam_len);
2916 if (rdata_len > mdrcnt ||
2917 rparam_len > mprcnt)
2919 reply = api_TooSmall(cnum,vuid,params,data,mdrcnt,mprcnt,
2920 &rdata,&rparam,&rdata_len,&rparam_len);
2924 /* if we get False back then it's actually unsupported */
2926 api_Unsupported(cnum,vuid,params,data,mdrcnt,mprcnt,
2927 &rdata,&rparam,&rdata_len,&rparam_len);
2931 /* now send the reply */
2932 send_trans_reply(outbuf,rdata,rparam,NULL,rdata_len,rparam_len,0);
2942 /****************************************************************************
2943 handle named pipe commands
2944 ****************************************************************************/
2945 static int named_pipe(int cnum,uint16 vuid, char *outbuf,char *name,
2946 uint16 *setup,char *data,char *params,
2947 int suwcnt,int tdscnt,int tpscnt,
2948 int msrcnt,int mdrcnt,int mprcnt)
2951 if (strequal(name,"LANMAN"))
2952 return(api_reply(cnum,vuid,outbuf,data,params,tdscnt,tpscnt,mdrcnt,mprcnt));
2954 if (strlen(name) < 1)
2955 return(api_fd_reply(cnum,vuid,outbuf,setup,data,params,suwcnt,tdscnt,tpscnt,mdrcnt,mprcnt));
2958 DEBUG(3,("named pipe command on <%s> 0x%X setup1=%d\n",
2959 name,(int)setup[0],(int)setup[1]));
2965 /****************************************************************************
2967 ****************************************************************************/
2968 int reply_trans(char *inbuf,char *outbuf)
2972 char *data=NULL,*params=NULL;
2976 int cnum = SVAL(inbuf,smb_tid);
2977 uint16 vuid = SVAL(inbuf,smb_uid);
2979 int tpscnt = SVAL(inbuf,smb_vwv0);
2980 int tdscnt = SVAL(inbuf,smb_vwv1);
2981 int mprcnt = SVAL(inbuf,smb_vwv2);
2982 int mdrcnt = SVAL(inbuf,smb_vwv3);
2983 int msrcnt = CVAL(inbuf,smb_vwv4);
2984 BOOL close_on_completion = BITSETW(inbuf+smb_vwv5,0);
2985 BOOL one_way = BITSETW(inbuf+smb_vwv5,1);
2986 int pscnt = SVAL(inbuf,smb_vwv9);
2987 int psoff = SVAL(inbuf,smb_vwv10);
2988 int dscnt = SVAL(inbuf,smb_vwv11);
2989 int dsoff = SVAL(inbuf,smb_vwv12);
2990 int suwcnt = CVAL(inbuf,smb_vwv13);
2992 StrnCpy(name,smb_buf(inbuf),sizeof(name)-1);
2996 data = (char *)malloc(tdscnt);
2997 memcpy(data,smb_base(inbuf)+dsoff,dscnt);
3001 params = (char *)malloc(tpscnt);
3002 memcpy(params,smb_base(inbuf)+psoff,pscnt);
3008 setup = (uint16 *)malloc(suwcnt*sizeof(setup[0]));
3009 for (i=0;i<suwcnt;i++)
3010 setup[i] = SVAL(inbuf,smb_vwv14+i*SIZEOFWORD);
3014 if (pscnt < tpscnt || dscnt < tdscnt)
3016 /* We need to send an interim response then receive the rest
3017 of the parameter/data bytes */
3018 outsize = set_message(outbuf,0,0,True);
3020 send_smb(Client,outbuf);
3023 /* receive the rest of the trans packet */
3024 while (pscnt < tpscnt || dscnt < tdscnt)
3026 int pcnt,poff,dcnt,doff,pdisp,ddisp;
3028 if (!receive_smb(Client,inbuf, SMB_SECONDARY_WAIT) ||
3029 CVAL(inbuf, smb_com) != SMBtrans)
3031 DEBUG(2,("Invalid secondary trans2 packet\n"));
3032 if (params) free(params);
3033 if (data) free(data);
3034 if (setup) free(setup);
3035 return(ERROR(ERRSRV,ERRerror));
3040 tpscnt = SVAL(inbuf,smb_vwv0);
3041 tdscnt = SVAL(inbuf,smb_vwv1);
3043 pcnt = SVAL(inbuf,smb_vwv2);
3044 poff = SVAL(inbuf,smb_vwv3);
3045 pdisp = SVAL(inbuf,smb_vwv4);
3047 dcnt = SVAL(inbuf,smb_vwv5);
3048 doff = SVAL(inbuf,smb_vwv6);
3049 ddisp = SVAL(inbuf,smb_vwv7);
3055 memcpy(params+pdisp,smb_base(inbuf)+poff,pcnt);
3057 memcpy(data+ddisp,smb_base(inbuf)+doff,dcnt);
3061 DEBUG(3,("trans <%s> data=%d params=%d setup=%d\n",name,tdscnt,tpscnt,suwcnt));
3064 if (strncmp(name,"\\PIPE\\",strlen("\\PIPE\\")) == 0)
3065 outsize = named_pipe(cnum,vuid,outbuf,name+strlen("\\PIPE\\"),setup,data,params,
3066 suwcnt,tdscnt,tpscnt,msrcnt,mdrcnt,mprcnt);
3069 if (data) free(data);
3070 if (params) free(params);
3071 if (setup) free(setup);
3073 if (close_on_completion)
3074 close_cnum(cnum,vuid);
3080 return(ERROR(ERRSRV,ERRnosupport));