2 Unix SMB/Netbios implementation.
4 Inter-process communication and named pipe handling
5 Copyright (C) Andrew Tridgell 1992-1998
8 Copyright (C) John H Terpstra 1995-1998
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 This file handles the named pipe and mailslot calls
26 in the SMBtrans protocol
36 extern int DEBUGLEVEL;
38 extern fstring local_machine;
39 extern fstring global_myworkgroup;
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)
50 #define ACCESS_READ 0x01
51 #define ACCESS_WRITE 0x02
52 #define ACCESS_CREATE 0x04
54 #define SHPWLEN 8 /* share password length */
56 static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param,char *data,
57 int mdrcnt,int mprcnt,
58 char **rdata,char **rparam,
59 int *rdata_len,int *rparam_len);
60 static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param,char *data,
61 int mdrcnt,int mprcnt,
62 char **rdata,char **rparam,
63 int *rdata_len,int *rparam_len);
66 static int CopyExpanded(connection_struct *conn,
67 int snum, char** dst, char* src, int* n)
72 if (!src || !dst || !n || !(*dst)) return(0);
74 StrnCpy(buf,src,sizeof(buf)/2);
75 pstring_sub(buf,"%S",lp_servicename(snum));
76 standard_sub_conn(conn,buf);
84 static int CopyAndAdvance(char** dst, char* src, int* n)
87 if (!src || !dst || !n || !(*dst)) return(0);
88 StrnCpy(*dst,src,*n-1);
95 static int StrlenExpanded(connection_struct *conn, int snum, char* s)
99 StrnCpy(buf,s,sizeof(buf)/2);
100 pstring_sub(buf,"%S",lp_servicename(snum));
101 standard_sub_conn(conn,buf);
102 return strlen(buf) + 1;
105 static char* Expand(connection_struct *conn, int snum, char* s)
108 if (!s) return(NULL);
109 StrnCpy(buf,s,sizeof(buf)/2);
110 pstring_sub(buf,"%S",lp_servicename(snum));
111 standard_sub_conn(conn,buf);
115 /*******************************************************************
116 check a API string for validity when we only need to check the prefix
117 ******************************************************************/
118 static BOOL prefix_ok(char *str,char *prefix)
120 return(strncmp(str,prefix,strlen(prefix)) == 0);
124 char* format; /* formatstring for structure */
125 char* subformat; /* subformat for structure */
126 char* base; /* baseaddress of buffer */
127 int buflen; /* remaining size for fixed part; on init: length of base */
128 int subcount; /* count of substructures */
129 char* structbuf; /* pointer into buffer for remaining fixed part */
130 int stringlen; /* remaining size for variable part */
131 char* stringbuf; /* pointer into buffer for remaining variable part */
132 int neededlen; /* total needed size */
133 int usedlen; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
134 char* curpos; /* current position; pointer into format or subformat */
138 static int get_counter(char** p)
141 if (!p || !(*p)) return(1);
142 if (!isdigit((int)**p)) return 1;
146 n = 10 * n + (i - '0');
153 static int getlen(char* p)
159 case 'W': /* word (2 byte) */
162 case 'K': /* status word? (2 byte) */
165 case 'N': /* count of substructures (word) at end */
168 case 'D': /* double word (4 byte) */
169 case 'z': /* offset to zero terminated string (4 byte) */
170 case 'l': /* offset to user data (4 byte) */
173 case 'b': /* offset to data (with counter) (4 byte) */
177 case 'B': /* byte (with optional counter) */
178 n += get_counter(&p);
185 static BOOL init_package(struct pack_desc* p, int count, int subcount)
190 if (!p->format || !p->base) return(False);
192 i = count * getlen(p->format);
193 if (p->subformat) i += subcount * getlen(p->subformat);
194 p->structbuf = p->base;
198 p->curpos = p->format;
202 p->errcode = ERRmoredata;
205 p->errcode = NERR_Success;
208 p->stringbuf = p->base + i;
210 return(p->errcode == NERR_Success);
214 static int package(struct pack_desc* p, ...)
217 static int package(va_alist)
223 int needed=0, stringneeded;
225 int is_string=0, stringused;
232 p = va_arg(args,struct pack_desc *);
237 p->curpos = p->format;
239 p->curpos = p->subformat;
244 str = va_arg(args,char*);
245 SMB_ASSERT(strncmp(str,p->curpos,strlen(str)) == 0);
254 switch( *p->curpos++ ) {
255 case 'W': /* word (2 byte) */
257 temp = va_arg(args,int);
258 if (p->buflen >= needed) SSVAL(p->structbuf,0,temp);
260 case 'K': /* status word? (2 byte) */
262 temp = va_arg(args,int);
263 if (p->buflen >= needed) SSVAL(p->structbuf,0,temp);
265 case 'N': /* count of substructures (word) at end */
267 p->subcount = va_arg(args,int);
268 if (p->buflen >= needed) SSVAL(p->structbuf,0,p->subcount);
270 case 'D': /* double word (4 byte) */
272 temp = va_arg(args,int);
273 if (p->buflen >= needed) SIVAL(p->structbuf,0,temp);
275 case 'B': /* byte (with optional counter) */
276 needed = get_counter(&p->curpos);
278 char *s = va_arg(args,char*);
279 if (p->buflen >= needed) StrnCpy(p->structbuf,s?s:"",needed-1);
282 case 'z': /* offset to zero terminated string (4 byte) */
283 str = va_arg(args,char*);
284 stringneeded = (str ? strlen(str)+1 : 0);
287 case 'l': /* offset to user data (4 byte) */
288 str = va_arg(args,char*);
289 stringneeded = va_arg(args,int);
292 case 'b': /* offset to data (with counter) (4 byte) */
293 str = va_arg(args,char*);
294 stringneeded = get_counter(&p->curpos);
299 if (stringneeded >= 0) {
301 if (p->buflen >= needed) {
302 stringused = stringneeded;
303 if (stringused > p->stringlen) {
304 stringused = (is_string ? p->stringlen : 0);
305 if (p->errcode == NERR_Success) p->errcode = ERRmoredata;
308 SIVAL(p->structbuf,0,0);
310 SIVAL(p->structbuf,0,PTR_DIFF(p->stringbuf,p->base));
311 memcpy(p->stringbuf,str?str:"",stringused);
312 if (is_string) p->stringbuf[stringused-1] = '\0';
313 p->stringbuf += stringused;
314 p->stringlen -= stringused;
315 p->usedlen += stringused;
318 p->neededlen += stringneeded;
320 p->neededlen += needed;
321 if (p->buflen >= needed) {
322 p->structbuf += needed;
324 p->usedlen += needed;
327 if (p->errcode == NERR_Success) p->errcode = ERRmoredata;
333 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
334 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
336 #define PACK(desc,t,v) package(desc,v)
337 #define PACKl(desc,t,v,l) package(desc,v,l)
340 static void PACKI(struct pack_desc* desc,char *t,int v)
345 static void PACKS(struct pack_desc* desc,char *t,char *v)
351 /****************************************************************************
353 ****************************************************************************/
354 static void PackDriverData(struct pack_desc* desc)
356 char drivdata[4+4+32];
357 SIVAL(drivdata,0,sizeof drivdata); /* cb */
358 SIVAL(drivdata,4,1000); /* lVersion */
359 memset(drivdata+8,0,32); /* szDeviceName */
360 pstrcpy(drivdata+8,"NULL");
361 PACKl(desc,"l",drivdata,sizeof drivdata); /* pDriverData */
364 static int check_printq_info(struct pack_desc* desc,
365 int uLevel, char *id1, char *id2)
367 desc->subformat = NULL;
370 desc->format = "B13";
373 desc->format = "B13BWWWzzzzzWW";
376 desc->format = "B13BWWWzzzzzWN";
377 desc->subformat = "WB21BB16B10zWWzDDz";
380 desc->format = "zWWWWzzzzWWzzl";
383 desc->format = "zWWWWzzzzWNzzl";
384 desc->subformat = "WWzWWDDzz";
393 desc->format = "WzzzzzzzzN";
394 desc->subformat = "z";
396 default: return False;
398 if (strcmp(desc->format,id1) != 0) return False;
399 if (desc->subformat && strcmp(desc->subformat,id2) != 0) return False;
404 #define JOB_STATUS_QUEUED 0
405 #define JOB_STATUS_PAUSED 1
406 #define JOB_STATUS_SPOOLING 2
407 #define JOB_STATUS_PRINTING 3
408 #define JOB_STATUS_PRINTED 4
410 #define QUEUE_STATUS_PAUSED 1
411 #define QUEUE_STATUS_ERROR 2
413 /* turn a print job status into a on the wire status
415 static int printj_status(int v)
419 return JOB_STATUS_QUEUED;
421 return JOB_STATUS_PAUSED;
423 return JOB_STATUS_SPOOLING;
425 return JOB_STATUS_PRINTING;
430 /* turn a print queue status into a on the wire status
432 static int printq_status(int v)
438 return QUEUE_STATUS_PAUSED;
440 return QUEUE_STATUS_ERROR;
443 static void fill_printjob_info(connection_struct *conn, int snum, int uLevel,
444 struct pack_desc* desc,
445 print_queue_struct* queue, int n)
447 time_t t = queue->time;
449 /* the client expects localtime */
452 PACKI(desc,"W",queue->job); /* uJobId */
454 PACKS(desc,"B21",queue->user); /* szUserName */
455 PACKS(desc,"B",""); /* pad */
456 PACKS(desc,"B16",""); /* szNotifyName */
457 PACKS(desc,"B10","PM_Q_RAW"); /* szDataType */
458 PACKS(desc,"z",""); /* pszParms */
459 PACKI(desc,"W",n+1); /* uPosition */
460 PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */
461 PACKS(desc,"z",""); /* pszStatus */
462 PACKI(desc,"D",t); /* ulSubmitted */
463 PACKI(desc,"D",queue->size); /* ulSize */
464 PACKS(desc,"z",queue->file); /* pszComment */
466 if (uLevel == 2 || uLevel == 3) {
467 PACKI(desc,"W",queue->priority); /* uPriority */
468 PACKS(desc,"z",queue->user); /* pszUserName */
469 PACKI(desc,"W",n+1); /* uPosition */
470 PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */
471 PACKI(desc,"D",t); /* ulSubmitted */
472 PACKI(desc,"D",queue->size); /* ulSize */
473 PACKS(desc,"z","Samba"); /* pszComment */
474 PACKS(desc,"z",queue->file); /* pszDocument */
476 PACKS(desc,"z",""); /* pszNotifyName */
477 PACKS(desc,"z","PM_Q_RAW"); /* pszDataType */
478 PACKS(desc,"z",""); /* pszParms */
479 PACKS(desc,"z",""); /* pszStatus */
480 PACKS(desc,"z",SERVICE(snum)); /* pszQueue */
481 PACKS(desc,"z","lpd"); /* pszQProcName */
482 PACKS(desc,"z",""); /* pszQProcParms */
483 PACKS(desc,"z","NULL"); /* pszDriverName */
484 PackDriverData(desc); /* pDriverData */
485 PACKS(desc,"z",""); /* pszPrinterName */
491 static void fill_printq_info_52(connection_struct *conn, int snum, int uLevel,
492 struct pack_desc* desc,
493 int count, print_queue_struct* queue,
494 print_status_struct* status)
497 pstring tok,driver,datafile,langmon,helpfile,datatype;
501 lines = file_lines_load(lp_driverfile(),NULL);
503 DEBUG(3,("fill_printq_info: Can't open %s - %s\n",
504 lp_driverfile(),strerror(errno)));
505 desc->errcode=NERR_notsupported;
509 /* lookup the long printer driver name in the file
511 for (i=0;lines[i] && !ok;i++) {
513 if (next_token(&p,tok,":",sizeof(tok)) &&
514 (strlen(lp_printerdriver(snum)) == strlen(tok)) &&
515 (!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum)))))
520 file_lines_free(lines);
522 /* driver file name */
523 if (ok && !next_token(&p,driver,":",sizeof(driver))) ok = 0;
525 if (ok && !next_token(&p,datafile,":",sizeof(datafile))) ok = 0;
527 * for the next tokens - which may be empty - I have
528 * to check for empty tokens first because the
529 * next_token function will skip all empty token
536 } else if (!next_token(&p,helpfile,":",sizeof(helpfile))) ok = 0;
540 /* language monitor */
544 } else if (!next_token(&p,langmon,":",sizeof(langmon)))
548 /* default data type */
549 if (ok && !next_token(&p,datatype,":",sizeof(datatype)))
553 PACKI(desc,"W",0x0400); /* don't know */
554 PACKS(desc,"z",lp_printerdriver(snum)); /* long printer name */
555 PACKS(desc,"z",driver); /* Driverfile Name */
556 PACKS(desc,"z",datafile); /* Datafile name */
557 PACKS(desc,"z",langmon); /* language monitor */
558 PACKS(desc,"z",lp_driverlocation(snum)); /* share to retrieve files */
559 PACKS(desc,"z",datatype); /* default data type */
560 PACKS(desc,"z",helpfile); /* helpfile name */
561 PACKS(desc,"z",driver); /* driver name */
562 DEBUG(3,("Driver:%s:\n",driver));
563 DEBUG(3,("Data File:%s:\n",datafile));
564 DEBUG(3,("Language Monitor:%s:\n",langmon));
565 DEBUG(3,("Data Type:%s:\n",datatype));
566 DEBUG(3,("Help File:%s:\n",helpfile));
567 PACKI(desc,"N",count); /* number of files to copy */
568 for (i=0;i<count;i++) {
569 /* no need to check return value here
570 * - it was already tested in
571 * get_printerdrivernumber */
572 next_token(&p,tok,",",sizeof(tok));
573 PACKS(desc,"z",tok); /* driver files to copy */
574 DEBUG(3,("file:%s:\n",tok));
577 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n",
578 SERVICE(snum),count));
580 DEBUG(3,("fill_printq_info: Can't supply driver files\n"));
581 desc->errcode=NERR_notsupported;
587 static void fill_printq_info(connection_struct *conn, int snum, int uLevel,
588 struct pack_desc* desc,
589 int count, print_queue_struct* queue,
590 print_status_struct* status)
595 PACKS(desc,"B13",SERVICE(snum));
600 PACKS(desc,"z",Expand(conn,snum,SERVICE(snum)));
603 PACKI(desc,"K",printq_status(status->status));
607 if (uLevel == 1 || uLevel == 2) {
608 PACKS(desc,"B",""); /* alignment */
609 PACKI(desc,"W",5); /* priority */
610 PACKI(desc,"W",0); /* start time */
611 PACKI(desc,"W",0); /* until time */
612 PACKS(desc,"z",""); /* pSepFile */
613 PACKS(desc,"z","lpd"); /* pPrProc */
614 PACKS(desc,"z",SERVICE(snum)); /* pDestinations */
615 PACKS(desc,"z",""); /* pParms */
617 PACKS(desc,"z","UNKNOWN PRINTER");
618 PACKI(desc,"W",LPSTAT_ERROR);
620 else if (!status || !status->message[0]) {
621 PACKS(desc,"z",Expand(conn,snum,lp_comment(snum)));
622 PACKI(desc,"W",LPSTAT_OK); /* status */
624 PACKS(desc,"z",status->message);
625 PACKI(desc,"W",printq_status(status->status)); /* status */
627 PACKI(desc,(uLevel == 1 ? "W" : "N"),count);
630 if (uLevel == 3 || uLevel == 4) {
631 PACKI(desc,"W",5); /* uPriority */
632 PACKI(desc,"W",0); /* uStarttime */
633 PACKI(desc,"W",0); /* uUntiltime */
634 PACKI(desc,"W",5); /* pad1 */
635 PACKS(desc,"z",""); /* pszSepFile */
636 PACKS(desc,"z","WinPrint"); /* pszPrProc */
637 PACKS(desc,"z",""); /* pszParms */
638 if (!status || !status->message[0]) {
639 PACKS(desc,"z",Expand(conn,snum,lp_comment(snum))); /* pszComment */
640 PACKI(desc,"W",LPSTAT_OK); /* fsStatus */
642 PACKS(desc,"z",status->message); /* pszComment */
643 PACKI(desc,"W",printq_status(status->status)); /* fsStatus */
645 PACKI(desc,(uLevel == 3 ? "W" : "N"),count); /* cJobs */
646 PACKS(desc,"z",SERVICE(snum)); /* pszPrinters */
647 PACKS(desc,"z",lp_printerdriver(snum)); /* pszDriverName */
648 PackDriverData(desc); /* pDriverData */
651 if (uLevel == 2 || uLevel == 4) {
653 for (i=0;i<count;i++)
654 fill_printjob_info(conn,snum,uLevel == 2 ? 1 : 2,desc,&queue[i],i);
658 fill_printq_info_52(conn, snum, uLevel, desc, count, queue, status);
662 /* This function returns the number of files for a given driver */
663 static int get_printerdrivernumber(int snum)
670 lines = file_lines_load(lp_driverfile(), NULL);
672 DEBUG(3,("get_printerdrivernumber: Can't open %s - %s\n",
673 lp_driverfile(),strerror(errno)));
677 /* lookup the long printer driver name in the file description */
678 for (i=0;lines[i] && !ok; i++) {
680 if (next_token(&p,tok,":",sizeof(tok)) &&
681 (!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum)))))
686 file_lines_free(lines);
692 if (*p++ == ':') i--;
697 /* count the number of files */
698 while (next_token(&p,tok,",",sizeof(tok)))
706 static BOOL api_DosPrintQGetInfo(connection_struct *conn,
707 uint16 vuid, char *param,char *data,
708 int mdrcnt,int mprcnt,
709 char **rdata,char **rparam,
710 int *rdata_len,int *rparam_len)
712 char *str1 = param+2;
713 char *str2 = skip_string(str1,1);
714 char *p = skip_string(str2,1);
720 struct pack_desc desc;
721 print_queue_struct *queue=NULL;
722 print_status_struct status;
724 memset((char *)&status,'\0',sizeof(status));
725 memset((char *)&desc,'\0',sizeof(desc));
727 p = skip_string(p,1);
731 /* remove any trailing username */
732 if ((p = strchr(QueueName,'%'))) *p = 0;
734 DEBUG(3,("PrintQueue uLevel=%d name=%s\n",uLevel,QueueName));
736 /* check it's a supported varient */
737 if (!prefix_ok(str1,"zWrLh")) return False;
738 if (!check_printq_info(&desc,uLevel,str2,str3)) {
740 * Patch from Scott Moomaw <scott@bridgewater.edu>
741 * to return the 'invalid info level' error if an
742 * unknown level was requested.
746 *rparam = REALLOC(*rparam,*rparam_len);
747 SSVALS(*rparam,0,ERROR_INVALID_LEVEL);
753 snum = lp_servicenumber(QueueName);
754 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
755 int pnum = lp_servicenumber(PRINTERS_NAME);
757 lp_add_printer(QueueName,pnum);
758 snum = lp_servicenumber(QueueName);
762 if (snum < 0 || !VALID_SNUM(snum)) return(False);
765 count = get_printerdrivernumber(snum);
766 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count));
768 count = print_queue_status(snum, &queue,&status);
771 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
773 desc.buflen = mdrcnt;
774 if (init_package(&desc,1,count)) {
775 desc.subcount = count;
776 fill_printq_info(conn,snum,uLevel,&desc,count,queue,&status);
777 } else if(uLevel == 0) {
779 * This is a *disgusting* hack.
780 * This is *so* bad that even I'm embarrassed (and I
781 * have no shame). Here's the deal :
782 * Until we get the correct SPOOLSS code into smbd
783 * then when we're running with NT SMB support then
784 * NT makes this call with a level of zero, and then
785 * immediately follows it with an open request to
786 * the \\SRVSVC pipe. If we allow that open to
787 * succeed then NT barfs when it cannot open the
788 * \\SPOOLSS pipe immediately after and continually
789 * whines saying "Printer name is invalid" forever
790 * after. If we cause *JUST THIS NEXT OPEN* of \\SRVSVC
791 * to fail, then NT downgrades to using the downlevel code
792 * and everything works as well as before. I hate
793 * myself for adding this code.... JRA.
796 fail_next_srvsvc_open();
799 *rdata_len = desc.usedlen;
802 *rparam = REALLOC(*rparam,*rparam_len);
803 SSVALS(*rparam,0,desc.errcode);
805 SSVAL(*rparam,4,desc.neededlen);
807 DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode));
809 if (queue) free(queue);
815 /****************************************************************************
816 view list of all print jobs on all queues
817 ****************************************************************************/
818 static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid, char* param, char* data,
819 int mdrcnt, int mprcnt,
820 char **rdata, char** rparam,
821 int *rdata_len, int *rparam_len)
823 char *param_format = param+2;
824 char *output_format1 = skip_string(param_format,1);
825 char *p = skip_string(output_format1,1);
826 int uLevel = SVAL(p,0);
827 char *output_format2 = p + 4;
828 int services = lp_numservices();
830 struct pack_desc desc;
831 print_queue_struct **queue = NULL;
832 print_status_struct *status = NULL;
833 int* subcntarr = NULL;
834 int queuecnt, subcnt=0, succnt=0;
836 memset((char *)&desc,'\0',sizeof(desc));
838 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
840 if (!prefix_ok(param_format,"WrLeh")) return False;
841 if (!check_printq_info(&desc,uLevel,output_format1,output_format2)) {
843 * Patch from Scott Moomaw <scott@bridgewater.edu>
844 * to return the 'invalid info level' error if an
845 * unknown level was requested.
849 *rparam = REALLOC(*rparam,*rparam_len);
850 SSVALS(*rparam,0,ERROR_INVALID_LEVEL);
857 for (i = 0; i < services; i++)
858 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
861 if((queue = (print_queue_struct**)malloc(queuecnt*sizeof(print_queue_struct*))) == NULL) {
862 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
865 memset(queue,0,queuecnt*sizeof(print_queue_struct*));
866 if((status = (print_status_struct*)malloc(queuecnt*sizeof(print_status_struct))) == NULL) {
867 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
870 memset(status,0,queuecnt*sizeof(print_status_struct));
871 if((subcntarr = (int*)malloc(queuecnt*sizeof(int))) == NULL) {
872 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
877 for (i = 0; i < services; i++)
878 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
879 subcntarr[n] = print_queue_status(i, &queue[n],&status[n]);
880 subcnt += subcntarr[n];
884 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
886 desc.buflen = mdrcnt;
888 if (init_package(&desc,queuecnt,subcnt)) {
891 for (i = 0; i < services; i++)
892 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
893 fill_printq_info(conn,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]);
895 if (desc.errcode == NERR_Success) succnt = n;
899 if (subcntarr) free(subcntarr);
901 *rdata_len = desc.usedlen;
903 *rparam = REALLOC(*rparam,*rparam_len);
904 SSVALS(*rparam,0,desc.errcode);
906 SSVAL(*rparam,4,succnt);
907 SSVAL(*rparam,6,queuecnt);
909 for (i = 0; i < queuecnt; i++) {
910 if (queue && queue[i]) free(queue[i]);
913 if (queue) free(queue);
914 if (status) free(status);
919 /****************************************************************************
920 get info level for a server list query
921 ****************************************************************************/
922 static BOOL check_server_info(int uLevel, char* id)
926 if (strcmp(id,"B16") != 0) return False;
929 if (strcmp(id,"B16BBDz") != 0) return False;
937 struct srv_info_struct
947 /*******************************************************************
948 get server info lists from the files saved by nmbd. Return the
950 ******************************************************************/
951 static int get_server_info(uint32 servertype,
952 struct srv_info_struct **servers,
958 BOOL local_list_only;
961 lines = file_lines_load(lock_path(SERVER_LIST), NULL);
963 DEBUG(4,("Can't open %s - %s\n",lock_path(SERVER_LIST),strerror(errno)));
967 /* request for everything is code for request all servers */
968 if (servertype == SV_TYPE_ALL)
969 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
971 local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY);
973 DEBUG(4,("Servertype search: %8x\n",servertype));
975 for (i=0;lines[i];i++) {
977 struct srv_info_struct *s;
978 char *ptr = lines[i];
983 if (count == alloced) {
985 (*servers) = (struct srv_info_struct *)
986 Realloc(*servers,sizeof(**servers)*alloced);
987 if (!(*servers)) return(0);
988 memset((char *)((*servers)+count),'\0',sizeof(**servers)*(alloced-count));
990 s = &(*servers)[count];
992 if (!next_token(&ptr,s->name , NULL, sizeof(s->name))) continue;
993 if (!next_token(&ptr,stype , NULL, sizeof(stype))) continue;
994 if (!next_token(&ptr,s->comment, NULL, sizeof(s->comment))) continue;
995 if (!next_token(&ptr,s->domain , NULL, sizeof(s->domain))) {
996 /* this allows us to cope with an old nmbd */
997 pstrcpy(s->domain,global_myworkgroup);
1000 if (sscanf(stype,"%X",&s->type) != 1) {
1001 DEBUG(4,("r:host file "));
1005 /* Filter the servers/domains we return based on what was asked for. */
1007 /* Check to see if we are being asked for a local list only. */
1008 if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) {
1009 DEBUG(4,("r: local list only"));
1013 /* doesn't match up: don't want it */
1014 if (!(servertype & s->type)) {
1015 DEBUG(4,("r:serv type "));
1019 if ((servertype & SV_TYPE_DOMAIN_ENUM) !=
1020 (s->type & SV_TYPE_DOMAIN_ENUM))
1022 DEBUG(4,("s: dom mismatch "));
1026 if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM))
1031 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1032 s->type &= ~SV_TYPE_LOCAL_LIST_ONLY;
1036 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1037 s->name, s->type, s->comment, s->domain));
1039 s->server_added = True;
1044 DEBUG(4,("%20s %8x %25s %15s\n",
1045 s->name, s->type, s->comment, s->domain));
1049 file_lines_free(lines);
1054 /*******************************************************************
1055 fill in a server info structure
1056 ******************************************************************/
1057 static int fill_srv_info(struct srv_info_struct *service,
1058 int uLevel, char **buf, int *buflen,
1059 char **stringbuf, int *stringspace, char *baseaddr)
1068 case 0: struct_len = 16; break;
1069 case 1: struct_len = 26; break;
1079 len = strlen(service->comment)+1;
1083 if (buflen) *buflen = struct_len;
1084 if (stringspace) *stringspace = len;
1085 return struct_len + len;
1090 if (*buflen < struct_len) return -1;
1098 p2 = p + struct_len;
1099 l2 = *buflen - struct_len;
1101 if (!baseaddr) baseaddr = p;
1106 StrnCpy(p,service->name,15);
1110 StrnCpy(p,service->name,15);
1111 SIVAL(p,18,service->type);
1112 SIVAL(p,22,PTR_DIFF(p2,baseaddr));
1113 len += CopyAndAdvance(&p2,service->comment,&l2);
1119 *buf = p + struct_len;
1120 *buflen -= struct_len;
1133 static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
1135 return(strcmp(s1->name,s2->name));
1138 /****************************************************************************
1139 view list of servers available (or possibly domains). The info is
1140 extracted from lists saved by nmbd on the local host
1141 ****************************************************************************/
1142 static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid, char *param, char *data,
1143 int mdrcnt, int mprcnt, char **rdata,
1144 char **rparam, int *rdata_len, int *rparam_len)
1146 char *str1 = param+2;
1147 char *str2 = skip_string(str1,1);
1148 char *p = skip_string(str2,1);
1149 int uLevel = SVAL(p,0);
1150 int buf_len = SVAL(p,2);
1151 uint32 servertype = IVAL(p,4);
1153 int data_len, fixed_len, string_len;
1154 int f_len = 0, s_len = 0;
1155 struct srv_info_struct *servers=NULL;
1156 int counted=0,total=0;
1159 BOOL domain_request;
1162 /* If someone sets all the bits they don't really mean to set
1163 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1166 if (servertype == SV_TYPE_ALL)
1167 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1169 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1170 any other bit (they may just set this bit on it's own) they
1171 want all the locally seen servers. However this bit can be
1172 set on its own so set the requested servers to be
1173 ALL - DOMAIN_ENUM. */
1175 if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM))
1176 servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
1178 domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
1179 local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
1183 if (!prefix_ok(str1,"WrLehD")) return False;
1184 if (!check_server_info(uLevel,str2)) return False;
1186 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1187 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1188 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1190 if (strcmp(str1, "WrLehDz") == 0) {
1191 StrnCpy(domain, p, sizeof(fstring)-1);
1193 StrnCpy(domain, global_myworkgroup, sizeof(fstring)-1);
1196 if (lp_browse_list())
1197 total = get_server_info(servertype,&servers,domain);
1199 data_len = fixed_len = string_len = 0;
1202 qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
1205 char *lastname=NULL;
1207 for (i=0;i<total;i++)
1209 struct srv_info_struct *s = &servers[i];
1210 if (lastname && strequal(lastname,s->name)) continue;
1212 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1213 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1214 s->name, s->type, s->comment, s->domain));
1216 if (data_len <= buf_len) {
1219 string_len += s_len;
1226 *rdata_len = fixed_len + string_len;
1227 *rdata = REALLOC(*rdata,*rdata_len);
1228 memset(*rdata,'\0',*rdata_len);
1230 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1236 char *lastname=NULL;
1237 int count2 = counted;
1238 for (i = 0; i < total && count2;i++)
1240 struct srv_info_struct *s = &servers[i];
1241 if (lastname && strequal(lastname,s->name)) continue;
1243 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1244 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1245 s->name, s->type, s->comment, s->domain));
1251 *rparam = REALLOC(*rparam,*rparam_len);
1252 SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata));
1254 SSVAL(*rparam,4,counted);
1255 SSVAL(*rparam,6,counted+missed);
1257 if (servers) free(servers);
1259 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1260 domain,uLevel,counted,counted+missed));
1265 /****************************************************************************
1266 command 0x34 - suspected of being a "Lookup Names" stub api
1267 ****************************************************************************/
1268 static BOOL api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid, char *param, char *data,
1269 int mdrcnt, int mprcnt, char **rdata,
1270 char **rparam, int *rdata_len, int *rparam_len)
1272 char *str1 = param+2;
1273 char *str2 = skip_string(str1,1);
1274 char *p = skip_string(str2,1);
1275 int uLevel = SVAL(p,0);
1276 int buf_len = SVAL(p,2);
1280 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1281 str1, str2, p, uLevel, buf_len));
1283 if (!prefix_ok(str1,"zWrLeh")) return False;
1288 *rparam = REALLOC(*rparam,*rparam_len);
1290 SSVAL(*rparam,0,0x08AC); /* informational warning message */
1292 SSVAL(*rparam,4,counted);
1293 SSVAL(*rparam,6,counted+missed);
1298 /****************************************************************************
1299 get info about a share
1300 ****************************************************************************/
1301 static BOOL check_share_info(int uLevel, char* id)
1305 if (strcmp(id,"B13") != 0) return False;
1308 if (strcmp(id,"B13BWz") != 0) return False;
1311 if (strcmp(id,"B13BWzWWWzB9B") != 0) return False;
1314 if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) return False;
1316 default: return False;
1321 static int fill_share_info(connection_struct *conn, int snum, int uLevel,
1322 char** buf, int* buflen,
1323 char** stringbuf, int* stringspace, char* baseaddr)
1332 case 0: struct_len = 13; break;
1333 case 1: struct_len = 20; break;
1334 case 2: struct_len = 40; break;
1335 case 91: struct_len = 68; break;
1343 if (uLevel > 0) len += StrlenExpanded(conn,snum,lp_comment(snum));
1344 if (uLevel > 1) len += strlen(lp_pathname(snum)) + 1;
1345 if (buflen) *buflen = struct_len;
1346 if (stringspace) *stringspace = len;
1347 return struct_len + len;
1352 if ((*buflen) < struct_len) return -1;
1360 p2 = p + struct_len;
1361 l2 = (*buflen) - struct_len;
1363 if (!baseaddr) baseaddr = p;
1365 StrnCpy(p,lp_servicename(snum),13);
1371 type = STYPE_DISKTREE;
1372 if (lp_print_ok(snum)) type = STYPE_PRINTQ;
1373 if (strequal("IPC$",lp_servicename(snum))) type = STYPE_IPC;
1374 SSVAL(p,14,type); /* device type */
1375 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1376 len += CopyExpanded(conn,snum,&p2,lp_comment(snum),&l2);
1381 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1382 SSVALS(p,22,-1); /* max uses */
1383 SSVAL(p,24,1); /* current uses */
1384 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1385 len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1386 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1391 memset(p+40,0,SHPWLEN+2);
1403 (*buf) = p + struct_len;
1404 (*buflen) -= struct_len;
1406 (*stringspace) = l2;
1416 static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
1417 int mdrcnt,int mprcnt,
1418 char **rdata,char **rparam,
1419 int *rdata_len,int *rparam_len)
1421 char *str1 = param+2;
1422 char *str2 = skip_string(str1,1);
1423 char *netname = skip_string(str2,1);
1424 char *p = skip_string(netname,1);
1425 int uLevel = SVAL(p,0);
1426 int snum = find_service(netname);
1428 if (snum < 0) return False;
1430 /* check it's a supported varient */
1431 if (!prefix_ok(str1,"zWrLh")) return False;
1432 if (!check_share_info(uLevel,str2)) return False;
1434 *rdata = REALLOC(*rdata,mdrcnt);
1436 *rdata_len = fill_share_info(conn,snum,uLevel,&p,&mdrcnt,0,0,0);
1437 if (*rdata_len < 0) return False;
1440 *rparam = REALLOC(*rparam,*rparam_len);
1441 SSVAL(*rparam,0,NERR_Success);
1442 SSVAL(*rparam,2,0); /* converter word */
1443 SSVAL(*rparam,4,*rdata_len);
1448 /****************************************************************************
1449 view list of shares available
1450 ****************************************************************************/
1451 static BOOL api_RNetShareEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
1452 int mdrcnt,int mprcnt,
1453 char **rdata,char **rparam,
1454 int *rdata_len,int *rparam_len)
1456 char *str1 = param+2;
1457 char *str2 = skip_string(str1,1);
1458 char *p = skip_string(str2,1);
1459 int uLevel = SVAL(p,0);
1460 int buf_len = SVAL(p,2);
1462 int count=lp_numservices();
1463 int total=0,counted=0;
1464 BOOL missed = False;
1466 int data_len, fixed_len, string_len;
1467 int f_len = 0, s_len = 0;
1469 if (!prefix_ok(str1,"WrLeh")) return False;
1470 if (!check_share_info(uLevel,str2)) return False;
1472 data_len = fixed_len = string_len = 0;
1473 for (i=0;i<count;i++)
1474 if (lp_browseable(i) && lp_snum_ok(i))
1477 data_len += fill_share_info(conn,i,uLevel,0,&f_len,0,&s_len,0);
1478 if (data_len <= buf_len)
1482 string_len += s_len;
1487 *rdata_len = fixed_len + string_len;
1488 *rdata = REALLOC(*rdata,*rdata_len);
1489 memset(*rdata,0,*rdata_len);
1491 p2 = (*rdata) + fixed_len; /* auxillery data (strings) will go here */
1495 for (i = 0; i < count;i++)
1496 if (lp_browseable(i) && lp_snum_ok(i))
1497 if (fill_share_info(conn,i,uLevel,&p,&f_len,&p2,&s_len,*rdata) < 0)
1501 *rparam = REALLOC(*rparam,*rparam_len);
1502 SSVAL(*rparam,0,missed ? ERRmoredata : NERR_Success);
1504 SSVAL(*rparam,4,counted);
1505 SSVAL(*rparam,6,total);
1507 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1508 counted,total,uLevel,
1509 buf_len,*rdata_len,mdrcnt));
1515 /****************************************************************************
1516 get the time of day info
1517 ****************************************************************************/
1518 static BOOL api_NetRemoteTOD(connection_struct *conn,uint16 vuid, char *param,char *data,
1519 int mdrcnt,int mprcnt,
1520 char **rdata,char **rparam,
1521 int *rdata_len,int *rparam_len)
1525 *rparam = REALLOC(*rparam,*rparam_len);
1528 *rdata = REALLOC(*rdata,*rdata_len);
1530 SSVAL(*rparam,0,NERR_Success);
1531 SSVAL(*rparam,2,0); /* converter word */
1537 time_t unixdate = time(NULL);
1539 put_dos_date3(p,0,unixdate); /* this is the time that is looked at
1540 by NT in a "net time" operation,
1541 it seems to ignore the one below */
1543 /* the client expects to get localtime, not GMT, in this bit
1544 (I think, this needs testing) */
1545 t = LocalTime(&unixdate);
1547 SIVAL(p,4,0); /* msecs ? */
1548 CVAL(p,8) = t->tm_hour;
1549 CVAL(p,9) = t->tm_min;
1550 CVAL(p,10) = t->tm_sec;
1551 CVAL(p,11) = 0; /* hundredths of seconds */
1552 SSVALS(p,12,TimeDiff(unixdate)/60); /* timezone in minutes from GMT */
1553 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
1554 CVAL(p,16) = t->tm_mday;
1555 CVAL(p,17) = t->tm_mon + 1;
1556 SSVAL(p,18,1900+t->tm_year);
1557 CVAL(p,20) = t->tm_wday;
1564 /****************************************************************************
1565 Set the user password.
1566 *****************************************************************************/
1568 static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param,char *data,
1569 int mdrcnt,int mprcnt,
1570 char **rdata,char **rparam,
1571 int *rdata_len,int *rparam_len)
1573 char *p = skip_string(param+2,2);
1575 fstring pass1,pass2;
1579 p = skip_string(p,1);
1581 memset(pass1,'\0',sizeof(pass1));
1582 memset(pass2,'\0',sizeof(pass2));
1584 memcpy(pass2,p+16,16);
1587 *rparam = REALLOC(*rparam,*rparam_len);
1591 SSVAL(*rparam,0,NERR_badpass);
1592 SSVAL(*rparam,2,0); /* converter word */
1594 DEBUG(3,("Set password for <%s>\n",user));
1597 * Pass the user through the NT -> unix user mapping
1601 (void)map_username(user);
1604 * Do any UNIX username case mangling.
1606 (void)Get_Pwnam( user, True);
1609 * Attempt to verify the old password against smbpasswd entries
1610 * Win98 clients send old and new password in plaintext for this call.
1614 fstring saved_pass2;
1615 struct smb_passwd *smbpw = NULL;
1618 * Save the new password as change_oem_password overwrites it
1622 fstrcpy(saved_pass2, pass2);
1624 if (check_plaintext_password(user,pass1,strlen(pass1),&smbpw) &&
1625 change_oem_password(smbpw,pass2,False))
1627 SSVAL(*rparam,0,NERR_Success);
1630 * If unix password sync was requested, attempt to change
1631 * the /etc/passwd database also. Return failure if this cannot
1635 if(lp_unix_password_sync() && !chgpasswd(user,pass1,saved_pass2,False))
1636 SSVAL(*rparam,0,NERR_badpass);
1641 * If the above failed, attempt the plaintext password change.
1642 * This tests against the /etc/passwd database only.
1645 if(SVAL(*rparam,0) != NERR_Success)
1647 if (password_ok(user, pass1,strlen(pass1),NULL) &&
1648 chgpasswd(user,pass1,pass2,False))
1650 SSVAL(*rparam,0,NERR_Success);
1655 * If the plaintext change failed, attempt
1656 * the old encrypted method. NT will generate this
1657 * after trying the samr method. Note that this
1658 * method is done as a last resort as this
1659 * password change method loses the NT password hash
1660 * and cannot change the UNIX password as no plaintext
1664 if(SVAL(*rparam,0) != NERR_Success)
1666 struct smb_passwd *sampw = NULL;
1668 if(check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &sampw) &&
1669 change_lanman_password(sampw,(unsigned char *)pass1,(unsigned char *)pass2))
1671 SSVAL(*rparam,0,NERR_Success);
1675 memset((char *)pass1,'\0',sizeof(fstring));
1676 memset((char *)pass2,'\0',sizeof(fstring));
1681 /****************************************************************************
1682 Set the user password (SamOEM version - gets plaintext).
1683 ****************************************************************************/
1685 static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char *param,char *data,
1686 int mdrcnt,int mprcnt,
1687 char **rdata,char **rparam,
1688 int *rdata_len,int *rparam_len)
1691 char *p = param + 2;
1693 *rparam = REALLOC(*rparam,*rparam_len);
1697 SSVAL(*rparam,0,NERR_badpass);
1700 * Check the parameter definition is correct.
1702 if(!strequal(param + 2, "zsT")) {
1703 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", param + 2));
1706 p = skip_string(p, 1);
1708 if(!strequal(p, "B516B16")) {
1709 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p));
1712 p = skip_string(p,1);
1715 p = skip_string(p,1);
1717 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user));
1720 * Pass the user through the NT -> unix user mapping
1724 (void)map_username(user);
1727 * Do any UNIX username case mangling.
1729 (void)Get_Pwnam( user, True);
1731 if (pass_oem_change(user, (uchar*) data, (uchar *)&data[516], NULL, NULL))
1733 SSVAL(*rparam,0,NERR_Success);
1739 /****************************************************************************
1742 ****************************************************************************/
1743 static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char *param,char *data,
1744 int mdrcnt,int mprcnt,
1745 char **rdata,char **rparam,
1746 int *rdata_len,int *rparam_len)
1748 int function = SVAL(param,0);
1749 char *str1 = param+2;
1750 char *str2 = skip_string(str1,1);
1751 char *p = skip_string(str2,1);
1756 /* check it's a supported varient */
1757 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
1761 *rparam = REALLOC(*rparam,*rparam_len);
1764 if (!print_job_exists(jobid)) {
1765 errcode = NERR_JobNotFound;
1769 errcode = NERR_notsupported;
1772 case 81: /* delete */
1773 if (print_job_delete(jobid)) errcode = NERR_Success;
1775 case 82: /* pause */
1776 if (print_job_pause(jobid)) errcode = NERR_Success;
1778 case 83: /* resume */
1779 if (print_job_resume(jobid)) errcode = NERR_Success;
1784 SSVAL(*rparam,0,errcode);
1785 SSVAL(*rparam,2,0); /* converter word */
1790 /****************************************************************************
1791 Purge a print queue - or pause or resume it.
1792 ****************************************************************************/
1793 static BOOL api_WPrintQueuePurge(connection_struct *conn,uint16 vuid, char *param,char *data,
1794 int mdrcnt,int mprcnt,
1795 char **rdata,char **rparam,
1796 int *rdata_len,int *rparam_len)
1798 int function = SVAL(param,0);
1799 char *str1 = param+2;
1800 char *str2 = skip_string(str1,1);
1801 char *QueueName = skip_string(str2,1);
1802 int errcode = NERR_notsupported;
1805 /* check it's a supported varient */
1806 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
1810 *rparam = REALLOC(*rparam,*rparam_len);
1813 snum = print_queue_snum(QueueName);
1816 errcode = NERR_JobNotFound;
1821 case 74: /* Pause queue */
1822 if (print_queue_pause(snum)) errcode = NERR_Success;
1824 case 75: /* Resume queue */
1825 if (print_queue_resume(snum)) errcode = NERR_Success;
1827 case 103: /* Purge */
1828 if (print_queue_purge(snum)) errcode = NERR_Success;
1833 SSVAL(*rparam,0,errcode);
1834 SSVAL(*rparam,2,0); /* converter word */
1840 /****************************************************************************
1841 set the property of a print job (undocumented?)
1842 ? function = 0xb -> set name of print job
1843 ? function = 0x6 -> move print job up/down
1844 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
1845 or <WWsTP> <WB21BB16B10zWWzDDz>
1846 ****************************************************************************/
1847 static int check_printjob_info(struct pack_desc* desc,
1848 int uLevel, char* id)
1850 desc->subformat = NULL;
1852 case 0: desc->format = "W"; break;
1853 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
1854 case 2: desc->format = "WWzWWDDzz"; break;
1855 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
1856 default: return False;
1858 if (strcmp(desc->format,id) != 0) return False;
1862 static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,char *data,
1863 int mdrcnt,int mprcnt,
1864 char **rdata,char **rparam,
1865 int *rdata_len,int *rparam_len)
1867 struct pack_desc desc;
1868 char *str1 = param+2;
1869 char *str2 = skip_string(str1,1);
1870 char *p = skip_string(str2,1);
1872 int uLevel = SVAL(p,2);
1873 int function = SVAL(p,4);
1878 *rparam = REALLOC(*rparam,*rparam_len);
1882 /* check it's a supported varient */
1883 if ((strcmp(str1,"WWsTP")) ||
1884 (!check_printjob_info(&desc,uLevel,str2)))
1887 if (!print_job_exists(jobid)) {
1888 errcode=NERR_JobNotFound;
1892 errcode = NERR_notsupported;
1896 /* change job place in the queue,
1897 data gives the new place */
1898 place = SVAL(data,0);
1899 if (print_job_set_place(jobid, place)) {
1900 errcode=NERR_Success;
1905 /* change print job name, data gives the name */
1906 if (print_job_set_name(jobid, data)) {
1907 errcode=NERR_Success;
1916 SSVALS(*rparam,0,errcode);
1917 SSVAL(*rparam,2,0); /* converter word */
1923 /****************************************************************************
1924 get info about the server
1925 ****************************************************************************/
1926 static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
1927 int mdrcnt,int mprcnt,
1928 char **rdata,char **rparam,
1929 int *rdata_len,int *rparam_len)
1931 char *str1 = param+2;
1932 char *str2 = skip_string(str1,1);
1933 char *p = skip_string(str2,1);
1934 int uLevel = SVAL(p,0);
1938 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
1940 /* check it's a supported varient */
1941 if (!prefix_ok(str1,"WrLh")) return False;
1944 if (strcmp(str2,"B16") != 0) return False;
1948 if (strcmp(str2,"B16BBDz") != 0) return False;
1952 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")
1957 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz")
1962 if (strcmp(str2,"DN") != 0) return False;
1966 if (strcmp(str2,"B16BBDzWWzzz") != 0) return False;
1969 default: return False;
1972 *rdata_len = mdrcnt;
1973 *rdata = REALLOC(*rdata,*rdata_len);
1976 p2 = p + struct_len;
1978 StrnCpy(p,local_machine,16);
1984 struct srv_info_struct *servers=NULL;
1987 uint32 servertype= lp_default_server_announce();
1989 pstrcpy(comment,string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH));
1991 if ((count=get_server_info(SV_TYPE_ALL,&servers,global_myworkgroup))>0) {
1992 for (i=0;i<count;i++)
1993 if (strequal(servers[i].name,local_machine))
1995 servertype = servers[i].type;
1996 pstrcpy(comment,servers[i].comment);
1999 if (servers) free(servers);
2001 SCVAL(p,0,lp_major_announce_version());
2002 SCVAL(p,1,lp_minor_announce_version());
2003 SIVAL(p,2,servertype);
2005 if (mdrcnt == struct_len) {
2008 SIVAL(p,6,PTR_DIFF(p2,*rdata));
2009 standard_sub_conn(conn,comment);
2010 StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
2011 p2 = skip_string(p2,1);
2016 return False; /* not yet implemented */
2019 *rdata_len = PTR_DIFF(p2,*rdata);
2022 *rparam = REALLOC(*rparam,*rparam_len);
2023 SSVAL(*rparam,0,NERR_Success);
2024 SSVAL(*rparam,2,0); /* converter word */
2025 SSVAL(*rparam,4,*rdata_len);
2031 /****************************************************************************
2032 get info about the server
2033 ****************************************************************************/
2034 static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2035 int mdrcnt,int mprcnt,
2036 char **rdata,char **rparam,
2037 int *rdata_len,int *rparam_len)
2039 char *str1 = param+2;
2040 char *str2 = skip_string(str1,1);
2041 char *p = skip_string(str2,1);
2043 extern pstring sesssetup_user;
2044 int level = SVAL(p,0);
2046 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
2049 *rparam = REALLOC(*rparam,*rparam_len);
2051 /* check it's a supported varient */
2052 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz")))
2055 *rdata_len = mdrcnt + 1024;
2056 *rdata = REALLOC(*rdata,*rdata_len);
2058 SSVAL(*rparam,0,NERR_Success);
2059 SSVAL(*rparam,2,0); /* converter word */
2065 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
2066 pstrcpy(p2,local_machine);
2068 p2 = skip_string(p2,1);
2071 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2072 pstrcpy(p2,sesssetup_user);
2073 p2 = skip_string(p2,1);
2076 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
2077 pstrcpy(p2,global_myworkgroup);
2079 p2 = skip_string(p2,1);
2082 SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
2083 SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
2086 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2087 pstrcpy(p2,global_myworkgroup); /* don't know. login domain?? */
2088 p2 = skip_string(p2,1);
2091 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
2093 p2 = skip_string(p2,1);
2096 *rdata_len = PTR_DIFF(p2,*rdata);
2098 SSVAL(*rparam,4,*rdata_len);
2103 /****************************************************************************
2104 get info about a user
2106 struct user_info_11 {
2107 char usri11_name[21]; 0-20
2109 char *usri11_comment; 22-25
2110 char *usri11_usr_comment; 26-29
2111 unsigned short usri11_priv; 30-31
2112 unsigned long usri11_auth_flags; 32-35
2113 long usri11_password_age; 36-39
2114 char *usri11_homedir; 40-43
2115 char *usri11_parms; 44-47
2116 long usri11_last_logon; 48-51
2117 long usri11_last_logoff; 52-55
2118 unsigned short usri11_bad_pw_count; 56-57
2119 unsigned short usri11_num_logons; 58-59
2120 char *usri11_logon_server; 60-63
2121 unsigned short usri11_country_code; 64-65
2122 char *usri11_workstations; 66-69
2123 unsigned long usri11_max_storage; 70-73
2124 unsigned short usri11_units_per_week; 74-75
2125 unsigned char *usri11_logon_hours; 76-79
2126 unsigned short usri11_code_page; 80-81
2131 usri11_name specifies the user name for which information is retireved
2133 usri11_pad aligns the next data structure element to a word boundary
2135 usri11_comment is a null terminated ASCII comment
2137 usri11_user_comment is a null terminated ASCII comment about the user
2139 usri11_priv specifies the level of the privilege assigned to the user.
2140 The possible values are:
2142 Name Value Description
2143 USER_PRIV_GUEST 0 Guest privilege
2144 USER_PRIV_USER 1 User privilege
2145 USER_PRV_ADMIN 2 Administrator privilege
2147 usri11_auth_flags specifies the account operator privileges. The
2148 possible values are:
2150 Name Value Description
2151 AF_OP_PRINT 0 Print operator
2154 Leach, Naik [Page 28]
\r\f
2157 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2160 AF_OP_COMM 1 Communications operator
2161 AF_OP_SERVER 2 Server operator
2162 AF_OP_ACCOUNTS 3 Accounts operator
2165 usri11_password_age specifies how many seconds have elapsed since the
2166 password was last changed.
2168 usri11_home_dir points to a null terminated ASCII string that contains
2169 the path name of the user's home directory.
2171 usri11_parms points to a null terminated ASCII string that is set
2172 aside for use by applications.
2174 usri11_last_logon specifies the time when the user last logged on.
2175 This value is stored as the number of seconds elapsed since
2176 00:00:00, January 1, 1970.
2178 usri11_last_logoff specifies the time when the user last logged off.
2179 This value is stored as the number of seconds elapsed since
2180 00:00:00, January 1, 1970. A value of 0 means the last logoff
2183 usri11_bad_pw_count specifies the number of incorrect passwords
2184 entered since the last successful logon.
2186 usri11_log1_num_logons specifies the number of times this user has
2187 logged on. A value of -1 means the number of logons is unknown.
2189 usri11_logon_server points to a null terminated ASCII string that
2190 contains the name of the server to which logon requests are sent.
2191 A null string indicates logon requests should be sent to the
2194 usri11_country_code specifies the country code for the user's language
2197 usri11_workstations points to a null terminated ASCII string that
2198 contains the names of workstations the user may log on from.
2199 There may be up to 8 workstations, with the names separated by
2200 commas. A null strings indicates there are no restrictions.
2202 usri11_max_storage specifies the maximum amount of disk space the user
2203 can occupy. A value of 0xffffffff indicates there are no
2206 usri11_units_per_week specifies the equal number of time units into
2207 which a week is divided. This value must be equal to 168.
2209 usri11_logon_hours points to a 21 byte (168 bits) string that
2210 specifies the time during which the user can log on. Each bit
2211 represents one unique hour in a week. The first bit (bit 0, word
2212 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
2216 Leach, Naik [Page 29]
\r\f
2219 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2222 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
2223 are no restrictions.
2225 usri11_code_page specifies the code page for the user's language of
2228 All of the pointers in this data structure need to be treated
2229 specially. The pointer is a 32 bit pointer. The higher 16 bits need
2230 to be ignored. The converter word returned in the parameters section
2231 needs to be subtracted from the lower 16 bits to calculate an offset
2232 into the return buffer where this ASCII string resides.
2234 There is no auxiliary data in the response.
2236 ****************************************************************************/
2238 #define usri11_name 0
2239 #define usri11_pad 21
2240 #define usri11_comment 22
2241 #define usri11_usr_comment 26
2242 #define usri11_full_name 30
2243 #define usri11_priv 34
2244 #define usri11_auth_flags 36
2245 #define usri11_password_age 40
2246 #define usri11_homedir 44
2247 #define usri11_parms 48
2248 #define usri11_last_logon 52
2249 #define usri11_last_logoff 56
2250 #define usri11_bad_pw_count 60
2251 #define usri11_num_logons 62
2252 #define usri11_logon_server 64
2253 #define usri11_country_code 68
2254 #define usri11_workstations 70
2255 #define usri11_max_storage 74
2256 #define usri11_units_per_week 78
2257 #define usri11_logon_hours 80
2258 #define usri11_code_page 84
2259 #define usri11_end 86
2261 #define USER_PRIV_GUEST 0
2262 #define USER_PRIV_USER 1
2263 #define USER_PRIV_ADMIN 2
2265 #define AF_OP_PRINT 0
2266 #define AF_OP_COMM 1
2267 #define AF_OP_SERVER 2
2268 #define AF_OP_ACCOUNTS 3
2271 static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2272 int mdrcnt,int mprcnt,
2273 char **rdata,char **rparam,
2274 int *rdata_len,int *rparam_len)
2276 char *str1 = param+2;
2277 char *str2 = skip_string(str1,1);
2278 char *UserName = skip_string(str2,1);
2279 char *p = skip_string(UserName,1);
2280 int uLevel = SVAL(p,0);
2283 /* get NIS home of a previously validated user - simeon */
2284 /* With share level security vuid will always be zero.
2285 Don't depend on vuser being non-null !!. JRA */
2286 user_struct *vuser = get_valid_user_struct(vuid);
2288 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid,
2289 vuser->user.unix_name));
2292 *rparam = REALLOC(*rparam,*rparam_len);
2294 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
2296 /* check it's a supported variant */
2297 if (strcmp(str1,"zWrLh") != 0) return False;
2300 case 0: p2 = "B21"; break;
2301 case 1: p2 = "B21BB16DWzzWz"; break;
2302 case 2: p2 = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
2303 case 10: p2 = "B21Bzzz"; break;
2304 case 11: p2 = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
2305 default: return False;
2308 if (strcmp(p2,str2) != 0) return False;
2310 *rdata_len = mdrcnt + 1024;
2311 *rdata = REALLOC(*rdata,*rdata_len);
2313 SSVAL(*rparam,0,NERR_Success);
2314 SSVAL(*rparam,2,0); /* converter word */
2317 p2 = p + usri11_end;
2320 fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
2324 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
2329 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
2330 pstrcpy(p2,"Comment");
2331 p2 = skip_string(p2,1);
2333 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
2334 pstrcpy(p2,"UserComment");
2335 p2 = skip_string(p2,1);
2337 /* EEK! the cifsrap.txt doesn't have this in!!!! */
2338 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
2339 pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName));
2340 p2 = skip_string(p2,1);
2343 if (uLevel == 11) /* modelled after NTAS 3.51 reply */
2345 SSVAL(p,usri11_priv,conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2346 SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
2347 SIVALS(p,usri11_password_age,-1); /* password age */
2348 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
2349 pstrcpy(p2, lp_logon_home());
2350 p2 = skip_string(p2,1);
2351 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
2353 p2 = skip_string(p2,1);
2354 SIVAL(p,usri11_last_logon,0); /* last logon */
2355 SIVAL(p,usri11_last_logoff,0); /* last logoff */
2356 SSVALS(p,usri11_bad_pw_count,-1); /* bad pw counts */
2357 SSVALS(p,usri11_num_logons,-1); /* num logons */
2358 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
2359 pstrcpy(p2,"\\\\*");
2360 p2 = skip_string(p2,1);
2361 SSVAL(p,usri11_country_code,0); /* country code */
2363 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
2365 p2 = skip_string(p2,1);
2367 SIVALS(p,usri11_max_storage,-1); /* max storage */
2368 SSVAL(p,usri11_units_per_week,168); /* units per week */
2369 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
2371 /* a simple way to get logon hours at all times. */
2373 SCVAL(p2,21,0); /* fix zero termination */
2374 p2 = skip_string(p2,1);
2376 SSVAL(p,usri11_code_page,0); /* code page */
2378 if (uLevel == 1 || uLevel == 2)
2380 memset(p+22,' ',16); /* password */
2381 SIVALS(p,38,-1); /* password age */
2383 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2384 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
2385 pstrcpy(p2,lp_logon_home());
2386 p2 = skip_string(p2,1);
2387 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
2389 SSVAL(p,52,0); /* flags */
2390 SIVAL(p,54,PTR_DIFF(p2,*rdata)); /* script_path */
2391 pstrcpy(p2,lp_logon_script());
2392 standard_sub_conn( conn, p2 );
2393 p2 = skip_string(p2,1);
2396 SIVAL(p,60,0); /* auth_flags */
2397 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
2398 pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName));
2399 p2 = skip_string(p2,1);
2400 SIVAL(p,68,0); /* urs_comment */
2401 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
2403 p2 = skip_string(p2,1);
2404 SIVAL(p,76,0); /* workstations */
2405 SIVAL(p,80,0); /* last_logon */
2406 SIVAL(p,84,0); /* last_logoff */
2407 SIVALS(p,88,-1); /* acct_expires */
2408 SIVALS(p,92,-1); /* max_storage */
2409 SSVAL(p,96,168); /* units_per_week */
2410 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
2413 SSVALS(p,102,-1); /* bad_pw_count */
2414 SSVALS(p,104,-1); /* num_logons */
2415 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
2416 pstrcpy(p2,"\\\\%L");
2417 standard_sub_conn(conn, p2);
2418 p2 = skip_string(p2,1);
2419 SSVAL(p,110,49); /* country_code */
2420 SSVAL(p,112,860); /* code page */
2424 *rdata_len = PTR_DIFF(p2,*rdata);
2426 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
2431 /*******************************************************************
2432 get groups that a user is a member of
2433 ******************************************************************/
2434 static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *param,char *data,
2435 int mdrcnt,int mprcnt,
2436 char **rdata,char **rparam,
2437 int *rdata_len,int *rparam_len)
2439 char *str1 = param+2;
2440 char *str2 = skip_string(str1,1);
2441 char *UserName = skip_string(str2,1);
2442 char *p = skip_string(UserName,1);
2443 int uLevel = SVAL(p,0);
2448 *rparam = REALLOC(*rparam,*rparam_len);
2450 /* check it's a supported varient */
2451 if (strcmp(str1,"zWrLeh") != 0) return False;
2453 case 0: p2 = "B21"; break;
2454 default: return False;
2456 if (strcmp(p2,str2) != 0) return False;
2458 *rdata_len = mdrcnt + 1024;
2459 *rdata = REALLOC(*rdata,*rdata_len);
2461 SSVAL(*rparam,0,NERR_Success);
2462 SSVAL(*rparam,2,0); /* converter word */
2466 /* XXXX we need a real SAM database some day */
2467 pstrcpy(p,"Users"); p += 21; count++;
2468 pstrcpy(p,"Domain Users"); p += 21; count++;
2469 pstrcpy(p,"Guests"); p += 21; count++;
2470 pstrcpy(p,"Domain Guests"); p += 21; count++;
2472 *rdata_len = PTR_DIFF(p,*rdata);
2474 SSVAL(*rparam,4,count); /* is this right?? */
2475 SSVAL(*rparam,6,count); /* is this right?? */
2481 static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param,char *data,
2482 int mdrcnt,int mprcnt,
2483 char **rdata,char **rparam,
2484 int *rdata_len,int *rparam_len)
2486 char *str1 = param+2;
2487 char *str2 = skip_string(str1,1);
2488 char *p = skip_string(str2,1);
2490 struct pack_desc desc;
2496 memset((char *)&desc,'\0',sizeof(desc));
2498 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
2500 /* check it's a supported varient */
2501 if (strcmp(str1,"OOWb54WrLh") != 0) return False;
2502 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) return False;
2503 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2505 desc.buflen = mdrcnt;
2506 desc.subformat = NULL;
2509 if (init_package(&desc,1,0))
2511 PACKI(&desc,"W",0); /* code */
2512 PACKS(&desc,"B21",name); /* eff. name */
2513 PACKS(&desc,"B",""); /* pad */
2515 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2516 PACKI(&desc,"D",0); /* auth flags XXX */
2517 PACKI(&desc,"W",0); /* num logons */
2518 PACKI(&desc,"W",0); /* bad pw count */
2519 PACKI(&desc,"D",0); /* last logon */
2520 PACKI(&desc,"D",-1); /* last logoff */
2521 PACKI(&desc,"D",-1); /* logoff time */
2522 PACKI(&desc,"D",-1); /* kickoff time */
2523 PACKI(&desc,"D",0); /* password age */
2524 PACKI(&desc,"D",0); /* password can change */
2525 PACKI(&desc,"D",-1); /* password must change */
2528 fstrcpy(mypath,"\\\\");
2529 fstrcat(mypath,local_machine);
2531 PACKS(&desc,"z",mypath); /* computer */
2533 PACKS(&desc,"z",global_myworkgroup);/* domain */
2535 /* JHT - By calling lp_logon_script() and standard_sub() we have */
2536 /* made sure all macros are fully substituted and available */
2538 pstring logon_script;
2539 pstrcpy(logon_script,lp_logon_script());
2540 standard_sub_conn( conn, logon_script );
2541 PACKS(&desc,"z", logon_script); /* script path */
2543 /* End of JHT mods */
2545 PACKI(&desc,"D",0x00000000); /* reserved */
2548 *rdata_len = desc.usedlen;
2550 *rparam = REALLOC(*rparam,*rparam_len);
2551 SSVALS(*rparam,0,desc.errcode);
2553 SSVAL(*rparam,4,desc.neededlen);
2555 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
2560 /****************************************************************************
2561 api_WAccessGetUserPerms
2562 ****************************************************************************/
2563 static BOOL api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid, char *param,char *data,
2564 int mdrcnt,int mprcnt,
2565 char **rdata,char **rparam,
2566 int *rdata_len,int *rparam_len)
2568 char *str1 = param+2;
2569 char *str2 = skip_string(str1,1);
2570 char *user = skip_string(str2,1);
2571 char *resource = skip_string(user,1);
2573 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
2575 /* check it's a supported varient */
2576 if (strcmp(str1,"zzh") != 0) return False;
2577 if (strcmp(str2,"") != 0) return False;
2580 *rparam = REALLOC(*rparam,*rparam_len);
2581 SSVALS(*rparam,0,0); /* errorcode */
2582 SSVAL(*rparam,2,0); /* converter word */
2583 SSVAL(*rparam,4,0x7f); /* permission flags */
2588 /****************************************************************************
2589 api_WPrintJobEnumerate
2590 ****************************************************************************/
2591 static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2592 int mdrcnt,int mprcnt,
2593 char **rdata,char **rparam,
2594 int *rdata_len,int *rparam_len)
2596 char *str1 = param+2;
2597 char *str2 = skip_string(str1,1);
2598 char *p = skip_string(str2,1);
2604 struct pack_desc desc;
2605 print_queue_struct *queue=NULL;
2606 print_status_struct status;
2610 memset((char *)&desc,'\0',sizeof(desc));
2611 memset((char *)&status,'\0',sizeof(status));
2613 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
2615 /* check it's a supported varient */
2616 if (strcmp(str1,"WWrLh") != 0) return False;
2617 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2620 snum = print_job_snum(job);
2622 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2624 count = print_queue_status(snum,&queue,&status);
2625 for (i = 0; i < count; i++) {
2626 if (queue[i].job == job) break;
2628 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2630 desc.buflen = mdrcnt;
2632 if (init_package(&desc,1,0)) {
2634 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
2635 *rdata_len = desc.usedlen;
2638 desc.errcode = NERR_JobNotFound;
2644 *rparam = REALLOC(*rparam,*rparam_len);
2645 SSVALS(*rparam,0,desc.errcode);
2647 SSVAL(*rparam,4,desc.neededlen);
2649 if (queue) free(queue);
2651 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
2655 static BOOL api_WPrintJobEnumerate(connection_struct *conn,uint16 vuid, char *param,char *data,
2656 int mdrcnt,int mprcnt,
2657 char **rdata,char **rparam,
2658 int *rdata_len,int *rparam_len)
2660 char *str1 = param+2;
2661 char *str2 = skip_string(str1,1);
2662 char *p = skip_string(str2,1);
2668 struct pack_desc desc;
2669 print_queue_struct *queue=NULL;
2670 print_status_struct status;
2672 memset((char *)&desc,'\0',sizeof(desc));
2673 memset((char *)&status,'\0',sizeof(status));
2675 p = skip_string(p,1);
2678 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
2680 /* check it's a supported varient */
2681 if (strcmp(str1,"zWrLeh") != 0) return False;
2682 if (uLevel > 2) return False; /* defined only for uLevel 0,1,2 */
2683 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2685 snum = lp_servicenumber(name);
2686 if (snum < 0 && pcap_printername_ok(name,NULL)) {
2687 int pnum = lp_servicenumber(PRINTERS_NAME);
2689 lp_add_printer(name,pnum);
2690 snum = lp_servicenumber(name);
2694 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2696 count = print_queue_status(snum,&queue,&status);
2697 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2699 desc.buflen = mdrcnt;
2701 if (init_package(&desc,count,0)) {
2703 for (i = 0; i < count; i++) {
2704 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
2705 if (desc.errcode == NERR_Success) succnt = i+1;
2709 *rdata_len = desc.usedlen;
2712 *rparam = REALLOC(*rparam,*rparam_len);
2713 SSVALS(*rparam,0,desc.errcode);
2715 SSVAL(*rparam,4,succnt);
2716 SSVAL(*rparam,6,count);
2718 if (queue) free(queue);
2720 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
2724 static int check_printdest_info(struct pack_desc* desc,
2725 int uLevel, char* id)
2727 desc->subformat = NULL;
2729 case 0: desc->format = "B9"; break;
2730 case 1: desc->format = "B9B21WWzW"; break;
2731 case 2: desc->format = "z"; break;
2732 case 3: desc->format = "zzzWWzzzWW"; break;
2733 default: return False;
2735 if (strcmp(desc->format,id) != 0) return False;
2739 static void fill_printdest_info(connection_struct *conn, int snum, int uLevel,
2740 struct pack_desc* desc)
2743 strncpy(buf,SERVICE(snum),sizeof(buf)-1);
2744 buf[sizeof(buf)-1] = 0;
2747 PACKS(desc,"B9",buf); /* szName */
2749 PACKS(desc,"B21",""); /* szUserName */
2750 PACKI(desc,"W",0); /* uJobId */
2751 PACKI(desc,"W",0); /* fsStatus */
2752 PACKS(desc,"z",""); /* pszStatus */
2753 PACKI(desc,"W",0); /* time */
2756 if (uLevel == 2 || uLevel == 3) {
2757 PACKS(desc,"z",buf); /* pszPrinterName */
2759 PACKS(desc,"z",""); /* pszUserName */
2760 PACKS(desc,"z",""); /* pszLogAddr */
2761 PACKI(desc,"W",0); /* uJobId */
2762 PACKI(desc,"W",0); /* fsStatus */
2763 PACKS(desc,"z",""); /* pszStatus */
2764 PACKS(desc,"z",""); /* pszComment */
2765 PACKS(desc,"z","NULL"); /* pszDrivers */
2766 PACKI(desc,"W",0); /* time */
2767 PACKI(desc,"W",0); /* pad1 */
2772 static BOOL api_WPrintDestGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2773 int mdrcnt,int mprcnt,
2774 char **rdata,char **rparam,
2775 int *rdata_len,int *rparam_len)
2777 char *str1 = param+2;
2778 char *str2 = skip_string(str1,1);
2779 char *p = skip_string(str2,1);
2780 char* PrinterName = p;
2782 struct pack_desc desc;
2785 memset((char *)&desc,'\0',sizeof(desc));
2787 p = skip_string(p,1);
2790 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
2792 /* check it's a supported varient */
2793 if (strcmp(str1,"zWrLh") != 0) return False;
2794 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2796 snum = lp_servicenumber(PrinterName);
2797 if (snum < 0 && pcap_printername_ok(PrinterName,NULL)) {
2798 int pnum = lp_servicenumber(PRINTERS_NAME);
2800 lp_add_printer(PrinterName,pnum);
2801 snum = lp_servicenumber(PrinterName);
2807 desc.errcode = NERR_DestNotFound;
2811 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2813 desc.buflen = mdrcnt;
2814 if (init_package(&desc,1,0)) {
2815 fill_printdest_info(conn,snum,uLevel,&desc);
2817 *rdata_len = desc.usedlen;
2821 *rparam = REALLOC(*rparam,*rparam_len);
2822 SSVALS(*rparam,0,desc.errcode);
2824 SSVAL(*rparam,4,desc.neededlen);
2826 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
2830 static BOOL api_WPrintDestEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
2831 int mdrcnt,int mprcnt,
2832 char **rdata,char **rparam,
2833 int *rdata_len,int *rparam_len)
2835 char *str1 = param+2;
2836 char *str2 = skip_string(str1,1);
2837 char *p = skip_string(str2,1);
2841 struct pack_desc desc;
2842 int services = lp_numservices();
2844 memset((char *)&desc,'\0',sizeof(desc));
2848 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
2850 /* check it's a supported varient */
2851 if (strcmp(str1,"WrLeh") != 0) return False;
2852 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2855 for (i = 0; i < services; i++)
2856 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
2859 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2861 desc.buflen = mdrcnt;
2862 if (init_package(&desc,queuecnt,0)) {
2865 for (i = 0; i < services; i++) {
2866 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
2867 fill_printdest_info(conn,i,uLevel,&desc);
2869 if (desc.errcode == NERR_Success) succnt = n;
2874 *rdata_len = desc.usedlen;
2877 *rparam = REALLOC(*rparam,*rparam_len);
2878 SSVALS(*rparam,0,desc.errcode);
2880 SSVAL(*rparam,4,succnt);
2881 SSVAL(*rparam,6,queuecnt);
2883 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
2887 static BOOL api_WPrintDriverEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
2888 int mdrcnt,int mprcnt,
2889 char **rdata,char **rparam,
2890 int *rdata_len,int *rparam_len)
2892 char *str1 = param+2;
2893 char *str2 = skip_string(str1,1);
2894 char *p = skip_string(str2,1);
2897 struct pack_desc desc;
2899 memset((char *)&desc,'\0',sizeof(desc));
2903 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
2905 /* check it's a supported varient */
2906 if (strcmp(str1,"WrLeh") != 0) return False;
2907 if (uLevel != 0 || strcmp(str2,"B41") != 0) return False;
2909 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2911 desc.buflen = mdrcnt;
2912 if (init_package(&desc,1,0)) {
2913 PACKS(&desc,"B41","NULL");
2916 succnt = (desc.errcode == NERR_Success ? 1 : 0);
2918 *rdata_len = desc.usedlen;
2921 *rparam = REALLOC(*rparam,*rparam_len);
2922 SSVALS(*rparam,0,desc.errcode);
2924 SSVAL(*rparam,4,succnt);
2927 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
2931 static BOOL api_WPrintQProcEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
2932 int mdrcnt,int mprcnt,
2933 char **rdata,char **rparam,
2934 int *rdata_len,int *rparam_len)
2936 char *str1 = param+2;
2937 char *str2 = skip_string(str1,1);
2938 char *p = skip_string(str2,1);
2941 struct pack_desc desc;
2943 memset((char *)&desc,'\0',sizeof(desc));
2947 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
2949 /* check it's a supported varient */
2950 if (strcmp(str1,"WrLeh") != 0) return False;
2951 if (uLevel != 0 || strcmp(str2,"B13") != 0) return False;
2953 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2955 desc.buflen = mdrcnt;
2957 if (init_package(&desc,1,0)) {
2958 PACKS(&desc,"B13","lpd");
2961 succnt = (desc.errcode == NERR_Success ? 1 : 0);
2963 *rdata_len = desc.usedlen;
2966 *rparam = REALLOC(*rparam,*rparam_len);
2967 SSVALS(*rparam,0,desc.errcode);
2969 SSVAL(*rparam,4,succnt);
2972 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
2976 static BOOL api_WPrintPortEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
2977 int mdrcnt,int mprcnt,
2978 char **rdata,char **rparam,
2979 int *rdata_len,int *rparam_len)
2981 char *str1 = param+2;
2982 char *str2 = skip_string(str1,1);
2983 char *p = skip_string(str2,1);
2986 struct pack_desc desc;
2988 memset((char *)&desc,'\0',sizeof(desc));
2992 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
2994 /* check it's a supported varient */
2995 if (strcmp(str1,"WrLeh") != 0) return False;
2996 if (uLevel != 0 || strcmp(str2,"B9") != 0) return False;
2998 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2999 memset((char *)&desc,'\0',sizeof(desc));
3001 desc.buflen = mdrcnt;
3003 if (init_package(&desc,1,0)) {
3004 PACKS(&desc,"B13","lp0");
3007 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3009 *rdata_len = desc.usedlen;
3012 *rparam = REALLOC(*rparam,*rparam_len);
3013 SSVALS(*rparam,0,desc.errcode);
3015 SSVAL(*rparam,4,succnt);
3018 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
3022 /****************************************************************************
3023 The buffer was too small
3024 ****************************************************************************/
3026 static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param,char *data,
3027 int mdrcnt,int mprcnt,
3028 char **rdata,char **rparam,
3029 int *rdata_len,int *rparam_len)
3031 *rparam_len = MIN(*rparam_len,mprcnt);
3032 *rparam = REALLOC(*rparam,*rparam_len);
3036 SSVAL(*rparam,0,NERR_BufTooSmall);
3038 DEBUG(3,("Supplied buffer too small in API command\n"));
3044 /****************************************************************************
3045 The request is not supported
3046 ****************************************************************************/
3048 static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param,char *data,
3049 int mdrcnt,int mprcnt,
3050 char **rdata,char **rparam,
3051 int *rdata_len,int *rparam_len)
3054 *rparam = REALLOC(*rparam,*rparam_len);
3058 SSVAL(*rparam,0,NERR_notsupported);
3059 SSVAL(*rparam,2,0); /* converter word */
3061 DEBUG(3,("Unsupported API command\n"));
3073 BOOL (*fn)(connection_struct *,uint16,char *,char *,
3074 int,int,char **,char **,int *,int *);
3076 } api_commands[] = {
3077 {"RNetShareEnum", 0, api_RNetShareEnum,0},
3078 {"RNetShareGetInfo", 1, api_RNetShareGetInfo,0},
3079 {"RNetServerGetInfo", 13, api_RNetServerGetInfo,0},
3080 {"RNetGroupGetUsers", 52, api_RNetGroupGetUsers,0},
3081 {"RNetUserGetInfo", 56, api_RNetUserGetInfo,0},
3082 {"NetUserGetGroups", 59, api_NetUserGetGroups,0},
3083 {"NetWkstaGetInfo", 63, api_NetWkstaGetInfo,0},
3084 {"DosPrintQEnum", 69, api_DosPrintQEnum,0},
3085 {"DosPrintQGetInfo", 70, api_DosPrintQGetInfo,0},
3086 {"WPrintQueuePause", 74, api_WPrintQueuePurge,0},
3087 {"WPrintQueueResume", 75, api_WPrintQueuePurge,0},
3088 {"WPrintJobEnumerate",76, api_WPrintJobEnumerate,0},
3089 {"WPrintJobGetInfo", 77, api_WPrintJobGetInfo,0},
3090 {"RDosPrintJobDel", 81, api_RDosPrintJobDel,0},
3091 {"RDosPrintJobPause", 82, api_RDosPrintJobDel,0},
3092 {"RDosPrintJobResume",83, api_RDosPrintJobDel,0},
3093 {"WPrintDestEnum", 84, api_WPrintDestEnum,0},
3094 {"WPrintDestGetInfo", 85, api_WPrintDestGetInfo,0},
3095 {"NetRemoteTOD", 91, api_NetRemoteTOD,0},
3096 {"WPrintQueuePurge", 103, api_WPrintQueuePurge,0},
3097 {"NetServerEnum", 104, api_RNetServerEnum,0},
3098 {"WAccessGetUserPerms",105, api_WAccessGetUserPerms,0},
3099 {"SetUserPassword", 115, api_SetUserPassword,0},
3100 {"WWkstaUserLogon", 132, api_WWkstaUserLogon,0},
3101 {"PrintJobInfo", 147, api_PrintJobInfo,0},
3102 {"WPrintDriverEnum", 205, api_WPrintDriverEnum,0},
3103 {"WPrintQProcEnum", 206, api_WPrintQProcEnum,0},
3104 {"WPrintPortEnum", 207, api_WPrintPortEnum,0},
3105 {"SamOEMChangePassword", 214, api_SamOEMChangePassword,0},
3106 {NULL, -1, api_Unsupported,0}};
3109 /****************************************************************************
3110 Handle remote api calls
3111 ****************************************************************************/
3113 int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data,char *params,
3114 int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
3118 char *rparam = NULL;
3125 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
3129 api_command = SVAL(params,0);
3131 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
3134 skip_string(params+2,1),
3135 tdscnt,tpscnt,mdrcnt,mprcnt));
3137 for (i=0;api_commands[i].name;i++) {
3138 if (api_commands[i].id == api_command && api_commands[i].fn) {
3139 DEBUG(3,("Doing %s\n",api_commands[i].name));
3144 rdata = (char *)malloc(1024);
3146 memset(rdata,'\0',1024);
3148 rparam = (char *)malloc(1024);
3150 memset(rparam,'\0',1024);
3152 if(!rdata || !rparam) {
3153 DEBUG(0,("api_reply: malloc fail !\n"));
3157 reply = api_commands[i].fn(conn,vuid,params,data,mdrcnt,mprcnt,
3158 &rdata,&rparam,&rdata_len,&rparam_len);
3161 if (rdata_len > mdrcnt ||
3162 rparam_len > mprcnt) {
3163 reply = api_TooSmall(conn,vuid,params,data,mdrcnt,mprcnt,
3164 &rdata,&rparam,&rdata_len,&rparam_len);
3167 /* if we get False back then it's actually unsupported */
3169 api_Unsupported(conn,vuid,params,data,mdrcnt,mprcnt,
3170 &rdata,&rparam,&rdata_len,&rparam_len);
3172 send_trans_reply(outbuf, rparam, rparam_len, rdata, rdata_len, False);