3 Unix SMB/Netbios implementation.
5 Inter-process communication and named pipe handling
6 Copyright (C) Andrew Tridgell 1992-1998
9 Copyright (C) John H Terpstra 1995-1998
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2 of the License, or
14 (at your option) any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 This file handles the named pipe and mailslot calls
27 in the SMBtrans protocol
37 extern int DEBUGLEVEL;
39 extern fstring local_machine;
40 extern fstring global_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)
51 #define ACCESS_READ 0x01
52 #define ACCESS_WRITE 0x02
53 #define ACCESS_CREATE 0x04
55 #define SHPWLEN 8 /* share password length */
57 static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param,char *data,
58 int mdrcnt,int mprcnt,
59 char **rdata,char **rparam,
60 int *rdata_len,int *rparam_len);
61 static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param,char *data,
62 int mdrcnt,int mprcnt,
63 char **rdata,char **rparam,
64 int *rdata_len,int *rparam_len);
67 static int CopyExpanded(connection_struct *conn,
68 int snum, char** dst, char* src, int* n)
73 if (!src || !dst || !n || !(*dst)) return(0);
75 StrnCpy(buf,src,sizeof(buf)/2);
76 pstring_sub(buf,"%S",lp_servicename(snum));
77 standard_sub_conn(conn,buf);
85 static int CopyAndAdvance(char** dst, char* src, int* n)
88 if (!src || !dst || !n || !(*dst)) return(0);
89 StrnCpy(*dst,src,*n-1);
96 static int StrlenExpanded(connection_struct *conn, int snum, char* s)
100 StrnCpy(buf,s,sizeof(buf)/2);
101 pstring_sub(buf,"%S",lp_servicename(snum));
102 standard_sub_conn(conn,buf);
103 return strlen(buf) + 1;
106 static char* Expand(connection_struct *conn, int snum, char* s)
109 if (!s) return(NULL);
110 StrnCpy(buf,s,sizeof(buf)/2);
111 pstring_sub(buf,"%S",lp_servicename(snum));
112 standard_sub_conn(conn,buf);
116 /*******************************************************************
117 check a API string for validity when we only need to check the prefix
118 ******************************************************************/
119 static BOOL prefix_ok(char *str,char *prefix)
121 return(strncmp(str,prefix,strlen(prefix)) == 0);
125 char* format; /* formatstring for structure */
126 char* subformat; /* subformat for structure */
127 char* base; /* baseaddress of buffer */
128 int buflen; /* remaining size for fixed part; on init: length of base */
129 int subcount; /* count of substructures */
130 char* structbuf; /* pointer into buffer for remaining fixed part */
131 int stringlen; /* remaining size for variable part */
132 char* stringbuf; /* pointer into buffer for remaining variable part */
133 int neededlen; /* total needed size */
134 int usedlen; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
135 char* curpos; /* current position; pointer into format or subformat */
139 static int get_counter(char** p)
142 if (!p || !(*p)) return(1);
143 if (!isdigit((int)**p)) return 1;
147 n = 10 * n + (i - '0');
154 static int getlen(char* p)
160 case 'W': /* word (2 byte) */
163 case 'K': /* status word? (2 byte) */
166 case 'N': /* count of substructures (word) at end */
169 case 'D': /* double word (4 byte) */
170 case 'z': /* offset to zero terminated string (4 byte) */
171 case 'l': /* offset to user data (4 byte) */
174 case 'b': /* offset to data (with counter) (4 byte) */
178 case 'B': /* byte (with optional counter) */
179 n += get_counter(&p);
186 static BOOL init_package(struct pack_desc* p, int count, int subcount)
191 if (!p->format || !p->base) return(False);
193 i = count * getlen(p->format);
194 if (p->subformat) i += subcount * getlen(p->subformat);
195 p->structbuf = p->base;
199 p->curpos = p->format;
203 p->errcode = ERRmoredata;
206 p->errcode = NERR_Success;
209 p->stringbuf = p->base + i;
211 return(p->errcode == NERR_Success);
215 static int package(struct pack_desc* p, ...)
218 static int package(va_alist)
224 int needed=0, stringneeded;
226 int is_string=0, stringused;
233 p = va_arg(args,struct pack_desc *);
238 p->curpos = p->format;
240 p->curpos = p->subformat;
245 str = va_arg(args,char*);
246 SMB_ASSERT(strncmp(str,p->curpos,strlen(str)) == 0);
255 switch( *p->curpos++ ) {
256 case 'W': /* word (2 byte) */
258 temp = va_arg(args,int);
259 if (p->buflen >= needed) SSVAL(p->structbuf,0,temp);
261 case 'K': /* status word? (2 byte) */
263 temp = va_arg(args,int);
264 if (p->buflen >= needed) SSVAL(p->structbuf,0,temp);
266 case 'N': /* count of substructures (word) at end */
268 p->subcount = va_arg(args,int);
269 if (p->buflen >= needed) SSVAL(p->structbuf,0,p->subcount);
271 case 'D': /* double word (4 byte) */
273 temp = va_arg(args,int);
274 if (p->buflen >= needed) SIVAL(p->structbuf,0,temp);
276 case 'B': /* byte (with optional counter) */
277 needed = get_counter(&p->curpos);
279 char *s = va_arg(args,char*);
280 if (p->buflen >= needed) StrnCpy(p->structbuf,s?s:"",needed-1);
283 case 'z': /* offset to zero terminated string (4 byte) */
284 str = va_arg(args,char*);
285 stringneeded = (str ? strlen(str)+1 : 0);
288 case 'l': /* offset to user data (4 byte) */
289 str = va_arg(args,char*);
290 stringneeded = va_arg(args,int);
293 case 'b': /* offset to data (with counter) (4 byte) */
294 str = va_arg(args,char*);
295 stringneeded = get_counter(&p->curpos);
300 if (stringneeded >= 0) {
302 if (p->buflen >= needed) {
303 stringused = stringneeded;
304 if (stringused > p->stringlen) {
305 stringused = (is_string ? p->stringlen : 0);
306 if (p->errcode == NERR_Success) p->errcode = ERRmoredata;
309 SIVAL(p->structbuf,0,0);
311 SIVAL(p->structbuf,0,PTR_DIFF(p->stringbuf,p->base));
312 memcpy(p->stringbuf,str?str:"",stringused);
313 if (is_string) p->stringbuf[stringused-1] = '\0';
314 p->stringbuf += stringused;
315 p->stringlen -= stringused;
316 p->usedlen += stringused;
319 p->neededlen += stringneeded;
321 p->neededlen += needed;
322 if (p->buflen >= needed) {
323 p->structbuf += needed;
325 p->usedlen += needed;
328 if (p->errcode == NERR_Success) p->errcode = ERRmoredata;
334 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
335 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
337 #define PACK(desc,t,v) package(desc,v)
338 #define PACKl(desc,t,v,l) package(desc,v,l)
341 static void PACKI(struct pack_desc* desc,char *t,int v)
346 static void PACKS(struct pack_desc* desc,char *t,char *v)
352 /****************************************************************************
354 ****************************************************************************/
355 static void PackDriverData(struct pack_desc* desc)
357 char drivdata[4+4+32];
358 SIVAL(drivdata,0,sizeof drivdata); /* cb */
359 SIVAL(drivdata,4,1000); /* lVersion */
360 memset(drivdata+8,0,32); /* szDeviceName */
361 pstrcpy(drivdata+8,"NULL");
362 PACKl(desc,"l",drivdata,sizeof drivdata); /* pDriverData */
365 static int check_printq_info(struct pack_desc* desc,
366 int uLevel, char *id1, char *id2)
368 desc->subformat = NULL;
371 desc->format = "B13";
374 desc->format = "B13BWWWzzzzzWW";
377 desc->format = "B13BWWWzzzzzWN";
378 desc->subformat = "WB21BB16B10zWWzDDz";
381 desc->format = "zWWWWzzzzWWzzl";
384 desc->format = "zWWWWzzzzWNzzl";
385 desc->subformat = "WWzWWDDzz";
394 desc->format = "WzzzzzzzzN";
395 desc->subformat = "z";
397 default: return False;
399 if (strcmp(desc->format,id1) != 0) return False;
400 if (desc->subformat && strcmp(desc->subformat,id2) != 0) return False;
405 #define JOB_STATUS_QUEUED 0
406 #define JOB_STATUS_PAUSED 1
407 #define JOB_STATUS_SPOOLING 2
408 #define JOB_STATUS_PRINTING 3
409 #define JOB_STATUS_PRINTED 4
411 #define QUEUE_STATUS_PAUSED 1
412 #define QUEUE_STATUS_ERROR 2
414 /* turn a print job status into a on the wire status
416 static int printj_status(int v)
420 return JOB_STATUS_QUEUED;
422 return JOB_STATUS_PAUSED;
424 return JOB_STATUS_SPOOLING;
426 return JOB_STATUS_PRINTING;
431 /* turn a print queue status into a on the wire status
433 static int printq_status(int v)
439 return QUEUE_STATUS_PAUSED;
441 return QUEUE_STATUS_ERROR;
444 static void fill_printjob_info(connection_struct *conn, int snum, int uLevel,
445 struct pack_desc* desc,
446 print_queue_struct* queue, int n)
448 time_t t = queue->time;
450 /* the client expects localtime */
453 PACKI(desc,"W",queue->job); /* uJobId */
455 PACKS(desc,"B21",queue->user); /* szUserName */
456 PACKS(desc,"B",""); /* pad */
457 PACKS(desc,"B16",""); /* szNotifyName */
458 PACKS(desc,"B10","PM_Q_RAW"); /* szDataType */
459 PACKS(desc,"z",""); /* pszParms */
460 PACKI(desc,"W",n+1); /* uPosition */
461 PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */
462 PACKS(desc,"z",""); /* pszStatus */
463 PACKI(desc,"D",t); /* ulSubmitted */
464 PACKI(desc,"D",queue->size); /* ulSize */
465 PACKS(desc,"z",queue->file); /* pszComment */
467 if (uLevel == 2 || uLevel == 3) {
468 PACKI(desc,"W",queue->priority); /* uPriority */
469 PACKS(desc,"z",queue->user); /* pszUserName */
470 PACKI(desc,"W",n+1); /* uPosition */
471 PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */
472 PACKI(desc,"D",t); /* ulSubmitted */
473 PACKI(desc,"D",queue->size); /* ulSize */
474 PACKS(desc,"z","Samba"); /* pszComment */
475 PACKS(desc,"z",queue->file); /* pszDocument */
477 PACKS(desc,"z",""); /* pszNotifyName */
478 PACKS(desc,"z","PM_Q_RAW"); /* pszDataType */
479 PACKS(desc,"z",""); /* pszParms */
480 PACKS(desc,"z",""); /* pszStatus */
481 PACKS(desc,"z",SERVICE(snum)); /* pszQueue */
482 PACKS(desc,"z","lpd"); /* pszQProcName */
483 PACKS(desc,"z",""); /* pszQProcParms */
484 PACKS(desc,"z","NULL"); /* pszDriverName */
485 PackDriverData(desc); /* pDriverData */
486 PACKS(desc,"z",""); /* pszPrinterName */
492 static void fill_printq_info_52(connection_struct *conn, int snum, int uLevel,
493 struct pack_desc* desc,
494 int count, print_queue_struct* queue,
495 print_status_struct* status)
498 pstring tok,driver,datafile,langmon,helpfile,datatype;
502 lines = file_lines_load(lp_driverfile(),NULL);
504 DEBUG(3,("fill_printq_info: Can't open %s - %s\n",
505 lp_driverfile(),strerror(errno)));
506 desc->errcode=NERR_notsupported;
510 /* lookup the long printer driver name in the file
512 for (i=0;lines[i] && !ok;i++) {
514 if (next_token(&p,tok,":",sizeof(tok)) &&
515 (strlen(lp_printerdriver(snum)) == strlen(tok)) &&
516 (!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum)))))
521 file_lines_free(lines);
523 /* driver file name */
524 if (ok && !next_token(&p,driver,":",sizeof(driver))) ok = 0;
526 if (ok && !next_token(&p,datafile,":",sizeof(datafile))) ok = 0;
528 * for the next tokens - which may be empty - I have
529 * to check for empty tokens first because the
530 * next_token function will skip all empty token
537 } else if (!next_token(&p,helpfile,":",sizeof(helpfile))) ok = 0;
541 /* language monitor */
545 } else if (!next_token(&p,langmon,":",sizeof(langmon)))
549 /* default data type */
550 if (ok && !next_token(&p,datatype,":",sizeof(datatype)))
554 PACKI(desc,"W",0x0400); /* don't know */
555 PACKS(desc,"z",lp_printerdriver(snum)); /* long printer name */
556 PACKS(desc,"z",driver); /* Driverfile Name */
557 PACKS(desc,"z",datafile); /* Datafile name */
558 PACKS(desc,"z",langmon); /* language monitor */
559 PACKS(desc,"z",lp_driverlocation(snum)); /* share to retrieve files */
560 PACKS(desc,"z",datatype); /* default data type */
561 PACKS(desc,"z",helpfile); /* helpfile name */
562 PACKS(desc,"z",driver); /* driver name */
563 DEBUG(3,("Driver:%s:\n",driver));
564 DEBUG(3,("Data File:%s:\n",datafile));
565 DEBUG(3,("Language Monitor:%s:\n",langmon));
566 DEBUG(3,("Data Type:%s:\n",datatype));
567 DEBUG(3,("Help File:%s:\n",helpfile));
568 PACKI(desc,"N",count); /* number of files to copy */
569 for (i=0;i<count;i++) {
570 /* no need to check return value here
571 * - it was already tested in
572 * get_printerdrivernumber */
573 next_token(&p,tok,",",sizeof(tok));
574 PACKS(desc,"z",tok); /* driver files to copy */
575 DEBUG(3,("file:%s:\n",tok));
578 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n",
579 SERVICE(snum),count));
581 DEBUG(3,("fill_printq_info: Can't supply driver files\n"));
582 desc->errcode=NERR_notsupported;
588 static void fill_printq_info(connection_struct *conn, int snum, int uLevel,
589 struct pack_desc* desc,
590 int count, print_queue_struct* queue,
591 print_status_struct* status)
596 PACKS(desc,"B13",SERVICE(snum));
601 PACKS(desc,"z",Expand(conn,snum,SERVICE(snum)));
604 PACKI(desc,"K",printq_status(status->status));
608 if (uLevel == 1 || uLevel == 2) {
609 PACKS(desc,"B",""); /* alignment */
610 PACKI(desc,"W",5); /* priority */
611 PACKI(desc,"W",0); /* start time */
612 PACKI(desc,"W",0); /* until time */
613 PACKS(desc,"z",""); /* pSepFile */
614 PACKS(desc,"z","lpd"); /* pPrProc */
615 PACKS(desc,"z",SERVICE(snum)); /* pDestinations */
616 PACKS(desc,"z",""); /* pParms */
618 PACKS(desc,"z","UNKNOWN PRINTER");
619 PACKI(desc,"W",LPSTAT_ERROR);
621 else if (!status || !status->message[0]) {
622 PACKS(desc,"z",Expand(conn,snum,lp_comment(snum)));
623 PACKI(desc,"W",LPSTAT_OK); /* status */
625 PACKS(desc,"z",status->message);
626 PACKI(desc,"W",printq_status(status->status)); /* status */
628 PACKI(desc,(uLevel == 1 ? "W" : "N"),count);
631 if (uLevel == 3 || uLevel == 4) {
632 PACKI(desc,"W",5); /* uPriority */
633 PACKI(desc,"W",0); /* uStarttime */
634 PACKI(desc,"W",0); /* uUntiltime */
635 PACKI(desc,"W",5); /* pad1 */
636 PACKS(desc,"z",""); /* pszSepFile */
637 PACKS(desc,"z","WinPrint"); /* pszPrProc */
638 PACKS(desc,"z",""); /* pszParms */
639 if (!status || !status->message[0]) {
640 PACKS(desc,"z",Expand(conn,snum,lp_comment(snum))); /* pszComment */
641 PACKI(desc,"W",LPSTAT_OK); /* fsStatus */
643 PACKS(desc,"z",status->message); /* pszComment */
644 PACKI(desc,"W",printq_status(status->status)); /* fsStatus */
646 PACKI(desc,(uLevel == 3 ? "W" : "N"),count); /* cJobs */
647 PACKS(desc,"z",SERVICE(snum)); /* pszPrinters */
648 PACKS(desc,"z",lp_printerdriver(snum)); /* pszDriverName */
649 PackDriverData(desc); /* pDriverData */
652 if (uLevel == 2 || uLevel == 4) {
654 for (i=0;i<count;i++)
655 fill_printjob_info(conn,snum,uLevel == 2 ? 1 : 2,desc,&queue[i],i);
659 fill_printq_info_52(conn, snum, uLevel, desc, count, queue, status);
663 /* This function returns the number of files for a given driver */
664 static int get_printerdrivernumber(int snum)
671 lines = file_lines_load(lp_driverfile(), NULL);
673 DEBUG(3,("get_printerdrivernumber: Can't open %s - %s\n",
674 lp_driverfile(),strerror(errno)));
678 /* lookup the long printer driver name in the file description */
679 for (i=0;lines[i] && !ok; i++) {
681 if (next_token(&p,tok,":",sizeof(tok)) &&
682 (!strncmp(tok,lp_printerdriver(snum),strlen(lp_printerdriver(snum)))))
687 file_lines_free(lines);
693 if (*p++ == ':') i--;
698 /* count the number of files */
699 while (next_token(&p,tok,",",sizeof(tok)))
707 static BOOL api_DosPrintQGetInfo(connection_struct *conn,
708 uint16 vuid, char *param,char *data,
709 int mdrcnt,int mprcnt,
710 char **rdata,char **rparam,
711 int *rdata_len,int *rparam_len)
713 char *str1 = param+2;
714 char *str2 = skip_string(str1,1);
715 char *p = skip_string(str2,1);
721 struct pack_desc desc;
722 print_queue_struct *queue=NULL;
723 print_status_struct status;
725 memset((char *)&status,'\0',sizeof(status));
726 memset((char *)&desc,'\0',sizeof(desc));
728 p = skip_string(p,1);
732 /* remove any trailing username */
733 if ((p = strchr(QueueName,'%'))) *p = 0;
735 DEBUG(3,("PrintQueue uLevel=%d name=%s\n",uLevel,QueueName));
737 /* check it's a supported varient */
738 if (!prefix_ok(str1,"zWrLh")) return False;
739 if (!check_printq_info(&desc,uLevel,str2,str3)) {
741 * Patch from Scott Moomaw <scott@bridgewater.edu>
742 * to return the 'invalid info level' error if an
743 * unknown level was requested.
747 *rparam = REALLOC(*rparam,*rparam_len);
748 SSVALS(*rparam,0,ERROR_INVALID_LEVEL);
754 snum = lp_servicenumber(QueueName);
755 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
756 int pnum = lp_servicenumber(PRINTERS_NAME);
758 lp_add_printer(QueueName,pnum);
759 snum = lp_servicenumber(QueueName);
763 if (snum < 0 || !VALID_SNUM(snum)) return(False);
766 count = get_printerdrivernumber(snum);
767 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count));
769 count = print_queue_status(snum, &queue,&status);
772 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
774 desc.buflen = mdrcnt;
775 if (init_package(&desc,1,count)) {
776 desc.subcount = count;
777 fill_printq_info(conn,snum,uLevel,&desc,count,queue,&status);
778 } else if(uLevel == 0) {
780 * This is a *disgusting* hack.
781 * This is *so* bad that even I'm embarrassed (and I
782 * have no shame). Here's the deal :
783 * Until we get the correct SPOOLSS code into smbd
784 * then when we're running with NT SMB support then
785 * NT makes this call with a level of zero, and then
786 * immediately follows it with an open request to
787 * the \\SRVSVC pipe. If we allow that open to
788 * succeed then NT barfs when it cannot open the
789 * \\SPOOLSS pipe immediately after and continually
790 * whines saying "Printer name is invalid" forever
791 * after. If we cause *JUST THIS NEXT OPEN* of \\SRVSVC
792 * to fail, then NT downgrades to using the downlevel code
793 * and everything works as well as before. I hate
794 * myself for adding this code.... JRA.
797 fail_next_srvsvc_open();
800 *rdata_len = desc.usedlen;
803 *rparam = REALLOC(*rparam,*rparam_len);
804 SSVALS(*rparam,0,desc.errcode);
806 SSVAL(*rparam,4,desc.neededlen);
808 DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode));
810 if (queue) free(queue);
816 /****************************************************************************
817 view list of all print jobs on all queues
818 ****************************************************************************/
819 static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid, char* param, char* data,
820 int mdrcnt, int mprcnt,
821 char **rdata, char** rparam,
822 int *rdata_len, int *rparam_len)
824 char *param_format = param+2;
825 char *output_format1 = skip_string(param_format,1);
826 char *p = skip_string(output_format1,1);
827 int uLevel = SVAL(p,0);
828 char *output_format2 = p + 4;
829 int services = lp_numservices();
831 struct pack_desc desc;
832 print_queue_struct **queue = NULL;
833 print_status_struct *status = NULL;
834 int* subcntarr = NULL;
835 int queuecnt, subcnt=0, succnt=0;
837 memset((char *)&desc,'\0',sizeof(desc));
839 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
841 if (!prefix_ok(param_format,"WrLeh")) return False;
842 if (!check_printq_info(&desc,uLevel,output_format1,output_format2)) {
844 * Patch from Scott Moomaw <scott@bridgewater.edu>
845 * to return the 'invalid info level' error if an
846 * unknown level was requested.
850 *rparam = REALLOC(*rparam,*rparam_len);
851 SSVALS(*rparam,0,ERROR_INVALID_LEVEL);
858 for (i = 0; i < services; i++)
859 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
862 if((queue = (print_queue_struct**)malloc(queuecnt*sizeof(print_queue_struct*))) == NULL) {
863 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
866 memset(queue,0,queuecnt*sizeof(print_queue_struct*));
867 if((status = (print_status_struct*)malloc(queuecnt*sizeof(print_status_struct))) == NULL) {
868 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
871 memset(status,0,queuecnt*sizeof(print_status_struct));
872 if((subcntarr = (int*)malloc(queuecnt*sizeof(int))) == NULL) {
873 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
878 for (i = 0; i < services; i++)
879 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
880 subcntarr[n] = print_queue_status(i, &queue[n],&status[n]);
881 subcnt += subcntarr[n];
885 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
887 desc.buflen = mdrcnt;
889 if (init_package(&desc,queuecnt,subcnt)) {
892 for (i = 0; i < services; i++)
893 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
894 fill_printq_info(conn,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]);
896 if (desc.errcode == NERR_Success) succnt = n;
900 if (subcntarr) free(subcntarr);
902 *rdata_len = desc.usedlen;
904 *rparam = REALLOC(*rparam,*rparam_len);
905 SSVALS(*rparam,0,desc.errcode);
907 SSVAL(*rparam,4,succnt);
908 SSVAL(*rparam,6,queuecnt);
910 for (i = 0; i < queuecnt; i++) {
911 if (queue && queue[i]) free(queue[i]);
914 if (queue) free(queue);
915 if (status) free(status);
920 /****************************************************************************
921 get info level for a server list query
922 ****************************************************************************/
923 static BOOL check_server_info(int uLevel, char* id)
927 if (strcmp(id,"B16") != 0) return False;
930 if (strcmp(id,"B16BBDz") != 0) return False;
938 struct srv_info_struct
948 /*******************************************************************
949 get server info lists from the files saved by nmbd. Return the
951 ******************************************************************/
952 static int get_server_info(uint32 servertype,
953 struct srv_info_struct **servers,
959 BOOL local_list_only;
962 lines = file_lines_load(lock_path(SERVER_LIST), NULL);
964 DEBUG(4,("Can't open %s - %s\n",lock_path(SERVER_LIST),strerror(errno)));
968 /* request for everything is code for request all servers */
969 if (servertype == SV_TYPE_ALL)
970 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
972 local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY);
974 DEBUG(4,("Servertype search: %8x\n",servertype));
976 for (i=0;lines[i];i++) {
978 struct srv_info_struct *s;
979 char *ptr = lines[i];
984 if (count == alloced) {
986 (*servers) = (struct srv_info_struct *)
987 Realloc(*servers,sizeof(**servers)*alloced);
988 if (!(*servers)) return(0);
989 memset((char *)((*servers)+count),'\0',sizeof(**servers)*(alloced-count));
991 s = &(*servers)[count];
993 if (!next_token(&ptr,s->name , NULL, sizeof(s->name))) continue;
994 if (!next_token(&ptr,stype , NULL, sizeof(stype))) continue;
995 if (!next_token(&ptr,s->comment, NULL, sizeof(s->comment))) continue;
996 if (!next_token(&ptr,s->domain , NULL, sizeof(s->domain))) {
997 /* this allows us to cope with an old nmbd */
998 pstrcpy(s->domain,global_myworkgroup);
1001 if (sscanf(stype,"%X",&s->type) != 1) {
1002 DEBUG(4,("r:host file "));
1006 /* Filter the servers/domains we return based on what was asked for. */
1008 /* Check to see if we are being asked for a local list only. */
1009 if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) {
1010 DEBUG(4,("r: local list only"));
1014 /* doesn't match up: don't want it */
1015 if (!(servertype & s->type)) {
1016 DEBUG(4,("r:serv type "));
1020 if ((servertype & SV_TYPE_DOMAIN_ENUM) !=
1021 (s->type & SV_TYPE_DOMAIN_ENUM))
1023 DEBUG(4,("s: dom mismatch "));
1027 if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM))
1032 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1033 s->type &= ~SV_TYPE_LOCAL_LIST_ONLY;
1037 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1038 s->name, s->type, s->comment, s->domain));
1040 s->server_added = True;
1045 DEBUG(4,("%20s %8x %25s %15s\n",
1046 s->name, s->type, s->comment, s->domain));
1050 file_lines_free(lines);
1055 /*******************************************************************
1056 fill in a server info structure
1057 ******************************************************************/
1058 static int fill_srv_info(struct srv_info_struct *service,
1059 int uLevel, char **buf, int *buflen,
1060 char **stringbuf, int *stringspace, char *baseaddr)
1069 case 0: struct_len = 16; break;
1070 case 1: struct_len = 26; break;
1080 len = strlen(service->comment)+1;
1084 if (buflen) *buflen = struct_len;
1085 if (stringspace) *stringspace = len;
1086 return struct_len + len;
1091 if (*buflen < struct_len) return -1;
1099 p2 = p + struct_len;
1100 l2 = *buflen - struct_len;
1102 if (!baseaddr) baseaddr = p;
1107 StrnCpy(p,service->name,15);
1111 StrnCpy(p,service->name,15);
1112 SIVAL(p,18,service->type);
1113 SIVAL(p,22,PTR_DIFF(p2,baseaddr));
1114 len += CopyAndAdvance(&p2,service->comment,&l2);
1120 *buf = p + struct_len;
1121 *buflen -= struct_len;
1134 static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
1136 return(strcmp(s1->name,s2->name));
1139 /****************************************************************************
1140 view list of servers available (or possibly domains). The info is
1141 extracted from lists saved by nmbd on the local host
1142 ****************************************************************************/
1143 static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid, char *param, char *data,
1144 int mdrcnt, int mprcnt, char **rdata,
1145 char **rparam, int *rdata_len, int *rparam_len)
1147 char *str1 = param+2;
1148 char *str2 = skip_string(str1,1);
1149 char *p = skip_string(str2,1);
1150 int uLevel = SVAL(p,0);
1151 int buf_len = SVAL(p,2);
1152 uint32 servertype = IVAL(p,4);
1154 int data_len, fixed_len, string_len;
1155 int f_len = 0, s_len = 0;
1156 struct srv_info_struct *servers=NULL;
1157 int counted=0,total=0;
1160 BOOL domain_request;
1163 /* If someone sets all the bits they don't really mean to set
1164 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1167 if (servertype == SV_TYPE_ALL)
1168 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1170 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1171 any other bit (they may just set this bit on it's own) they
1172 want all the locally seen servers. However this bit can be
1173 set on its own so set the requested servers to be
1174 ALL - DOMAIN_ENUM. */
1176 if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM))
1177 servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
1179 domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
1180 local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
1184 if (!prefix_ok(str1,"WrLehD")) return False;
1185 if (!check_server_info(uLevel,str2)) return False;
1187 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1188 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1189 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1191 if (strcmp(str1, "WrLehDz") == 0) {
1192 StrnCpy(domain, p, sizeof(fstring)-1);
1194 StrnCpy(domain, global_myworkgroup, sizeof(fstring)-1);
1197 if (lp_browse_list())
1198 total = get_server_info(servertype,&servers,domain);
1200 data_len = fixed_len = string_len = 0;
1203 qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
1206 char *lastname=NULL;
1208 for (i=0;i<total;i++)
1210 struct srv_info_struct *s = &servers[i];
1211 if (lastname && strequal(lastname,s->name)) continue;
1213 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1214 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1215 s->name, s->type, s->comment, s->domain));
1217 if (data_len <= buf_len) {
1220 string_len += s_len;
1227 *rdata_len = fixed_len + string_len;
1228 *rdata = REALLOC(*rdata,*rdata_len);
1229 memset(*rdata,'\0',*rdata_len);
1231 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1237 char *lastname=NULL;
1238 int count2 = counted;
1239 for (i = 0; i < total && count2;i++)
1241 struct srv_info_struct *s = &servers[i];
1242 if (lastname && strequal(lastname,s->name)) continue;
1244 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1245 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1246 s->name, s->type, s->comment, s->domain));
1252 *rparam = REALLOC(*rparam,*rparam_len);
1253 SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata));
1255 SSVAL(*rparam,4,counted);
1256 SSVAL(*rparam,6,counted+missed);
1258 if (servers) free(servers);
1260 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1261 domain,uLevel,counted,counted+missed));
1266 /****************************************************************************
1267 command 0x34 - suspected of being a "Lookup Names" stub api
1268 ****************************************************************************/
1269 static BOOL api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid, char *param, char *data,
1270 int mdrcnt, int mprcnt, char **rdata,
1271 char **rparam, int *rdata_len, int *rparam_len)
1273 char *str1 = param+2;
1274 char *str2 = skip_string(str1,1);
1275 char *p = skip_string(str2,1);
1276 int uLevel = SVAL(p,0);
1277 int buf_len = SVAL(p,2);
1281 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1282 str1, str2, p, uLevel, buf_len));
1284 if (!prefix_ok(str1,"zWrLeh")) return False;
1289 *rparam = REALLOC(*rparam,*rparam_len);
1291 SSVAL(*rparam,0,0x08AC); /* informational warning message */
1293 SSVAL(*rparam,4,counted);
1294 SSVAL(*rparam,6,counted+missed);
1299 /****************************************************************************
1300 get info about a share
1301 ****************************************************************************/
1302 static BOOL check_share_info(int uLevel, char* id)
1306 if (strcmp(id,"B13") != 0) return False;
1309 if (strcmp(id,"B13BWz") != 0) return False;
1312 if (strcmp(id,"B13BWzWWWzB9B") != 0) return False;
1315 if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) return False;
1317 default: return False;
1322 static int fill_share_info(connection_struct *conn, int snum, int uLevel,
1323 char** buf, int* buflen,
1324 char** stringbuf, int* stringspace, char* baseaddr)
1333 case 0: struct_len = 13; break;
1334 case 1: struct_len = 20; break;
1335 case 2: struct_len = 40; break;
1336 case 91: struct_len = 68; break;
1344 if (uLevel > 0) len += StrlenExpanded(conn,snum,lp_comment(snum));
1345 if (uLevel > 1) len += strlen(lp_pathname(snum)) + 1;
1346 if (buflen) *buflen = struct_len;
1347 if (stringspace) *stringspace = len;
1348 return struct_len + len;
1353 if ((*buflen) < struct_len) return -1;
1361 p2 = p + struct_len;
1362 l2 = (*buflen) - struct_len;
1364 if (!baseaddr) baseaddr = p;
1366 StrnCpy(p,lp_servicename(snum),13);
1372 type = STYPE_DISKTREE;
1373 if (lp_print_ok(snum)) type = STYPE_PRINTQ;
1374 if (strequal("IPC$",lp_servicename(snum))) type = STYPE_IPC;
1375 SSVAL(p,14,type); /* device type */
1376 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1377 len += CopyExpanded(conn,snum,&p2,lp_comment(snum),&l2);
1382 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1383 SSVALS(p,22,-1); /* max uses */
1384 SSVAL(p,24,1); /* current uses */
1385 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1386 len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1387 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1392 memset(p+40,0,SHPWLEN+2);
1404 (*buf) = p + struct_len;
1405 (*buflen) -= struct_len;
1407 (*stringspace) = l2;
1417 static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
1418 int mdrcnt,int mprcnt,
1419 char **rdata,char **rparam,
1420 int *rdata_len,int *rparam_len)
1422 char *str1 = param+2;
1423 char *str2 = skip_string(str1,1);
1424 char *netname = skip_string(str2,1);
1425 char *p = skip_string(netname,1);
1426 int uLevel = SVAL(p,0);
1427 int snum = find_service(netname);
1429 if (snum < 0) return False;
1431 /* check it's a supported varient */
1432 if (!prefix_ok(str1,"zWrLh")) return False;
1433 if (!check_share_info(uLevel,str2)) return False;
1435 *rdata = REALLOC(*rdata,mdrcnt);
1437 *rdata_len = fill_share_info(conn,snum,uLevel,&p,&mdrcnt,0,0,0);
1438 if (*rdata_len < 0) return False;
1441 *rparam = REALLOC(*rparam,*rparam_len);
1442 SSVAL(*rparam,0,NERR_Success);
1443 SSVAL(*rparam,2,0); /* converter word */
1444 SSVAL(*rparam,4,*rdata_len);
1449 /****************************************************************************
1450 view list of shares available
1451 ****************************************************************************/
1452 static BOOL api_RNetShareEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
1453 int mdrcnt,int mprcnt,
1454 char **rdata,char **rparam,
1455 int *rdata_len,int *rparam_len)
1457 char *str1 = param+2;
1458 char *str2 = skip_string(str1,1);
1459 char *p = skip_string(str2,1);
1460 int uLevel = SVAL(p,0);
1461 int buf_len = SVAL(p,2);
1463 int count=lp_numservices();
1464 int total=0,counted=0;
1465 BOOL missed = False;
1467 int data_len, fixed_len, string_len;
1468 int f_len = 0, s_len = 0;
1470 if (!prefix_ok(str1,"WrLeh")) return False;
1471 if (!check_share_info(uLevel,str2)) return False;
1473 data_len = fixed_len = string_len = 0;
1474 for (i=0;i<count;i++)
1475 if (lp_browseable(i) && lp_snum_ok(i))
1478 data_len += fill_share_info(conn,i,uLevel,0,&f_len,0,&s_len,0);
1479 if (data_len <= buf_len)
1483 string_len += s_len;
1488 *rdata_len = fixed_len + string_len;
1489 *rdata = REALLOC(*rdata,*rdata_len);
1490 memset(*rdata,0,*rdata_len);
1492 p2 = (*rdata) + fixed_len; /* auxillery data (strings) will go here */
1496 for (i = 0; i < count;i++)
1497 if (lp_browseable(i) && lp_snum_ok(i))
1498 if (fill_share_info(conn,i,uLevel,&p,&f_len,&p2,&s_len,*rdata) < 0)
1502 *rparam = REALLOC(*rparam,*rparam_len);
1503 SSVAL(*rparam,0,missed ? ERRmoredata : NERR_Success);
1505 SSVAL(*rparam,4,counted);
1506 SSVAL(*rparam,6,total);
1508 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1509 counted,total,uLevel,
1510 buf_len,*rdata_len,mdrcnt));
1516 /****************************************************************************
1517 get the time of day info
1518 ****************************************************************************/
1519 static BOOL api_NetRemoteTOD(connection_struct *conn,uint16 vuid, char *param,char *data,
1520 int mdrcnt,int mprcnt,
1521 char **rdata,char **rparam,
1522 int *rdata_len,int *rparam_len)
1526 *rparam = REALLOC(*rparam,*rparam_len);
1529 *rdata = REALLOC(*rdata,*rdata_len);
1531 SSVAL(*rparam,0,NERR_Success);
1532 SSVAL(*rparam,2,0); /* converter word */
1538 time_t unixdate = time(NULL);
1540 put_dos_date3(p,0,unixdate); /* this is the time that is looked at
1541 by NT in a "net time" operation,
1542 it seems to ignore the one below */
1544 /* the client expects to get localtime, not GMT, in this bit
1545 (I think, this needs testing) */
1546 t = LocalTime(&unixdate);
1548 SIVAL(p,4,0); /* msecs ? */
1549 CVAL(p,8) = t->tm_hour;
1550 CVAL(p,9) = t->tm_min;
1551 CVAL(p,10) = t->tm_sec;
1552 CVAL(p,11) = 0; /* hundredths of seconds */
1553 SSVALS(p,12,TimeDiff(unixdate)/60); /* timezone in minutes from GMT */
1554 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
1555 CVAL(p,16) = t->tm_mday;
1556 CVAL(p,17) = t->tm_mon + 1;
1557 SSVAL(p,18,1900+t->tm_year);
1558 CVAL(p,20) = t->tm_wday;
1565 /****************************************************************************
1566 Set the user password.
1567 *****************************************************************************/
1569 static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param,char *data,
1570 int mdrcnt,int mprcnt,
1571 char **rdata,char **rparam,
1572 int *rdata_len,int *rparam_len)
1574 char *p = skip_string(param+2,2);
1576 fstring pass1,pass2;
1580 p = skip_string(p,1);
1582 memset(pass1,'\0',sizeof(pass1));
1583 memset(pass2,'\0',sizeof(pass2));
1585 memcpy(pass2,p+16,16);
1588 *rparam = REALLOC(*rparam,*rparam_len);
1592 SSVAL(*rparam,0,NERR_badpass);
1593 SSVAL(*rparam,2,0); /* converter word */
1595 DEBUG(3,("Set password for <%s>\n",user));
1598 * Pass the user through the NT -> unix user mapping
1602 (void)map_username(user);
1605 * Do any UNIX username case mangling.
1607 (void)Get_Pwnam( user, True);
1610 * Attempt to verify the old password against smbpasswd entries
1611 * Win98 clients send old and new password in plaintext for this call.
1615 fstring saved_pass2;
1616 struct smb_passwd *smbpw = NULL;
1619 * Save the new password as change_oem_password overwrites it
1623 fstrcpy(saved_pass2, pass2);
1625 if (check_plaintext_password(user,pass1,strlen(pass1),&smbpw) &&
1626 change_oem_password(smbpw,pass2,False))
1628 SSVAL(*rparam,0,NERR_Success);
1631 * If unix password sync was requested, attempt to change
1632 * the /etc/passwd database also. Return failure if this cannot
1636 if(lp_unix_password_sync() && !chgpasswd(user,pass1,saved_pass2,False))
1637 SSVAL(*rparam,0,NERR_badpass);
1642 * If the above failed, attempt the plaintext password change.
1643 * This tests against the /etc/passwd database only.
1646 if(SVAL(*rparam,0) != NERR_Success)
1648 if (password_ok(user, pass1,strlen(pass1),NULL) &&
1649 chgpasswd(user,pass1,pass2,False))
1651 SSVAL(*rparam,0,NERR_Success);
1656 * If the plaintext change failed, attempt
1657 * the old encrypted method. NT will generate this
1658 * after trying the samr method. Note that this
1659 * method is done as a last resort as this
1660 * password change method loses the NT password hash
1661 * and cannot change the UNIX password as no plaintext
1665 if(SVAL(*rparam,0) != NERR_Success)
1667 struct smb_passwd *sampw = NULL;
1669 if(check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &sampw) &&
1670 change_lanman_password(sampw,(unsigned char *)pass1,(unsigned char *)pass2))
1672 SSVAL(*rparam,0,NERR_Success);
1676 memset((char *)pass1,'\0',sizeof(fstring));
1677 memset((char *)pass2,'\0',sizeof(fstring));
1682 /****************************************************************************
1683 Set the user password (SamOEM version - gets plaintext).
1684 ****************************************************************************/
1686 static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char *param,char *data,
1687 int mdrcnt,int mprcnt,
1688 char **rdata,char **rparam,
1689 int *rdata_len,int *rparam_len)
1692 char *p = param + 2;
1694 *rparam = REALLOC(*rparam,*rparam_len);
1698 SSVAL(*rparam,0,NERR_badpass);
1701 * Check the parameter definition is correct.
1703 if(!strequal(param + 2, "zsT")) {
1704 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", param + 2));
1707 p = skip_string(p, 1);
1709 if(!strequal(p, "B516B16")) {
1710 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p));
1713 p = skip_string(p,1);
1716 p = skip_string(p,1);
1718 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user));
1721 * Pass the user through the NT -> unix user mapping
1725 (void)map_username(user);
1728 * Do any UNIX username case mangling.
1730 (void)Get_Pwnam( user, True);
1732 if (pass_oem_change(user, (uchar*) data, (uchar *)&data[516], NULL, NULL))
1734 SSVAL(*rparam,0,NERR_Success);
1740 /****************************************************************************
1743 ****************************************************************************/
1744 static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char *param,char *data,
1745 int mdrcnt,int mprcnt,
1746 char **rdata,char **rparam,
1747 int *rdata_len,int *rparam_len)
1749 int function = SVAL(param,0);
1750 char *str1 = param+2;
1751 char *str2 = skip_string(str1,1);
1752 char *p = skip_string(str2,1);
1757 /* check it's a supported varient */
1758 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
1762 *rparam = REALLOC(*rparam,*rparam_len);
1765 if (!print_job_exists(jobid)) {
1766 errcode = NERR_JobNotFound;
1770 errcode = NERR_notsupported;
1773 case 81: /* delete */
1774 if (print_job_delete(jobid)) errcode = NERR_Success;
1776 case 82: /* pause */
1777 if (print_job_pause(jobid)) errcode = NERR_Success;
1779 case 83: /* resume */
1780 if (print_job_resume(jobid)) errcode = NERR_Success;
1785 SSVAL(*rparam,0,errcode);
1786 SSVAL(*rparam,2,0); /* converter word */
1791 /****************************************************************************
1792 Purge a print queue - or pause or resume it.
1793 ****************************************************************************/
1794 static BOOL api_WPrintQueuePurge(connection_struct *conn,uint16 vuid, char *param,char *data,
1795 int mdrcnt,int mprcnt,
1796 char **rdata,char **rparam,
1797 int *rdata_len,int *rparam_len)
1799 int function = SVAL(param,0);
1800 char *str1 = param+2;
1801 char *str2 = skip_string(str1,1);
1802 char *QueueName = skip_string(str2,1);
1803 int errcode = NERR_notsupported;
1806 /* check it's a supported varient */
1807 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
1811 *rparam = REALLOC(*rparam,*rparam_len);
1814 snum = print_queue_snum(QueueName);
1817 errcode = NERR_JobNotFound;
1822 case 74: /* Pause queue */
1823 if (print_queue_pause(snum)) errcode = NERR_Success;
1825 case 75: /* Resume queue */
1826 if (print_queue_resume(snum)) errcode = NERR_Success;
1828 case 103: /* Purge */
1829 if (print_queue_purge(snum)) errcode = NERR_Success;
1834 SSVAL(*rparam,0,errcode);
1835 SSVAL(*rparam,2,0); /* converter word */
1841 /****************************************************************************
1842 set the property of a print job (undocumented?)
1843 ? function = 0xb -> set name of print job
1844 ? function = 0x6 -> move print job up/down
1845 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
1846 or <WWsTP> <WB21BB16B10zWWzDDz>
1847 ****************************************************************************/
1848 static int check_printjob_info(struct pack_desc* desc,
1849 int uLevel, char* id)
1851 desc->subformat = NULL;
1853 case 0: desc->format = "W"; break;
1854 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
1855 case 2: desc->format = "WWzWWDDzz"; break;
1856 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
1857 default: return False;
1859 if (strcmp(desc->format,id) != 0) return False;
1863 static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,char *data,
1864 int mdrcnt,int mprcnt,
1865 char **rdata,char **rparam,
1866 int *rdata_len,int *rparam_len)
1868 struct pack_desc desc;
1869 char *str1 = param+2;
1870 char *str2 = skip_string(str1,1);
1871 char *p = skip_string(str2,1);
1873 int uLevel = SVAL(p,2);
1874 int function = SVAL(p,4);
1879 *rparam = REALLOC(*rparam,*rparam_len);
1883 /* check it's a supported varient */
1884 if ((strcmp(str1,"WWsTP")) ||
1885 (!check_printjob_info(&desc,uLevel,str2)))
1888 if (!print_job_exists(jobid)) {
1889 errcode=NERR_JobNotFound;
1893 errcode = NERR_notsupported;
1897 /* change job place in the queue,
1898 data gives the new place */
1899 place = SVAL(data,0);
1900 if (print_job_set_place(jobid, place)) {
1901 errcode=NERR_Success;
1906 /* change print job name, data gives the name */
1907 if (print_job_set_name(jobid, data)) {
1908 errcode=NERR_Success;
1917 SSVALS(*rparam,0,errcode);
1918 SSVAL(*rparam,2,0); /* converter word */
1924 /****************************************************************************
1925 get info about the server
1926 ****************************************************************************/
1927 static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
1928 int mdrcnt,int mprcnt,
1929 char **rdata,char **rparam,
1930 int *rdata_len,int *rparam_len)
1932 char *str1 = param+2;
1933 char *str2 = skip_string(str1,1);
1934 char *p = skip_string(str2,1);
1935 int uLevel = SVAL(p,0);
1939 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
1941 /* check it's a supported varient */
1942 if (!prefix_ok(str1,"WrLh")) return False;
1945 if (strcmp(str2,"B16") != 0) return False;
1949 if (strcmp(str2,"B16BBDz") != 0) return False;
1953 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")
1958 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz")
1963 if (strcmp(str2,"DN") != 0) return False;
1967 if (strcmp(str2,"B16BBDzWWzzz") != 0) return False;
1970 default: return False;
1973 *rdata_len = mdrcnt;
1974 *rdata = REALLOC(*rdata,*rdata_len);
1977 p2 = p + struct_len;
1979 StrnCpy(p,local_machine,16);
1985 struct srv_info_struct *servers=NULL;
1988 uint32 servertype= lp_default_server_announce();
1990 pstrcpy(comment,string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH));
1992 if ((count=get_server_info(SV_TYPE_ALL,&servers,global_myworkgroup))>0) {
1993 for (i=0;i<count;i++)
1994 if (strequal(servers[i].name,local_machine))
1996 servertype = servers[i].type;
1997 pstrcpy(comment,servers[i].comment);
2000 if (servers) free(servers);
2002 SCVAL(p,0,lp_major_announce_version());
2003 SCVAL(p,1,lp_minor_announce_version());
2004 SIVAL(p,2,servertype);
2006 if (mdrcnt == struct_len) {
2009 SIVAL(p,6,PTR_DIFF(p2,*rdata));
2010 standard_sub_conn(conn,comment);
2011 StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
2012 p2 = skip_string(p2,1);
2017 return False; /* not yet implemented */
2020 *rdata_len = PTR_DIFF(p2,*rdata);
2023 *rparam = REALLOC(*rparam,*rparam_len);
2024 SSVAL(*rparam,0,NERR_Success);
2025 SSVAL(*rparam,2,0); /* converter word */
2026 SSVAL(*rparam,4,*rdata_len);
2032 /****************************************************************************
2033 get info about the server
2034 ****************************************************************************/
2035 static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2036 int mdrcnt,int mprcnt,
2037 char **rdata,char **rparam,
2038 int *rdata_len,int *rparam_len)
2040 char *str1 = param+2;
2041 char *str2 = skip_string(str1,1);
2042 char *p = skip_string(str2,1);
2044 extern pstring sesssetup_user;
2045 int level = SVAL(p,0);
2047 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
2050 *rparam = REALLOC(*rparam,*rparam_len);
2052 /* check it's a supported varient */
2053 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz")))
2056 *rdata_len = mdrcnt + 1024;
2057 *rdata = REALLOC(*rdata,*rdata_len);
2059 SSVAL(*rparam,0,NERR_Success);
2060 SSVAL(*rparam,2,0); /* converter word */
2066 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
2067 pstrcpy(p2,local_machine);
2069 p2 = skip_string(p2,1);
2072 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2073 pstrcpy(p2,sesssetup_user);
2074 p2 = skip_string(p2,1);
2077 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
2078 pstrcpy(p2,global_myworkgroup);
2080 p2 = skip_string(p2,1);
2083 SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
2084 SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
2087 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2088 pstrcpy(p2,global_myworkgroup); /* don't know. login domain?? */
2089 p2 = skip_string(p2,1);
2092 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
2094 p2 = skip_string(p2,1);
2097 *rdata_len = PTR_DIFF(p2,*rdata);
2099 SSVAL(*rparam,4,*rdata_len);
2104 /****************************************************************************
2105 get info about a user
2107 struct user_info_11 {
2108 char usri11_name[21]; 0-20
2110 char *usri11_comment; 22-25
2111 char *usri11_usr_comment; 26-29
2112 unsigned short usri11_priv; 30-31
2113 unsigned long usri11_auth_flags; 32-35
2114 long usri11_password_age; 36-39
2115 char *usri11_homedir; 40-43
2116 char *usri11_parms; 44-47
2117 long usri11_last_logon; 48-51
2118 long usri11_last_logoff; 52-55
2119 unsigned short usri11_bad_pw_count; 56-57
2120 unsigned short usri11_num_logons; 58-59
2121 char *usri11_logon_server; 60-63
2122 unsigned short usri11_country_code; 64-65
2123 char *usri11_workstations; 66-69
2124 unsigned long usri11_max_storage; 70-73
2125 unsigned short usri11_units_per_week; 74-75
2126 unsigned char *usri11_logon_hours; 76-79
2127 unsigned short usri11_code_page; 80-81
2132 usri11_name specifies the user name for which information is retireved
2134 usri11_pad aligns the next data structure element to a word boundary
2136 usri11_comment is a null terminated ASCII comment
2138 usri11_user_comment is a null terminated ASCII comment about the user
2140 usri11_priv specifies the level of the privilege assigned to the user.
2141 The possible values are:
2143 Name Value Description
2144 USER_PRIV_GUEST 0 Guest privilege
2145 USER_PRIV_USER 1 User privilege
2146 USER_PRV_ADMIN 2 Administrator privilege
2148 usri11_auth_flags specifies the account operator privileges. The
2149 possible values are:
2151 Name Value Description
2152 AF_OP_PRINT 0 Print operator
2155 Leach, Naik [Page 28]
\r\f
2158 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2161 AF_OP_COMM 1 Communications operator
2162 AF_OP_SERVER 2 Server operator
2163 AF_OP_ACCOUNTS 3 Accounts operator
2166 usri11_password_age specifies how many seconds have elapsed since the
2167 password was last changed.
2169 usri11_home_dir points to a null terminated ASCII string that contains
2170 the path name of the user's home directory.
2172 usri11_parms points to a null terminated ASCII string that is set
2173 aside for use by applications.
2175 usri11_last_logon specifies the time when the user last logged on.
2176 This value is stored as the number of seconds elapsed since
2177 00:00:00, January 1, 1970.
2179 usri11_last_logoff specifies the time when the user last logged off.
2180 This value is stored as the number of seconds elapsed since
2181 00:00:00, January 1, 1970. A value of 0 means the last logoff
2184 usri11_bad_pw_count specifies the number of incorrect passwords
2185 entered since the last successful logon.
2187 usri11_log1_num_logons specifies the number of times this user has
2188 logged on. A value of -1 means the number of logons is unknown.
2190 usri11_logon_server points to a null terminated ASCII string that
2191 contains the name of the server to which logon requests are sent.
2192 A null string indicates logon requests should be sent to the
2195 usri11_country_code specifies the country code for the user's language
2198 usri11_workstations points to a null terminated ASCII string that
2199 contains the names of workstations the user may log on from.
2200 There may be up to 8 workstations, with the names separated by
2201 commas. A null strings indicates there are no restrictions.
2203 usri11_max_storage specifies the maximum amount of disk space the user
2204 can occupy. A value of 0xffffffff indicates there are no
2207 usri11_units_per_week specifies the equal number of time units into
2208 which a week is divided. This value must be equal to 168.
2210 usri11_logon_hours points to a 21 byte (168 bits) string that
2211 specifies the time during which the user can log on. Each bit
2212 represents one unique hour in a week. The first bit (bit 0, word
2213 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
2217 Leach, Naik [Page 29]
\r\f
2220 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2223 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
2224 are no restrictions.
2226 usri11_code_page specifies the code page for the user's language of
2229 All of the pointers in this data structure need to be treated
2230 specially. The pointer is a 32 bit pointer. The higher 16 bits need
2231 to be ignored. The converter word returned in the parameters section
2232 needs to be subtracted from the lower 16 bits to calculate an offset
2233 into the return buffer where this ASCII string resides.
2235 There is no auxiliary data in the response.
2237 ****************************************************************************/
2239 #define usri11_name 0
2240 #define usri11_pad 21
2241 #define usri11_comment 22
2242 #define usri11_usr_comment 26
2243 #define usri11_full_name 30
2244 #define usri11_priv 34
2245 #define usri11_auth_flags 36
2246 #define usri11_password_age 40
2247 #define usri11_homedir 44
2248 #define usri11_parms 48
2249 #define usri11_last_logon 52
2250 #define usri11_last_logoff 56
2251 #define usri11_bad_pw_count 60
2252 #define usri11_num_logons 62
2253 #define usri11_logon_server 64
2254 #define usri11_country_code 68
2255 #define usri11_workstations 70
2256 #define usri11_max_storage 74
2257 #define usri11_units_per_week 78
2258 #define usri11_logon_hours 80
2259 #define usri11_code_page 84
2260 #define usri11_end 86
2262 #define USER_PRIV_GUEST 0
2263 #define USER_PRIV_USER 1
2264 #define USER_PRIV_ADMIN 2
2266 #define AF_OP_PRINT 0
2267 #define AF_OP_COMM 1
2268 #define AF_OP_SERVER 2
2269 #define AF_OP_ACCOUNTS 3
2272 static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2273 int mdrcnt,int mprcnt,
2274 char **rdata,char **rparam,
2275 int *rdata_len,int *rparam_len)
2277 char *str1 = param+2;
2278 char *str2 = skip_string(str1,1);
2279 char *UserName = skip_string(str2,1);
2280 char *p = skip_string(UserName,1);
2281 int uLevel = SVAL(p,0);
2284 /* get NIS home of a previously validated user - simeon */
2285 /* With share level security vuid will always be zero.
2286 Don't depend on vuser being non-null !!. JRA */
2287 user_struct *vuser = get_valid_user_struct(vuid);
2289 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid,
2290 vuser->user.unix_name));
2293 *rparam = REALLOC(*rparam,*rparam_len);
2295 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
2297 /* check it's a supported variant */
2298 if (strcmp(str1,"zWrLh") != 0) return False;
2301 case 0: p2 = "B21"; break;
2302 case 1: p2 = "B21BB16DWzzWz"; break;
2303 case 2: p2 = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
2304 case 10: p2 = "B21Bzzz"; break;
2305 case 11: p2 = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
2306 default: return False;
2309 if (strcmp(p2,str2) != 0) return False;
2311 *rdata_len = mdrcnt + 1024;
2312 *rdata = REALLOC(*rdata,*rdata_len);
2314 SSVAL(*rparam,0,NERR_Success);
2315 SSVAL(*rparam,2,0); /* converter word */
2318 p2 = p + usri11_end;
2321 fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
2325 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
2330 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
2331 pstrcpy(p2,"Comment");
2332 p2 = skip_string(p2,1);
2334 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
2335 pstrcpy(p2,"UserComment");
2336 p2 = skip_string(p2,1);
2338 /* EEK! the cifsrap.txt doesn't have this in!!!! */
2339 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
2340 pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName));
2341 p2 = skip_string(p2,1);
2344 if (uLevel == 11) /* modelled after NTAS 3.51 reply */
2346 SSVAL(p,usri11_priv,conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2347 SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
2348 SIVALS(p,usri11_password_age,-1); /* password age */
2349 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
2350 pstrcpy(p2, lp_logon_home());
2351 p2 = skip_string(p2,1);
2352 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
2354 p2 = skip_string(p2,1);
2355 SIVAL(p,usri11_last_logon,0); /* last logon */
2356 SIVAL(p,usri11_last_logoff,0); /* last logoff */
2357 SSVALS(p,usri11_bad_pw_count,-1); /* bad pw counts */
2358 SSVALS(p,usri11_num_logons,-1); /* num logons */
2359 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
2360 pstrcpy(p2,"\\\\*");
2361 p2 = skip_string(p2,1);
2362 SSVAL(p,usri11_country_code,0); /* country code */
2364 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
2366 p2 = skip_string(p2,1);
2368 SIVALS(p,usri11_max_storage,-1); /* max storage */
2369 SSVAL(p,usri11_units_per_week,168); /* units per week */
2370 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
2372 /* a simple way to get logon hours at all times. */
2374 SCVAL(p2,21,0); /* fix zero termination */
2375 p2 = skip_string(p2,1);
2377 SSVAL(p,usri11_code_page,0); /* code page */
2379 if (uLevel == 1 || uLevel == 2)
2381 memset(p+22,' ',16); /* password */
2382 SIVALS(p,38,-1); /* password age */
2384 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2385 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
2386 pstrcpy(p2,lp_logon_home());
2387 p2 = skip_string(p2,1);
2388 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
2390 SSVAL(p,52,0); /* flags */
2391 SIVAL(p,54,PTR_DIFF(p2,*rdata)); /* script_path */
2392 pstrcpy(p2,lp_logon_script());
2393 standard_sub_conn( conn, p2 );
2394 p2 = skip_string(p2,1);
2397 SIVAL(p,60,0); /* auth_flags */
2398 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
2399 pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName));
2400 p2 = skip_string(p2,1);
2401 SIVAL(p,68,0); /* urs_comment */
2402 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
2404 p2 = skip_string(p2,1);
2405 SIVAL(p,76,0); /* workstations */
2406 SIVAL(p,80,0); /* last_logon */
2407 SIVAL(p,84,0); /* last_logoff */
2408 SIVALS(p,88,-1); /* acct_expires */
2409 SIVALS(p,92,-1); /* max_storage */
2410 SSVAL(p,96,168); /* units_per_week */
2411 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
2414 SSVALS(p,102,-1); /* bad_pw_count */
2415 SSVALS(p,104,-1); /* num_logons */
2416 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
2417 pstrcpy(p2,"\\\\%L");
2418 standard_sub_conn(conn, p2);
2419 p2 = skip_string(p2,1);
2420 SSVAL(p,110,49); /* country_code */
2421 SSVAL(p,112,860); /* code page */
2425 *rdata_len = PTR_DIFF(p2,*rdata);
2427 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
2432 /*******************************************************************
2433 get groups that a user is a member of
2434 ******************************************************************/
2435 static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *param,char *data,
2436 int mdrcnt,int mprcnt,
2437 char **rdata,char **rparam,
2438 int *rdata_len,int *rparam_len)
2440 char *str1 = param+2;
2441 char *str2 = skip_string(str1,1);
2442 char *UserName = skip_string(str2,1);
2443 char *p = skip_string(UserName,1);
2444 int uLevel = SVAL(p,0);
2449 *rparam = REALLOC(*rparam,*rparam_len);
2451 /* check it's a supported varient */
2452 if (strcmp(str1,"zWrLeh") != 0) return False;
2454 case 0: p2 = "B21"; break;
2455 default: return False;
2457 if (strcmp(p2,str2) != 0) return False;
2459 *rdata_len = mdrcnt + 1024;
2460 *rdata = REALLOC(*rdata,*rdata_len);
2462 SSVAL(*rparam,0,NERR_Success);
2463 SSVAL(*rparam,2,0); /* converter word */
2467 /* XXXX we need a real SAM database some day */
2468 pstrcpy(p,"Users"); p += 21; count++;
2469 pstrcpy(p,"Domain Users"); p += 21; count++;
2470 pstrcpy(p,"Guests"); p += 21; count++;
2471 pstrcpy(p,"Domain Guests"); p += 21; count++;
2473 *rdata_len = PTR_DIFF(p,*rdata);
2475 SSVAL(*rparam,4,count); /* is this right?? */
2476 SSVAL(*rparam,6,count); /* is this right?? */
2482 static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param,char *data,
2483 int mdrcnt,int mprcnt,
2484 char **rdata,char **rparam,
2485 int *rdata_len,int *rparam_len)
2487 char *str1 = param+2;
2488 char *str2 = skip_string(str1,1);
2489 char *p = skip_string(str2,1);
2491 struct pack_desc desc;
2497 memset((char *)&desc,'\0',sizeof(desc));
2499 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
2501 /* check it's a supported varient */
2502 if (strcmp(str1,"OOWb54WrLh") != 0) return False;
2503 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) return False;
2504 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2506 desc.buflen = mdrcnt;
2507 desc.subformat = NULL;
2510 if (init_package(&desc,1,0))
2512 PACKI(&desc,"W",0); /* code */
2513 PACKS(&desc,"B21",name); /* eff. name */
2514 PACKS(&desc,"B",""); /* pad */
2516 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2517 PACKI(&desc,"D",0); /* auth flags XXX */
2518 PACKI(&desc,"W",0); /* num logons */
2519 PACKI(&desc,"W",0); /* bad pw count */
2520 PACKI(&desc,"D",0); /* last logon */
2521 PACKI(&desc,"D",-1); /* last logoff */
2522 PACKI(&desc,"D",-1); /* logoff time */
2523 PACKI(&desc,"D",-1); /* kickoff time */
2524 PACKI(&desc,"D",0); /* password age */
2525 PACKI(&desc,"D",0); /* password can change */
2526 PACKI(&desc,"D",-1); /* password must change */
2529 fstrcpy(mypath,"\\\\");
2530 fstrcat(mypath,local_machine);
2532 PACKS(&desc,"z",mypath); /* computer */
2534 PACKS(&desc,"z",global_myworkgroup);/* domain */
2536 /* JHT - By calling lp_logon_script() and standard_sub() we have */
2537 /* made sure all macros are fully substituted and available */
2539 pstring logon_script;
2540 pstrcpy(logon_script,lp_logon_script());
2541 standard_sub_conn( conn, logon_script );
2542 PACKS(&desc,"z", logon_script); /* script path */
2544 /* End of JHT mods */
2546 PACKI(&desc,"D",0x00000000); /* reserved */
2549 *rdata_len = desc.usedlen;
2551 *rparam = REALLOC(*rparam,*rparam_len);
2552 SSVALS(*rparam,0,desc.errcode);
2554 SSVAL(*rparam,4,desc.neededlen);
2556 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
2561 /****************************************************************************
2562 api_WAccessGetUserPerms
2563 ****************************************************************************/
2564 static BOOL api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid, char *param,char *data,
2565 int mdrcnt,int mprcnt,
2566 char **rdata,char **rparam,
2567 int *rdata_len,int *rparam_len)
2569 char *str1 = param+2;
2570 char *str2 = skip_string(str1,1);
2571 char *user = skip_string(str2,1);
2572 char *resource = skip_string(user,1);
2574 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
2576 /* check it's a supported varient */
2577 if (strcmp(str1,"zzh") != 0) return False;
2578 if (strcmp(str2,"") != 0) return False;
2581 *rparam = REALLOC(*rparam,*rparam_len);
2582 SSVALS(*rparam,0,0); /* errorcode */
2583 SSVAL(*rparam,2,0); /* converter word */
2584 SSVAL(*rparam,4,0x7f); /* permission flags */
2589 /****************************************************************************
2590 api_WPrintJobEnumerate
2591 ****************************************************************************/
2592 static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2593 int mdrcnt,int mprcnt,
2594 char **rdata,char **rparam,
2595 int *rdata_len,int *rparam_len)
2597 char *str1 = param+2;
2598 char *str2 = skip_string(str1,1);
2599 char *p = skip_string(str2,1);
2605 struct pack_desc desc;
2606 print_queue_struct *queue=NULL;
2607 print_status_struct status;
2611 memset((char *)&desc,'\0',sizeof(desc));
2612 memset((char *)&status,'\0',sizeof(status));
2614 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
2616 /* check it's a supported varient */
2617 if (strcmp(str1,"WWrLh") != 0) return False;
2618 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2621 snum = print_job_snum(job);
2623 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2625 count = print_queue_status(snum,&queue,&status);
2626 for (i = 0; i < count; i++) {
2627 if (queue[i].job == job) break;
2629 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2631 desc.buflen = mdrcnt;
2633 if (init_package(&desc,1,0)) {
2635 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
2636 *rdata_len = desc.usedlen;
2639 desc.errcode = NERR_JobNotFound;
2645 *rparam = REALLOC(*rparam,*rparam_len);
2646 SSVALS(*rparam,0,desc.errcode);
2648 SSVAL(*rparam,4,desc.neededlen);
2650 if (queue) free(queue);
2652 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
2656 static BOOL api_WPrintJobEnumerate(connection_struct *conn,uint16 vuid, char *param,char *data,
2657 int mdrcnt,int mprcnt,
2658 char **rdata,char **rparam,
2659 int *rdata_len,int *rparam_len)
2661 char *str1 = param+2;
2662 char *str2 = skip_string(str1,1);
2663 char *p = skip_string(str2,1);
2669 struct pack_desc desc;
2670 print_queue_struct *queue=NULL;
2671 print_status_struct status;
2673 memset((char *)&desc,'\0',sizeof(desc));
2674 memset((char *)&status,'\0',sizeof(status));
2676 p = skip_string(p,1);
2679 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
2681 /* check it's a supported varient */
2682 if (strcmp(str1,"zWrLeh") != 0) return False;
2683 if (uLevel > 2) return False; /* defined only for uLevel 0,1,2 */
2684 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2686 snum = lp_servicenumber(name);
2687 if (snum < 0 && pcap_printername_ok(name,NULL)) {
2688 int pnum = lp_servicenumber(PRINTERS_NAME);
2690 lp_add_printer(name,pnum);
2691 snum = lp_servicenumber(name);
2695 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2697 count = print_queue_status(snum,&queue,&status);
2698 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2700 desc.buflen = mdrcnt;
2702 if (init_package(&desc,count,0)) {
2704 for (i = 0; i < count; i++) {
2705 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
2706 if (desc.errcode == NERR_Success) succnt = i+1;
2710 *rdata_len = desc.usedlen;
2713 *rparam = REALLOC(*rparam,*rparam_len);
2714 SSVALS(*rparam,0,desc.errcode);
2716 SSVAL(*rparam,4,succnt);
2717 SSVAL(*rparam,6,count);
2719 if (queue) free(queue);
2721 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
2725 static int check_printdest_info(struct pack_desc* desc,
2726 int uLevel, char* id)
2728 desc->subformat = NULL;
2730 case 0: desc->format = "B9"; break;
2731 case 1: desc->format = "B9B21WWzW"; break;
2732 case 2: desc->format = "z"; break;
2733 case 3: desc->format = "zzzWWzzzWW"; break;
2734 default: return False;
2736 if (strcmp(desc->format,id) != 0) return False;
2740 static void fill_printdest_info(connection_struct *conn, int snum, int uLevel,
2741 struct pack_desc* desc)
2744 strncpy(buf,SERVICE(snum),sizeof(buf)-1);
2745 buf[sizeof(buf)-1] = 0;
2748 PACKS(desc,"B9",buf); /* szName */
2750 PACKS(desc,"B21",""); /* szUserName */
2751 PACKI(desc,"W",0); /* uJobId */
2752 PACKI(desc,"W",0); /* fsStatus */
2753 PACKS(desc,"z",""); /* pszStatus */
2754 PACKI(desc,"W",0); /* time */
2757 if (uLevel == 2 || uLevel == 3) {
2758 PACKS(desc,"z",buf); /* pszPrinterName */
2760 PACKS(desc,"z",""); /* pszUserName */
2761 PACKS(desc,"z",""); /* pszLogAddr */
2762 PACKI(desc,"W",0); /* uJobId */
2763 PACKI(desc,"W",0); /* fsStatus */
2764 PACKS(desc,"z",""); /* pszStatus */
2765 PACKS(desc,"z",""); /* pszComment */
2766 PACKS(desc,"z","NULL"); /* pszDrivers */
2767 PACKI(desc,"W",0); /* time */
2768 PACKI(desc,"W",0); /* pad1 */
2773 static BOOL api_WPrintDestGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2774 int mdrcnt,int mprcnt,
2775 char **rdata,char **rparam,
2776 int *rdata_len,int *rparam_len)
2778 char *str1 = param+2;
2779 char *str2 = skip_string(str1,1);
2780 char *p = skip_string(str2,1);
2781 char* PrinterName = p;
2783 struct pack_desc desc;
2786 memset((char *)&desc,'\0',sizeof(desc));
2788 p = skip_string(p,1);
2791 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
2793 /* check it's a supported varient */
2794 if (strcmp(str1,"zWrLh") != 0) return False;
2795 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2797 snum = lp_servicenumber(PrinterName);
2798 if (snum < 0 && pcap_printername_ok(PrinterName,NULL)) {
2799 int pnum = lp_servicenumber(PRINTERS_NAME);
2801 lp_add_printer(PrinterName,pnum);
2802 snum = lp_servicenumber(PrinterName);
2808 desc.errcode = NERR_DestNotFound;
2812 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2814 desc.buflen = mdrcnt;
2815 if (init_package(&desc,1,0)) {
2816 fill_printdest_info(conn,snum,uLevel,&desc);
2818 *rdata_len = desc.usedlen;
2822 *rparam = REALLOC(*rparam,*rparam_len);
2823 SSVALS(*rparam,0,desc.errcode);
2825 SSVAL(*rparam,4,desc.neededlen);
2827 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
2831 static BOOL api_WPrintDestEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
2832 int mdrcnt,int mprcnt,
2833 char **rdata,char **rparam,
2834 int *rdata_len,int *rparam_len)
2836 char *str1 = param+2;
2837 char *str2 = skip_string(str1,1);
2838 char *p = skip_string(str2,1);
2842 struct pack_desc desc;
2843 int services = lp_numservices();
2845 memset((char *)&desc,'\0',sizeof(desc));
2849 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
2851 /* check it's a supported varient */
2852 if (strcmp(str1,"WrLeh") != 0) return False;
2853 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2856 for (i = 0; i < services; i++)
2857 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
2860 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2862 desc.buflen = mdrcnt;
2863 if (init_package(&desc,queuecnt,0)) {
2866 for (i = 0; i < services; i++) {
2867 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
2868 fill_printdest_info(conn,i,uLevel,&desc);
2870 if (desc.errcode == NERR_Success) succnt = n;
2875 *rdata_len = desc.usedlen;
2878 *rparam = REALLOC(*rparam,*rparam_len);
2879 SSVALS(*rparam,0,desc.errcode);
2881 SSVAL(*rparam,4,succnt);
2882 SSVAL(*rparam,6,queuecnt);
2884 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
2888 static BOOL api_WPrintDriverEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
2889 int mdrcnt,int mprcnt,
2890 char **rdata,char **rparam,
2891 int *rdata_len,int *rparam_len)
2893 char *str1 = param+2;
2894 char *str2 = skip_string(str1,1);
2895 char *p = skip_string(str2,1);
2898 struct pack_desc desc;
2900 memset((char *)&desc,'\0',sizeof(desc));
2904 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
2906 /* check it's a supported varient */
2907 if (strcmp(str1,"WrLeh") != 0) return False;
2908 if (uLevel != 0 || strcmp(str2,"B41") != 0) return False;
2910 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2912 desc.buflen = mdrcnt;
2913 if (init_package(&desc,1,0)) {
2914 PACKS(&desc,"B41","NULL");
2917 succnt = (desc.errcode == NERR_Success ? 1 : 0);
2919 *rdata_len = desc.usedlen;
2922 *rparam = REALLOC(*rparam,*rparam_len);
2923 SSVALS(*rparam,0,desc.errcode);
2925 SSVAL(*rparam,4,succnt);
2928 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
2932 static BOOL api_WPrintQProcEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
2933 int mdrcnt,int mprcnt,
2934 char **rdata,char **rparam,
2935 int *rdata_len,int *rparam_len)
2937 char *str1 = param+2;
2938 char *str2 = skip_string(str1,1);
2939 char *p = skip_string(str2,1);
2942 struct pack_desc desc;
2944 memset((char *)&desc,'\0',sizeof(desc));
2948 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
2950 /* check it's a supported varient */
2951 if (strcmp(str1,"WrLeh") != 0) return False;
2952 if (uLevel != 0 || strcmp(str2,"B13") != 0) return False;
2954 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2956 desc.buflen = mdrcnt;
2958 if (init_package(&desc,1,0)) {
2959 PACKS(&desc,"B13","lpd");
2962 succnt = (desc.errcode == NERR_Success ? 1 : 0);
2964 *rdata_len = desc.usedlen;
2967 *rparam = REALLOC(*rparam,*rparam_len);
2968 SSVALS(*rparam,0,desc.errcode);
2970 SSVAL(*rparam,4,succnt);
2973 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
2977 static BOOL api_WPrintPortEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
2978 int mdrcnt,int mprcnt,
2979 char **rdata,char **rparam,
2980 int *rdata_len,int *rparam_len)
2982 char *str1 = param+2;
2983 char *str2 = skip_string(str1,1);
2984 char *p = skip_string(str2,1);
2987 struct pack_desc desc;
2989 memset((char *)&desc,'\0',sizeof(desc));
2993 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
2995 /* check it's a supported varient */
2996 if (strcmp(str1,"WrLeh") != 0) return False;
2997 if (uLevel != 0 || strcmp(str2,"B9") != 0) return False;
2999 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3000 memset((char *)&desc,'\0',sizeof(desc));
3002 desc.buflen = mdrcnt;
3004 if (init_package(&desc,1,0)) {
3005 PACKS(&desc,"B13","lp0");
3008 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3010 *rdata_len = desc.usedlen;
3013 *rparam = REALLOC(*rparam,*rparam_len);
3014 SSVALS(*rparam,0,desc.errcode);
3016 SSVAL(*rparam,4,succnt);
3019 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
3023 /****************************************************************************
3024 The buffer was too small
3025 ****************************************************************************/
3027 static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param,char *data,
3028 int mdrcnt,int mprcnt,
3029 char **rdata,char **rparam,
3030 int *rdata_len,int *rparam_len)
3032 *rparam_len = MIN(*rparam_len,mprcnt);
3033 *rparam = REALLOC(*rparam,*rparam_len);
3037 SSVAL(*rparam,0,NERR_BufTooSmall);
3039 DEBUG(3,("Supplied buffer too small in API command\n"));
3045 /****************************************************************************
3046 The request is not supported
3047 ****************************************************************************/
3049 static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param,char *data,
3050 int mdrcnt,int mprcnt,
3051 char **rdata,char **rparam,
3052 int *rdata_len,int *rparam_len)
3055 *rparam = REALLOC(*rparam,*rparam_len);
3059 SSVAL(*rparam,0,NERR_notsupported);
3060 SSVAL(*rparam,2,0); /* converter word */
3062 DEBUG(3,("Unsupported API command\n"));
3074 BOOL (*fn)(connection_struct *,uint16,char *,char *,
3075 int,int,char **,char **,int *,int *);
3077 } api_commands[] = {
3078 {"RNetShareEnum", 0, api_RNetShareEnum,0},
3079 {"RNetShareGetInfo", 1, api_RNetShareGetInfo,0},
3080 {"RNetServerGetInfo", 13, api_RNetServerGetInfo,0},
3081 {"RNetGroupGetUsers", 52, api_RNetGroupGetUsers,0},
3082 {"RNetUserGetInfo", 56, api_RNetUserGetInfo,0},
3083 {"NetUserGetGroups", 59, api_NetUserGetGroups,0},
3084 {"NetWkstaGetInfo", 63, api_NetWkstaGetInfo,0},
3085 {"DosPrintQEnum", 69, api_DosPrintQEnum,0},
3086 {"DosPrintQGetInfo", 70, api_DosPrintQGetInfo,0},
3087 {"WPrintQueuePause", 74, api_WPrintQueuePurge,0},
3088 {"WPrintQueueResume", 75, api_WPrintQueuePurge,0},
3089 {"WPrintJobEnumerate",76, api_WPrintJobEnumerate,0},
3090 {"WPrintJobGetInfo", 77, api_WPrintJobGetInfo,0},
3091 {"RDosPrintJobDel", 81, api_RDosPrintJobDel,0},
3092 {"RDosPrintJobPause", 82, api_RDosPrintJobDel,0},
3093 {"RDosPrintJobResume",83, api_RDosPrintJobDel,0},
3094 {"WPrintDestEnum", 84, api_WPrintDestEnum,0},
3095 {"WPrintDestGetInfo", 85, api_WPrintDestGetInfo,0},
3096 {"NetRemoteTOD", 91, api_NetRemoteTOD,0},
3097 {"WPrintQueuePurge", 103, api_WPrintQueuePurge,0},
3098 {"NetServerEnum", 104, api_RNetServerEnum,0},
3099 {"WAccessGetUserPerms",105, api_WAccessGetUserPerms,0},
3100 {"SetUserPassword", 115, api_SetUserPassword,0},
3101 {"WWkstaUserLogon", 132, api_WWkstaUserLogon,0},
3102 {"PrintJobInfo", 147, api_PrintJobInfo,0},
3103 {"WPrintDriverEnum", 205, api_WPrintDriverEnum,0},
3104 {"WPrintQProcEnum", 206, api_WPrintQProcEnum,0},
3105 {"WPrintPortEnum", 207, api_WPrintPortEnum,0},
3106 {"SamOEMChangePassword", 214, api_SamOEMChangePassword,0},
3107 {NULL, -1, api_Unsupported,0}};
3110 /****************************************************************************
3111 Handle remote api calls
3112 ****************************************************************************/
3114 int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data,char *params,
3115 int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
3119 char *rparam = NULL;
3126 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
3130 api_command = SVAL(params,0);
3132 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
3135 skip_string(params+2,1),
3136 tdscnt,tpscnt,mdrcnt,mprcnt));
3138 for (i=0;api_commands[i].name;i++) {
3139 if (api_commands[i].id == api_command && api_commands[i].fn) {
3140 DEBUG(3,("Doing %s\n",api_commands[i].name));
3145 rdata = (char *)malloc(1024);
3147 memset(rdata,'\0',1024);
3149 rparam = (char *)malloc(1024);
3151 memset(rparam,'\0',1024);
3153 if(!rdata || !rparam) {
3154 DEBUG(0,("api_reply: malloc fail !\n"));
3158 reply = api_commands[i].fn(conn,vuid,params,data,mdrcnt,mprcnt,
3159 &rdata,&rparam,&rdata_len,&rparam_len);
3162 if (rdata_len > mdrcnt ||
3163 rparam_len > mprcnt) {
3164 reply = api_TooSmall(conn,vuid,params,data,mdrcnt,mprcnt,
3165 &rdata,&rparam,&rdata_len,&rparam_len);
3168 /* if we get False back then it's actually unsupported */
3170 api_Unsupported(conn,vuid,params,data,mdrcnt,mprcnt,
3171 &rdata,&rparam,&rdata_len,&rparam_len);
3173 send_trans_reply(outbuf, rparam, rparam_len, rdata, rdata_len, False);