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(snum),NULL);
504 DEBUG(3,("fill_printq_info: Can't open %s - %s\n",
505 lp_driverfile(snum),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(snum), NULL);
673 DEBUG(3,("get_printerdrivernumber: Can't open %s - %s\n",
674 lp_driverfile(snum),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) {
781 * This is a *disgusting* hack.
782 * This is *so* bad that even I'm embarrassed (and I
783 * have no shame). Here's the deal :
784 * Until we get the correct SPOOLSS code into smbd
785 * then when we're running with NT SMB support then
786 * NT makes this call with a level of zero, and then
787 * immediately follows it with an open request to
788 * the \\SRVSVC pipe. If we allow that open to
789 * succeed then NT barfs when it cannot open the
790 * \\SPOOLSS pipe immediately after and continually
791 * whines saying "Printer name is invalid" forever
792 * after. If we cause *JUST THIS NEXT OPEN* of \\SRVSVC
793 * to fail, then NT downgrades to using the downlevel code
794 * and everything works as well as before. I hate
795 * myself for adding this code.... JRA.
798 fail_next_srvsvc_open();
802 *rdata_len = desc.usedlen;
805 *rparam = REALLOC(*rparam,*rparam_len);
806 SSVALS(*rparam,0,desc.errcode);
808 SSVAL(*rparam,4,desc.neededlen);
810 DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode));
812 if (queue) free(queue);
818 /****************************************************************************
819 view list of all print jobs on all queues
820 ****************************************************************************/
821 static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid, char* param, char* data,
822 int mdrcnt, int mprcnt,
823 char **rdata, char** rparam,
824 int *rdata_len, int *rparam_len)
826 char *param_format = param+2;
827 char *output_format1 = skip_string(param_format,1);
828 char *p = skip_string(output_format1,1);
829 int uLevel = SVAL(p,0);
830 char *output_format2 = p + 4;
831 int services = lp_numservices();
833 struct pack_desc desc;
834 print_queue_struct **queue = NULL;
835 print_status_struct *status = NULL;
836 int* subcntarr = NULL;
837 int queuecnt, subcnt=0, succnt=0;
839 memset((char *)&desc,'\0',sizeof(desc));
841 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
843 if (!prefix_ok(param_format,"WrLeh")) return False;
844 if (!check_printq_info(&desc,uLevel,output_format1,output_format2)) {
846 * Patch from Scott Moomaw <scott@bridgewater.edu>
847 * to return the 'invalid info level' error if an
848 * unknown level was requested.
852 *rparam = REALLOC(*rparam,*rparam_len);
853 SSVALS(*rparam,0,ERROR_INVALID_LEVEL);
860 for (i = 0; i < services; i++)
861 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
864 if((queue = (print_queue_struct**)malloc(queuecnt*sizeof(print_queue_struct*))) == NULL) {
865 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
868 memset(queue,0,queuecnt*sizeof(print_queue_struct*));
869 if((status = (print_status_struct*)malloc(queuecnt*sizeof(print_status_struct))) == NULL) {
870 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
873 memset(status,0,queuecnt*sizeof(print_status_struct));
874 if((subcntarr = (int*)malloc(queuecnt*sizeof(int))) == NULL) {
875 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
880 for (i = 0; i < services; i++)
881 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
882 subcntarr[n] = print_queue_status(i, &queue[n],&status[n]);
883 subcnt += subcntarr[n];
887 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
889 desc.buflen = mdrcnt;
891 if (init_package(&desc,queuecnt,subcnt)) {
894 for (i = 0; i < services; i++)
895 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
896 fill_printq_info(conn,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]);
898 if (desc.errcode == NERR_Success) succnt = n;
902 if (subcntarr) free(subcntarr);
904 *rdata_len = desc.usedlen;
906 *rparam = REALLOC(*rparam,*rparam_len);
907 SSVALS(*rparam,0,desc.errcode);
909 SSVAL(*rparam,4,succnt);
910 SSVAL(*rparam,6,queuecnt);
912 for (i = 0; i < queuecnt; i++) {
913 if (queue && queue[i]) free(queue[i]);
916 if (queue) free(queue);
917 if (status) free(status);
922 /****************************************************************************
923 get info level for a server list query
924 ****************************************************************************/
925 static BOOL check_server_info(int uLevel, char* id)
929 if (strcmp(id,"B16") != 0) return False;
932 if (strcmp(id,"B16BBDz") != 0) return False;
940 struct srv_info_struct
950 /*******************************************************************
951 get server info lists from the files saved by nmbd. Return the
953 ******************************************************************/
954 static int get_server_info(uint32 servertype,
955 struct srv_info_struct **servers,
961 BOOL local_list_only;
964 lines = file_lines_load(lock_path(SERVER_LIST), NULL);
966 DEBUG(4,("Can't open %s - %s\n",lock_path(SERVER_LIST),strerror(errno)));
970 /* request for everything is code for request all servers */
971 if (servertype == SV_TYPE_ALL)
972 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
974 local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY);
976 DEBUG(4,("Servertype search: %8x\n",servertype));
978 for (i=0;lines[i];i++) {
980 struct srv_info_struct *s;
981 char *ptr = lines[i];
986 if (count == alloced) {
988 (*servers) = (struct srv_info_struct *)
989 Realloc(*servers,sizeof(**servers)*alloced);
990 if (!(*servers)) return(0);
991 memset((char *)((*servers)+count),'\0',sizeof(**servers)*(alloced-count));
993 s = &(*servers)[count];
995 if (!next_token(&ptr,s->name , NULL, sizeof(s->name))) continue;
996 if (!next_token(&ptr,stype , NULL, sizeof(stype))) continue;
997 if (!next_token(&ptr,s->comment, NULL, sizeof(s->comment))) continue;
998 if (!next_token(&ptr,s->domain , NULL, sizeof(s->domain))) {
999 /* this allows us to cope with an old nmbd */
1000 pstrcpy(s->domain,global_myworkgroup);
1003 if (sscanf(stype,"%X",&s->type) != 1) {
1004 DEBUG(4,("r:host file "));
1008 /* Filter the servers/domains we return based on what was asked for. */
1010 /* Check to see if we are being asked for a local list only. */
1011 if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) {
1012 DEBUG(4,("r: local list only"));
1016 /* doesn't match up: don't want it */
1017 if (!(servertype & s->type)) {
1018 DEBUG(4,("r:serv type "));
1022 if ((servertype & SV_TYPE_DOMAIN_ENUM) !=
1023 (s->type & SV_TYPE_DOMAIN_ENUM))
1025 DEBUG(4,("s: dom mismatch "));
1029 if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM))
1034 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1035 s->type &= ~SV_TYPE_LOCAL_LIST_ONLY;
1039 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1040 s->name, s->type, s->comment, s->domain));
1042 s->server_added = True;
1047 DEBUG(4,("%20s %8x %25s %15s\n",
1048 s->name, s->type, s->comment, s->domain));
1052 file_lines_free(lines);
1057 /*******************************************************************
1058 fill in a server info structure
1059 ******************************************************************/
1060 static int fill_srv_info(struct srv_info_struct *service,
1061 int uLevel, char **buf, int *buflen,
1062 char **stringbuf, int *stringspace, char *baseaddr)
1071 case 0: struct_len = 16; break;
1072 case 1: struct_len = 26; break;
1082 len = strlen(service->comment)+1;
1086 if (buflen) *buflen = struct_len;
1087 if (stringspace) *stringspace = len;
1088 return struct_len + len;
1093 if (*buflen < struct_len) return -1;
1101 p2 = p + struct_len;
1102 l2 = *buflen - struct_len;
1104 if (!baseaddr) baseaddr = p;
1109 StrnCpy(p,service->name,15);
1113 StrnCpy(p,service->name,15);
1114 SIVAL(p,18,service->type);
1115 SIVAL(p,22,PTR_DIFF(p2,baseaddr));
1116 len += CopyAndAdvance(&p2,service->comment,&l2);
1122 *buf = p + struct_len;
1123 *buflen -= struct_len;
1136 static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
1138 return(strcmp(s1->name,s2->name));
1141 /****************************************************************************
1142 view list of servers available (or possibly domains). The info is
1143 extracted from lists saved by nmbd on the local host
1144 ****************************************************************************/
1145 static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid, char *param, char *data,
1146 int mdrcnt, int mprcnt, char **rdata,
1147 char **rparam, int *rdata_len, int *rparam_len)
1149 char *str1 = param+2;
1150 char *str2 = skip_string(str1,1);
1151 char *p = skip_string(str2,1);
1152 int uLevel = SVAL(p,0);
1153 int buf_len = SVAL(p,2);
1154 uint32 servertype = IVAL(p,4);
1156 int data_len, fixed_len, string_len;
1157 int f_len = 0, s_len = 0;
1158 struct srv_info_struct *servers=NULL;
1159 int counted=0,total=0;
1162 BOOL domain_request;
1165 /* If someone sets all the bits they don't really mean to set
1166 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1169 if (servertype == SV_TYPE_ALL)
1170 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1172 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1173 any other bit (they may just set this bit on it's own) they
1174 want all the locally seen servers. However this bit can be
1175 set on its own so set the requested servers to be
1176 ALL - DOMAIN_ENUM. */
1178 if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM))
1179 servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
1181 domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
1182 local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
1186 if (!prefix_ok(str1,"WrLehD")) return False;
1187 if (!check_server_info(uLevel,str2)) return False;
1189 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1190 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1191 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1193 if (strcmp(str1, "WrLehDz") == 0) {
1194 StrnCpy(domain, p, sizeof(fstring)-1);
1196 StrnCpy(domain, global_myworkgroup, sizeof(fstring)-1);
1199 if (lp_browse_list())
1200 total = get_server_info(servertype,&servers,domain);
1202 data_len = fixed_len = string_len = 0;
1205 qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
1208 char *lastname=NULL;
1210 for (i=0;i<total;i++)
1212 struct srv_info_struct *s = &servers[i];
1213 if (lastname && strequal(lastname,s->name)) continue;
1215 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1216 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1217 s->name, s->type, s->comment, s->domain));
1219 if (data_len <= buf_len) {
1222 string_len += s_len;
1229 *rdata_len = fixed_len + string_len;
1230 *rdata = REALLOC(*rdata,*rdata_len);
1231 memset(*rdata,'\0',*rdata_len);
1233 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1239 char *lastname=NULL;
1240 int count2 = counted;
1241 for (i = 0; i < total && count2;i++)
1243 struct srv_info_struct *s = &servers[i];
1244 if (lastname && strequal(lastname,s->name)) continue;
1246 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1247 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1248 s->name, s->type, s->comment, s->domain));
1254 *rparam = REALLOC(*rparam,*rparam_len);
1255 SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata));
1257 SSVAL(*rparam,4,counted);
1258 SSVAL(*rparam,6,counted+missed);
1260 if (servers) free(servers);
1262 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1263 domain,uLevel,counted,counted+missed));
1268 /****************************************************************************
1269 command 0x34 - suspected of being a "Lookup Names" stub api
1270 ****************************************************************************/
1271 static BOOL api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid, char *param, char *data,
1272 int mdrcnt, int mprcnt, char **rdata,
1273 char **rparam, int *rdata_len, int *rparam_len)
1275 char *str1 = param+2;
1276 char *str2 = skip_string(str1,1);
1277 char *p = skip_string(str2,1);
1278 int uLevel = SVAL(p,0);
1279 int buf_len = SVAL(p,2);
1283 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1284 str1, str2, p, uLevel, buf_len));
1286 if (!prefix_ok(str1,"zWrLeh")) return False;
1291 *rparam = REALLOC(*rparam,*rparam_len);
1293 SSVAL(*rparam,0,0x08AC); /* informational warning message */
1295 SSVAL(*rparam,4,counted);
1296 SSVAL(*rparam,6,counted+missed);
1301 /****************************************************************************
1302 get info about a share
1303 ****************************************************************************/
1304 static BOOL check_share_info(int uLevel, char* id)
1308 if (strcmp(id,"B13") != 0) return False;
1311 if (strcmp(id,"B13BWz") != 0) return False;
1314 if (strcmp(id,"B13BWzWWWzB9B") != 0) return False;
1317 if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) return False;
1319 default: return False;
1324 static int fill_share_info(connection_struct *conn, int snum, int uLevel,
1325 char** buf, int* buflen,
1326 char** stringbuf, int* stringspace, char* baseaddr)
1335 case 0: struct_len = 13; break;
1336 case 1: struct_len = 20; break;
1337 case 2: struct_len = 40; break;
1338 case 91: struct_len = 68; break;
1346 if (uLevel > 0) len += StrlenExpanded(conn,snum,lp_comment(snum));
1347 if (uLevel > 1) len += strlen(lp_pathname(snum)) + 1;
1348 if (buflen) *buflen = struct_len;
1349 if (stringspace) *stringspace = len;
1350 return struct_len + len;
1355 if ((*buflen) < struct_len) return -1;
1363 p2 = p + struct_len;
1364 l2 = (*buflen) - struct_len;
1366 if (!baseaddr) baseaddr = p;
1368 StrnCpy(p,lp_servicename(snum),13);
1374 type = STYPE_DISKTREE;
1375 if (lp_print_ok(snum)) type = STYPE_PRINTQ;
1376 if (strequal("IPC$",lp_servicename(snum))) type = STYPE_IPC;
1377 SSVAL(p,14,type); /* device type */
1378 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1379 len += CopyExpanded(conn,snum,&p2,lp_comment(snum),&l2);
1384 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1385 SSVALS(p,22,-1); /* max uses */
1386 SSVAL(p,24,1); /* current uses */
1387 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1388 len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1389 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1394 memset(p+40,0,SHPWLEN+2);
1406 (*buf) = p + struct_len;
1407 (*buflen) -= struct_len;
1409 (*stringspace) = l2;
1419 static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
1420 int mdrcnt,int mprcnt,
1421 char **rdata,char **rparam,
1422 int *rdata_len,int *rparam_len)
1424 char *str1 = param+2;
1425 char *str2 = skip_string(str1,1);
1426 char *netname = skip_string(str2,1);
1427 char *p = skip_string(netname,1);
1428 int uLevel = SVAL(p,0);
1429 int snum = find_service(netname);
1431 if (snum < 0) return False;
1433 /* check it's a supported varient */
1434 if (!prefix_ok(str1,"zWrLh")) return False;
1435 if (!check_share_info(uLevel,str2)) return False;
1437 *rdata = REALLOC(*rdata,mdrcnt);
1439 *rdata_len = fill_share_info(conn,snum,uLevel,&p,&mdrcnt,0,0,0);
1440 if (*rdata_len < 0) return False;
1443 *rparam = REALLOC(*rparam,*rparam_len);
1444 SSVAL(*rparam,0,NERR_Success);
1445 SSVAL(*rparam,2,0); /* converter word */
1446 SSVAL(*rparam,4,*rdata_len);
1451 /****************************************************************************
1452 view list of shares available
1453 ****************************************************************************/
1454 static BOOL api_RNetShareEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
1455 int mdrcnt,int mprcnt,
1456 char **rdata,char **rparam,
1457 int *rdata_len,int *rparam_len)
1459 char *str1 = param+2;
1460 char *str2 = skip_string(str1,1);
1461 char *p = skip_string(str2,1);
1462 int uLevel = SVAL(p,0);
1463 int buf_len = SVAL(p,2);
1465 int count=lp_numservices();
1466 int total=0,counted=0;
1467 BOOL missed = False;
1469 int data_len, fixed_len, string_len;
1470 int f_len = 0, s_len = 0;
1472 if (!prefix_ok(str1,"WrLeh")) return False;
1473 if (!check_share_info(uLevel,str2)) return False;
1475 data_len = fixed_len = string_len = 0;
1476 for (i=0;i<count;i++)
1477 if (lp_browseable(i) && lp_snum_ok(i))
1480 data_len += fill_share_info(conn,i,uLevel,0,&f_len,0,&s_len,0);
1481 if (data_len <= buf_len)
1485 string_len += s_len;
1490 *rdata_len = fixed_len + string_len;
1491 *rdata = REALLOC(*rdata,*rdata_len);
1492 memset(*rdata,0,*rdata_len);
1494 p2 = (*rdata) + fixed_len; /* auxillery data (strings) will go here */
1498 for (i = 0; i < count;i++)
1499 if (lp_browseable(i) && lp_snum_ok(i))
1500 if (fill_share_info(conn,i,uLevel,&p,&f_len,&p2,&s_len,*rdata) < 0)
1504 *rparam = REALLOC(*rparam,*rparam_len);
1505 SSVAL(*rparam,0,missed ? ERRmoredata : NERR_Success);
1507 SSVAL(*rparam,4,counted);
1508 SSVAL(*rparam,6,total);
1510 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1511 counted,total,uLevel,
1512 buf_len,*rdata_len,mdrcnt));
1518 /****************************************************************************
1519 get the time of day info
1520 ****************************************************************************/
1521 static BOOL api_NetRemoteTOD(connection_struct *conn,uint16 vuid, char *param,char *data,
1522 int mdrcnt,int mprcnt,
1523 char **rdata,char **rparam,
1524 int *rdata_len,int *rparam_len)
1528 *rparam = REALLOC(*rparam,*rparam_len);
1531 *rdata = REALLOC(*rdata,*rdata_len);
1533 SSVAL(*rparam,0,NERR_Success);
1534 SSVAL(*rparam,2,0); /* converter word */
1540 time_t unixdate = time(NULL);
1542 put_dos_date3(p,0,unixdate); /* this is the time that is looked at
1543 by NT in a "net time" operation,
1544 it seems to ignore the one below */
1546 /* the client expects to get localtime, not GMT, in this bit
1547 (I think, this needs testing) */
1548 t = LocalTime(&unixdate);
1550 SIVAL(p,4,0); /* msecs ? */
1551 CVAL(p,8) = t->tm_hour;
1552 CVAL(p,9) = t->tm_min;
1553 CVAL(p,10) = t->tm_sec;
1554 CVAL(p,11) = 0; /* hundredths of seconds */
1555 SSVALS(p,12,TimeDiff(unixdate)/60); /* timezone in minutes from GMT */
1556 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
1557 CVAL(p,16) = t->tm_mday;
1558 CVAL(p,17) = t->tm_mon + 1;
1559 SSVAL(p,18,1900+t->tm_year);
1560 CVAL(p,20) = t->tm_wday;
1567 /****************************************************************************
1568 Set the user password.
1569 *****************************************************************************/
1571 static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param,char *data,
1572 int mdrcnt,int mprcnt,
1573 char **rdata,char **rparam,
1574 int *rdata_len,int *rparam_len)
1576 char *p = skip_string(param+2,2);
1578 fstring pass1,pass2;
1582 p = skip_string(p,1);
1584 memset(pass1,'\0',sizeof(pass1));
1585 memset(pass2,'\0',sizeof(pass2));
1587 memcpy(pass2,p+16,16);
1590 *rparam = REALLOC(*rparam,*rparam_len);
1594 SSVAL(*rparam,0,NERR_badpass);
1595 SSVAL(*rparam,2,0); /* converter word */
1597 DEBUG(3,("Set password for <%s>\n",user));
1600 * Pass the user through the NT -> unix user mapping
1604 (void)map_username(user);
1607 * Do any UNIX username case mangling.
1609 (void)Get_Pwnam( user, True);
1612 * Attempt to verify the old password against smbpasswd entries
1613 * Win98 clients send old and new password in plaintext for this call.
1617 fstring saved_pass2;
1618 struct smb_passwd *smbpw = NULL;
1621 * Save the new password as change_oem_password overwrites it
1625 fstrcpy(saved_pass2, pass2);
1627 if (check_plaintext_password(user,pass1,strlen(pass1),&smbpw) &&
1628 change_oem_password(smbpw,pass2,False))
1630 SSVAL(*rparam,0,NERR_Success);
1633 * If unix password sync was requested, attempt to change
1634 * the /etc/passwd database also. Return failure if this cannot
1638 if(lp_unix_password_sync() && !chgpasswd(user,pass1,saved_pass2,False))
1639 SSVAL(*rparam,0,NERR_badpass);
1644 * If the above failed, attempt the plaintext password change.
1645 * This tests against the /etc/passwd database only.
1648 if(SVAL(*rparam,0) != NERR_Success)
1650 if (password_ok(user, pass1,strlen(pass1),NULL) &&
1651 chgpasswd(user,pass1,pass2,False))
1653 SSVAL(*rparam,0,NERR_Success);
1658 * If the plaintext change failed, attempt
1659 * the old encrypted method. NT will generate this
1660 * after trying the samr method. Note that this
1661 * method is done as a last resort as this
1662 * password change method loses the NT password hash
1663 * and cannot change the UNIX password as no plaintext
1667 if(SVAL(*rparam,0) != NERR_Success)
1669 struct smb_passwd *sampw = NULL;
1671 if(check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &sampw) &&
1672 change_lanman_password(sampw,(unsigned char *)pass1,(unsigned char *)pass2))
1674 SSVAL(*rparam,0,NERR_Success);
1678 memset((char *)pass1,'\0',sizeof(fstring));
1679 memset((char *)pass2,'\0',sizeof(fstring));
1684 /****************************************************************************
1685 Set the user password (SamOEM version - gets plaintext).
1686 ****************************************************************************/
1688 static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char *param,char *data,
1689 int mdrcnt,int mprcnt,
1690 char **rdata,char **rparam,
1691 int *rdata_len,int *rparam_len)
1694 char *p = param + 2;
1696 *rparam = REALLOC(*rparam,*rparam_len);
1700 SSVAL(*rparam,0,NERR_badpass);
1703 * Check the parameter definition is correct.
1705 if(!strequal(param + 2, "zsT")) {
1706 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", param + 2));
1709 p = skip_string(p, 1);
1711 if(!strequal(p, "B516B16")) {
1712 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p));
1715 p = skip_string(p,1);
1718 p = skip_string(p,1);
1720 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user));
1723 * Pass the user through the NT -> unix user mapping
1727 (void)map_username(user);
1730 * Do any UNIX username case mangling.
1732 (void)Get_Pwnam( user, True);
1734 if (pass_oem_change(user, (uchar*) data, (uchar *)&data[516], NULL, NULL))
1736 SSVAL(*rparam,0,NERR_Success);
1742 /****************************************************************************
1745 ****************************************************************************/
1746 static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char *param,char *data,
1747 int mdrcnt,int mprcnt,
1748 char **rdata,char **rparam,
1749 int *rdata_len,int *rparam_len)
1751 int function = SVAL(param,0);
1752 char *str1 = param+2;
1753 char *str2 = skip_string(str1,1);
1754 char *p = skip_string(str2,1);
1756 extern struct current_user current_user;
1760 /* check it's a supported varient */
1761 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
1765 *rparam = REALLOC(*rparam,*rparam_len);
1768 if (!print_job_exists(jobid)) {
1769 errcode = NERR_JobNotFound;
1773 errcode = NERR_notsupported;
1776 case 81: /* delete */
1777 if (print_job_delete(¤t_user, jobid))
1778 errcode = NERR_Success;
1780 case 82: /* pause */
1781 if (print_job_pause(¤t_user, jobid))
1782 errcode = NERR_Success;
1784 case 83: /* resume */
1785 if (print_job_resume(¤t_user, jobid))
1786 errcode = NERR_Success;
1791 SSVAL(*rparam,0,errcode);
1792 SSVAL(*rparam,2,0); /* converter word */
1797 /****************************************************************************
1798 Purge a print queue - or pause or resume it.
1799 ****************************************************************************/
1800 static BOOL api_WPrintQueuePurge(connection_struct *conn,uint16 vuid, char *param,char *data,
1801 int mdrcnt,int mprcnt,
1802 char **rdata,char **rparam,
1803 int *rdata_len,int *rparam_len)
1805 int function = SVAL(param,0);
1806 char *str1 = param+2;
1807 char *str2 = skip_string(str1,1);
1808 char *QueueName = skip_string(str2,1);
1809 int errcode = NERR_notsupported;
1812 /* check it's a supported varient */
1813 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
1817 *rparam = REALLOC(*rparam,*rparam_len);
1820 snum = print_queue_snum(QueueName);
1823 errcode = NERR_JobNotFound;
1828 case 74: /* Pause queue */
1829 if (print_queue_pause(NULL, snum)) errcode = NERR_Success;
1831 case 75: /* Resume queue */
1832 if (print_queue_resume(NULL, snum)) errcode = NERR_Success;
1834 case 103: /* Purge */
1835 if (print_queue_purge(NULL, snum)) errcode = NERR_Success;
1840 SSVAL(*rparam,0,errcode);
1841 SSVAL(*rparam,2,0); /* converter word */
1847 /****************************************************************************
1848 set the property of a print job (undocumented?)
1849 ? function = 0xb -> set name of print job
1850 ? function = 0x6 -> move print job up/down
1851 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
1852 or <WWsTP> <WB21BB16B10zWWzDDz>
1853 ****************************************************************************/
1854 static int check_printjob_info(struct pack_desc* desc,
1855 int uLevel, char* id)
1857 desc->subformat = NULL;
1859 case 0: desc->format = "W"; break;
1860 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
1861 case 2: desc->format = "WWzWWDDzz"; break;
1862 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
1863 default: return False;
1865 if (strcmp(desc->format,id) != 0) return False;
1869 static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,char *data,
1870 int mdrcnt,int mprcnt,
1871 char **rdata,char **rparam,
1872 int *rdata_len,int *rparam_len)
1874 struct pack_desc desc;
1875 char *str1 = param+2;
1876 char *str2 = skip_string(str1,1);
1877 char *p = skip_string(str2,1);
1879 int uLevel = SVAL(p,2);
1880 int function = SVAL(p,4);
1885 *rparam = REALLOC(*rparam,*rparam_len);
1889 /* check it's a supported varient */
1890 if ((strcmp(str1,"WWsTP")) ||
1891 (!check_printjob_info(&desc,uLevel,str2)))
1894 if (!print_job_exists(jobid)) {
1895 errcode=NERR_JobNotFound;
1899 errcode = NERR_notsupported;
1903 /* change job place in the queue,
1904 data gives the new place */
1905 place = SVAL(data,0);
1906 if (print_job_set_place(jobid, place)) {
1907 errcode=NERR_Success;
1912 /* change print job name, data gives the name */
1913 if (print_job_set_name(jobid, data)) {
1914 errcode=NERR_Success;
1923 SSVALS(*rparam,0,errcode);
1924 SSVAL(*rparam,2,0); /* converter word */
1930 /****************************************************************************
1931 get info about the server
1932 ****************************************************************************/
1933 static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
1934 int mdrcnt,int mprcnt,
1935 char **rdata,char **rparam,
1936 int *rdata_len,int *rparam_len)
1938 char *str1 = param+2;
1939 char *str2 = skip_string(str1,1);
1940 char *p = skip_string(str2,1);
1941 int uLevel = SVAL(p,0);
1945 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
1947 /* check it's a supported varient */
1948 if (!prefix_ok(str1,"WrLh")) return False;
1951 if (strcmp(str2,"B16") != 0) return False;
1955 if (strcmp(str2,"B16BBDz") != 0) return False;
1959 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")
1964 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz")
1969 if (strcmp(str2,"DN") != 0) return False;
1973 if (strcmp(str2,"B16BBDzWWzzz") != 0) return False;
1976 default: return False;
1979 *rdata_len = mdrcnt;
1980 *rdata = REALLOC(*rdata,*rdata_len);
1983 p2 = p + struct_len;
1985 StrnCpy(p,local_machine,16);
1991 struct srv_info_struct *servers=NULL;
1994 uint32 servertype= lp_default_server_announce();
1996 pstrcpy(comment,string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH));
1998 if ((count=get_server_info(SV_TYPE_ALL,&servers,global_myworkgroup))>0) {
1999 for (i=0;i<count;i++)
2000 if (strequal(servers[i].name,local_machine))
2002 servertype = servers[i].type;
2003 pstrcpy(comment,servers[i].comment);
2006 if (servers) free(servers);
2008 SCVAL(p,0,lp_major_announce_version());
2009 SCVAL(p,1,lp_minor_announce_version());
2010 SIVAL(p,2,servertype);
2012 if (mdrcnt == struct_len) {
2015 SIVAL(p,6,PTR_DIFF(p2,*rdata));
2016 standard_sub_conn(conn,comment);
2017 StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
2018 p2 = skip_string(p2,1);
2023 return False; /* not yet implemented */
2026 *rdata_len = PTR_DIFF(p2,*rdata);
2029 *rparam = REALLOC(*rparam,*rparam_len);
2030 SSVAL(*rparam,0,NERR_Success);
2031 SSVAL(*rparam,2,0); /* converter word */
2032 SSVAL(*rparam,4,*rdata_len);
2038 /****************************************************************************
2039 get info about the server
2040 ****************************************************************************/
2041 static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2042 int mdrcnt,int mprcnt,
2043 char **rdata,char **rparam,
2044 int *rdata_len,int *rparam_len)
2046 char *str1 = param+2;
2047 char *str2 = skip_string(str1,1);
2048 char *p = skip_string(str2,1);
2050 extern pstring sesssetup_user;
2051 int level = SVAL(p,0);
2053 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
2056 *rparam = REALLOC(*rparam,*rparam_len);
2058 /* check it's a supported varient */
2059 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz")))
2062 *rdata_len = mdrcnt + 1024;
2063 *rdata = REALLOC(*rdata,*rdata_len);
2065 SSVAL(*rparam,0,NERR_Success);
2066 SSVAL(*rparam,2,0); /* converter word */
2072 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
2073 pstrcpy(p2,local_machine);
2075 p2 = skip_string(p2,1);
2078 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2079 pstrcpy(p2,sesssetup_user);
2080 p2 = skip_string(p2,1);
2083 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
2084 pstrcpy(p2,global_myworkgroup);
2086 p2 = skip_string(p2,1);
2089 SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
2090 SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
2093 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2094 pstrcpy(p2,global_myworkgroup); /* don't know. login domain?? */
2095 p2 = skip_string(p2,1);
2098 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
2100 p2 = skip_string(p2,1);
2103 *rdata_len = PTR_DIFF(p2,*rdata);
2105 SSVAL(*rparam,4,*rdata_len);
2110 /****************************************************************************
2111 get info about a user
2113 struct user_info_11 {
2114 char usri11_name[21]; 0-20
2116 char *usri11_comment; 22-25
2117 char *usri11_usr_comment; 26-29
2118 unsigned short usri11_priv; 30-31
2119 unsigned long usri11_auth_flags; 32-35
2120 long usri11_password_age; 36-39
2121 char *usri11_homedir; 40-43
2122 char *usri11_parms; 44-47
2123 long usri11_last_logon; 48-51
2124 long usri11_last_logoff; 52-55
2125 unsigned short usri11_bad_pw_count; 56-57
2126 unsigned short usri11_num_logons; 58-59
2127 char *usri11_logon_server; 60-63
2128 unsigned short usri11_country_code; 64-65
2129 char *usri11_workstations; 66-69
2130 unsigned long usri11_max_storage; 70-73
2131 unsigned short usri11_units_per_week; 74-75
2132 unsigned char *usri11_logon_hours; 76-79
2133 unsigned short usri11_code_page; 80-81
2138 usri11_name specifies the user name for which information is retireved
2140 usri11_pad aligns the next data structure element to a word boundary
2142 usri11_comment is a null terminated ASCII comment
2144 usri11_user_comment is a null terminated ASCII comment about the user
2146 usri11_priv specifies the level of the privilege assigned to the user.
2147 The possible values are:
2149 Name Value Description
2150 USER_PRIV_GUEST 0 Guest privilege
2151 USER_PRIV_USER 1 User privilege
2152 USER_PRV_ADMIN 2 Administrator privilege
2154 usri11_auth_flags specifies the account operator privileges. The
2155 possible values are:
2157 Name Value Description
2158 AF_OP_PRINT 0 Print operator
2161 Leach, Naik [Page 28]
\r\f
2164 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2167 AF_OP_COMM 1 Communications operator
2168 AF_OP_SERVER 2 Server operator
2169 AF_OP_ACCOUNTS 3 Accounts operator
2172 usri11_password_age specifies how many seconds have elapsed since the
2173 password was last changed.
2175 usri11_home_dir points to a null terminated ASCII string that contains
2176 the path name of the user's home directory.
2178 usri11_parms points to a null terminated ASCII string that is set
2179 aside for use by applications.
2181 usri11_last_logon specifies the time when the user last logged on.
2182 This value is stored as the number of seconds elapsed since
2183 00:00:00, January 1, 1970.
2185 usri11_last_logoff specifies the time when the user last logged off.
2186 This value is stored as the number of seconds elapsed since
2187 00:00:00, January 1, 1970. A value of 0 means the last logoff
2190 usri11_bad_pw_count specifies the number of incorrect passwords
2191 entered since the last successful logon.
2193 usri11_log1_num_logons specifies the number of times this user has
2194 logged on. A value of -1 means the number of logons is unknown.
2196 usri11_logon_server points to a null terminated ASCII string that
2197 contains the name of the server to which logon requests are sent.
2198 A null string indicates logon requests should be sent to the
2201 usri11_country_code specifies the country code for the user's language
2204 usri11_workstations points to a null terminated ASCII string that
2205 contains the names of workstations the user may log on from.
2206 There may be up to 8 workstations, with the names separated by
2207 commas. A null strings indicates there are no restrictions.
2209 usri11_max_storage specifies the maximum amount of disk space the user
2210 can occupy. A value of 0xffffffff indicates there are no
2213 usri11_units_per_week specifies the equal number of time units into
2214 which a week is divided. This value must be equal to 168.
2216 usri11_logon_hours points to a 21 byte (168 bits) string that
2217 specifies the time during which the user can log on. Each bit
2218 represents one unique hour in a week. The first bit (bit 0, word
2219 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
2223 Leach, Naik [Page 29]
\r\f
2226 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2229 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
2230 are no restrictions.
2232 usri11_code_page specifies the code page for the user's language of
2235 All of the pointers in this data structure need to be treated
2236 specially. The pointer is a 32 bit pointer. The higher 16 bits need
2237 to be ignored. The converter word returned in the parameters section
2238 needs to be subtracted from the lower 16 bits to calculate an offset
2239 into the return buffer where this ASCII string resides.
2241 There is no auxiliary data in the response.
2243 ****************************************************************************/
2245 #define usri11_name 0
2246 #define usri11_pad 21
2247 #define usri11_comment 22
2248 #define usri11_usr_comment 26
2249 #define usri11_full_name 30
2250 #define usri11_priv 34
2251 #define usri11_auth_flags 36
2252 #define usri11_password_age 40
2253 #define usri11_homedir 44
2254 #define usri11_parms 48
2255 #define usri11_last_logon 52
2256 #define usri11_last_logoff 56
2257 #define usri11_bad_pw_count 60
2258 #define usri11_num_logons 62
2259 #define usri11_logon_server 64
2260 #define usri11_country_code 68
2261 #define usri11_workstations 70
2262 #define usri11_max_storage 74
2263 #define usri11_units_per_week 78
2264 #define usri11_logon_hours 80
2265 #define usri11_code_page 84
2266 #define usri11_end 86
2268 #define USER_PRIV_GUEST 0
2269 #define USER_PRIV_USER 1
2270 #define USER_PRIV_ADMIN 2
2272 #define AF_OP_PRINT 0
2273 #define AF_OP_COMM 1
2274 #define AF_OP_SERVER 2
2275 #define AF_OP_ACCOUNTS 3
2278 static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2279 int mdrcnt,int mprcnt,
2280 char **rdata,char **rparam,
2281 int *rdata_len,int *rparam_len)
2283 char *str1 = param+2;
2284 char *str2 = skip_string(str1,1);
2285 char *UserName = skip_string(str2,1);
2286 char *p = skip_string(UserName,1);
2287 int uLevel = SVAL(p,0);
2290 /* get NIS home of a previously validated user - simeon */
2291 /* With share level security vuid will always be zero.
2292 Don't depend on vuser being non-null !!. JRA */
2293 user_struct *vuser = get_valid_user_struct(vuid);
2295 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid,
2296 vuser->user.unix_name));
2299 *rparam = REALLOC(*rparam,*rparam_len);
2301 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
2303 /* check it's a supported variant */
2304 if (strcmp(str1,"zWrLh") != 0) return False;
2307 case 0: p2 = "B21"; break;
2308 case 1: p2 = "B21BB16DWzzWz"; break;
2309 case 2: p2 = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
2310 case 10: p2 = "B21Bzzz"; break;
2311 case 11: p2 = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
2312 default: return False;
2315 if (strcmp(p2,str2) != 0) return False;
2317 *rdata_len = mdrcnt + 1024;
2318 *rdata = REALLOC(*rdata,*rdata_len);
2320 SSVAL(*rparam,0,NERR_Success);
2321 SSVAL(*rparam,2,0); /* converter word */
2324 p2 = p + usri11_end;
2327 fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
2331 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
2336 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
2337 pstrcpy(p2,"Comment");
2338 p2 = skip_string(p2,1);
2340 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
2341 pstrcpy(p2,"UserComment");
2342 p2 = skip_string(p2,1);
2344 /* EEK! the cifsrap.txt doesn't have this in!!!! */
2345 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
2346 pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName));
2347 p2 = skip_string(p2,1);
2350 if (uLevel == 11) /* modelled after NTAS 3.51 reply */
2352 SSVAL(p,usri11_priv,conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2353 SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
2354 SIVALS(p,usri11_password_age,-1); /* password age */
2355 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
2356 pstrcpy(p2, lp_logon_home());
2357 p2 = skip_string(p2,1);
2358 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
2360 p2 = skip_string(p2,1);
2361 SIVAL(p,usri11_last_logon,0); /* last logon */
2362 SIVAL(p,usri11_last_logoff,0); /* last logoff */
2363 SSVALS(p,usri11_bad_pw_count,-1); /* bad pw counts */
2364 SSVALS(p,usri11_num_logons,-1); /* num logons */
2365 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
2366 pstrcpy(p2,"\\\\*");
2367 p2 = skip_string(p2,1);
2368 SSVAL(p,usri11_country_code,0); /* country code */
2370 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
2372 p2 = skip_string(p2,1);
2374 SIVALS(p,usri11_max_storage,-1); /* max storage */
2375 SSVAL(p,usri11_units_per_week,168); /* units per week */
2376 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
2378 /* a simple way to get logon hours at all times. */
2380 SCVAL(p2,21,0); /* fix zero termination */
2381 p2 = skip_string(p2,1);
2383 SSVAL(p,usri11_code_page,0); /* code page */
2385 if (uLevel == 1 || uLevel == 2)
2387 memset(p+22,' ',16); /* password */
2388 SIVALS(p,38,-1); /* password age */
2390 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2391 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
2392 pstrcpy(p2,lp_logon_home());
2393 p2 = skip_string(p2,1);
2394 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
2396 SSVAL(p,52,0); /* flags */
2397 SIVAL(p,54,PTR_DIFF(p2,*rdata)); /* script_path */
2398 pstrcpy(p2,lp_logon_script());
2399 standard_sub_conn( conn, p2 );
2400 p2 = skip_string(p2,1);
2403 SIVAL(p,60,0); /* auth_flags */
2404 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
2405 pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName));
2406 p2 = skip_string(p2,1);
2407 SIVAL(p,68,0); /* urs_comment */
2408 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
2410 p2 = skip_string(p2,1);
2411 SIVAL(p,76,0); /* workstations */
2412 SIVAL(p,80,0); /* last_logon */
2413 SIVAL(p,84,0); /* last_logoff */
2414 SIVALS(p,88,-1); /* acct_expires */
2415 SIVALS(p,92,-1); /* max_storage */
2416 SSVAL(p,96,168); /* units_per_week */
2417 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
2420 SSVALS(p,102,-1); /* bad_pw_count */
2421 SSVALS(p,104,-1); /* num_logons */
2422 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
2423 pstrcpy(p2,"\\\\%L");
2424 standard_sub_conn(conn, p2);
2425 p2 = skip_string(p2,1);
2426 SSVAL(p,110,49); /* country_code */
2427 SSVAL(p,112,860); /* code page */
2431 *rdata_len = PTR_DIFF(p2,*rdata);
2433 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
2438 /*******************************************************************
2439 get groups that a user is a member of
2440 ******************************************************************/
2441 static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *param,char *data,
2442 int mdrcnt,int mprcnt,
2443 char **rdata,char **rparam,
2444 int *rdata_len,int *rparam_len)
2446 char *str1 = param+2;
2447 char *str2 = skip_string(str1,1);
2448 char *UserName = skip_string(str2,1);
2449 char *p = skip_string(UserName,1);
2450 int uLevel = SVAL(p,0);
2455 *rparam = REALLOC(*rparam,*rparam_len);
2457 /* check it's a supported varient */
2458 if (strcmp(str1,"zWrLeh") != 0) return False;
2460 case 0: p2 = "B21"; break;
2461 default: return False;
2463 if (strcmp(p2,str2) != 0) return False;
2465 *rdata_len = mdrcnt + 1024;
2466 *rdata = REALLOC(*rdata,*rdata_len);
2468 SSVAL(*rparam,0,NERR_Success);
2469 SSVAL(*rparam,2,0); /* converter word */
2473 /* XXXX we need a real SAM database some day */
2474 pstrcpy(p,"Users"); p += 21; count++;
2475 pstrcpy(p,"Domain Users"); p += 21; count++;
2476 pstrcpy(p,"Guests"); p += 21; count++;
2477 pstrcpy(p,"Domain Guests"); p += 21; count++;
2479 *rdata_len = PTR_DIFF(p,*rdata);
2481 SSVAL(*rparam,4,count); /* is this right?? */
2482 SSVAL(*rparam,6,count); /* is this right?? */
2488 static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param,char *data,
2489 int mdrcnt,int mprcnt,
2490 char **rdata,char **rparam,
2491 int *rdata_len,int *rparam_len)
2493 char *str1 = param+2;
2494 char *str2 = skip_string(str1,1);
2495 char *p = skip_string(str2,1);
2497 struct pack_desc desc;
2503 memset((char *)&desc,'\0',sizeof(desc));
2505 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
2507 /* check it's a supported varient */
2508 if (strcmp(str1,"OOWb54WrLh") != 0) return False;
2509 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) return False;
2510 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2512 desc.buflen = mdrcnt;
2513 desc.subformat = NULL;
2516 if (init_package(&desc,1,0))
2518 PACKI(&desc,"W",0); /* code */
2519 PACKS(&desc,"B21",name); /* eff. name */
2520 PACKS(&desc,"B",""); /* pad */
2522 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2523 PACKI(&desc,"D",0); /* auth flags XXX */
2524 PACKI(&desc,"W",0); /* num logons */
2525 PACKI(&desc,"W",0); /* bad pw count */
2526 PACKI(&desc,"D",0); /* last logon */
2527 PACKI(&desc,"D",-1); /* last logoff */
2528 PACKI(&desc,"D",-1); /* logoff time */
2529 PACKI(&desc,"D",-1); /* kickoff time */
2530 PACKI(&desc,"D",0); /* password age */
2531 PACKI(&desc,"D",0); /* password can change */
2532 PACKI(&desc,"D",-1); /* password must change */
2535 fstrcpy(mypath,"\\\\");
2536 fstrcat(mypath,local_machine);
2538 PACKS(&desc,"z",mypath); /* computer */
2540 PACKS(&desc,"z",global_myworkgroup);/* domain */
2542 /* JHT - By calling lp_logon_script() and standard_sub() we have */
2543 /* made sure all macros are fully substituted and available */
2545 pstring logon_script;
2546 pstrcpy(logon_script,lp_logon_script());
2547 standard_sub_conn( conn, logon_script );
2548 PACKS(&desc,"z", logon_script); /* script path */
2550 /* End of JHT mods */
2552 PACKI(&desc,"D",0x00000000); /* reserved */
2555 *rdata_len = desc.usedlen;
2557 *rparam = REALLOC(*rparam,*rparam_len);
2558 SSVALS(*rparam,0,desc.errcode);
2560 SSVAL(*rparam,4,desc.neededlen);
2562 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
2567 /****************************************************************************
2568 api_WAccessGetUserPerms
2569 ****************************************************************************/
2570 static BOOL api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid, char *param,char *data,
2571 int mdrcnt,int mprcnt,
2572 char **rdata,char **rparam,
2573 int *rdata_len,int *rparam_len)
2575 char *str1 = param+2;
2576 char *str2 = skip_string(str1,1);
2577 char *user = skip_string(str2,1);
2578 char *resource = skip_string(user,1);
2580 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
2582 /* check it's a supported varient */
2583 if (strcmp(str1,"zzh") != 0) return False;
2584 if (strcmp(str2,"") != 0) return False;
2587 *rparam = REALLOC(*rparam,*rparam_len);
2588 SSVALS(*rparam,0,0); /* errorcode */
2589 SSVAL(*rparam,2,0); /* converter word */
2590 SSVAL(*rparam,4,0x7f); /* permission flags */
2595 /****************************************************************************
2596 api_WPrintJobEnumerate
2597 ****************************************************************************/
2598 static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2599 int mdrcnt,int mprcnt,
2600 char **rdata,char **rparam,
2601 int *rdata_len,int *rparam_len)
2603 char *str1 = param+2;
2604 char *str2 = skip_string(str1,1);
2605 char *p = skip_string(str2,1);
2611 struct pack_desc desc;
2612 print_queue_struct *queue=NULL;
2613 print_status_struct status;
2617 memset((char *)&desc,'\0',sizeof(desc));
2618 memset((char *)&status,'\0',sizeof(status));
2620 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
2622 /* check it's a supported varient */
2623 if (strcmp(str1,"WWrLh") != 0) return False;
2624 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2627 snum = print_job_snum(job);
2629 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2631 count = print_queue_status(snum,&queue,&status);
2632 for (i = 0; i < count; i++) {
2633 if (queue[i].job == job) break;
2635 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2637 desc.buflen = mdrcnt;
2639 if (init_package(&desc,1,0)) {
2641 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
2642 *rdata_len = desc.usedlen;
2645 desc.errcode = NERR_JobNotFound;
2651 *rparam = REALLOC(*rparam,*rparam_len);
2652 SSVALS(*rparam,0,desc.errcode);
2654 SSVAL(*rparam,4,desc.neededlen);
2656 if (queue) free(queue);
2658 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
2662 static BOOL api_WPrintJobEnumerate(connection_struct *conn,uint16 vuid, char *param,char *data,
2663 int mdrcnt,int mprcnt,
2664 char **rdata,char **rparam,
2665 int *rdata_len,int *rparam_len)
2667 char *str1 = param+2;
2668 char *str2 = skip_string(str1,1);
2669 char *p = skip_string(str2,1);
2675 struct pack_desc desc;
2676 print_queue_struct *queue=NULL;
2677 print_status_struct status;
2679 memset((char *)&desc,'\0',sizeof(desc));
2680 memset((char *)&status,'\0',sizeof(status));
2682 p = skip_string(p,1);
2685 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
2687 /* check it's a supported varient */
2688 if (strcmp(str1,"zWrLeh") != 0) return False;
2689 if (uLevel > 2) return False; /* defined only for uLevel 0,1,2 */
2690 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2692 snum = lp_servicenumber(name);
2693 if (snum < 0 && pcap_printername_ok(name,NULL)) {
2694 int pnum = lp_servicenumber(PRINTERS_NAME);
2696 lp_add_printer(name,pnum);
2697 snum = lp_servicenumber(name);
2701 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2703 count = print_queue_status(snum,&queue,&status);
2704 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2706 desc.buflen = mdrcnt;
2708 if (init_package(&desc,count,0)) {
2710 for (i = 0; i < count; i++) {
2711 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
2712 if (desc.errcode == NERR_Success) succnt = i+1;
2716 *rdata_len = desc.usedlen;
2719 *rparam = REALLOC(*rparam,*rparam_len);
2720 SSVALS(*rparam,0,desc.errcode);
2722 SSVAL(*rparam,4,succnt);
2723 SSVAL(*rparam,6,count);
2725 if (queue) free(queue);
2727 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
2731 static int check_printdest_info(struct pack_desc* desc,
2732 int uLevel, char* id)
2734 desc->subformat = NULL;
2736 case 0: desc->format = "B9"; break;
2737 case 1: desc->format = "B9B21WWzW"; break;
2738 case 2: desc->format = "z"; break;
2739 case 3: desc->format = "zzzWWzzzWW"; break;
2740 default: return False;
2742 if (strcmp(desc->format,id) != 0) return False;
2746 static void fill_printdest_info(connection_struct *conn, int snum, int uLevel,
2747 struct pack_desc* desc)
2750 strncpy(buf,SERVICE(snum),sizeof(buf)-1);
2751 buf[sizeof(buf)-1] = 0;
2754 PACKS(desc,"B9",buf); /* szName */
2756 PACKS(desc,"B21",""); /* szUserName */
2757 PACKI(desc,"W",0); /* uJobId */
2758 PACKI(desc,"W",0); /* fsStatus */
2759 PACKS(desc,"z",""); /* pszStatus */
2760 PACKI(desc,"W",0); /* time */
2763 if (uLevel == 2 || uLevel == 3) {
2764 PACKS(desc,"z",buf); /* pszPrinterName */
2766 PACKS(desc,"z",""); /* pszUserName */
2767 PACKS(desc,"z",""); /* pszLogAddr */
2768 PACKI(desc,"W",0); /* uJobId */
2769 PACKI(desc,"W",0); /* fsStatus */
2770 PACKS(desc,"z",""); /* pszStatus */
2771 PACKS(desc,"z",""); /* pszComment */
2772 PACKS(desc,"z","NULL"); /* pszDrivers */
2773 PACKI(desc,"W",0); /* time */
2774 PACKI(desc,"W",0); /* pad1 */
2779 static BOOL api_WPrintDestGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2780 int mdrcnt,int mprcnt,
2781 char **rdata,char **rparam,
2782 int *rdata_len,int *rparam_len)
2784 char *str1 = param+2;
2785 char *str2 = skip_string(str1,1);
2786 char *p = skip_string(str2,1);
2787 char* PrinterName = p;
2789 struct pack_desc desc;
2792 memset((char *)&desc,'\0',sizeof(desc));
2794 p = skip_string(p,1);
2797 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
2799 /* check it's a supported varient */
2800 if (strcmp(str1,"zWrLh") != 0) return False;
2801 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2803 snum = lp_servicenumber(PrinterName);
2804 if (snum < 0 && pcap_printername_ok(PrinterName,NULL)) {
2805 int pnum = lp_servicenumber(PRINTERS_NAME);
2807 lp_add_printer(PrinterName,pnum);
2808 snum = lp_servicenumber(PrinterName);
2814 desc.errcode = NERR_DestNotFound;
2818 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2820 desc.buflen = mdrcnt;
2821 if (init_package(&desc,1,0)) {
2822 fill_printdest_info(conn,snum,uLevel,&desc);
2824 *rdata_len = desc.usedlen;
2828 *rparam = REALLOC(*rparam,*rparam_len);
2829 SSVALS(*rparam,0,desc.errcode);
2831 SSVAL(*rparam,4,desc.neededlen);
2833 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
2837 static BOOL api_WPrintDestEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
2838 int mdrcnt,int mprcnt,
2839 char **rdata,char **rparam,
2840 int *rdata_len,int *rparam_len)
2842 char *str1 = param+2;
2843 char *str2 = skip_string(str1,1);
2844 char *p = skip_string(str2,1);
2848 struct pack_desc desc;
2849 int services = lp_numservices();
2851 memset((char *)&desc,'\0',sizeof(desc));
2855 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
2857 /* check it's a supported varient */
2858 if (strcmp(str1,"WrLeh") != 0) return False;
2859 if (!check_printdest_info(&desc,uLevel,str2)) return False;
2862 for (i = 0; i < services; i++)
2863 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
2866 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2868 desc.buflen = mdrcnt;
2869 if (init_package(&desc,queuecnt,0)) {
2872 for (i = 0; i < services; i++) {
2873 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
2874 fill_printdest_info(conn,i,uLevel,&desc);
2876 if (desc.errcode == NERR_Success) succnt = n;
2881 *rdata_len = desc.usedlen;
2884 *rparam = REALLOC(*rparam,*rparam_len);
2885 SSVALS(*rparam,0,desc.errcode);
2887 SSVAL(*rparam,4,succnt);
2888 SSVAL(*rparam,6,queuecnt);
2890 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
2894 static BOOL api_WPrintDriverEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
2895 int mdrcnt,int mprcnt,
2896 char **rdata,char **rparam,
2897 int *rdata_len,int *rparam_len)
2899 char *str1 = param+2;
2900 char *str2 = skip_string(str1,1);
2901 char *p = skip_string(str2,1);
2904 struct pack_desc desc;
2906 memset((char *)&desc,'\0',sizeof(desc));
2910 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
2912 /* check it's a supported varient */
2913 if (strcmp(str1,"WrLeh") != 0) return False;
2914 if (uLevel != 0 || strcmp(str2,"B41") != 0) return False;
2916 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2918 desc.buflen = mdrcnt;
2919 if (init_package(&desc,1,0)) {
2920 PACKS(&desc,"B41","NULL");
2923 succnt = (desc.errcode == NERR_Success ? 1 : 0);
2925 *rdata_len = desc.usedlen;
2928 *rparam = REALLOC(*rparam,*rparam_len);
2929 SSVALS(*rparam,0,desc.errcode);
2931 SSVAL(*rparam,4,succnt);
2934 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
2938 static BOOL api_WPrintQProcEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
2939 int mdrcnt,int mprcnt,
2940 char **rdata,char **rparam,
2941 int *rdata_len,int *rparam_len)
2943 char *str1 = param+2;
2944 char *str2 = skip_string(str1,1);
2945 char *p = skip_string(str2,1);
2948 struct pack_desc desc;
2950 memset((char *)&desc,'\0',sizeof(desc));
2954 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
2956 /* check it's a supported varient */
2957 if (strcmp(str1,"WrLeh") != 0) return False;
2958 if (uLevel != 0 || strcmp(str2,"B13") != 0) return False;
2960 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2962 desc.buflen = mdrcnt;
2964 if (init_package(&desc,1,0)) {
2965 PACKS(&desc,"B13","lpd");
2968 succnt = (desc.errcode == NERR_Success ? 1 : 0);
2970 *rdata_len = desc.usedlen;
2973 *rparam = REALLOC(*rparam,*rparam_len);
2974 SSVALS(*rparam,0,desc.errcode);
2976 SSVAL(*rparam,4,succnt);
2979 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
2983 static BOOL api_WPrintPortEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
2984 int mdrcnt,int mprcnt,
2985 char **rdata,char **rparam,
2986 int *rdata_len,int *rparam_len)
2988 char *str1 = param+2;
2989 char *str2 = skip_string(str1,1);
2990 char *p = skip_string(str2,1);
2993 struct pack_desc desc;
2995 memset((char *)&desc,'\0',sizeof(desc));
2999 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
3001 /* check it's a supported varient */
3002 if (strcmp(str1,"WrLeh") != 0) return False;
3003 if (uLevel != 0 || strcmp(str2,"B9") != 0) return False;
3005 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3006 memset((char *)&desc,'\0',sizeof(desc));
3008 desc.buflen = mdrcnt;
3010 if (init_package(&desc,1,0)) {
3011 PACKS(&desc,"B13","lp0");
3014 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3016 *rdata_len = desc.usedlen;
3019 *rparam = REALLOC(*rparam,*rparam_len);
3020 SSVALS(*rparam,0,desc.errcode);
3022 SSVAL(*rparam,4,succnt);
3025 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
3029 /****************************************************************************
3030 The buffer was too small
3031 ****************************************************************************/
3033 static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param,char *data,
3034 int mdrcnt,int mprcnt,
3035 char **rdata,char **rparam,
3036 int *rdata_len,int *rparam_len)
3038 *rparam_len = MIN(*rparam_len,mprcnt);
3039 *rparam = REALLOC(*rparam,*rparam_len);
3043 SSVAL(*rparam,0,NERR_BufTooSmall);
3045 DEBUG(3,("Supplied buffer too small in API command\n"));
3051 /****************************************************************************
3052 The request is not supported
3053 ****************************************************************************/
3055 static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param,char *data,
3056 int mdrcnt,int mprcnt,
3057 char **rdata,char **rparam,
3058 int *rdata_len,int *rparam_len)
3061 *rparam = REALLOC(*rparam,*rparam_len);
3065 SSVAL(*rparam,0,NERR_notsupported);
3066 SSVAL(*rparam,2,0); /* converter word */
3068 DEBUG(3,("Unsupported API command\n"));
3080 BOOL (*fn)(connection_struct *,uint16,char *,char *,
3081 int,int,char **,char **,int *,int *);
3083 } api_commands[] = {
3084 {"RNetShareEnum", 0, api_RNetShareEnum,0},
3085 {"RNetShareGetInfo", 1, api_RNetShareGetInfo,0},
3086 {"RNetServerGetInfo", 13, api_RNetServerGetInfo,0},
3087 {"RNetGroupGetUsers", 52, api_RNetGroupGetUsers,0},
3088 {"RNetUserGetInfo", 56, api_RNetUserGetInfo,0},
3089 {"NetUserGetGroups", 59, api_NetUserGetGroups,0},
3090 {"NetWkstaGetInfo", 63, api_NetWkstaGetInfo,0},
3091 {"DosPrintQEnum", 69, api_DosPrintQEnum,0},
3092 {"DosPrintQGetInfo", 70, api_DosPrintQGetInfo,0},
3093 {"WPrintQueuePause", 74, api_WPrintQueuePurge,0},
3094 {"WPrintQueueResume", 75, api_WPrintQueuePurge,0},
3095 {"WPrintJobEnumerate",76, api_WPrintJobEnumerate,0},
3096 {"WPrintJobGetInfo", 77, api_WPrintJobGetInfo,0},
3097 {"RDosPrintJobDel", 81, api_RDosPrintJobDel,0},
3098 {"RDosPrintJobPause", 82, api_RDosPrintJobDel,0},
3099 {"RDosPrintJobResume",83, api_RDosPrintJobDel,0},
3100 {"WPrintDestEnum", 84, api_WPrintDestEnum,0},
3101 {"WPrintDestGetInfo", 85, api_WPrintDestGetInfo,0},
3102 {"NetRemoteTOD", 91, api_NetRemoteTOD,0},
3103 {"WPrintQueuePurge", 103, api_WPrintQueuePurge,0},
3104 {"NetServerEnum", 104, api_RNetServerEnum,0},
3105 {"WAccessGetUserPerms",105, api_WAccessGetUserPerms,0},
3106 {"SetUserPassword", 115, api_SetUserPassword,0},
3107 {"WWkstaUserLogon", 132, api_WWkstaUserLogon,0},
3108 {"PrintJobInfo", 147, api_PrintJobInfo,0},
3109 {"WPrintDriverEnum", 205, api_WPrintDriverEnum,0},
3110 {"WPrintQProcEnum", 206, api_WPrintQProcEnum,0},
3111 {"WPrintPortEnum", 207, api_WPrintPortEnum,0},
3112 {"SamOEMChangePassword", 214, api_SamOEMChangePassword,0},
3113 {NULL, -1, api_Unsupported,0}};
3116 /****************************************************************************
3117 Handle remote api calls
3118 ****************************************************************************/
3120 int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data,char *params,
3121 int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
3125 char *rparam = NULL;
3132 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
3136 api_command = SVAL(params,0);
3138 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
3141 skip_string(params+2,1),
3142 tdscnt,tpscnt,mdrcnt,mprcnt));
3144 for (i=0;api_commands[i].name;i++) {
3145 if (api_commands[i].id == api_command && api_commands[i].fn) {
3146 DEBUG(3,("Doing %s\n",api_commands[i].name));
3151 rdata = (char *)malloc(1024);
3153 memset(rdata,'\0',1024);
3155 rparam = (char *)malloc(1024);
3157 memset(rparam,'\0',1024);
3159 if(!rdata || !rparam) {
3160 DEBUG(0,("api_reply: malloc fail !\n"));
3164 reply = api_commands[i].fn(conn,vuid,params,data,mdrcnt,mprcnt,
3165 &rdata,&rparam,&rdata_len,&rparam_len);
3168 if (rdata_len > mdrcnt ||
3169 rparam_len > mprcnt) {
3170 reply = api_TooSmall(conn,vuid,params,data,mdrcnt,mprcnt,
3171 &rdata,&rparam,&rdata_len,&rparam_len);
3174 /* if we get False back then it's actually unsupported */
3176 api_Unsupported(conn,vuid,params,data,mdrcnt,mprcnt,
3177 &rdata,&rparam,&rdata_len,&rparam_len);
3179 send_trans_reply(outbuf, rparam, rparam_len, rdata, rdata_len, False);