2 Unix SMB/CIFS implementation.
3 Inter-process communication and named pipe handling
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Jeremy Allison 2007.
8 Copyright (C) John H Terpstra 1995-1998
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 This file handles the named pipe and mailslot calls
25 in the SMBtrans protocol
35 #define NERR_Success 0
36 #define NERR_badpass 86
37 #define NERR_notsupported 50
39 #define NERR_BASE (2100)
40 #define NERR_BufTooSmall (NERR_BASE+23)
41 #define NERR_JobNotFound (NERR_BASE+51)
42 #define NERR_DestNotFound (NERR_BASE+52)
44 #define ACCESS_READ 0x01
45 #define ACCESS_WRITE 0x02
46 #define ACCESS_CREATE 0x04
48 #define SHPWLEN 8 /* share password length */
50 /* Limit size of ipc replies */
52 static char *smb_realloc_limit(void *ptr, size_t size)
56 size = MAX((size),4*1024);
57 val = (char *)SMB_REALLOC(ptr,size);
59 memset(val,'\0',size);
64 static bool api_Unsupported(connection_struct *conn, uint16 vuid,
65 char *param, int tpscnt,
66 char *data, int tdscnt,
67 int mdrcnt, int mprcnt,
68 char **rdata, char **rparam,
69 int *rdata_len, int *rparam_len);
71 static bool api_TooSmall(connection_struct *conn, uint16 vuid, char *param, char *data,
72 int mdrcnt, int mprcnt,
73 char **rdata, char **rparam,
74 int *rdata_len, int *rparam_len);
77 static int CopyExpanded(connection_struct *conn,
78 int snum, char **dst, char *src, int *p_space_remaining)
80 TALLOC_CTX *ctx = talloc_tos();
84 if (!src || !dst || !p_space_remaining || !(*dst) ||
85 *p_space_remaining <= 0) {
89 buf = talloc_strdup(ctx, src);
91 *p_space_remaining = 0;
94 buf = talloc_string_sub(ctx, buf,"%S",lp_servicename(snum));
96 *p_space_remaining = 0;
99 buf = talloc_sub_advanced(ctx,
100 lp_servicename(SNUM(conn)),
101 conn->server_info->unix_name,
103 conn->server_info->utok.gid,
104 conn->server_info->sanitized_username,
105 pdb_get_domain(conn->server_info->sam_account),
108 *p_space_remaining = 0;
111 l = push_ascii(*dst,buf,*p_space_remaining, STR_TERMINATE);
116 (*p_space_remaining) -= l;
120 static int CopyAndAdvance(char **dst, char *src, int *n)
123 if (!src || !dst || !n || !(*dst)) {
126 l = push_ascii(*dst,src,*n, STR_TERMINATE);
135 static int StrlenExpanded(connection_struct *conn, int snum, char *s)
137 TALLOC_CTX *ctx = talloc_tos();
142 buf = talloc_strdup(ctx,s);
146 buf = talloc_string_sub(ctx,buf,"%S",lp_servicename(snum));
150 buf = talloc_sub_advanced(ctx,
151 lp_servicename(SNUM(conn)),
152 conn->server_info->unix_name,
154 conn->server_info->utok.gid,
155 conn->server_info->sanitized_username,
156 pdb_get_domain(conn->server_info->sam_account),
161 return strlen(buf) + 1;
164 static char *Expand(connection_struct *conn, int snum, char *s)
166 TALLOC_CTX *ctx = talloc_tos();
172 buf = talloc_strdup(ctx,s);
176 buf = talloc_string_sub(ctx,buf,"%S",lp_servicename(snum));
180 return talloc_sub_advanced(ctx,
181 lp_servicename(SNUM(conn)),
182 conn->server_info->unix_name,
184 conn->server_info->utok.gid,
185 conn->server_info->sanitized_username,
186 pdb_get_domain(conn->server_info->sam_account),
190 /*******************************************************************
191 Check a API string for validity when we only need to check the prefix.
192 ******************************************************************/
194 static bool prefix_ok(const char *str, const char *prefix)
196 return(strncmp(str,prefix,strlen(prefix)) == 0);
200 const char *format; /* formatstring for structure */
201 const char *subformat; /* subformat for structure */
202 char *base; /* baseaddress of buffer */
203 int buflen; /* remaining size for fixed part; on init: length of base */
204 int subcount; /* count of substructures */
205 char *structbuf; /* pointer into buffer for remaining fixed part */
206 int stringlen; /* remaining size for variable part */
207 char *stringbuf; /* pointer into buffer for remaining variable part */
208 int neededlen; /* total needed size */
209 int usedlen; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
210 const char *curpos; /* current position; pointer into format or subformat */
214 static int get_counter(const char **p)
220 if (!isdigit((int)**p)) {
226 n = 10 * n + (i - '0');
234 static int getlen(const char *p)
243 case 'W': /* word (2 byte) */
246 case 'K': /* status word? (2 byte) */
249 case 'N': /* count of substructures (word) at end */
252 case 'D': /* double word (4 byte) */
253 case 'z': /* offset to zero terminated string (4 byte) */
254 case 'l': /* offset to user data (4 byte) */
257 case 'b': /* offset to data (with counter) (4 byte) */
261 case 'B': /* byte (with optional counter) */
262 n += get_counter(&p);
269 static bool init_package(struct pack_desc *p, int count, int subcount)
274 if (!p->format || !p->base) {
278 i = count * getlen(p->format);
280 i += subcount * getlen(p->subformat);
282 p->structbuf = p->base;
286 p->curpos = p->format;
292 * This is the old error code we used. Aparently
293 * WinNT/2k systems return ERRbuftoosmall (2123) and
294 * OS/2 needs this. I'm leaving this here so we can revert
297 p->errcode = ERRmoredata;
299 p->errcode = ERRbuftoosmall;
302 p->errcode = NERR_Success;
306 p->stringbuf = p->base + i;
308 return (p->errcode == NERR_Success);
311 static int package(struct pack_desc *p, ...)
314 int needed=0, stringneeded;
315 const char *str=NULL;
316 int is_string=0, stringused;
323 p->curpos = p->format;
325 p->curpos = p->subformat;
330 str = va_arg(args,char*);
331 SMB_ASSERT(strncmp(str,p->curpos,strlen(str)) == 0);
340 switch( *p->curpos++ ) {
341 case 'W': /* word (2 byte) */
343 temp = va_arg(args,int);
344 if (p->buflen >= needed) {
345 SSVAL(p->structbuf,0,temp);
348 case 'K': /* status word? (2 byte) */
350 temp = va_arg(args,int);
351 if (p->buflen >= needed) {
352 SSVAL(p->structbuf,0,temp);
355 case 'N': /* count of substructures (word) at end */
357 p->subcount = va_arg(args,int);
358 if (p->buflen >= needed) {
359 SSVAL(p->structbuf,0,p->subcount);
362 case 'D': /* double word (4 byte) */
364 temp = va_arg(args,int);
365 if (p->buflen >= needed) {
366 SIVAL(p->structbuf,0,temp);
369 case 'B': /* byte (with optional counter) */
370 needed = get_counter(&p->curpos);
372 char *s = va_arg(args,char*);
373 if (p->buflen >= needed) {
374 StrnCpy(p->structbuf,s?s:"",needed-1);
378 case 'z': /* offset to zero terminated string (4 byte) */
379 str = va_arg(args,char*);
380 stringneeded = (str ? strlen(str)+1 : 0);
383 case 'l': /* offset to user data (4 byte) */
384 str = va_arg(args,char*);
385 stringneeded = va_arg(args,int);
388 case 'b': /* offset to data (with counter) (4 byte) */
389 str = va_arg(args,char*);
390 stringneeded = get_counter(&p->curpos);
396 if (stringneeded >= 0) {
398 if (p->buflen >= needed) {
399 stringused = stringneeded;
400 if (stringused > p->stringlen) {
401 stringused = (is_string ? p->stringlen : 0);
402 if (p->errcode == NERR_Success) {
403 p->errcode = ERRmoredata;
407 SIVAL(p->structbuf,0,0);
409 SIVAL(p->structbuf,0,PTR_DIFF(p->stringbuf,p->base));
410 memcpy(p->stringbuf,str?str:"",stringused);
412 p->stringbuf[stringused-1] = '\0';
414 p->stringbuf += stringused;
415 p->stringlen -= stringused;
416 p->usedlen += stringused;
419 p->neededlen += stringneeded;
422 p->neededlen += needed;
423 if (p->buflen >= needed) {
424 p->structbuf += needed;
426 p->usedlen += needed;
428 if (p->errcode == NERR_Success) {
429 p->errcode = ERRmoredata;
436 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
437 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
439 #define PACK(desc,t,v) package(desc,v)
440 #define PACKl(desc,t,v,l) package(desc,v,l)
443 static void PACKI(struct pack_desc* desc, const char *t,int v)
448 static void PACKS(struct pack_desc* desc,const char *t,const char *v)
453 /****************************************************************************
455 ****************************************************************************/
457 static void PackDriverData(struct pack_desc* desc)
459 char drivdata[4+4+32];
460 SIVAL(drivdata,0,sizeof drivdata); /* cb */
461 SIVAL(drivdata,4,1000); /* lVersion */
462 memset(drivdata+8,0,32); /* szDeviceName */
463 push_ascii(drivdata+8,"NULL",32, STR_TERMINATE);
464 PACKl(desc,"l",drivdata,sizeof drivdata); /* pDriverData */
467 static int check_printq_info(struct pack_desc* desc,
468 unsigned int uLevel, char *id1, char *id2)
470 desc->subformat = NULL;
473 desc->format = "B13";
476 desc->format = "B13BWWWzzzzzWW";
479 desc->format = "B13BWWWzzzzzWN";
480 desc->subformat = "WB21BB16B10zWWzDDz";
483 desc->format = "zWWWWzzzzWWzzl";
486 desc->format = "zWWWWzzzzWNzzl";
487 desc->subformat = "WWzWWDDzz";
496 desc->format = "WzzzzzzzzN";
497 desc->subformat = "z";
500 DEBUG(0,("check_printq_info: invalid level %d\n",
504 if (id1 == NULL || strcmp(desc->format,id1) != 0) {
505 DEBUG(0,("check_printq_info: invalid format %s\n",
506 id1 ? id1 : "<NULL>" ));
509 if (desc->subformat && (id2 == NULL || strcmp(desc->subformat,id2) != 0)) {
510 DEBUG(0,("check_printq_info: invalid subformat %s\n",
511 id2 ? id2 : "<NULL>" ));
518 #define RAP_JOB_STATUS_QUEUED 0
519 #define RAP_JOB_STATUS_PAUSED 1
520 #define RAP_JOB_STATUS_SPOOLING 2
521 #define RAP_JOB_STATUS_PRINTING 3
522 #define RAP_JOB_STATUS_PRINTED 4
524 #define RAP_QUEUE_STATUS_PAUSED 1
525 #define RAP_QUEUE_STATUS_ERROR 2
527 /* turn a print job status into a on the wire status
529 static int printj_status(int v)
533 return RAP_JOB_STATUS_QUEUED;
535 return RAP_JOB_STATUS_PAUSED;
537 return RAP_JOB_STATUS_SPOOLING;
539 return RAP_JOB_STATUS_PRINTING;
544 /* turn a print queue status into a on the wire status
546 static int printq_status(int v)
552 return RAP_QUEUE_STATUS_PAUSED;
554 return RAP_QUEUE_STATUS_ERROR;
557 static void fill_printjob_info(connection_struct *conn, int snum, int uLevel,
558 struct pack_desc *desc,
559 print_queue_struct *queue, int n)
561 time_t t = queue->time;
563 /* the client expects localtime */
564 t -= get_time_zone(t);
566 PACKI(desc,"W",pjobid_to_rap(lp_const_servicename(snum),queue->job)); /* uJobId */
568 PACKS(desc,"B21",queue->fs_user); /* szUserName */
569 PACKS(desc,"B",""); /* pad */
570 PACKS(desc,"B16",""); /* szNotifyName */
571 PACKS(desc,"B10","PM_Q_RAW"); /* szDataType */
572 PACKS(desc,"z",""); /* pszParms */
573 PACKI(desc,"W",n+1); /* uPosition */
574 PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */
575 PACKS(desc,"z",""); /* pszStatus */
576 PACKI(desc,"D",t); /* ulSubmitted */
577 PACKI(desc,"D",queue->size); /* ulSize */
578 PACKS(desc,"z",queue->fs_file); /* pszComment */
580 if (uLevel == 2 || uLevel == 3 || uLevel == 4) {
581 PACKI(desc,"W",queue->priority); /* uPriority */
582 PACKS(desc,"z",queue->fs_user); /* pszUserName */
583 PACKI(desc,"W",n+1); /* uPosition */
584 PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */
585 PACKI(desc,"D",t); /* ulSubmitted */
586 PACKI(desc,"D",queue->size); /* ulSize */
587 PACKS(desc,"z","Samba"); /* pszComment */
588 PACKS(desc,"z",queue->fs_file); /* pszDocument */
590 PACKS(desc,"z",""); /* pszNotifyName */
591 PACKS(desc,"z","PM_Q_RAW"); /* pszDataType */
592 PACKS(desc,"z",""); /* pszParms */
593 PACKS(desc,"z",""); /* pszStatus */
594 PACKS(desc,"z",SERVICE(snum)); /* pszQueue */
595 PACKS(desc,"z","lpd"); /* pszQProcName */
596 PACKS(desc,"z",""); /* pszQProcParms */
597 PACKS(desc,"z","NULL"); /* pszDriverName */
598 PackDriverData(desc); /* pDriverData */
599 PACKS(desc,"z",""); /* pszPrinterName */
600 } else if (uLevel == 4) { /* OS2 */
601 PACKS(desc,"z",""); /* pszSpoolFileName */
602 PACKS(desc,"z",""); /* pszPortName */
603 PACKS(desc,"z",""); /* pszStatus */
604 PACKI(desc,"D",0); /* ulPagesSpooled */
605 PACKI(desc,"D",0); /* ulPagesSent */
606 PACKI(desc,"D",0); /* ulPagesPrinted */
607 PACKI(desc,"D",0); /* ulTimePrinted */
608 PACKI(desc,"D",0); /* ulExtendJobStatus */
609 PACKI(desc,"D",0); /* ulStartPage */
610 PACKI(desc,"D",0); /* ulEndPage */
615 /********************************************************************
616 Return a driver name given an snum.
617 Returns True if from tdb, False otherwise.
618 ********************************************************************/
620 static bool get_driver_name(int snum, char **pp_drivername)
622 NT_PRINTER_INFO_LEVEL *info = NULL;
625 get_a_printer (NULL, &info, 2, lp_servicename(snum));
627 *pp_drivername = talloc_strdup(talloc_tos(),
628 info->info_2->drivername);
630 free_a_printer(&info, 2);
631 if (!*pp_drivername) {
639 /********************************************************************
640 Respond to the DosPrintQInfo command with a level of 52
641 This is used to get printer driver information for Win9x clients
642 ********************************************************************/
643 static void fill_printq_info_52(connection_struct *conn, int snum,
644 struct pack_desc* desc, int count )
648 NT_PRINTER_DRIVER_INFO_LEVEL driver;
649 NT_PRINTER_INFO_LEVEL *printer = NULL;
653 if ( !W_ERROR_IS_OK(get_a_printer( NULL, &printer, 2, lp_servicename(snum))) ) {
654 DEBUG(3,("fill_printq_info_52: Failed to lookup printer [%s]\n",
655 lp_servicename(snum)));
659 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername,
662 DEBUG(3,("fill_printq_info_52: Failed to lookup driver [%s]\n",
663 printer->info_2->drivername));
667 trim_string(driver.info_3->driverpath, "\\print$\\WIN40\\0\\", 0);
668 trim_string(driver.info_3->datafile, "\\print$\\WIN40\\0\\", 0);
669 trim_string(driver.info_3->helpfile, "\\print$\\WIN40\\0\\", 0);
671 PACKI(desc, "W", 0x0400); /* don't know */
672 PACKS(desc, "z", driver.info_3->name); /* long printer name */
673 PACKS(desc, "z", driver.info_3->driverpath); /* Driverfile Name */
674 PACKS(desc, "z", driver.info_3->datafile); /* Datafile name */
675 PACKS(desc, "z", driver.info_3->monitorname); /* language monitor */
677 fstrcpy(location, "\\\\%L\\print$\\WIN40\\0");
678 standard_sub_basic( "", "", location, sizeof(location)-1 );
679 PACKS(desc,"z", location); /* share to retrieve files */
681 PACKS(desc,"z", driver.info_3->defaultdatatype); /* default data type */
682 PACKS(desc,"z", driver.info_3->helpfile); /* helpfile name */
683 PACKS(desc,"z", driver.info_3->driverpath); /* driver name */
685 DEBUG(3,("Printer Driver Name: %s:\n",driver.info_3->name));
686 DEBUG(3,("Driver: %s:\n",driver.info_3->driverpath));
687 DEBUG(3,("Data File: %s:\n",driver.info_3->datafile));
688 DEBUG(3,("Language Monitor: %s:\n",driver.info_3->monitorname));
689 DEBUG(3,("Driver Location: %s:\n",location));
690 DEBUG(3,("Data Type: %s:\n",driver.info_3->defaultdatatype));
691 DEBUG(3,("Help File: %s:\n",driver.info_3->helpfile));
692 PACKI(desc,"N",count); /* number of files to copy */
694 for ( i=0; i<count && driver.info_3->dependentfiles && *driver.info_3->dependentfiles[i]; i++)
696 trim_string(driver.info_3->dependentfiles[i], "\\print$\\WIN40\\0\\", 0);
697 PACKS(desc,"z",driver.info_3->dependentfiles[i]); /* driver files to copy */
698 DEBUG(3,("Dependent File: %s:\n",driver.info_3->dependentfiles[i]));
703 DEBUG(3,("fill_printq_info_52: file count specified by client [%d] != number of dependent files [%i]\n",
706 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n", SERVICE(snum),i));
708 desc->errcode=NERR_Success;
712 DEBUG(3,("fill_printq_info: Can't supply driver files\n"));
713 desc->errcode=NERR_notsupported;
717 free_a_printer( &printer, 2 );
720 free_a_printer_driver( driver, 3 );
724 static void fill_printq_info(connection_struct *conn, int snum, int uLevel,
725 struct pack_desc* desc,
726 int count, print_queue_struct* queue,
727 print_status_struct* status)
732 PACKS(desc,"B13",SERVICE(snum));
737 PACKS(desc,"z",Expand(conn,snum,SERVICE(snum)));
740 PACKI(desc,"K",printq_status(status->status));
744 if (uLevel == 1 || uLevel == 2) {
745 PACKS(desc,"B",""); /* alignment */
746 PACKI(desc,"W",5); /* priority */
747 PACKI(desc,"W",0); /* start time */
748 PACKI(desc,"W",0); /* until time */
749 PACKS(desc,"z",""); /* pSepFile */
750 PACKS(desc,"z","lpd"); /* pPrProc */
751 PACKS(desc,"z",SERVICE(snum)); /* pDestinations */
752 PACKS(desc,"z",""); /* pParms */
754 PACKS(desc,"z","UNKNOWN PRINTER");
755 PACKI(desc,"W",LPSTAT_ERROR);
757 else if (!status || !status->message[0]) {
758 PACKS(desc,"z",Expand(conn,snum,lp_comment(snum)));
759 PACKI(desc,"W",LPSTAT_OK); /* status */
761 PACKS(desc,"z",status->message);
762 PACKI(desc,"W",printq_status(status->status)); /* status */
764 PACKI(desc,(uLevel == 1 ? "W" : "N"),count);
767 if (uLevel == 3 || uLevel == 4) {
768 char *drivername = NULL;
770 PACKI(desc,"W",5); /* uPriority */
771 PACKI(desc,"W",0); /* uStarttime */
772 PACKI(desc,"W",0); /* uUntiltime */
773 PACKI(desc,"W",5); /* pad1 */
774 PACKS(desc,"z",""); /* pszSepFile */
775 PACKS(desc,"z","WinPrint"); /* pszPrProc */
776 PACKS(desc,"z",NULL); /* pszParms */
777 PACKS(desc,"z",NULL); /* pszComment - don't ask.... JRA */
778 /* "don't ask" that it's done this way to fix corrupted
779 Win9X/ME printer comments. */
781 PACKI(desc,"W",LPSTAT_OK); /* fsStatus */
783 PACKI(desc,"W",printq_status(status->status)); /* fsStatus */
785 PACKI(desc,(uLevel == 3 ? "W" : "N"),count); /* cJobs */
786 PACKS(desc,"z",SERVICE(snum)); /* pszPrinters */
787 get_driver_name(snum,&drivername);
791 PACKS(desc,"z",drivername); /* pszDriverName */
792 PackDriverData(desc); /* pDriverData */
795 if (uLevel == 2 || uLevel == 4) {
797 for (i=0;i<count;i++)
798 fill_printjob_info(conn,snum,uLevel == 2 ? 1 : 2,desc,&queue[i],i);
802 fill_printq_info_52( conn, snum, desc, count );
805 /* This function returns the number of files for a given driver */
806 static int get_printerdrivernumber(int snum)
809 NT_PRINTER_DRIVER_INFO_LEVEL driver;
810 NT_PRINTER_INFO_LEVEL *printer = NULL;
814 if ( !W_ERROR_IS_OK(get_a_printer( NULL, &printer, 2, lp_servicename(snum))) ) {
815 DEBUG(3,("get_printerdrivernumber: Failed to lookup printer [%s]\n",
816 lp_servicename(snum)));
820 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername,
823 DEBUG(3,("get_printerdrivernumber: Failed to lookup driver [%s]\n",
824 printer->info_2->drivername));
828 /* count the number of files */
829 while ( driver.info_3->dependentfiles && *driver.info_3->dependentfiles[result] )
834 free_a_printer( &printer, 2 );
837 free_a_printer_driver( driver, 3 );
842 static bool api_DosPrintQGetInfo(connection_struct *conn, uint16 vuid,
843 char *param, int tpscnt,
844 char *data, int tdscnt,
845 int mdrcnt,int mprcnt,
846 char **rdata,char **rparam,
847 int *rdata_len,int *rparam_len)
849 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
850 char *str2 = skip_string(param,tpscnt,str1);
851 char *p = skip_string(param,tpscnt,str2);
857 struct pack_desc desc;
858 print_queue_struct *queue=NULL;
859 print_status_struct status;
862 if (!str1 || !str2 || !p) {
865 memset((char *)&status,'\0',sizeof(status));
866 memset((char *)&desc,'\0',sizeof(desc));
868 p = skip_string(param,tpscnt,p);
872 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
873 str3 = get_safe_str_ptr(param,tpscnt,p,4);
874 /* str3 may be null here and is checked in check_printq_info(). */
876 /* remove any trailing username */
877 if ((p = strchr_m(QueueName,'%')))
880 DEBUG(3,("api_DosPrintQGetInfo uLevel=%d name=%s\n",uLevel,QueueName));
882 /* check it's a supported varient */
883 if (!prefix_ok(str1,"zWrLh"))
885 if (!check_printq_info(&desc,uLevel,str2,str3)) {
887 * Patch from Scott Moomaw <scott@bridgewater.edu>
888 * to return the 'invalid info level' error if an
889 * unknown level was requested.
893 *rparam = smb_realloc_limit(*rparam,*rparam_len);
897 SSVALS(*rparam,0,ERRunknownlevel);
903 snum = find_service(QueueName);
904 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
908 count = get_printerdrivernumber(snum);
909 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count));
911 count = print_queue_status(snum, &queue,&status);
915 *rdata = smb_realloc_limit(*rdata,mdrcnt);
921 desc.buflen = mdrcnt;
924 * Don't return data but need to get correct length
925 * init_package will return wrong size if buflen=0
927 desc.buflen = getlen(desc.format);
928 desc.base = tmpdata = (char *) SMB_MALLOC (desc.buflen);
931 if (init_package(&desc,1,count)) {
932 desc.subcount = count;
933 fill_printq_info(conn,snum,uLevel,&desc,count,queue,&status);
936 *rdata_len = desc.usedlen;
939 * We must set the return code to ERRbuftoosmall
940 * in order to support lanman style printing with Win NT/2k
943 if (!mdrcnt && lp_disable_spoolss())
944 desc.errcode = ERRbuftoosmall;
946 *rdata_len = desc.usedlen;
948 *rparam = smb_realloc_limit(*rparam,*rparam_len);
954 SSVALS(*rparam,0,desc.errcode);
956 SSVAL(*rparam,4,desc.neededlen);
958 DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode));
966 /****************************************************************************
967 View list of all print jobs on all queues.
968 ****************************************************************************/
970 static bool api_DosPrintQEnum(connection_struct *conn, uint16 vuid,
971 char *param, int tpscnt,
972 char *data, int tdscnt,
973 int mdrcnt, int mprcnt,
974 char **rdata, char** rparam,
975 int *rdata_len, int *rparam_len)
977 char *param_format = get_safe_str_ptr(param,tpscnt,param,2);
978 char *output_format1 = skip_string(param,tpscnt,param_format);
979 char *p = skip_string(param,tpscnt,output_format1);
980 unsigned int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
981 char *output_format2 = get_safe_str_ptr(param,tpscnt,p,4);
982 int services = lp_numservices();
984 struct pack_desc desc;
985 print_queue_struct **queue = NULL;
986 print_status_struct *status = NULL;
987 int *subcntarr = NULL;
988 int queuecnt = 0, subcnt = 0, succnt = 0;
990 if (!param_format || !output_format1 || !p) {
994 memset((char *)&desc,'\0',sizeof(desc));
996 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
998 if (!prefix_ok(param_format,"WrLeh")) {
1001 if (!check_printq_info(&desc,uLevel,output_format1,output_format2)) {
1003 * Patch from Scott Moomaw <scott@bridgewater.edu>
1004 * to return the 'invalid info level' error if an
1005 * unknown level was requested.
1009 *rparam = smb_realloc_limit(*rparam,*rparam_len);
1013 SSVALS(*rparam,0,ERRunknownlevel);
1019 for (i = 0; i < services; i++) {
1020 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
1025 if((queue = SMB_MALLOC_ARRAY(print_queue_struct*, queuecnt)) == NULL) {
1026 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
1029 memset(queue,0,queuecnt*sizeof(print_queue_struct*));
1030 if((status = SMB_MALLOC_ARRAY(print_status_struct,queuecnt)) == NULL) {
1031 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
1034 memset(status,0,queuecnt*sizeof(print_status_struct));
1035 if((subcntarr = SMB_MALLOC_ARRAY(int,queuecnt)) == NULL) {
1036 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
1042 for (i = 0; i < services; i++) {
1043 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
1044 subcntarr[n] = print_queue_status(i, &queue[n],&status[n]);
1045 subcnt += subcntarr[n];
1051 *rdata = smb_realloc_limit(*rdata,mdrcnt);
1057 desc.buflen = mdrcnt;
1059 if (init_package(&desc,queuecnt,subcnt)) {
1062 for (i = 0; i < services; i++) {
1063 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
1064 fill_printq_info(conn,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]);
1066 if (desc.errcode == NERR_Success) {
1073 SAFE_FREE(subcntarr);
1075 *rdata_len = desc.usedlen;
1077 *rparam = smb_realloc_limit(*rparam,*rparam_len);
1081 SSVALS(*rparam,0,desc.errcode);
1083 SSVAL(*rparam,4,succnt);
1084 SSVAL(*rparam,6,queuecnt);
1086 for (i = 0; i < queuecnt; i++) {
1088 SAFE_FREE(queue[i]);
1099 SAFE_FREE(subcntarr);
1100 for (i = 0; i < queuecnt; i++) {
1102 SAFE_FREE(queue[i]);
1111 /****************************************************************************
1112 Get info level for a server list query.
1113 ****************************************************************************/
1115 static bool check_server_info(int uLevel, char* id)
1119 if (strcmp(id,"B16") != 0) {
1124 if (strcmp(id,"B16BBDz") != 0) {
1134 struct srv_info_struct {
1142 /*******************************************************************
1143 Get server info lists from the files saved by nmbd. Return the
1145 ******************************************************************/
1147 static int get_server_info(uint32 servertype,
1148 struct srv_info_struct **servers,
1154 bool local_list_only;
1157 lines = file_lines_load(cache_path(SERVER_LIST), NULL, 0, NULL);
1159 DEBUG(4,("Can't open %s - %s\n",cache_path(SERVER_LIST),strerror(errno)));
1163 /* request for everything is code for request all servers */
1164 if (servertype == SV_TYPE_ALL) {
1165 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1168 local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY);
1170 DEBUG(4,("Servertype search: %8x\n",servertype));
1172 for (i=0;lines[i];i++) {
1174 struct srv_info_struct *s;
1175 const char *ptr = lines[i];
1177 TALLOC_CTX *frame = NULL;
1184 if (count == alloced) {
1186 *servers = SMB_REALLOC_ARRAY(*servers,struct srv_info_struct, alloced);
1188 DEBUG(0,("get_server_info: failed to enlarge servers info struct!\n"));
1192 memset((char *)((*servers)+count),'\0',sizeof(**servers)*(alloced-count));
1194 s = &(*servers)[count];
1196 frame = talloc_stackframe();
1198 if (!next_token_talloc(frame,&ptr,&p, NULL)) {
1202 fstrcpy(s->name, p);
1205 if (!next_token_talloc(frame,&ptr, &p, NULL)) {
1211 s->comment[0] = '\0';
1212 if (!next_token_talloc(frame,&ptr, &p, NULL)) {
1216 fstrcpy(s->comment, p);
1218 s->domain[0] = '\0';
1219 if (!next_token_talloc(frame,&ptr,&p, NULL)) {
1220 /* this allows us to cope with an old nmbd */
1221 fstrcpy(s->domain,lp_workgroup());
1223 fstrcpy(s->domain, p);
1227 if (sscanf(stype,"%X",&s->type) != 1) {
1228 DEBUG(4,("r:host file "));
1232 /* Filter the servers/domains we return based on what was asked for. */
1234 /* Check to see if we are being asked for a local list only. */
1235 if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) {
1236 DEBUG(4,("r: local list only"));
1240 /* doesn't match up: don't want it */
1241 if (!(servertype & s->type)) {
1242 DEBUG(4,("r:serv type "));
1246 if ((servertype & SV_TYPE_DOMAIN_ENUM) !=
1247 (s->type & SV_TYPE_DOMAIN_ENUM)) {
1248 DEBUG(4,("s: dom mismatch "));
1252 if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM)) {
1256 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1257 s->type &= ~SV_TYPE_LOCAL_LIST_ONLY;
1260 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1261 s->name, s->type, s->comment, s->domain));
1262 s->server_added = True;
1265 DEBUG(4,("%20s %8x %25s %15s\n",
1266 s->name, s->type, s->comment, s->domain));
1274 /*******************************************************************
1275 Fill in a server info structure.
1276 ******************************************************************/
1278 static int fill_srv_info(struct srv_info_struct *service,
1279 int uLevel, char **buf, int *buflen,
1280 char **stringbuf, int *stringspace, char *baseaddr)
1303 len = strlen(service->comment)+1;
1307 *buflen = struct_len;
1309 return struct_len + len;
1314 if (*buflen < struct_len) {
1321 p2 = p + struct_len;
1322 l2 = *buflen - struct_len;
1330 push_ascii(p,service->name, MAX_NETBIOSNAME_LEN, STR_TERMINATE);
1334 push_ascii(p,service->name,MAX_NETBIOSNAME_LEN, STR_TERMINATE);
1335 SIVAL(p,18,service->type);
1336 SIVAL(p,22,PTR_DIFF(p2,baseaddr));
1337 len += CopyAndAdvance(&p2,service->comment,&l2);
1342 *buf = p + struct_len;
1343 *buflen -= struct_len;
1354 static bool srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
1356 return(strcmp(s1->name,s2->name));
1359 /****************************************************************************
1360 View list of servers available (or possibly domains). The info is
1361 extracted from lists saved by nmbd on the local host.
1362 ****************************************************************************/
1364 static bool api_RNetServerEnum(connection_struct *conn, uint16 vuid,
1365 char *param, int tpscnt,
1366 char *data, int tdscnt,
1367 int mdrcnt, int mprcnt, char **rdata,
1368 char **rparam, int *rdata_len, int *rparam_len)
1370 char *str1 = get_safe_str_ptr(param, tpscnt, param, 2);
1371 char *str2 = skip_string(param,tpscnt,str1);
1372 char *p = skip_string(param,tpscnt,str2);
1373 int uLevel = get_safe_SVAL(param, tpscnt, p, 0, -1);
1374 int buf_len = get_safe_SVAL(param,tpscnt, p, 2, 0);
1375 uint32 servertype = get_safe_IVAL(param,tpscnt,p,4, 0);
1377 int data_len, fixed_len, string_len;
1378 int f_len = 0, s_len = 0;
1379 struct srv_info_struct *servers=NULL;
1380 int counted=0,total=0;
1383 bool domain_request;
1386 if (!str1 || !str2 || !p) {
1390 /* If someone sets all the bits they don't really mean to set
1391 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1394 if (servertype == SV_TYPE_ALL) {
1395 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1398 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1399 any other bit (they may just set this bit on its own) they
1400 want all the locally seen servers. However this bit can be
1401 set on its own so set the requested servers to be
1402 ALL - DOMAIN_ENUM. */
1404 if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM)) {
1405 servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
1408 domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
1409 local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
1413 if (!prefix_ok(str1,"WrLehD")) {
1416 if (!check_server_info(uLevel,str2)) {
1420 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1421 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1422 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1424 if (strcmp(str1, "WrLehDz") == 0) {
1425 if (skip_string(param,tpscnt,p) == NULL) {
1428 pull_ascii_fstring(domain, p);
1430 fstrcpy(domain, lp_workgroup());
1433 if (lp_browse_list()) {
1434 total = get_server_info(servertype,&servers,domain);
1437 data_len = fixed_len = string_len = 0;
1441 qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
1445 char *lastname=NULL;
1447 for (i=0;i<total;i++) {
1448 struct srv_info_struct *s = &servers[i];
1450 if (lastname && strequal(lastname,s->name)) {
1454 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1455 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1456 s->name, s->type, s->comment, s->domain));
1458 if (data_len <= buf_len) {
1461 string_len += s_len;
1468 *rdata_len = fixed_len + string_len;
1469 *rdata = smb_realloc_limit(*rdata,*rdata_len);
1474 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1480 char *lastname=NULL;
1481 int count2 = counted;
1483 for (i = 0; i < total && count2;i++) {
1484 struct srv_info_struct *s = &servers[i];
1486 if (lastname && strequal(lastname,s->name)) {
1490 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1491 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1492 s->name, s->type, s->comment, s->domain));
1498 *rparam = smb_realloc_limit(*rparam,*rparam_len);
1502 SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata));
1504 SSVAL(*rparam,4,counted);
1505 SSVAL(*rparam,6,counted+missed);
1509 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1510 domain,uLevel,counted,counted+missed));
1515 /****************************************************************************
1516 command 0x34 - suspected of being a "Lookup Names" stub api
1517 ****************************************************************************/
1519 static bool api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid,
1520 char *param, int tpscnt,
1521 char *data, int tdscnt,
1522 int mdrcnt, int mprcnt, char **rdata,
1523 char **rparam, int *rdata_len, int *rparam_len)
1525 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
1526 char *str2 = skip_string(param,tpscnt,str1);
1527 char *p = skip_string(param,tpscnt,str2);
1528 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
1529 int buf_len = get_safe_SVAL(param,tpscnt,p,2,0);
1533 if (!str1 || !str2 || !p) {
1537 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1538 str1, str2, p, uLevel, buf_len));
1540 if (!prefix_ok(str1,"zWrLeh")) {
1547 *rparam = smb_realloc_limit(*rparam,*rparam_len);
1552 SSVAL(*rparam,0,0x08AC); /* informational warning message */
1554 SSVAL(*rparam,4,counted);
1555 SSVAL(*rparam,6,counted+missed);
1560 /****************************************************************************
1561 get info about a share
1562 ****************************************************************************/
1564 static bool check_share_info(int uLevel, char* id)
1568 if (strcmp(id,"B13") != 0) {
1573 if (strcmp(id,"B13BWz") != 0) {
1578 if (strcmp(id,"B13BWzWWWzB9B") != 0) {
1583 if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) {
1593 static int fill_share_info(connection_struct *conn, int snum, int uLevel,
1594 char** buf, int* buflen,
1595 char** stringbuf, int* stringspace, char* baseaddr)
1624 len += StrlenExpanded(conn,snum,lp_comment(snum));
1627 len += strlen(lp_pathname(snum)) + 1;
1630 *buflen = struct_len;
1635 return struct_len + len;
1640 if ((*buflen) < struct_len) {
1648 p2 = p + struct_len;
1649 l2 = (*buflen) - struct_len;
1656 push_ascii(p,lp_servicename(snum),13, STR_TERMINATE);
1662 type = STYPE_DISKTREE;
1663 if (lp_print_ok(snum)) {
1664 type = STYPE_PRINTQ;
1666 if (strequal("IPC",lp_fstype(snum))) {
1669 SSVAL(p,14,type); /* device type */
1670 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1671 len += CopyExpanded(conn,snum,&p2,lp_comment(snum),&l2);
1675 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1676 SSVALS(p,22,-1); /* max uses */
1677 SSVAL(p,24,1); /* current uses */
1678 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1679 len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1680 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1684 memset(p+40,0,SHPWLEN+2);
1695 (*buf) = p + struct_len;
1696 (*buflen) -= struct_len;
1698 (*stringspace) = l2;
1707 static bool api_RNetShareGetInfo(connection_struct *conn,uint16 vuid,
1708 char *param, int tpscnt,
1709 char *data, int tdscnt,
1710 int mdrcnt,int mprcnt,
1711 char **rdata,char **rparam,
1712 int *rdata_len,int *rparam_len)
1714 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
1715 char *str2 = skip_string(param,tpscnt,str1);
1716 char *netname = skip_string(param,tpscnt,str2);
1717 char *p = skip_string(param,tpscnt,netname);
1718 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
1721 if (!str1 || !str2 || !netname || !p) {
1725 snum = find_service(netname);
1730 /* check it's a supported varient */
1731 if (!prefix_ok(str1,"zWrLh")) {
1734 if (!check_share_info(uLevel,str2)) {
1738 *rdata = smb_realloc_limit(*rdata,mdrcnt);
1743 *rdata_len = fill_share_info(conn,snum,uLevel,&p,&mdrcnt,0,0,0);
1744 if (*rdata_len < 0) {
1749 *rparam = smb_realloc_limit(*rparam,*rparam_len);
1753 SSVAL(*rparam,0,NERR_Success);
1754 SSVAL(*rparam,2,0); /* converter word */
1755 SSVAL(*rparam,4,*rdata_len);
1760 /****************************************************************************
1761 View the list of available shares.
1763 This function is the server side of the NetShareEnum() RAP call.
1764 It fills the return buffer with share names and share comments.
1765 Note that the return buffer normally (in all known cases) allows only
1766 twelve byte strings for share names (plus one for a nul terminator).
1767 Share names longer than 12 bytes must be skipped.
1768 ****************************************************************************/
1770 static bool api_RNetShareEnum( connection_struct *conn, uint16 vuid,
1771 char *param, int tpscnt,
1772 char *data, int tdscnt,
1780 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
1781 char *str2 = skip_string(param,tpscnt,str1);
1782 char *p = skip_string(param,tpscnt,str2);
1783 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
1784 int buf_len = get_safe_SVAL(param,tpscnt,p,2,0);
1787 int total=0,counted=0;
1788 bool missed = False;
1790 int data_len, fixed_len, string_len;
1791 int f_len = 0, s_len = 0;
1793 if (!str1 || !str2 || !p) {
1797 if (!prefix_ok(str1,"WrLeh")) {
1800 if (!check_share_info(uLevel,str2)) {
1804 /* Ensure all the usershares are loaded. */
1806 load_registry_shares();
1807 count = load_usershare_shares();
1810 data_len = fixed_len = string_len = 0;
1811 for (i=0;i<count;i++) {
1812 fstring servicename_dos;
1813 if (!(lp_browseable(i) && lp_snum_ok(i))) {
1816 push_ascii_fstring(servicename_dos, lp_servicename(i));
1817 /* Maximum name length = 13. */
1818 if( lp_browseable( i ) && lp_snum_ok( i ) && (strlen(servicename_dos) < 13)) {
1820 data_len += fill_share_info(conn,i,uLevel,0,&f_len,0,&s_len,0);
1821 if (data_len <= buf_len) {
1824 string_len += s_len;
1831 *rdata_len = fixed_len + string_len;
1832 *rdata = smb_realloc_limit(*rdata,*rdata_len);
1837 p2 = (*rdata) + fixed_len; /* auxiliary data (strings) will go here */
1842 for( i = 0; i < count; i++ ) {
1843 fstring servicename_dos;
1844 if (!(lp_browseable(i) && lp_snum_ok(i))) {
1848 push_ascii_fstring(servicename_dos, lp_servicename(i));
1849 if (lp_browseable(i) && lp_snum_ok(i) && (strlen(servicename_dos) < 13)) {
1850 if (fill_share_info( conn,i,uLevel,&p,&f_len,&p2,&s_len,*rdata ) < 0) {
1857 *rparam = smb_realloc_limit(*rparam,*rparam_len);
1861 SSVAL(*rparam,0,missed ? ERRmoredata : NERR_Success);
1863 SSVAL(*rparam,4,counted);
1864 SSVAL(*rparam,6,total);
1866 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1867 counted,total,uLevel,
1868 buf_len,*rdata_len,mdrcnt));
1873 /****************************************************************************
1875 ****************************************************************************/
1877 static bool api_RNetShareAdd(connection_struct *conn,uint16 vuid,
1878 char *param, int tpscnt,
1879 char *data, int tdscnt,
1880 int mdrcnt,int mprcnt,
1881 char **rdata,char **rparam,
1882 int *rdata_len,int *rparam_len)
1884 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
1885 char *str2 = skip_string(param,tpscnt,str1);
1886 char *p = skip_string(param,tpscnt,str2);
1887 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
1890 char *pathname = NULL;
1891 char *command, *cmdname;
1892 unsigned int offset;
1895 size_t converted_size;
1897 if (!str1 || !str2 || !p) {
1901 /* check it's a supported varient */
1902 if (!prefix_ok(str1,RAP_WShareAdd_REQ)) {
1905 if (!check_share_info(uLevel,str2)) {
1912 /* Do we have a string ? */
1913 if (skip_string(data,mdrcnt,data) == NULL) {
1916 pull_ascii_fstring(sharename,data);
1917 snum = find_service(sharename);
1918 if (snum >= 0) { /* already exists */
1927 /* only support disk share adds */
1928 if (SVAL(data,14)!=STYPE_DISKTREE) {
1932 offset = IVAL(data, 16);
1933 if (offset >= mdrcnt) {
1934 res = ERRinvalidparam;
1938 /* Do we have a string ? */
1939 if (skip_string(data,mdrcnt,data+offset) == NULL) {
1942 pull_ascii_fstring(comment, offset? (data+offset) : "");
1944 offset = IVAL(data, 26);
1946 if (offset >= mdrcnt) {
1947 res = ERRinvalidparam;
1951 /* Do we have a string ? */
1952 if (skip_string(data,mdrcnt,data+offset) == NULL) {
1956 if (!pull_ascii_talloc(talloc_tos(), &pathname,
1957 offset ? (data+offset) : "", &converted_size))
1959 DEBUG(0,("api_RNetShareAdd: pull_ascii_talloc failed: %s",
1967 string_replace(sharename, '"', ' ');
1968 string_replace(pathname, '"', ' ');
1969 string_replace(comment, '"', ' ');
1971 cmdname = lp_add_share_cmd();
1973 if (!cmdname || *cmdname == '\0') {
1977 if (asprintf(&command, "%s \"%s\" \"%s\" \"%s\" \"%s\"",
1978 lp_add_share_cmd(), get_dyn_CONFIGFILE(), sharename,
1979 pathname, comment) == -1) {
1983 DEBUG(10,("api_RNetShareAdd: Running [%s]\n", command ));
1985 if ((res = smbrun(command, NULL)) != 0) {
1986 DEBUG(1,("api_RNetShareAdd: Running [%s] returned (%d)\n",
1993 message_send_all(smbd_messaging_context(),
1994 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
1998 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2002 SSVAL(*rparam,0,NERR_Success);
2003 SSVAL(*rparam,2,0); /* converter word */
2004 SSVAL(*rparam,4,*rdata_len);
2012 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2017 SSVAL(*rparam,0,res);
2022 /****************************************************************************
2023 view list of groups available
2024 ****************************************************************************/
2026 static bool api_RNetGroupEnum(connection_struct *conn,uint16 vuid,
2027 char *param, int tpscnt,
2028 char *data, int tdscnt,
2029 int mdrcnt,int mprcnt,
2030 char **rdata,char **rparam,
2031 int *rdata_len,int *rparam_len)
2035 int resume_context, cli_buf_size;
2036 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2037 char *str2 = skip_string(param,tpscnt,str1);
2038 char *p = skip_string(param,tpscnt,str2);
2040 uint32_t num_groups;
2041 uint32_t resume_handle;
2042 struct rpc_pipe_client *samr_pipe;
2043 struct policy_handle samr_handle, domain_handle;
2046 if (!str1 || !str2 || !p) {
2050 if (strcmp(str1,"WrLeh") != 0) {
2055 * W-> resume context (number of users to skip)
2056 * r -> return parameter pointer to receive buffer
2057 * L -> length of receive buffer
2058 * e -> return parameter number of entries
2059 * h -> return parameter total number of users
2062 if (strcmp("B21",str2) != 0) {
2066 status = rpc_pipe_open_internal(
2067 talloc_tos(), &ndr_table_samr.syntax_id, rpc_samr_dispatch,
2068 conn->server_info, &samr_pipe);
2069 if (!NT_STATUS_IS_OK(status)) {
2070 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2071 nt_errstr(status)));
2075 status = rpccli_samr_Connect2(samr_pipe, talloc_tos(), global_myname(),
2076 SAMR_ACCESS_OPEN_DOMAIN, &samr_handle);
2077 if (!NT_STATUS_IS_OK(status)) {
2078 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2079 nt_errstr(status)));
2083 status = rpccli_samr_OpenDomain(samr_pipe, talloc_tos(), &samr_handle,
2084 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS,
2085 get_global_sam_sid(), &domain_handle);
2086 if (!NT_STATUS_IS_OK(status)) {
2087 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2088 nt_errstr(status)));
2089 rpccli_samr_Close(samr_pipe, talloc_tos(), &samr_handle);
2093 resume_context = get_safe_SVAL(param,tpscnt,p,0,-1);
2094 cli_buf_size= get_safe_SVAL(param,tpscnt,p,2,0);
2095 DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: "
2096 "%d\n", resume_context, cli_buf_size));
2098 *rdata_len = cli_buf_size;
2099 *rdata = smb_realloc_limit(*rdata,*rdata_len);
2106 errflags = NERR_Success;
2111 struct samr_SamArray *sam_entries;
2112 uint32_t num_entries;
2114 status = rpccli_samr_EnumDomainGroups(samr_pipe, talloc_tos(),
2119 if (!NT_STATUS_IS_OK(status)) {
2120 DEBUG(10, ("rpccli_samr_EnumDomainGroups returned "
2121 "%s\n", nt_errstr(status)));
2125 if (num_entries == 0) {
2126 DEBUG(10, ("rpccli_samr_EnumDomainGroups returned "
2127 "no entries -- done\n"));
2131 for(i=0; i<num_entries; i++) {
2134 name = sam_entries->entries[i].name.string;
2136 if( ((PTR_DIFF(p,*rdata)+21) > *rdata_len) ) {
2137 /* set overflow error */
2138 DEBUG(3,("overflow on entry %d group %s\n", i,
2144 /* truncate the name at 21 chars. */
2146 strlcpy(p, name, 21);
2147 DEBUG(10,("adding entry %d group %s\n", i, p));
2149 p += 5; /* Both NT4 and W2k3SP1 do padding here. No
2154 if (errflags != NERR_Success) {
2158 TALLOC_FREE(sam_entries);
2161 rpccli_samr_Close(samr_pipe, talloc_tos(), &domain_handle);
2162 rpccli_samr_Close(samr_pipe, talloc_tos(), &samr_handle);
2164 *rdata_len = PTR_DIFF(p,*rdata);
2167 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2171 SSVAL(*rparam, 0, errflags);
2172 SSVAL(*rparam, 2, 0); /* converter word */
2173 SSVAL(*rparam, 4, num_groups); /* is this right?? */
2174 SSVAL(*rparam, 6, resume_context+num_groups); /* is this right?? */
2179 /*******************************************************************
2180 Get groups that a user is a member of.
2181 ******************************************************************/
2183 static bool api_NetUserGetGroups(connection_struct *conn,uint16 vuid,
2184 char *param, int tpscnt,
2185 char *data, int tdscnt,
2186 int mdrcnt,int mprcnt,
2187 char **rdata,char **rparam,
2188 int *rdata_len,int *rparam_len)
2190 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2191 char *str2 = skip_string(param,tpscnt,str1);
2192 char *UserName = skip_string(param,tpscnt,str2);
2193 char *p = skip_string(param,tpscnt,UserName);
2194 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
2195 const char *level_string;
2197 struct samu *sampw = NULL;
2205 enum lsa_SidType type;
2207 TALLOC_CTX *mem_ctx;
2209 if (!str1 || !str2 || !UserName || !p) {
2214 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2219 /* check it's a supported varient */
2221 if ( strcmp(str1,"zWrLeh") != 0 )
2226 level_string = "B21";
2232 if (strcmp(level_string,str2) != 0)
2235 *rdata_len = mdrcnt + 1024;
2236 *rdata = smb_realloc_limit(*rdata,*rdata_len);
2241 SSVAL(*rparam,0,NERR_Success);
2242 SSVAL(*rparam,2,0); /* converter word */
2245 endp = *rdata + *rdata_len;
2247 mem_ctx = talloc_new(NULL);
2248 if (mem_ctx == NULL) {
2249 DEBUG(0, ("talloc_new failed\n"));
2253 if ( !(sampw = samu_new(mem_ctx)) ) {
2254 DEBUG(0, ("samu_new() failed!\n"));
2255 TALLOC_FREE(mem_ctx);
2259 /* Lookup the user information; This should only be one of
2260 our accounts (not remote domains) */
2262 become_root(); /* ROOT BLOCK */
2264 if (!lookup_name(mem_ctx, UserName, LOOKUP_NAME_ALL,
2265 NULL, NULL, &user_sid, &type)) {
2266 DEBUG(10, ("lookup_name(%s) failed\n", UserName));
2270 if (type != SID_NAME_USER) {
2271 DEBUG(10, ("%s is a %s, not a user\n", UserName,
2272 sid_type_lookup(type)));
2276 if ( !pdb_getsampwsid(sampw, &user_sid) ) {
2277 DEBUG(10, ("pdb_getsampwsid(%s) failed for user %s\n",
2278 sid_string_dbg(&user_sid), UserName));
2286 result = pdb_enum_group_memberships(mem_ctx, sampw,
2287 &sids, &gids, &num_groups);
2289 if (!NT_STATUS_IS_OK(result)) {
2290 DEBUG(10, ("pdb_enum_group_memberships failed for %s\n",
2295 for (i=0; i<num_groups; i++) {
2296 const char *grp_name;
2298 if ( lookup_sid(mem_ctx, &sids[i], NULL, &grp_name, NULL) ) {
2299 strlcpy(p, grp_name, PTR_DIFF(endp,p));
2305 *rdata_len = PTR_DIFF(p,*rdata);
2307 SSVAL(*rparam,4,count); /* is this right?? */
2308 SSVAL(*rparam,6,count); /* is this right?? */
2313 unbecome_root(); /* END ROOT BLOCK */
2315 TALLOC_FREE(mem_ctx);
2320 /*******************************************************************
2322 ******************************************************************/
2324 static bool api_RNetUserEnum(connection_struct *conn, uint16 vuid,
2325 char *param, int tpscnt,
2326 char *data, int tdscnt,
2327 int mdrcnt,int mprcnt,
2328 char **rdata,char **rparam,
2329 int *rdata_len,int *rparam_len)
2334 int i, resume_context, cli_buf_size;
2335 uint32_t resume_handle;
2337 struct rpc_pipe_client *samr_pipe;
2338 struct policy_handle samr_handle, domain_handle;
2341 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2342 char *str2 = skip_string(param,tpscnt,str1);
2343 char *p = skip_string(param,tpscnt,str2);
2346 if (!str1 || !str2 || !p) {
2350 if (strcmp(str1,"WrLeh") != 0)
2353 * W-> resume context (number of users to skip)
2354 * r -> return parameter pointer to receive buffer
2355 * L -> length of receive buffer
2356 * e -> return parameter number of entries
2357 * h -> return parameter total number of users
2360 resume_context = get_safe_SVAL(param,tpscnt,p,0,-1);
2361 cli_buf_size= get_safe_SVAL(param,tpscnt,p,2,0);
2362 DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n",
2363 resume_context, cli_buf_size));
2366 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2371 /* check it's a supported varient */
2372 if (strcmp("B21",str2) != 0)
2375 *rdata_len = cli_buf_size;
2376 *rdata = smb_realloc_limit(*rdata,*rdata_len);
2382 endp = *rdata + *rdata_len;
2384 status = rpc_pipe_open_internal(
2385 talloc_tos(), &ndr_table_samr.syntax_id, rpc_samr_dispatch,
2386 conn->server_info, &samr_pipe);
2387 if (!NT_STATUS_IS_OK(status)) {
2388 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2389 nt_errstr(status)));
2393 status = rpccli_samr_Connect2(samr_pipe, talloc_tos(), global_myname(),
2394 SAMR_ACCESS_OPEN_DOMAIN, &samr_handle);
2395 if (!NT_STATUS_IS_OK(status)) {
2396 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2397 nt_errstr(status)));
2401 status = rpccli_samr_OpenDomain(samr_pipe, talloc_tos(), &samr_handle,
2402 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS,
2403 get_global_sam_sid(), &domain_handle);
2404 if (!NT_STATUS_IS_OK(status)) {
2405 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2406 nt_errstr(status)));
2407 rpccli_samr_Close(samr_pipe, talloc_tos(), &samr_handle);
2411 errflags=NERR_Success;
2416 struct samr_SamArray *sam_entries;
2417 uint32_t num_entries;
2419 status = rpccli_samr_EnumDomainUsers(samr_pipe, talloc_tos(),
2425 if (!NT_STATUS_IS_OK(status)) {
2426 DEBUG(10, ("rpccli_samr_EnumDomainUsers returned "
2427 "%s\n", nt_errstr(status)));
2431 if (num_entries == 0) {
2432 DEBUG(10, ("rpccli_samr_EnumDomainUsers returned "
2433 "no entries -- done\n"));
2437 for (i=0; i<num_entries; i++) {
2440 name = sam_entries->entries[i].name.string;
2442 if(((PTR_DIFF(p,*rdata)+21)<=*rdata_len)
2443 &&(strlen(name)<=21)) {
2444 strlcpy(p,name,PTR_DIFF(endp,p));
2445 DEBUG(10,("api_RNetUserEnum:adding entry %d "
2446 "username %s\n",count_sent,p));
2450 /* set overflow error */
2451 DEBUG(10,("api_RNetUserEnum:overflow on entry %d "
2452 "username %s\n",count_sent,name));
2458 if (errflags != NERR_Success) {
2462 TALLOC_FREE(sam_entries);
2465 rpccli_samr_Close(samr_pipe, talloc_tos(), &domain_handle);
2466 rpccli_samr_Close(samr_pipe, talloc_tos(), &samr_handle);
2468 *rdata_len = PTR_DIFF(p,*rdata);
2470 SSVAL(*rparam,0,errflags);
2471 SSVAL(*rparam,2,0); /* converter word */
2472 SSVAL(*rparam,4,count_sent); /* is this right?? */
2473 SSVAL(*rparam,6,num_users); /* is this right?? */
2478 /****************************************************************************
2479 Get the time of day info.
2480 ****************************************************************************/
2482 static bool api_NetRemoteTOD(connection_struct *conn,uint16 vuid,
2483 char *param, int tpscnt,
2484 char *data, int tdscnt,
2485 int mdrcnt,int mprcnt,
2486 char **rdata,char **rparam,
2487 int *rdata_len,int *rparam_len)
2490 time_t unixdate = time(NULL);
2494 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2500 *rdata = smb_realloc_limit(*rdata,*rdata_len);
2505 SSVAL(*rparam,0,NERR_Success);
2506 SSVAL(*rparam,2,0); /* converter word */
2510 srv_put_dos_date3(p,0,unixdate); /* this is the time that is looked at
2511 by NT in a "net time" operation,
2512 it seems to ignore the one below */
2514 /* the client expects to get localtime, not GMT, in this bit
2515 (I think, this needs testing) */
2516 t = localtime(&unixdate);
2521 SIVAL(p,4,0); /* msecs ? */
2522 SCVAL(p,8,t->tm_hour);
2523 SCVAL(p,9,t->tm_min);
2524 SCVAL(p,10,t->tm_sec);
2525 SCVAL(p,11,0); /* hundredths of seconds */
2526 SSVALS(p,12,get_time_zone(unixdate)/60); /* timezone in minutes from GMT */
2527 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
2528 SCVAL(p,16,t->tm_mday);
2529 SCVAL(p,17,t->tm_mon + 1);
2530 SSVAL(p,18,1900+t->tm_year);
2531 SCVAL(p,20,t->tm_wday);
2536 /****************************************************************************
2537 Set the user password.
2538 *****************************************************************************/
2540 static bool api_SetUserPassword(connection_struct *conn,uint16 vuid,
2541 char *param, int tpscnt,
2542 char *data, int tdscnt,
2543 int mdrcnt,int mprcnt,
2544 char **rdata,char **rparam,
2545 int *rdata_len,int *rparam_len)
2547 char *np = get_safe_str_ptr(param,tpscnt,param,2);
2550 fstring pass1,pass2;
2552 /* Skip 2 strings. */
2553 p = skip_string(param,tpscnt,np);
2554 p = skip_string(param,tpscnt,p);
2560 /* Do we have a string ? */
2561 if (skip_string(param,tpscnt,p) == NULL) {
2564 pull_ascii_fstring(user,p);
2566 p = skip_string(param,tpscnt,p);
2571 memset(pass1,'\0',sizeof(pass1));
2572 memset(pass2,'\0',sizeof(pass2));
2574 * We use 31 here not 32 as we're checking
2575 * the last byte we want to access is safe.
2577 if (!is_offset_safe(param,tpscnt,p,31)) {
2581 memcpy(pass2,p+16,16);
2584 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2591 SSVAL(*rparam,0,NERR_badpass);
2592 SSVAL(*rparam,2,0); /* converter word */
2594 DEBUG(3,("Set password for <%s>\n",user));
2597 * Attempt to verify the old password against smbpasswd entries
2598 * Win98 clients send old and new password in plaintext for this call.
2602 auth_serversupplied_info *server_info = NULL;
2603 DATA_BLOB password = data_blob(pass1, strlen(pass1)+1);
2605 if (NT_STATUS_IS_OK(check_plaintext_password(user,password,&server_info))) {
2608 if (NT_STATUS_IS_OK(change_oem_password(server_info->sam_account, pass1, pass2, False, NULL))) {
2609 SSVAL(*rparam,0,NERR_Success);
2613 TALLOC_FREE(server_info);
2615 data_blob_clear_free(&password);
2619 * If the plaintext change failed, attempt
2620 * the old encrypted method. NT will generate this
2621 * after trying the samr method. Note that this
2622 * method is done as a last resort as this
2623 * password change method loses the NT password hash
2624 * and cannot change the UNIX password as no plaintext
2628 if(SVAL(*rparam,0) != NERR_Success) {
2629 struct samu *hnd = NULL;
2631 if (check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &hnd)) {
2633 if (change_lanman_password(hnd,(uchar *)pass2)) {
2634 SSVAL(*rparam,0,NERR_Success);
2641 memset((char *)pass1,'\0',sizeof(fstring));
2642 memset((char *)pass2,'\0',sizeof(fstring));
2647 /****************************************************************************
2648 Set the user password (SamOEM version - gets plaintext).
2649 ****************************************************************************/
2651 static bool api_SamOEMChangePassword(connection_struct *conn,uint16 vuid,
2652 char *param, int tpscnt,
2653 char *data, int tdscnt,
2654 int mdrcnt,int mprcnt,
2655 char **rdata,char **rparam,
2656 int *rdata_len,int *rparam_len)
2659 char *p = get_safe_str_ptr(param,tpscnt,param,2);
2661 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2671 SSVAL(*rparam,0,NERR_badpass);
2674 * Check the parameter definition is correct.
2677 /* Do we have a string ? */
2678 if (skip_string(param,tpscnt,p) == 0) {
2681 if(!strequal(p, "zsT")) {
2682 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", p));
2685 p = skip_string(param, tpscnt, p);
2690 /* Do we have a string ? */
2691 if (skip_string(param,tpscnt,p) == 0) {
2694 if(!strequal(p, "B516B16")) {
2695 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p));
2698 p = skip_string(param,tpscnt,p);
2702 /* Do we have a string ? */
2703 if (skip_string(param,tpscnt,p) == 0) {
2706 p += pull_ascii_fstring(user,p);
2708 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user));
2711 * Pass the user through the NT -> unix user mapping
2715 (void)map_username(user);
2717 if (NT_STATUS_IS_OK(pass_oem_change(user, (uchar*) data, (uchar *)&data[516], NULL, NULL, NULL))) {
2718 SSVAL(*rparam,0,NERR_Success);
2724 /****************************************************************************
2727 ****************************************************************************/
2729 static bool api_RDosPrintJobDel(connection_struct *conn,uint16 vuid,
2730 char *param, int tpscnt,
2731 char *data, int tdscnt,
2732 int mdrcnt,int mprcnt,
2733 char **rdata,char **rparam,
2734 int *rdata_len,int *rparam_len)
2736 int function = get_safe_SVAL(param,tpscnt,param,0,0);
2737 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2738 char *str2 = skip_string(param,tpscnt,str1);
2739 char *p = skip_string(param,tpscnt,str2);
2744 WERROR werr = WERR_OK;
2746 if (!str1 || !str2 || !p) {
2750 * We use 1 here not 2 as we're checking
2751 * the last byte we want to access is safe.
2753 if (!is_offset_safe(param,tpscnt,p,1)) {
2756 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
2759 /* check it's a supported varient */
2760 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
2764 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2770 if (!print_job_exists(sharename, jobid)) {
2771 errcode = NERR_JobNotFound;
2775 snum = lp_servicenumber( sharename);
2777 errcode = NERR_DestNotFound;
2781 errcode = NERR_notsupported;
2784 case 81: /* delete */
2785 if (print_job_delete(conn->server_info, snum, jobid, &werr))
2786 errcode = NERR_Success;
2788 case 82: /* pause */
2789 if (print_job_pause(conn->server_info, snum, jobid, &werr))
2790 errcode = NERR_Success;
2792 case 83: /* resume */
2793 if (print_job_resume(conn->server_info, snum, jobid, &werr))
2794 errcode = NERR_Success;
2798 if (!W_ERROR_IS_OK(werr))
2799 errcode = W_ERROR_V(werr);
2802 SSVAL(*rparam,0,errcode);
2803 SSVAL(*rparam,2,0); /* converter word */
2808 /****************************************************************************
2809 Purge a print queue - or pause or resume it.
2810 ****************************************************************************/
2812 static bool api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid,
2813 char *param, int tpscnt,
2814 char *data, int tdscnt,
2815 int mdrcnt,int mprcnt,
2816 char **rdata,char **rparam,
2817 int *rdata_len,int *rparam_len)
2819 int function = get_safe_SVAL(param,tpscnt,param,0,0);
2820 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2821 char *str2 = skip_string(param,tpscnt,str1);
2822 char *QueueName = skip_string(param,tpscnt,str2);
2823 int errcode = NERR_notsupported;
2825 WERROR werr = WERR_OK;
2827 if (!str1 || !str2 || !QueueName) {
2831 /* check it's a supported varient */
2832 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
2836 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2842 if (skip_string(param,tpscnt,QueueName) == NULL) {
2845 snum = print_queue_snum(QueueName);
2848 errcode = NERR_JobNotFound;
2853 case 74: /* Pause queue */
2854 if (print_queue_pause(conn->server_info, snum, &werr)) {
2855 errcode = NERR_Success;
2858 case 75: /* Resume queue */
2859 if (print_queue_resume(conn->server_info, snum, &werr)) {
2860 errcode = NERR_Success;
2863 case 103: /* Purge */
2864 if (print_queue_purge(conn->server_info, snum, &werr)) {
2865 errcode = NERR_Success;
2870 if (!W_ERROR_IS_OK(werr)) errcode = W_ERROR_V(werr);
2873 SSVAL(*rparam,0,errcode);
2874 SSVAL(*rparam,2,0); /* converter word */
2879 /****************************************************************************
2880 set the property of a print job (undocumented?)
2881 ? function = 0xb -> set name of print job
2882 ? function = 0x6 -> move print job up/down
2883 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
2884 or <WWsTP> <WB21BB16B10zWWzDDz>
2885 ****************************************************************************/
2887 static int check_printjob_info(struct pack_desc* desc,
2888 int uLevel, char* id)
2890 desc->subformat = NULL;
2892 case 0: desc->format = "W"; break;
2893 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
2894 case 2: desc->format = "WWzWWDDzz"; break;
2895 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
2896 case 4: desc->format = "WWzWWDDzzzzzDDDDDDD"; break;
2898 DEBUG(0,("check_printjob_info: invalid level %d\n",
2902 if (id == NULL || strcmp(desc->format,id) != 0) {
2903 DEBUG(0,("check_printjob_info: invalid format %s\n",
2904 id ? id : "<NULL>" ));
2910 static bool api_PrintJobInfo(connection_struct *conn, uint16 vuid,
2911 char *param, int tpscnt,
2912 char *data, int tdscnt,
2913 int mdrcnt,int mprcnt,
2914 char **rdata,char **rparam,
2915 int *rdata_len,int *rparam_len)
2917 struct pack_desc desc;
2918 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2919 char *str2 = skip_string(param,tpscnt,str1);
2920 char *p = skip_string(param,tpscnt,str2);
2923 int uLevel = get_safe_SVAL(param,tpscnt,p,2,-1);
2924 int function = get_safe_SVAL(param,tpscnt,p,4,-1);
2927 if (!str1 || !str2 || !p) {
2931 * We use 1 here not 2 as we're checking
2932 * the last byte we want to access is safe.
2934 if (!is_offset_safe(param,tpscnt,p,1)) {
2937 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
2940 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2945 if (!share_defined(sharename)) {
2946 DEBUG(0,("api_PrintJobInfo: sharen [%s] not defined\n",
2953 /* check it's a supported varient */
2954 if ((strcmp(str1,"WWsTP")) ||
2955 (!check_printjob_info(&desc,uLevel,str2)))
2958 if (!print_job_exists(sharename, jobid)) {
2959 errcode=NERR_JobNotFound;
2963 errcode = NERR_notsupported;
2967 /* change job place in the queue,
2968 data gives the new place */
2969 place = SVAL(data,0);
2970 if (print_job_set_place(sharename, jobid, place)) {
2971 errcode=NERR_Success;
2976 /* change print job name, data gives the name */
2977 if (print_job_set_name(sharename, jobid, data)) {
2978 errcode=NERR_Success;
2987 SSVALS(*rparam,0,errcode);
2988 SSVAL(*rparam,2,0); /* converter word */
2994 /****************************************************************************
2995 Get info about the server.
2996 ****************************************************************************/
2998 static bool api_RNetServerGetInfo(connection_struct *conn,uint16 vuid,
2999 char *param, int tpscnt,
3000 char *data, int tdscnt,
3001 int mdrcnt,int mprcnt,
3002 char **rdata,char **rparam,
3003 int *rdata_len,int *rparam_len)
3005 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3006 char *str2 = skip_string(param,tpscnt,str1);
3007 char *p = skip_string(param,tpscnt,str2);
3008 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
3012 if (!str1 || !str2 || !p) {
3016 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
3018 /* check it's a supported varient */
3019 if (!prefix_ok(str1,"WrLh")) {
3025 if (strcmp(str2,"B16") != 0) {
3031 if (strcmp(str2,"B16BBDz") != 0) {
3037 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")!= 0) {
3043 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz") != 0) {
3049 if (strcmp(str2,"DN") != 0) {
3055 if (strcmp(str2,"B16BBDzWWzzz") != 0) {
3064 *rdata_len = mdrcnt;
3065 *rdata = smb_realloc_limit(*rdata,*rdata_len);
3071 p2 = p + struct_len;
3073 srvstr_push(NULL, 0, p,global_myname(),16,
3074 STR_ASCII|STR_UPPER|STR_TERMINATE);
3078 struct srv_info_struct *servers=NULL;
3080 char *comment = NULL;
3081 TALLOC_CTX *ctx = talloc_tos();
3082 uint32 servertype= lp_default_server_announce();
3084 comment = talloc_strdup(ctx,lp_serverstring());
3089 if ((count=get_server_info(SV_TYPE_ALL,&servers,lp_workgroup()))>0) {
3090 for (i=0;i<count;i++) {
3091 if (strequal(servers[i].name,global_myname())) {
3092 servertype = servers[i].type;
3093 TALLOC_FREE(comment);
3094 comment = talloc_strdup(ctx,
3095 servers[i].comment);
3105 SCVAL(p,0,lp_major_announce_version());
3106 SCVAL(p,1,lp_minor_announce_version());
3107 SIVAL(p,2,servertype);
3109 if (mdrcnt == struct_len) {
3112 SIVAL(p,6,PTR_DIFF(p2,*rdata));
3113 comment = talloc_sub_advanced(
3115 lp_servicename(SNUM(conn)),
3116 conn->server_info->unix_name,
3118 conn->server_info->utok.gid,
3119 conn->server_info->sanitized_username,
3120 pdb_get_domain(conn->server_info->sam_account),
3125 if (mdrcnt - struct_len <= 0) {
3130 MIN(mdrcnt - struct_len,
3131 MAX_SERVER_STRING_LENGTH),
3133 p2 = skip_string(*rdata,*rdata_len,p2);
3141 return False; /* not yet implemented */
3144 *rdata_len = PTR_DIFF(p2,*rdata);
3147 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3151 SSVAL(*rparam,0,NERR_Success);
3152 SSVAL(*rparam,2,0); /* converter word */
3153 SSVAL(*rparam,4,*rdata_len);
3158 /****************************************************************************
3159 Get info about the server.
3160 ****************************************************************************/
3162 static bool api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid,
3163 char *param, int tpscnt,
3164 char *data, int tdscnt,
3165 int mdrcnt,int mprcnt,
3166 char **rdata,char **rparam,
3167 int *rdata_len,int *rparam_len)
3169 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3170 char *str2 = skip_string(param,tpscnt,str1);
3171 char *p = skip_string(param,tpscnt,str2);
3174 int level = get_safe_SVAL(param,tpscnt,p,0,-1);
3176 if (!str1 || !str2 || !p) {
3180 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
3183 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3188 /* check it's a supported varient */
3189 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz"))) {
3193 *rdata_len = mdrcnt + 1024;
3194 *rdata = smb_realloc_limit(*rdata,*rdata_len);
3199 SSVAL(*rparam,0,NERR_Success);
3200 SSVAL(*rparam,2,0); /* converter word */
3203 endp = *rdata + *rdata_len;
3205 p2 = get_safe_ptr(*rdata,*rdata_len,p,22);
3210 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
3211 strlcpy(p2,get_local_machine_name(),PTR_DIFF(endp,p2));
3213 p2 = skip_string(*rdata,*rdata_len,p2);
3219 SIVAL(p,0,PTR_DIFF(p2,*rdata));
3220 strlcpy(p2,conn->server_info->sanitized_username,PTR_DIFF(endp,p2));
3221 p2 = skip_string(*rdata,*rdata_len,p2);
3227 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
3228 strlcpy(p2,lp_workgroup(),PTR_DIFF(endp,p2));
3230 p2 = skip_string(*rdata,*rdata_len,p2);
3236 SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
3237 SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
3240 SIVAL(p,0,PTR_DIFF(p2,*rdata));
3241 strlcpy(p2,lp_workgroup(),PTR_DIFF(endp,p2)); /* don't know. login domain?? */
3242 p2 = skip_string(*rdata,*rdata_len,p2);
3248 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
3249 strlcpy(p2,"",PTR_DIFF(endp,p2));
3250 p2 = skip_string(*rdata,*rdata_len,p2);
3256 *rdata_len = PTR_DIFF(p2,*rdata);
3258 SSVAL(*rparam,4,*rdata_len);
3263 /****************************************************************************
3264 get info about a user
3266 struct user_info_11 {
3267 char usri11_name[21]; 0-20
3269 char *usri11_comment; 22-25
3270 char *usri11_usr_comment; 26-29
3271 unsigned short usri11_priv; 30-31
3272 unsigned long usri11_auth_flags; 32-35
3273 long usri11_password_age; 36-39
3274 char *usri11_homedir; 40-43
3275 char *usri11_parms; 44-47
3276 long usri11_last_logon; 48-51
3277 long usri11_last_logoff; 52-55
3278 unsigned short usri11_bad_pw_count; 56-57
3279 unsigned short usri11_num_logons; 58-59
3280 char *usri11_logon_server; 60-63
3281 unsigned short usri11_country_code; 64-65
3282 char *usri11_workstations; 66-69
3283 unsigned long usri11_max_storage; 70-73
3284 unsigned short usri11_units_per_week; 74-75
3285 unsigned char *usri11_logon_hours; 76-79
3286 unsigned short usri11_code_page; 80-81
3291 usri11_name specifies the user name for which information is retrieved
3293 usri11_pad aligns the next data structure element to a word boundary
3295 usri11_comment is a null terminated ASCII comment
3297 usri11_user_comment is a null terminated ASCII comment about the user
3299 usri11_priv specifies the level of the privilege assigned to the user.
3300 The possible values are:
3302 Name Value Description
3303 USER_PRIV_GUEST 0 Guest privilege
3304 USER_PRIV_USER 1 User privilege
3305 USER_PRV_ADMIN 2 Administrator privilege
3307 usri11_auth_flags specifies the account operator privileges. The
3308 possible values are:
3310 Name Value Description
3311 AF_OP_PRINT 0 Print operator
3314 Leach, Naik [Page 28]
3318 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
3321 AF_OP_COMM 1 Communications operator
3322 AF_OP_SERVER 2 Server operator
3323 AF_OP_ACCOUNTS 3 Accounts operator
3326 usri11_password_age specifies how many seconds have elapsed since the
3327 password was last changed.
3329 usri11_home_dir points to a null terminated ASCII string that contains
3330 the path name of the user's home directory.
3332 usri11_parms points to a null terminated ASCII string that is set
3333 aside for use by applications.
3335 usri11_last_logon specifies the time when the user last logged on.
3336 This value is stored as the number of seconds elapsed since
3337 00:00:00, January 1, 1970.
3339 usri11_last_logoff specifies the time when the user last logged off.
3340 This value is stored as the number of seconds elapsed since
3341 00:00:00, January 1, 1970. A value of 0 means the last logoff
3344 usri11_bad_pw_count specifies the number of incorrect passwords
3345 entered since the last successful logon.
3347 usri11_log1_num_logons specifies the number of times this user has
3348 logged on. A value of -1 means the number of logons is unknown.
3350 usri11_logon_server points to a null terminated ASCII string that
3351 contains the name of the server to which logon requests are sent.
3352 A null string indicates logon requests should be sent to the
3355 usri11_country_code specifies the country code for the user's language
3358 usri11_workstations points to a null terminated ASCII string that
3359 contains the names of workstations the user may log on from.
3360 There may be up to 8 workstations, with the names separated by
3361 commas. A null strings indicates there are no restrictions.
3363 usri11_max_storage specifies the maximum amount of disk space the user
3364 can occupy. A value of 0xffffffff indicates there are no
3367 usri11_units_per_week specifies the equal number of time units into
3368 which a week is divided. This value must be equal to 168.
3370 usri11_logon_hours points to a 21 byte (168 bits) string that
3371 specifies the time during which the user can log on. Each bit
3372 represents one unique hour in a week. The first bit (bit 0, word
3373 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
3377 Leach, Naik [Page 29]
3381 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
3384 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
3385 are no restrictions.
3387 usri11_code_page specifies the code page for the user's language of
3390 All of the pointers in this data structure need to be treated
3391 specially. The pointer is a 32 bit pointer. The higher 16 bits need
3392 to be ignored. The converter word returned in the parameters section
3393 needs to be subtracted from the lower 16 bits to calculate an offset
3394 into the return buffer where this ASCII string resides.
3396 There is no auxiliary data in the response.
3398 ****************************************************************************/
3400 #define usri11_name 0
3401 #define usri11_pad 21
3402 #define usri11_comment 22
3403 #define usri11_usr_comment 26
3404 #define usri11_full_name 30
3405 #define usri11_priv 34
3406 #define usri11_auth_flags 36
3407 #define usri11_password_age 40
3408 #define usri11_homedir 44
3409 #define usri11_parms 48
3410 #define usri11_last_logon 52
3411 #define usri11_last_logoff 56
3412 #define usri11_bad_pw_count 60
3413 #define usri11_num_logons 62
3414 #define usri11_logon_server 64
3415 #define usri11_country_code 68
3416 #define usri11_workstations 70
3417 #define usri11_max_storage 74
3418 #define usri11_units_per_week 78
3419 #define usri11_logon_hours 80
3420 #define usri11_code_page 84
3421 #define usri11_end 86
3423 #define USER_PRIV_GUEST 0
3424 #define USER_PRIV_USER 1
3425 #define USER_PRIV_ADMIN 2
3427 #define AF_OP_PRINT 0
3428 #define AF_OP_COMM 1
3429 #define AF_OP_SERVER 2
3430 #define AF_OP_ACCOUNTS 3
3433 static bool api_RNetUserGetInfo(connection_struct *conn, uint16 vuid,
3434 char *param, int tpscnt,
3435 char *data, int tdscnt,
3436 int mdrcnt,int mprcnt,
3437 char **rdata,char **rparam,
3438 int *rdata_len,int *rparam_len)
3440 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3441 char *str2 = skip_string(param,tpscnt,str1);
3442 char *UserName = skip_string(param,tpscnt,str2);
3443 char *p = skip_string(param,tpscnt,UserName);
3444 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
3447 const char *level_string;
3449 /* get NIS home of a previously validated user - simeon */
3450 /* With share level security vuid will always be zero.
3451 Don't depend on vuser being non-null !!. JRA */
3452 user_struct *vuser = get_valid_user_struct(vuid);
3454 DEBUG(3,(" Username of UID %d is %s\n",
3455 (int)vuser->server_info->utok.uid,
3456 vuser->server_info->unix_name));
3459 if (!str1 || !str2 || !UserName || !p) {
3464 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3469 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
3471 /* check it's a supported variant */
3472 if (strcmp(str1,"zWrLh") != 0) {
3476 case 0: level_string = "B21"; break;
3477 case 1: level_string = "B21BB16DWzzWz"; break;
3478 case 2: level_string = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
3479 case 10: level_string = "B21Bzzz"; break;
3480 case 11: level_string = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
3481 default: return False;
3484 if (strcmp(level_string,str2) != 0) {
3488 *rdata_len = mdrcnt + 1024;
3489 *rdata = smb_realloc_limit(*rdata,*rdata_len);
3494 SSVAL(*rparam,0,NERR_Success);
3495 SSVAL(*rparam,2,0); /* converter word */
3498 endp = *rdata + *rdata_len;
3499 p2 = get_safe_ptr(*rdata,*rdata_len,p,usri11_end);
3505 fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
3508 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
3513 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
3514 strlcpy(p2,"Comment",PTR_DIFF(endp,p2));
3515 p2 = skip_string(*rdata,*rdata_len,p2);
3520 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
3521 strlcpy(p2,"UserComment",PTR_DIFF(endp,p2));
3522 p2 = skip_string(*rdata,*rdata_len,p2);
3527 /* EEK! the cifsrap.txt doesn't have this in!!!! */
3528 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
3529 strlcpy(p2,((vuser != NULL)
3530 ? pdb_get_fullname(vuser->server_info->sam_account)
3531 : UserName),PTR_DIFF(endp,p2));
3532 p2 = skip_string(*rdata,*rdata_len,p2);
3539 const char *homedir = "";
3540 if (vuser != NULL) {
3541 homedir = pdb_get_homedir(
3542 vuser->server_info->sam_account);
3544 /* modelled after NTAS 3.51 reply */
3545 SSVAL(p,usri11_priv,conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
3546 SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
3547 SIVALS(p,usri11_password_age,-1); /* password age */
3548 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
3549 strlcpy(p2, homedir, PTR_DIFF(endp,p2));
3550 p2 = skip_string(*rdata,*rdata_len,p2);
3554 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
3555 strlcpy(p2,"",PTR_DIFF(endp,p2));
3556 p2 = skip_string(*rdata,*rdata_len,p2);
3560 SIVAL(p,usri11_last_logon,0); /* last logon */
3561 SIVAL(p,usri11_last_logoff,0); /* last logoff */
3562 SSVALS(p,usri11_bad_pw_count,-1); /* bad pw counts */
3563 SSVALS(p,usri11_num_logons,-1); /* num logons */
3564 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
3565 strlcpy(p2,"\\\\*",PTR_DIFF(endp,p2));
3566 p2 = skip_string(*rdata,*rdata_len,p2);
3570 SSVAL(p,usri11_country_code,0); /* country code */
3572 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
3573 strlcpy(p2,"",PTR_DIFF(endp,p2));
3574 p2 = skip_string(*rdata,*rdata_len,p2);
3579 SIVALS(p,usri11_max_storage,-1); /* max storage */
3580 SSVAL(p,usri11_units_per_week,168); /* units per week */
3581 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
3583 /* a simple way to get logon hours at all times. */
3585 SCVAL(p2,21,0); /* fix zero termination */
3586 p2 = skip_string(*rdata,*rdata_len,p2);
3591 SSVAL(p,usri11_code_page,0); /* code page */
3594 if (uLevel == 1 || uLevel == 2) {
3595 memset(p+22,' ',16); /* password */
3596 SIVALS(p,38,-1); /* password age */
3598 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
3599 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
3600 strlcpy(p2, vuser ? pdb_get_homedir(
3601 vuser->server_info->sam_account) : "",
3603 p2 = skip_string(*rdata,*rdata_len,p2);
3607 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
3609 SSVAL(p,52,0); /* flags */
3610 SIVAL(p,54,PTR_DIFF(p2,*rdata)); /* script_path */
3611 strlcpy(p2, vuser ? pdb_get_logon_script(
3612 vuser->server_info->sam_account) : "",
3614 p2 = skip_string(*rdata,*rdata_len,p2);
3619 SIVAL(p,60,0); /* auth_flags */
3620 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
3621 strlcpy(p2,((vuser != NULL)
3622 ? pdb_get_fullname(vuser->server_info->sam_account)
3623 : UserName),PTR_DIFF(endp,p2));
3624 p2 = skip_string(*rdata,*rdata_len,p2);
3628 SIVAL(p,68,0); /* urs_comment */
3629 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
3630 strlcpy(p2,"",PTR_DIFF(endp,p2));
3631 p2 = skip_string(*rdata,*rdata_len,p2);
3635 SIVAL(p,76,0); /* workstations */
3636 SIVAL(p,80,0); /* last_logon */
3637 SIVAL(p,84,0); /* last_logoff */
3638 SIVALS(p,88,-1); /* acct_expires */
3639 SIVALS(p,92,-1); /* max_storage */
3640 SSVAL(p,96,168); /* units_per_week */
3641 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
3644 SSVALS(p,102,-1); /* bad_pw_count */
3645 SSVALS(p,104,-1); /* num_logons */
3646 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
3648 TALLOC_CTX *ctx = talloc_tos();
3649 int space_rem = *rdata_len - (p2 - *rdata);
3652 if (space_rem <= 0) {
3655 tmp = talloc_strdup(ctx, "\\\\%L");
3659 tmp = talloc_sub_basic(ctx,
3672 p2 = skip_string(*rdata,*rdata_len,p2);
3676 SSVAL(p,110,49); /* country_code */
3677 SSVAL(p,112,860); /* code page */
3681 *rdata_len = PTR_DIFF(p2,*rdata);
3683 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
3688 static bool api_WWkstaUserLogon(connection_struct *conn,uint16 vuid,
3689 char *param, int tpscnt,
3690 char *data, int tdscnt,
3691 int mdrcnt,int mprcnt,
3692 char **rdata,char **rparam,
3693 int *rdata_len,int *rparam_len)
3695 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3696 char *str2 = skip_string(param,tpscnt,str1);
3697 char *p = skip_string(param,tpscnt,str2);
3699 struct pack_desc desc;
3701 /* With share level security vuid will always be zero.
3702 Don't depend on vuser being non-null !!. JRA */
3703 user_struct *vuser = get_valid_user_struct(vuid);
3705 if (!str1 || !str2 || !p) {
3710 DEBUG(3,(" Username of UID %d is %s\n",
3711 (int)vuser->server_info->utok.uid,
3712 vuser->server_info->unix_name));
3715 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
3716 name = get_safe_str_ptr(param,tpscnt,p,2);
3721 memset((char *)&desc,'\0',sizeof(desc));
3723 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
3725 /* check it's a supported varient */
3726 if (strcmp(str1,"OOWb54WrLh") != 0) {
3729 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) {
3733 *rdata = smb_realloc_limit(*rdata,mdrcnt);
3740 desc.buflen = mdrcnt;
3741 desc.subformat = NULL;
3744 if (init_package(&desc,1,0)) {
3745 PACKI(&desc,"W",0); /* code */
3746 PACKS(&desc,"B21",name); /* eff. name */
3747 PACKS(&desc,"B",""); /* pad */
3748 PACKI(&desc,"W", conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
3749 PACKI(&desc,"D",0); /* auth flags XXX */
3750 PACKI(&desc,"W",0); /* num logons */
3751 PACKI(&desc,"W",0); /* bad pw count */
3752 PACKI(&desc,"D",0); /* last logon */
3753 PACKI(&desc,"D",-1); /* last logoff */
3754 PACKI(&desc,"D",-1); /* logoff time */
3755 PACKI(&desc,"D",-1); /* kickoff time */
3756 PACKI(&desc,"D",0); /* password age */
3757 PACKI(&desc,"D",0); /* password can change */
3758 PACKI(&desc,"D",-1); /* password must change */
3762 fstrcpy(mypath,"\\\\");
3763 fstrcat(mypath,get_local_machine_name());
3765 PACKS(&desc,"z",mypath); /* computer */
3768 PACKS(&desc,"z",lp_workgroup());/* domain */
3769 PACKS(&desc,"z", vuser ? pdb_get_logon_script(
3770 vuser->server_info->sam_account) : ""); /* script path */
3771 PACKI(&desc,"D",0x00000000); /* reserved */
3774 *rdata_len = desc.usedlen;
3776 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3780 SSVALS(*rparam,0,desc.errcode);
3782 SSVAL(*rparam,4,desc.neededlen);
3784 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
3789 /****************************************************************************
3790 api_WAccessGetUserPerms
3791 ****************************************************************************/
3793 static bool api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid,
3794 char *param, int tpscnt,
3795 char *data, int tdscnt,
3796 int mdrcnt,int mprcnt,
3797 char **rdata,char **rparam,
3798 int *rdata_len,int *rparam_len)
3800 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3801 char *str2 = skip_string(param,tpscnt,str1);
3802 char *user = skip_string(param,tpscnt,str2);
3803 char *resource = skip_string(param,tpscnt,user);
3805 if (!str1 || !str2 || !user || !resource) {
3809 if (skip_string(param,tpscnt,resource) == NULL) {
3812 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
3814 /* check it's a supported varient */
3815 if (strcmp(str1,"zzh") != 0) {
3818 if (strcmp(str2,"") != 0) {
3823 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3827 SSVALS(*rparam,0,0); /* errorcode */
3828 SSVAL(*rparam,2,0); /* converter word */
3829 SSVAL(*rparam,4,0x7f); /* permission flags */
3834 /****************************************************************************
3835 api_WPrintJobEnumerate
3836 ****************************************************************************/
3838 static bool api_WPrintJobGetInfo(connection_struct *conn, uint16 vuid,
3839 char *param, int tpscnt,
3840 char *data, int tdscnt,
3841 int mdrcnt,int mprcnt,
3842 char **rdata,char **rparam,
3843 int *rdata_len,int *rparam_len)
3845 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3846 char *str2 = skip_string(param,tpscnt,str1);
3847 char *p = skip_string(param,tpscnt,str2);
3854 struct pack_desc desc;
3855 print_queue_struct *queue=NULL;
3856 print_status_struct status;
3859 if (!str1 || !str2 || !p) {
3863 uLevel = get_safe_SVAL(param,tpscnt,p,2,-1);
3865 memset((char *)&desc,'\0',sizeof(desc));
3866 memset((char *)&status,'\0',sizeof(status));
3868 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
3870 /* check it's a supported varient */
3871 if (strcmp(str1,"WWrLh") != 0) {
3874 if (!check_printjob_info(&desc,uLevel,str2)) {
3878 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid)) {
3882 snum = lp_servicenumber( sharename);
3883 if (snum < 0 || !VALID_SNUM(snum)) {
3887 count = print_queue_status(snum,&queue,&status);
3888 for (i = 0; i < count; i++) {
3889 if (queue[i].job == jobid) {
3895 *rdata = smb_realloc_limit(*rdata,mdrcnt);
3900 desc.buflen = mdrcnt;
3903 * Don't return data but need to get correct length
3904 * init_package will return wrong size if buflen=0
3906 desc.buflen = getlen(desc.format);
3907 desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen );
3910 if (init_package(&desc,1,0)) {
3912 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
3913 *rdata_len = desc.usedlen;
3915 desc.errcode = NERR_JobNotFound;
3921 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3925 SSVALS(*rparam,0,desc.errcode);
3927 SSVAL(*rparam,4,desc.neededlen);
3932 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
3937 static bool api_WPrintJobEnumerate(connection_struct *conn, uint16 vuid,
3938 char *param, int tpscnt,
3939 char *data, int tdscnt,
3940 int mdrcnt,int mprcnt,
3941 char **rdata,char **rparam,
3942 int *rdata_len,int *rparam_len)
3944 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3945 char *str2 = skip_string(param,tpscnt,str1);
3946 char *p = skip_string(param,tpscnt,str2);
3952 struct pack_desc desc;
3953 print_queue_struct *queue=NULL;
3954 print_status_struct status;
3956 if (!str1 || !str2 || !p) {
3960 memset((char *)&desc,'\0',sizeof(desc));
3961 memset((char *)&status,'\0',sizeof(status));
3963 p = skip_string(param,tpscnt,p);
3967 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
3969 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
3971 /* check it's a supported variant */
3972 if (strcmp(str1,"zWrLeh") != 0) {
3977 return False; /* defined only for uLevel 0,1,2 */
3980 if (!check_printjob_info(&desc,uLevel,str2)) {
3984 snum = find_service(name);
3985 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) ) {
3989 count = print_queue_status(snum,&queue,&status);
3991 *rdata = smb_realloc_limit(*rdata,mdrcnt);
3997 desc.buflen = mdrcnt;
3999 if (init_package(&desc,count,0)) {
4001 for (i = 0; i < count; i++) {
4002 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
4003 if (desc.errcode == NERR_Success) {
4009 *rdata_len = desc.usedlen;
4012 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4016 SSVALS(*rparam,0,desc.errcode);
4018 SSVAL(*rparam,4,succnt);
4019 SSVAL(*rparam,6,count);
4023 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
4028 static int check_printdest_info(struct pack_desc* desc,
4029 int uLevel, char* id)
4031 desc->subformat = NULL;
4034 desc->format = "B9";
4037 desc->format = "B9B21WWzW";
4043 desc->format = "zzzWWzzzWW";
4046 DEBUG(0,("check_printdest_info: invalid level %d\n",
4050 if (id == NULL || strcmp(desc->format,id) != 0) {
4051 DEBUG(0,("check_printdest_info: invalid string %s\n",
4052 id ? id : "<NULL>" ));
4058 static void fill_printdest_info(connection_struct *conn, int snum, int uLevel,
4059 struct pack_desc* desc)
4063 strncpy(buf,SERVICE(snum),sizeof(buf)-1);
4064 buf[sizeof(buf)-1] = 0;
4068 PACKS(desc,"B9",buf); /* szName */
4070 PACKS(desc,"B21",""); /* szUserName */
4071 PACKI(desc,"W",0); /* uJobId */
4072 PACKI(desc,"W",0); /* fsStatus */
4073 PACKS(desc,"z",""); /* pszStatus */
4074 PACKI(desc,"W",0); /* time */
4078 if (uLevel == 2 || uLevel == 3) {
4079 PACKS(desc,"z",buf); /* pszPrinterName */
4081 PACKS(desc,"z",""); /* pszUserName */
4082 PACKS(desc,"z",""); /* pszLogAddr */
4083 PACKI(desc,"W",0); /* uJobId */
4084 PACKI(desc,"W",0); /* fsStatus */
4085 PACKS(desc,"z",""); /* pszStatus */
4086 PACKS(desc,"z",""); /* pszComment */
4087 PACKS(desc,"z","NULL"); /* pszDrivers */
4088 PACKI(desc,"W",0); /* time */
4089 PACKI(desc,"W",0); /* pad1 */
4094 static bool api_WPrintDestGetInfo(connection_struct *conn, uint16 vuid,
4095 char *param, int tpscnt,
4096 char *data, int tdscnt,
4097 int mdrcnt,int mprcnt,
4098 char **rdata,char **rparam,
4099 int *rdata_len,int *rparam_len)
4101 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4102 char *str2 = skip_string(param,tpscnt,str1);
4103 char *p = skip_string(param,tpscnt,str2);
4104 char* PrinterName = p;
4106 struct pack_desc desc;
4110 if (!str1 || !str2 || !p) {
4114 memset((char *)&desc,'\0',sizeof(desc));
4116 p = skip_string(param,tpscnt,p);
4120 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4122 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
4124 /* check it's a supported varient */
4125 if (strcmp(str1,"zWrLh") != 0) {
4128 if (!check_printdest_info(&desc,uLevel,str2)) {
4132 snum = find_service(PrinterName);
4133 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) ) {
4135 desc.errcode = NERR_DestNotFound;
4139 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4144 desc.buflen = mdrcnt;
4147 * Don't return data but need to get correct length
4148 * init_package will return wrong size if buflen=0
4150 desc.buflen = getlen(desc.format);
4151 desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen );
4153 if (init_package(&desc,1,0)) {
4154 fill_printdest_info(conn,snum,uLevel,&desc);
4156 *rdata_len = desc.usedlen;
4160 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4164 SSVALS(*rparam,0,desc.errcode);
4166 SSVAL(*rparam,4,desc.neededlen);
4168 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
4174 static bool api_WPrintDestEnum(connection_struct *conn, uint16 vuid,
4175 char *param, int tpscnt,
4176 char *data, int tdscnt,
4177 int mdrcnt,int mprcnt,
4178 char **rdata,char **rparam,
4179 int *rdata_len,int *rparam_len)
4181 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4182 char *str2 = skip_string(param,tpscnt,str1);
4183 char *p = skip_string(param,tpscnt,str2);
4187 struct pack_desc desc;
4188 int services = lp_numservices();
4190 if (!str1 || !str2 || !p) {
4194 memset((char *)&desc,'\0',sizeof(desc));
4196 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4198 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
4200 /* check it's a supported varient */
4201 if (strcmp(str1,"WrLeh") != 0) {
4204 if (!check_printdest_info(&desc,uLevel,str2)) {
4209 for (i = 0; i < services; i++) {
4210 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
4216 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4223 desc.buflen = mdrcnt;
4224 if (init_package(&desc,queuecnt,0)) {
4227 for (i = 0; i < services; i++) {
4228 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
4229 fill_printdest_info(conn,i,uLevel,&desc);
4231 if (desc.errcode == NERR_Success) {
4238 *rdata_len = desc.usedlen;
4241 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4245 SSVALS(*rparam,0,desc.errcode);
4247 SSVAL(*rparam,4,succnt);
4248 SSVAL(*rparam,6,queuecnt);
4250 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
4255 static bool api_WPrintDriverEnum(connection_struct *conn, uint16 vuid,
4256 char *param, int tpscnt,
4257 char *data, int tdscnt,
4258 int mdrcnt,int mprcnt,
4259 char **rdata,char **rparam,
4260 int *rdata_len,int *rparam_len)
4262 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4263 char *str2 = skip_string(param,tpscnt,str1);
4264 char *p = skip_string(param,tpscnt,str2);
4267 struct pack_desc desc;
4269 if (!str1 || !str2 || !p) {
4273 memset((char *)&desc,'\0',sizeof(desc));
4275 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4277 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
4279 /* check it's a supported varient */
4280 if (strcmp(str1,"WrLeh") != 0) {
4283 if (uLevel != 0 || strcmp(str2,"B41") != 0) {
4288 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4294 desc.buflen = mdrcnt;
4295 if (init_package(&desc,1,0)) {
4296 PACKS(&desc,"B41","NULL");
4299 succnt = (desc.errcode == NERR_Success ? 1 : 0);
4301 *rdata_len = desc.usedlen;
4304 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4308 SSVALS(*rparam,0,desc.errcode);
4310 SSVAL(*rparam,4,succnt);
4313 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
4318 static bool api_WPrintQProcEnum(connection_struct *conn, uint16 vuid,
4319 char *param, int tpscnt,
4320 char *data, int tdscnt,
4321 int mdrcnt,int mprcnt,
4322 char **rdata,char **rparam,
4323 int *rdata_len,int *rparam_len)
4325 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4326 char *str2 = skip_string(param,tpscnt,str1);
4327 char *p = skip_string(param,tpscnt,str2);
4330 struct pack_desc desc;
4332 if (!str1 || !str2 || !p) {
4335 memset((char *)&desc,'\0',sizeof(desc));
4337 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4339 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
4341 /* check it's a supported varient */
4342 if (strcmp(str1,"WrLeh") != 0) {
4345 if (uLevel != 0 || strcmp(str2,"B13") != 0) {
4350 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4356 desc.buflen = mdrcnt;
4358 if (init_package(&desc,1,0)) {
4359 PACKS(&desc,"B13","lpd");
4362 succnt = (desc.errcode == NERR_Success ? 1 : 0);
4364 *rdata_len = desc.usedlen;
4367 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4371 SSVALS(*rparam,0,desc.errcode);
4373 SSVAL(*rparam,4,succnt);
4376 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
4381 static bool api_WPrintPortEnum(connection_struct *conn, uint16 vuid,
4382 char *param, int tpscnt,
4383 char *data, int tdscnt,
4384 int mdrcnt,int mprcnt,
4385 char **rdata,char **rparam,
4386 int *rdata_len,int *rparam_len)
4388 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4389 char *str2 = skip_string(param,tpscnt,str1);
4390 char *p = skip_string(param,tpscnt,str2);
4393 struct pack_desc desc;
4395 if (!str1 || !str2 || !p) {
4399 memset((char *)&desc,'\0',sizeof(desc));
4401 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4403 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
4405 /* check it's a supported varient */
4406 if (strcmp(str1,"WrLeh") != 0) {
4409 if (uLevel != 0 || strcmp(str2,"B9") != 0) {
4414 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4419 memset((char *)&desc,'\0',sizeof(desc));
4421 desc.buflen = mdrcnt;
4423 if (init_package(&desc,1,0)) {
4424 PACKS(&desc,"B13","lp0");
4427 succnt = (desc.errcode == NERR_Success ? 1 : 0);
4429 *rdata_len = desc.usedlen;
4432 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4436 SSVALS(*rparam,0,desc.errcode);
4438 SSVAL(*rparam,4,succnt);
4441 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
4446 /****************************************************************************
4448 ****************************************************************************/
4450 static bool api_RNetSessionEnum(connection_struct *conn, uint16 vuid,
4451 char *param, int tpscnt,
4452 char *data, int tdscnt,
4453 int mdrcnt,int mprcnt,
4454 char **rdata,char **rparam,
4455 int *rdata_len,int *rparam_len)
4458 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4459 char *str2 = skip_string(param,tpscnt,str1);
4460 char *p = skip_string(param,tpscnt,str2);
4462 struct pack_desc desc;
4463 struct sessionid *session_list;
4464 int i, num_sessions;
4466 if (!str1 || !str2 || !p) {
4470 memset((char *)&desc,'\0',sizeof(desc));
4472 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4474 DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel));
4475 DEBUG(7,("RNetSessionEnum req string=%s\n",str1));
4476 DEBUG(7,("RNetSessionEnum ret string=%s\n",str2));
4478 /* check it's a supported varient */
4479 if (strcmp(str1,RAP_NetSessionEnum_REQ) != 0) {
4482 if (uLevel != 2 || strcmp(str2,RAP_SESSION_INFO_L2) != 0) {
4486 num_sessions = list_sessions(talloc_tos(), &session_list);
4489 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4494 memset((char *)&desc,'\0',sizeof(desc));
4496 desc.buflen = mdrcnt;
4498 if (!init_package(&desc,num_sessions,0)) {
4502 for(i=0; i<num_sessions; i++) {
4503 PACKS(&desc, "z", session_list[i].remote_machine);
4504 PACKS(&desc, "z", session_list[i].username);
4505 PACKI(&desc, "W", 1); /* num conns */
4506 PACKI(&desc, "W", 0); /* num opens */
4507 PACKI(&desc, "W", 1); /* num users */
4508 PACKI(&desc, "D", 0); /* session time */
4509 PACKI(&desc, "D", 0); /* idle time */
4510 PACKI(&desc, "D", 0); /* flags */
4511 PACKS(&desc, "z", "Unknown Client"); /* client type string */
4514 *rdata_len = desc.usedlen;
4517 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4521 SSVALS(*rparam,0,desc.errcode);
4522 SSVAL(*rparam,2,0); /* converter */
4523 SSVAL(*rparam,4,num_sessions); /* count */
4525 DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc.errcode));
4531 /****************************************************************************
4532 The buffer was too small.
4533 ****************************************************************************/
4535 static bool api_TooSmall(connection_struct *conn,uint16 vuid, char *param, char *data,
4536 int mdrcnt, int mprcnt,
4537 char **rdata, char **rparam,
4538 int *rdata_len, int *rparam_len)
4540 *rparam_len = MIN(*rparam_len,mprcnt);
4541 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4548 SSVAL(*rparam,0,NERR_BufTooSmall);
4550 DEBUG(3,("Supplied buffer too small in API command\n"));
4555 /****************************************************************************
4556 The request is not supported.
4557 ****************************************************************************/
4559 static bool api_Unsupported(connection_struct *conn, uint16 vuid,
4560 char *param, int tpscnt,
4561 char *data, int tdscnt,
4562 int mdrcnt, int mprcnt,
4563 char **rdata, char **rparam,
4564 int *rdata_len, int *rparam_len)
4567 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4574 SSVAL(*rparam,0,NERR_notsupported);
4575 SSVAL(*rparam,2,0); /* converter word */
4577 DEBUG(3,("Unsupported API command\n"));
4582 static const struct {
4585 bool (*fn)(connection_struct *, uint16,
4588 int,int,char **,char **,int *,int *);
4589 bool auth_user; /* Deny anonymous access? */
4590 } api_commands[] = {
4591 {"RNetShareEnum", RAP_WshareEnum, api_RNetShareEnum, True},
4592 {"RNetShareGetInfo", RAP_WshareGetInfo, api_RNetShareGetInfo},
4593 {"RNetShareAdd", RAP_WshareAdd, api_RNetShareAdd},
4594 {"RNetSessionEnum", RAP_WsessionEnum, api_RNetSessionEnum, True},
4595 {"RNetServerGetInfo", RAP_WserverGetInfo, api_RNetServerGetInfo},
4596 {"RNetGroupEnum", RAP_WGroupEnum, api_RNetGroupEnum, True},
4597 {"RNetGroupGetUsers", RAP_WGroupGetUsers, api_RNetGroupGetUsers, True},
4598 {"RNetUserEnum", RAP_WUserEnum, api_RNetUserEnum, True},
4599 {"RNetUserGetInfo", RAP_WUserGetInfo, api_RNetUserGetInfo},
4600 {"NetUserGetGroups", RAP_WUserGetGroups, api_NetUserGetGroups},
4601 {"NetWkstaGetInfo", RAP_WWkstaGetInfo, api_NetWkstaGetInfo},
4602 {"DosPrintQEnum", RAP_WPrintQEnum, api_DosPrintQEnum, True},
4603 {"DosPrintQGetInfo", RAP_WPrintQGetInfo, api_DosPrintQGetInfo},
4604 {"WPrintQueuePause", RAP_WPrintQPause, api_WPrintQueueCtrl},
4605 {"WPrintQueueResume", RAP_WPrintQContinue, api_WPrintQueueCtrl},
4606 {"WPrintJobEnumerate",RAP_WPrintJobEnum, api_WPrintJobEnumerate},
4607 {"WPrintJobGetInfo", RAP_WPrintJobGetInfo, api_WPrintJobGetInfo},
4608 {"RDosPrintJobDel", RAP_WPrintJobDel, api_RDosPrintJobDel},
4609 {"RDosPrintJobPause", RAP_WPrintJobPause, api_RDosPrintJobDel},
4610 {"RDosPrintJobResume",RAP_WPrintJobContinue, api_RDosPrintJobDel},
4611 {"WPrintDestEnum", RAP_WPrintDestEnum, api_WPrintDestEnum},
4612 {"WPrintDestGetInfo", RAP_WPrintDestGetInfo, api_WPrintDestGetInfo},
4613 {"NetRemoteTOD", RAP_NetRemoteTOD, api_NetRemoteTOD},
4614 {"WPrintQueuePurge", RAP_WPrintQPurge, api_WPrintQueueCtrl},
4615 {"NetServerEnum", RAP_NetServerEnum2, api_RNetServerEnum}, /* anon OK */
4616 {"WAccessGetUserPerms",RAP_WAccessGetUserPerms,api_WAccessGetUserPerms},
4617 {"SetUserPassword", RAP_WUserPasswordSet2, api_SetUserPassword},
4618 {"WWkstaUserLogon", RAP_WWkstaUserLogon, api_WWkstaUserLogon},
4619 {"PrintJobInfo", RAP_WPrintJobSetInfo, api_PrintJobInfo},
4620 {"WPrintDriverEnum", RAP_WPrintDriverEnum, api_WPrintDriverEnum},
4621 {"WPrintQProcEnum", RAP_WPrintQProcessorEnum,api_WPrintQProcEnum},
4622 {"WPrintPortEnum", RAP_WPrintPortEnum, api_WPrintPortEnum},
4623 {"SamOEMChangePassword",RAP_SamOEMChgPasswordUser2_P,api_SamOEMChangePassword}, /* anon OK */
4624 {NULL, -1, api_Unsupported}
4625 /* The following RAP calls are not implemented by Samba:
4627 RAP_WFileEnum2 - anon not OK
4632 /****************************************************************************
4633 Handle remote api calls.
4634 ****************************************************************************/
4636 void api_reply(connection_struct *conn, uint16 vuid,
4637 struct smb_request *req,
4638 char *data, char *params,
4639 int tdscnt, int tpscnt,
4640 int mdrcnt, int mprcnt)
4644 char *rparam = NULL;
4645 const char *name1 = NULL;
4646 const char *name2 = NULL;
4653 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
4654 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4659 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4662 api_command = SVAL(params,0);
4663 /* Is there a string at position params+2 ? */
4664 if (skip_string(params,tpscnt,params+2)) {
4669 name2 = skip_string(params,tpscnt,params+2);
4674 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
4678 tdscnt,tpscnt,mdrcnt,mprcnt));
4680 for (i=0;api_commands[i].name;i++) {
4681 if (api_commands[i].id == api_command && api_commands[i].fn) {
4682 DEBUG(3,("Doing %s\n",api_commands[i].name));
4687 /* Check whether this api call can be done anonymously */
4689 if (api_commands[i].auth_user && lp_restrict_anonymous()) {
4690 user_struct *user = get_valid_user_struct(vuid);
4692 if (!user || user->server_info->guest) {
4693 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4698 rdata = (char *)SMB_MALLOC(1024);
4700 memset(rdata,'\0',1024);
4703 rparam = (char *)SMB_MALLOC(1024);
4705 memset(rparam,'\0',1024);
4708 if(!rdata || !rparam) {
4709 DEBUG(0,("api_reply: malloc fail !\n"));
4712 reply_nterror(req, NT_STATUS_NO_MEMORY);
4716 reply = api_commands[i].fn(conn,
4718 params,tpscnt, /* params + length */
4719 data,tdscnt, /* data + length */
4721 &rdata,&rparam,&rdata_len,&rparam_len);
4724 if (rdata_len > mdrcnt || rparam_len > mprcnt) {
4725 reply = api_TooSmall(conn,vuid,params,data,mdrcnt,mprcnt,
4726 &rdata,&rparam,&rdata_len,&rparam_len);
4729 /* if we get False back then it's actually unsupported */
4731 reply = api_Unsupported(conn,vuid,params,tpscnt,data,tdscnt,mdrcnt,mprcnt,
4732 &rdata,&rparam,&rdata_len,&rparam_len);
4735 /* If api_Unsupported returns false we can't return anything. */
4737 send_trans_reply(conn, req, rparam, rparam_len,
4738 rdata, rdata_len, False);