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
29 #include "smbd/globals.h"
30 #include "../librpc/gen_ndr/cli_samr.h"
31 #include "../librpc/gen_ndr/srv_samr.h"
32 #include "../lib/util/binsearch.h"
39 #define NERR_Success 0
40 #define NERR_badpass 86
41 #define NERR_notsupported 50
43 #define NERR_BASE (2100)
44 #define NERR_BufTooSmall (NERR_BASE+23)
45 #define NERR_JobNotFound (NERR_BASE+51)
46 #define NERR_DestNotFound (NERR_BASE+52)
48 #define ACCESS_READ 0x01
49 #define ACCESS_WRITE 0x02
50 #define ACCESS_CREATE 0x04
52 #define SHPWLEN 8 /* share password length */
54 /* Limit size of ipc replies */
56 static char *smb_realloc_limit(void *ptr, size_t size)
60 size = MAX((size),4*1024);
61 val = (char *)SMB_REALLOC(ptr,size);
63 memset(val,'\0',size);
68 static bool api_Unsupported(connection_struct *conn, uint16 vuid,
69 char *param, int tpscnt,
70 char *data, int tdscnt,
71 int mdrcnt, int mprcnt,
72 char **rdata, char **rparam,
73 int *rdata_len, int *rparam_len);
75 static bool api_TooSmall(connection_struct *conn, uint16 vuid, char *param, char *data,
76 int mdrcnt, int mprcnt,
77 char **rdata, char **rparam,
78 int *rdata_len, int *rparam_len);
81 static int CopyExpanded(connection_struct *conn,
82 int snum, char **dst, char *src, int *p_space_remaining)
84 TALLOC_CTX *ctx = talloc_tos();
88 if (!src || !dst || !p_space_remaining || !(*dst) ||
89 *p_space_remaining <= 0) {
93 buf = talloc_strdup(ctx, src);
95 *p_space_remaining = 0;
98 buf = talloc_string_sub(ctx, buf,"%S",lp_servicename(snum));
100 *p_space_remaining = 0;
103 buf = talloc_sub_advanced(ctx,
104 lp_servicename(SNUM(conn)),
105 conn->server_info->unix_name,
107 conn->server_info->utok.gid,
108 conn->server_info->sanitized_username,
109 pdb_get_domain(conn->server_info->sam_account),
112 *p_space_remaining = 0;
115 l = push_ascii(*dst,buf,*p_space_remaining, STR_TERMINATE);
120 (*p_space_remaining) -= l;
124 static int CopyAndAdvance(char **dst, char *src, int *n)
127 if (!src || !dst || !n || !(*dst)) {
130 l = push_ascii(*dst,src,*n, STR_TERMINATE);
139 static int StrlenExpanded(connection_struct *conn, int snum, char *s)
141 TALLOC_CTX *ctx = talloc_tos();
146 buf = talloc_strdup(ctx,s);
150 buf = talloc_string_sub(ctx,buf,"%S",lp_servicename(snum));
154 buf = talloc_sub_advanced(ctx,
155 lp_servicename(SNUM(conn)),
156 conn->server_info->unix_name,
158 conn->server_info->utok.gid,
159 conn->server_info->sanitized_username,
160 pdb_get_domain(conn->server_info->sam_account),
165 return strlen(buf) + 1;
168 static char *Expand(connection_struct *conn, int snum, char *s)
170 TALLOC_CTX *ctx = talloc_tos();
176 buf = talloc_strdup(ctx,s);
180 buf = talloc_string_sub(ctx,buf,"%S",lp_servicename(snum));
184 return talloc_sub_advanced(ctx,
185 lp_servicename(SNUM(conn)),
186 conn->server_info->unix_name,
188 conn->server_info->utok.gid,
189 conn->server_info->sanitized_username,
190 pdb_get_domain(conn->server_info->sam_account),
194 /*******************************************************************
195 Check a API string for validity when we only need to check the prefix.
196 ******************************************************************/
198 static bool prefix_ok(const char *str, const char *prefix)
200 return(strncmp(str,prefix,strlen(prefix)) == 0);
204 const char *format; /* formatstring for structure */
205 const char *subformat; /* subformat for structure */
206 char *base; /* baseaddress of buffer */
207 int buflen; /* remaining size for fixed part; on init: length of base */
208 int subcount; /* count of substructures */
209 char *structbuf; /* pointer into buffer for remaining fixed part */
210 int stringlen; /* remaining size for variable part */
211 char *stringbuf; /* pointer into buffer for remaining variable part */
212 int neededlen; /* total needed size */
213 int usedlen; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
214 const char *curpos; /* current position; pointer into format or subformat */
218 static int get_counter(const char **p)
224 if (!isdigit((int)**p)) {
230 n = 10 * n + (i - '0');
238 static int getlen(const char *p)
247 case 'W': /* word (2 byte) */
250 case 'K': /* status word? (2 byte) */
253 case 'N': /* count of substructures (word) at end */
256 case 'D': /* double word (4 byte) */
257 case 'z': /* offset to zero terminated string (4 byte) */
258 case 'l': /* offset to user data (4 byte) */
261 case 'b': /* offset to data (with counter) (4 byte) */
265 case 'B': /* byte (with optional counter) */
266 n += get_counter(&p);
273 static bool init_package(struct pack_desc *p, int count, int subcount)
278 if (!p->format || !p->base) {
282 i = count * getlen(p->format);
284 i += subcount * getlen(p->subformat);
286 p->structbuf = p->base;
290 p->curpos = p->format;
296 * This is the old error code we used. Aparently
297 * WinNT/2k systems return ERRbuftoosmall (2123) and
298 * OS/2 needs this. I'm leaving this here so we can revert
301 p->errcode = ERRmoredata;
303 p->errcode = ERRbuftoosmall;
306 p->errcode = NERR_Success;
310 p->stringbuf = p->base + i;
312 return (p->errcode == NERR_Success);
315 static int package(struct pack_desc *p, ...)
318 int needed=0, stringneeded;
319 const char *str=NULL;
320 int is_string=0, stringused;
327 p->curpos = p->format;
329 p->curpos = p->subformat;
334 str = va_arg(args,char*);
335 SMB_ASSERT(strncmp(str,p->curpos,strlen(str)) == 0);
344 switch( *p->curpos++ ) {
345 case 'W': /* word (2 byte) */
347 temp = va_arg(args,int);
348 if (p->buflen >= needed) {
349 SSVAL(p->structbuf,0,temp);
352 case 'K': /* status word? (2 byte) */
354 temp = va_arg(args,int);
355 if (p->buflen >= needed) {
356 SSVAL(p->structbuf,0,temp);
359 case 'N': /* count of substructures (word) at end */
361 p->subcount = va_arg(args,int);
362 if (p->buflen >= needed) {
363 SSVAL(p->structbuf,0,p->subcount);
366 case 'D': /* double word (4 byte) */
368 temp = va_arg(args,int);
369 if (p->buflen >= needed) {
370 SIVAL(p->structbuf,0,temp);
373 case 'B': /* byte (with optional counter) */
374 needed = get_counter(&p->curpos);
376 char *s = va_arg(args,char*);
377 if (p->buflen >= needed) {
378 StrnCpy(p->structbuf,s?s:"",needed-1);
382 case 'z': /* offset to zero terminated string (4 byte) */
383 str = va_arg(args,char*);
384 stringneeded = (str ? strlen(str)+1 : 0);
387 case 'l': /* offset to user data (4 byte) */
388 str = va_arg(args,char*);
389 stringneeded = va_arg(args,int);
392 case 'b': /* offset to data (with counter) (4 byte) */
393 str = va_arg(args,char*);
394 stringneeded = get_counter(&p->curpos);
400 if (stringneeded >= 0) {
402 if (p->buflen >= needed) {
403 stringused = stringneeded;
404 if (stringused > p->stringlen) {
405 stringused = (is_string ? p->stringlen : 0);
406 if (p->errcode == NERR_Success) {
407 p->errcode = ERRmoredata;
411 SIVAL(p->structbuf,0,0);
413 SIVAL(p->structbuf,0,PTR_DIFF(p->stringbuf,p->base));
414 memcpy(p->stringbuf,str?str:"",stringused);
416 p->stringbuf[stringused-1] = '\0';
418 p->stringbuf += stringused;
419 p->stringlen -= stringused;
420 p->usedlen += stringused;
423 p->neededlen += stringneeded;
426 p->neededlen += needed;
427 if (p->buflen >= needed) {
428 p->structbuf += needed;
430 p->usedlen += needed;
432 if (p->errcode == NERR_Success) {
433 p->errcode = ERRmoredata;
440 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
441 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
443 #define PACK(desc,t,v) package(desc,v)
444 #define PACKl(desc,t,v,l) package(desc,v,l)
447 static void PACKI(struct pack_desc* desc, const char *t,int v)
452 static void PACKS(struct pack_desc* desc,const char *t,const char *v)
457 /****************************************************************************
459 ****************************************************************************/
461 static void PackDriverData(struct pack_desc* desc)
463 char drivdata[4+4+32];
464 SIVAL(drivdata,0,sizeof drivdata); /* cb */
465 SIVAL(drivdata,4,1000); /* lVersion */
466 memset(drivdata+8,0,32); /* szDeviceName */
467 push_ascii(drivdata+8,"NULL",32, STR_TERMINATE);
468 PACKl(desc,"l",drivdata,sizeof drivdata); /* pDriverData */
471 static int check_printq_info(struct pack_desc* desc,
472 unsigned int uLevel, char *id1, char *id2)
474 desc->subformat = NULL;
477 desc->format = "B13";
480 desc->format = "B13BWWWzzzzzWW";
483 desc->format = "B13BWWWzzzzzWN";
484 desc->subformat = "WB21BB16B10zWWzDDz";
487 desc->format = "zWWWWzzzzWWzzl";
490 desc->format = "zWWWWzzzzWNzzl";
491 desc->subformat = "WWzWWDDzz";
500 desc->format = "WzzzzzzzzN";
501 desc->subformat = "z";
504 DEBUG(0,("check_printq_info: invalid level %d\n",
508 if (id1 == NULL || strcmp(desc->format,id1) != 0) {
509 DEBUG(0,("check_printq_info: invalid format %s\n",
510 id1 ? id1 : "<NULL>" ));
513 if (desc->subformat && (id2 == NULL || strcmp(desc->subformat,id2) != 0)) {
514 DEBUG(0,("check_printq_info: invalid subformat %s\n",
515 id2 ? id2 : "<NULL>" ));
522 #define RAP_JOB_STATUS_QUEUED 0
523 #define RAP_JOB_STATUS_PAUSED 1
524 #define RAP_JOB_STATUS_SPOOLING 2
525 #define RAP_JOB_STATUS_PRINTING 3
526 #define RAP_JOB_STATUS_PRINTED 4
528 #define RAP_QUEUE_STATUS_PAUSED 1
529 #define RAP_QUEUE_STATUS_ERROR 2
531 /* turn a print job status into a on the wire status
533 static int printj_status(int v)
537 return RAP_JOB_STATUS_QUEUED;
539 return RAP_JOB_STATUS_PAUSED;
541 return RAP_JOB_STATUS_SPOOLING;
543 return RAP_JOB_STATUS_PRINTING;
548 /* turn a print queue status into a on the wire status
550 static int printq_status(int v)
556 return RAP_QUEUE_STATUS_PAUSED;
558 return RAP_QUEUE_STATUS_ERROR;
561 static void fill_printjob_info(connection_struct *conn, int snum, int uLevel,
562 struct pack_desc *desc,
563 print_queue_struct *queue, int n)
565 time_t t = queue->time;
567 /* the client expects localtime */
568 t -= get_time_zone(t);
570 PACKI(desc,"W",pjobid_to_rap(lp_const_servicename(snum),queue->job)); /* uJobId */
572 PACKS(desc,"B21",queue->fs_user); /* szUserName */
573 PACKS(desc,"B",""); /* pad */
574 PACKS(desc,"B16",""); /* szNotifyName */
575 PACKS(desc,"B10","PM_Q_RAW"); /* szDataType */
576 PACKS(desc,"z",""); /* pszParms */
577 PACKI(desc,"W",n+1); /* uPosition */
578 PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */
579 PACKS(desc,"z",""); /* pszStatus */
580 PACKI(desc,"D",t); /* ulSubmitted */
581 PACKI(desc,"D",queue->size); /* ulSize */
582 PACKS(desc,"z",queue->fs_file); /* pszComment */
584 if (uLevel == 2 || uLevel == 3 || uLevel == 4) {
585 PACKI(desc,"W",queue->priority); /* uPriority */
586 PACKS(desc,"z",queue->fs_user); /* pszUserName */
587 PACKI(desc,"W",n+1); /* uPosition */
588 PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */
589 PACKI(desc,"D",t); /* ulSubmitted */
590 PACKI(desc,"D",queue->size); /* ulSize */
591 PACKS(desc,"z","Samba"); /* pszComment */
592 PACKS(desc,"z",queue->fs_file); /* pszDocument */
594 PACKS(desc,"z",""); /* pszNotifyName */
595 PACKS(desc,"z","PM_Q_RAW"); /* pszDataType */
596 PACKS(desc,"z",""); /* pszParms */
597 PACKS(desc,"z",""); /* pszStatus */
598 PACKS(desc,"z",SERVICE(snum)); /* pszQueue */
599 PACKS(desc,"z","lpd"); /* pszQProcName */
600 PACKS(desc,"z",""); /* pszQProcParms */
601 PACKS(desc,"z","NULL"); /* pszDriverName */
602 PackDriverData(desc); /* pDriverData */
603 PACKS(desc,"z",""); /* pszPrinterName */
604 } else if (uLevel == 4) { /* OS2 */
605 PACKS(desc,"z",""); /* pszSpoolFileName */
606 PACKS(desc,"z",""); /* pszPortName */
607 PACKS(desc,"z",""); /* pszStatus */
608 PACKI(desc,"D",0); /* ulPagesSpooled */
609 PACKI(desc,"D",0); /* ulPagesSent */
610 PACKI(desc,"D",0); /* ulPagesPrinted */
611 PACKI(desc,"D",0); /* ulTimePrinted */
612 PACKI(desc,"D",0); /* ulExtendJobStatus */
613 PACKI(desc,"D",0); /* ulStartPage */
614 PACKI(desc,"D",0); /* ulEndPage */
619 /********************************************************************
620 Return a driver name given an snum.
621 Returns True if from tdb, False otherwise.
622 ********************************************************************/
624 static bool get_driver_name(int snum, char **pp_drivername)
626 NT_PRINTER_INFO_LEVEL *info = NULL;
629 get_a_printer (NULL, &info, 2, lp_servicename(snum));
631 *pp_drivername = talloc_strdup(talloc_tos(),
632 info->info_2->drivername);
634 free_a_printer(&info, 2);
635 if (!*pp_drivername) {
643 /********************************************************************
644 Respond to the DosPrintQInfo command with a level of 52
645 This is used to get printer driver information for Win9x clients
646 ********************************************************************/
647 static void fill_printq_info_52(connection_struct *conn, int snum,
648 struct pack_desc* desc, int count )
652 struct spoolss_DriverInfo8 *driver = NULL;
653 NT_PRINTER_INFO_LEVEL *printer = NULL;
655 if ( !W_ERROR_IS_OK(get_a_printer( NULL, &printer, 2, lp_servicename(snum))) ) {
656 DEBUG(3,("fill_printq_info_52: Failed to lookup printer [%s]\n",
657 lp_servicename(snum)));
661 if (!W_ERROR_IS_OK(get_a_printer_driver(talloc_tos(), &driver, printer->info_2->drivername,
664 DEBUG(3,("fill_printq_info_52: Failed to lookup driver [%s]\n",
665 printer->info_2->drivername));
669 trim_string((char *)driver->driver_path, "\\print$\\WIN40\\0\\", 0);
670 trim_string((char *)driver->data_file, "\\print$\\WIN40\\0\\", 0);
671 trim_string((char *)driver->help_file, "\\print$\\WIN40\\0\\", 0);
673 PACKI(desc, "W", 0x0400); /* don't know */
674 PACKS(desc, "z", driver->driver_name); /* long printer name */
675 PACKS(desc, "z", driver->driver_path); /* Driverfile Name */
676 PACKS(desc, "z", driver->data_file); /* Datafile name */
677 PACKS(desc, "z", driver->monitor_name); /* language monitor */
679 fstrcpy(location, "\\\\%L\\print$\\WIN40\\0");
680 standard_sub_basic( "", "", location, sizeof(location)-1 );
681 PACKS(desc,"z", location); /* share to retrieve files */
683 PACKS(desc,"z", driver->default_datatype); /* default data type */
684 PACKS(desc,"z", driver->help_file); /* helpfile name */
685 PACKS(desc,"z", driver->driver_path); /* driver name */
687 DEBUG(3,("Printer Driver Name: %s:\n",driver->driver_name));
688 DEBUG(3,("Driver: %s:\n",driver->driver_path));
689 DEBUG(3,("Data File: %s:\n",driver->data_file));
690 DEBUG(3,("Language Monitor: %s:\n",driver->monitor_name));
691 DEBUG(3,("Driver Location: %s:\n",location));
692 DEBUG(3,("Data Type: %s:\n",driver->default_datatype));
693 DEBUG(3,("Help File: %s:\n",driver->help_file));
694 PACKI(desc,"N",count); /* number of files to copy */
696 for ( i=0; i<count && driver->dependent_files && *driver->dependent_files[i]; i++)
698 trim_string((char *)driver->dependent_files[i], "\\print$\\WIN40\\0\\", 0);
699 PACKS(desc,"z",driver->dependent_files[i]); /* driver files to copy */
700 DEBUG(3,("Dependent File: %s:\n", driver->dependent_files[i]));
705 DEBUG(3,("fill_printq_info_52: file count specified by client [%d] != number of dependent files [%i]\n",
708 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n", SERVICE(snum),i));
710 desc->errcode=NERR_Success;
714 DEBUG(3,("fill_printq_info: Can't supply driver files\n"));
715 desc->errcode=NERR_notsupported;
719 free_a_printer( &printer, 2 );
721 free_a_printer_driver(driver);
725 static void fill_printq_info(connection_struct *conn, int snum, int uLevel,
726 struct pack_desc* desc,
727 int count, print_queue_struct* queue,
728 print_status_struct* status)
733 PACKS(desc,"B13",SERVICE(snum));
738 PACKS(desc,"z",Expand(conn,snum,SERVICE(snum)));
741 PACKI(desc,"K",printq_status(status->status));
745 if (uLevel == 1 || uLevel == 2) {
746 PACKS(desc,"B",""); /* alignment */
747 PACKI(desc,"W",5); /* priority */
748 PACKI(desc,"W",0); /* start time */
749 PACKI(desc,"W",0); /* until time */
750 PACKS(desc,"z",""); /* pSepFile */
751 PACKS(desc,"z","lpd"); /* pPrProc */
752 PACKS(desc,"z",SERVICE(snum)); /* pDestinations */
753 PACKS(desc,"z",""); /* pParms */
755 PACKS(desc,"z","UNKNOWN PRINTER");
756 PACKI(desc,"W",LPSTAT_ERROR);
758 else if (!status || !status->message[0]) {
759 PACKS(desc,"z",Expand(conn,snum,lp_comment(snum)));
760 PACKI(desc,"W",LPSTAT_OK); /* status */
762 PACKS(desc,"z",status->message);
763 PACKI(desc,"W",printq_status(status->status)); /* status */
765 PACKI(desc,(uLevel == 1 ? "W" : "N"),count);
768 if (uLevel == 3 || uLevel == 4) {
769 char *drivername = NULL;
771 PACKI(desc,"W",5); /* uPriority */
772 PACKI(desc,"W",0); /* uStarttime */
773 PACKI(desc,"W",0); /* uUntiltime */
774 PACKI(desc,"W",5); /* pad1 */
775 PACKS(desc,"z",""); /* pszSepFile */
776 PACKS(desc,"z","WinPrint"); /* pszPrProc */
777 PACKS(desc,"z",NULL); /* pszParms */
778 PACKS(desc,"z",NULL); /* pszComment - don't ask.... JRA */
779 /* "don't ask" that it's done this way to fix corrupted
780 Win9X/ME printer comments. */
782 PACKI(desc,"W",LPSTAT_OK); /* fsStatus */
784 PACKI(desc,"W",printq_status(status->status)); /* fsStatus */
786 PACKI(desc,(uLevel == 3 ? "W" : "N"),count); /* cJobs */
787 PACKS(desc,"z",SERVICE(snum)); /* pszPrinters */
788 get_driver_name(snum,&drivername);
792 PACKS(desc,"z",drivername); /* pszDriverName */
793 PackDriverData(desc); /* pDriverData */
796 if (uLevel == 2 || uLevel == 4) {
798 for (i=0;i<count;i++)
799 fill_printjob_info(conn,snum,uLevel == 2 ? 1 : 2,desc,&queue[i],i);
803 fill_printq_info_52( conn, snum, desc, count );
806 /* This function returns the number of files for a given driver */
807 static int get_printerdrivernumber(int snum)
810 struct spoolss_DriverInfo8 *driver;
811 NT_PRINTER_INFO_LEVEL *printer = NULL;
815 if ( !W_ERROR_IS_OK(get_a_printer( NULL, &printer, 2, lp_servicename(snum))) ) {
816 DEBUG(3,("get_printerdrivernumber: Failed to lookup printer [%s]\n",
817 lp_servicename(snum)));
821 if (!W_ERROR_IS_OK(get_a_printer_driver(talloc_tos(), &driver, printer->info_2->drivername,
824 DEBUG(3,("get_printerdrivernumber: Failed to lookup driver [%s]\n",
825 printer->info_2->drivername));
829 /* count the number of files */
830 while (driver->dependent_files && *driver->dependent_files[result])
834 free_a_printer( &printer, 2 );
836 free_a_printer_driver(driver);
841 static bool api_DosPrintQGetInfo(connection_struct *conn, uint16 vuid,
842 char *param, int tpscnt,
843 char *data, int tdscnt,
844 int mdrcnt,int mprcnt,
845 char **rdata,char **rparam,
846 int *rdata_len,int *rparam_len)
848 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
849 char *str2 = skip_string(param,tpscnt,str1);
850 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, share_name);
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);
1217 string_truncate(s->comment, MAX_SERVER_STRING_LENGTH);
1219 s->domain[0] = '\0';
1220 if (!next_token_talloc(frame,&ptr,&p, NULL)) {
1221 /* this allows us to cope with an old nmbd */
1222 fstrcpy(s->domain,lp_workgroup());
1224 fstrcpy(s->domain, p);
1228 if (sscanf(stype,"%X",&s->type) != 1) {
1229 DEBUG(4,("r:host file "));
1233 /* Filter the servers/domains we return based on what was asked for. */
1235 /* Check to see if we are being asked for a local list only. */
1236 if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) {
1237 DEBUG(4,("r: local list only"));
1241 /* doesn't match up: don't want it */
1242 if (!(servertype & s->type)) {
1243 DEBUG(4,("r:serv type "));
1247 if ((servertype & SV_TYPE_DOMAIN_ENUM) !=
1248 (s->type & SV_TYPE_DOMAIN_ENUM)) {
1249 DEBUG(4,("s: dom mismatch "));
1253 if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM)) {
1257 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1258 s->type &= ~SV_TYPE_LOCAL_LIST_ONLY;
1261 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1262 s->name, s->type, s->comment, s->domain));
1263 s->server_added = True;
1266 DEBUG(4,("%20s %8x %25s %15s\n",
1267 s->name, s->type, s->comment, s->domain));
1275 /*******************************************************************
1276 Fill in a server info structure.
1277 ******************************************************************/
1279 static int fill_srv_info(struct srv_info_struct *service,
1280 int uLevel, char **buf, int *buflen,
1281 char **stringbuf, int *stringspace, char *baseaddr)
1304 len = strlen(service->comment)+1;
1308 *buflen = struct_len;
1310 return struct_len + len;
1315 if (*buflen < struct_len) {
1322 p2 = p + struct_len;
1323 l2 = *buflen - struct_len;
1331 push_ascii(p,service->name, MAX_NETBIOSNAME_LEN, STR_TERMINATE);
1335 push_ascii(p,service->name,MAX_NETBIOSNAME_LEN, STR_TERMINATE);
1336 SIVAL(p,18,service->type);
1337 SIVAL(p,22,PTR_DIFF(p2,baseaddr));
1338 len += CopyAndAdvance(&p2,service->comment,&l2);
1343 *buf = p + struct_len;
1344 *buflen -= struct_len;
1355 static int srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
1357 return StrCaseCmp(s1->name,s2->name);
1360 /****************************************************************************
1361 View list of servers available (or possibly domains). The info is
1362 extracted from lists saved by nmbd on the local host.
1363 ****************************************************************************/
1365 static bool api_RNetServerEnum2(connection_struct *conn, uint16 vuid,
1366 char *param, int tpscnt,
1367 char *data, int tdscnt,
1368 int mdrcnt, int mprcnt, char **rdata,
1369 char **rparam, int *rdata_len, int *rparam_len)
1371 char *str1 = get_safe_str_ptr(param, tpscnt, param, 2);
1372 char *str2 = skip_string(param,tpscnt,str1);
1373 char *p = skip_string(param,tpscnt,str2);
1374 int uLevel = get_safe_SVAL(param, tpscnt, p, 0, -1);
1375 int buf_len = get_safe_SVAL(param,tpscnt, p, 2, 0);
1376 uint32 servertype = get_safe_IVAL(param,tpscnt,p,4, 0);
1378 int data_len, fixed_len, string_len;
1379 int f_len = 0, s_len = 0;
1380 struct srv_info_struct *servers=NULL;
1381 int counted=0,total=0;
1384 bool domain_request;
1387 if (!str1 || !str2 || !p) {
1391 /* If someone sets all the bits they don't really mean to set
1392 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1395 if (servertype == SV_TYPE_ALL) {
1396 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1399 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1400 any other bit (they may just set this bit on its own) they
1401 want all the locally seen servers. However this bit can be
1402 set on its own so set the requested servers to be
1403 ALL - DOMAIN_ENUM. */
1405 if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM)) {
1406 servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
1409 domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
1410 local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
1414 if (!prefix_ok(str1,"WrLehD")) {
1417 if (!check_server_info(uLevel,str2)) {
1421 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1422 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1423 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1425 if (strcmp(str1, "WrLehDz") == 0) {
1426 if (skip_string(param,tpscnt,p) == NULL) {
1429 pull_ascii_fstring(domain, p);
1431 fstrcpy(domain, lp_workgroup());
1434 DEBUG(4, ("domain [%s]\n", domain));
1436 if (lp_browse_list()) {
1437 total = get_server_info(servertype,&servers,domain);
1440 data_len = fixed_len = string_len = 0;
1444 qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
1448 char *lastname=NULL;
1450 for (i=0;i<total;i++) {
1451 struct srv_info_struct *s = &servers[i];
1453 if (lastname && strequal(lastname,s->name)) {
1457 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1458 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1459 i, s->name, s->type, s->comment, s->domain));
1461 if (data_len < buf_len) {
1464 string_len += s_len;
1471 *rdata_len = fixed_len + string_len;
1472 *rdata = smb_realloc_limit(*rdata,*rdata_len);
1477 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1483 char *lastname=NULL;
1484 int count2 = counted;
1486 for (i = 0; i < total && count2;i++) {
1487 struct srv_info_struct *s = &servers[i];
1489 if (lastname && strequal(lastname,s->name)) {
1493 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1494 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1495 i, s->name, s->type, s->comment, s->domain));
1501 *rparam = smb_realloc_limit(*rparam,*rparam_len);
1505 SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata));
1507 SSVAL(*rparam,4,counted);
1508 SSVAL(*rparam,6,counted+missed);
1512 DEBUG(3,("NetServerEnum2 domain = %s uLevel=%d counted=%d total=%d\n",
1513 domain,uLevel,counted,counted+missed));
1518 static int srv_name_match(const char *n1, const char *n2)
1521 * [MS-RAP] footnote <88> for Section 3.2.5.15 says:
1523 * In Windows, FirstNameToReturn need not be an exact match:
1524 * the server will return a list of servers that exist on
1525 * the network greater than or equal to the FirstNameToReturn.
1527 int ret = StrCaseCmp(n1, n2);
1536 static bool api_RNetServerEnum3(connection_struct *conn, uint16 vuid,
1537 char *param, int tpscnt,
1538 char *data, int tdscnt,
1539 int mdrcnt, int mprcnt, char **rdata,
1540 char **rparam, int *rdata_len, int *rparam_len)
1542 char *str1 = get_safe_str_ptr(param, tpscnt, param, 2);
1543 char *str2 = skip_string(param,tpscnt,str1);
1544 char *p = skip_string(param,tpscnt,str2);
1545 int uLevel = get_safe_SVAL(param, tpscnt, p, 0, -1);
1546 int buf_len = get_safe_SVAL(param,tpscnt, p, 2, 0);
1547 uint32 servertype = get_safe_IVAL(param,tpscnt,p,4, 0);
1549 int data_len, fixed_len, string_len;
1550 int f_len = 0, s_len = 0;
1551 struct srv_info_struct *servers=NULL;
1552 int counted=0,first=0,total=0;
1556 bool domain_request;
1559 if (!str1 || !str2 || !p) {
1563 /* If someone sets all the bits they don't really mean to set
1564 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1567 if (servertype == SV_TYPE_ALL) {
1568 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1571 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1572 any other bit (they may just set this bit on its own) they
1573 want all the locally seen servers. However this bit can be
1574 set on its own so set the requested servers to be
1575 ALL - DOMAIN_ENUM. */
1577 if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM)) {
1578 servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
1581 domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
1582 local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
1586 if (strcmp(str1, "WrLehDzz") != 0) {
1589 if (!check_server_info(uLevel,str2)) {
1593 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1594 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1595 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1597 if (skip_string(param,tpscnt,p) == NULL) {
1600 pull_ascii_fstring(domain, p);
1601 if (domain[0] == '\0') {
1602 fstrcpy(domain, lp_workgroup());
1604 p = skip_string(param,tpscnt,p);
1605 if (skip_string(param,tpscnt,p) == NULL) {
1608 pull_ascii_fstring(first_name, p);
1610 DEBUG(4, ("domain: '%s' first_name: '%s'\n",
1611 domain, first_name));
1613 if (lp_browse_list()) {
1614 total = get_server_info(servertype,&servers,domain);
1617 data_len = fixed_len = string_len = 0;
1621 qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
1624 if (first_name[0] != '\0') {
1625 struct srv_info_struct *first_server = NULL;
1627 BINARY_ARRAY_SEARCH(servers, total, name, first_name,
1628 srv_name_match, first_server);
1630 first = PTR_DIFF(first_server, servers) / sizeof(*servers);
1632 * The binary search may not find the exact match
1633 * so we need to search backward to find the first match
1635 * This implements the strange matching windows
1636 * implements. (see the comment in srv_name_match().
1640 ret = StrCaseCmp(first_name,
1641 servers[first-1].name);
1648 /* we should return no entries */
1654 char *lastname=NULL;
1656 for (i=first;i<total;i++) {
1657 struct srv_info_struct *s = &servers[i];
1659 if (lastname && strequal(lastname,s->name)) {
1663 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1664 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1665 i, s->name, s->type, s->comment, s->domain));
1667 if (data_len < buf_len) {
1670 string_len += s_len;
1677 *rdata_len = fixed_len + string_len;
1678 *rdata = smb_realloc_limit(*rdata,*rdata_len);
1683 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1689 char *lastname=NULL;
1690 int count2 = counted;
1692 for (i = first; i < total && count2;i++) {
1693 struct srv_info_struct *s = &servers[i];
1695 if (lastname && strequal(lastname,s->name)) {
1699 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1700 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1701 i, s->name, s->type, s->comment, s->domain));
1707 *rparam = smb_realloc_limit(*rparam,*rparam_len);
1711 SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata));
1713 SSVAL(*rparam,4,counted);
1714 SSVAL(*rparam,6,counted+missed);
1716 DEBUG(3,("NetServerEnum3 domain = %s uLevel=%d first=%d[%s => %s] counted=%d total=%d\n",
1717 domain,uLevel,first,first_name,
1718 first < total ? servers[first].name : "",
1719 counted,counted+missed));
1726 /****************************************************************************
1727 command 0x34 - suspected of being a "Lookup Names" stub api
1728 ****************************************************************************/
1730 static bool api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid,
1731 char *param, int tpscnt,
1732 char *data, int tdscnt,
1733 int mdrcnt, int mprcnt, char **rdata,
1734 char **rparam, int *rdata_len, int *rparam_len)
1736 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
1737 char *str2 = skip_string(param,tpscnt,str1);
1738 char *p = skip_string(param,tpscnt,str2);
1739 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
1740 int buf_len = get_safe_SVAL(param,tpscnt,p,2,0);
1744 if (!str1 || !str2 || !p) {
1748 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1749 str1, str2, p, uLevel, buf_len));
1751 if (!prefix_ok(str1,"zWrLeh")) {
1758 *rparam = smb_realloc_limit(*rparam,*rparam_len);
1763 SSVAL(*rparam,0,0x08AC); /* informational warning message */
1765 SSVAL(*rparam,4,counted);
1766 SSVAL(*rparam,6,counted+missed);
1771 /****************************************************************************
1772 get info about a share
1773 ****************************************************************************/
1775 static bool check_share_info(int uLevel, char* id)
1779 if (strcmp(id,"B13") != 0) {
1784 /* Level-2 descriptor is allowed (and ignored) */
1785 if (strcmp(id,"B13BWz") != 0 &&
1786 strcmp(id,"B13BWzWWWzB9B") != 0) {
1791 if (strcmp(id,"B13BWzWWWzB9B") != 0) {
1796 if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) {
1806 static int fill_share_info(connection_struct *conn, int snum, int uLevel,
1807 char** buf, int* buflen,
1808 char** stringbuf, int* stringspace, char* baseaddr)
1837 len += StrlenExpanded(conn,snum,lp_comment(snum));
1840 len += strlen(lp_pathname(snum)) + 1;
1843 *buflen = struct_len;
1848 return struct_len + len;
1853 if ((*buflen) < struct_len) {
1861 p2 = p + struct_len;
1862 l2 = (*buflen) - struct_len;
1869 push_ascii(p,lp_servicename(snum),13, STR_TERMINATE);
1875 type = STYPE_DISKTREE;
1876 if (lp_print_ok(snum)) {
1877 type = STYPE_PRINTQ;
1879 if (strequal("IPC",lp_fstype(snum))) {
1882 SSVAL(p,14,type); /* device type */
1883 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1884 len += CopyExpanded(conn,snum,&p2,lp_comment(snum),&l2);
1888 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1889 SSVALS(p,22,-1); /* max uses */
1890 SSVAL(p,24,1); /* current uses */
1891 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1892 len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1893 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1897 memset(p+40,0,SHPWLEN+2);
1908 (*buf) = p + struct_len;
1909 (*buflen) -= struct_len;
1911 (*stringspace) = l2;
1920 static bool api_RNetShareGetInfo(connection_struct *conn,uint16 vuid,
1921 char *param, int tpscnt,
1922 char *data, int tdscnt,
1923 int mdrcnt,int mprcnt,
1924 char **rdata,char **rparam,
1925 int *rdata_len,int *rparam_len)
1927 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
1928 char *str2 = skip_string(param,tpscnt,str1);
1929 char *netname = skip_string(param,tpscnt,str2);
1930 char *p = skip_string(param,tpscnt,netname);
1931 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
1935 if (!str1 || !str2 || !netname || !p) {
1939 snum = find_service(netname, share_name);
1944 /* check it's a supported varient */
1945 if (!prefix_ok(str1,"zWrLh")) {
1948 if (!check_share_info(uLevel,str2)) {
1952 *rdata = smb_realloc_limit(*rdata,mdrcnt);
1957 *rdata_len = fill_share_info(conn,snum,uLevel,&p,&mdrcnt,0,0,0);
1958 if (*rdata_len < 0) {
1963 *rparam = smb_realloc_limit(*rparam,*rparam_len);
1967 SSVAL(*rparam,0,NERR_Success);
1968 SSVAL(*rparam,2,0); /* converter word */
1969 SSVAL(*rparam,4,*rdata_len);
1974 /****************************************************************************
1975 View the list of available shares.
1977 This function is the server side of the NetShareEnum() RAP call.
1978 It fills the return buffer with share names and share comments.
1979 Note that the return buffer normally (in all known cases) allows only
1980 twelve byte strings for share names (plus one for a nul terminator).
1981 Share names longer than 12 bytes must be skipped.
1982 ****************************************************************************/
1984 static bool api_RNetShareEnum( connection_struct *conn, uint16 vuid,
1985 char *param, int tpscnt,
1986 char *data, int tdscnt,
1994 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
1995 char *str2 = skip_string(param,tpscnt,str1);
1996 char *p = skip_string(param,tpscnt,str2);
1997 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
1998 int buf_len = get_safe_SVAL(param,tpscnt,p,2,0);
2001 int total=0,counted=0;
2002 bool missed = False;
2004 int data_len, fixed_len, string_len;
2005 int f_len = 0, s_len = 0;
2007 if (!str1 || !str2 || !p) {
2011 if (!prefix_ok(str1,"WrLeh")) {
2014 if (!check_share_info(uLevel,str2)) {
2018 /* Ensure all the usershares are loaded. */
2020 load_registry_shares();
2021 count = load_usershare_shares();
2024 data_len = fixed_len = string_len = 0;
2025 for (i=0;i<count;i++) {
2026 fstring servicename_dos;
2027 if (!(lp_browseable(i) && lp_snum_ok(i))) {
2030 push_ascii_fstring(servicename_dos, lp_servicename(i));
2031 /* Maximum name length = 13. */
2032 if( lp_browseable( i ) && lp_snum_ok( i ) && (strlen(servicename_dos) < 13)) {
2034 data_len += fill_share_info(conn,i,uLevel,0,&f_len,0,&s_len,0);
2035 if (data_len < buf_len) {
2038 string_len += s_len;
2045 *rdata_len = fixed_len + string_len;
2046 *rdata = smb_realloc_limit(*rdata,*rdata_len);
2051 p2 = (*rdata) + fixed_len; /* auxiliary data (strings) will go here */
2056 for( i = 0; i < count; i++ ) {
2057 fstring servicename_dos;
2058 if (!(lp_browseable(i) && lp_snum_ok(i))) {
2062 push_ascii_fstring(servicename_dos, lp_servicename(i));
2063 if (lp_browseable(i) && lp_snum_ok(i) && (strlen(servicename_dos) < 13)) {
2064 if (fill_share_info( conn,i,uLevel,&p,&f_len,&p2,&s_len,*rdata ) < 0) {
2071 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2075 SSVAL(*rparam,0,missed ? ERRmoredata : NERR_Success);
2077 SSVAL(*rparam,4,counted);
2078 SSVAL(*rparam,6,total);
2080 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
2081 counted,total,uLevel,
2082 buf_len,*rdata_len,mdrcnt));
2087 /****************************************************************************
2089 ****************************************************************************/
2091 static bool api_RNetShareAdd(connection_struct *conn,uint16 vuid,
2092 char *param, int tpscnt,
2093 char *data, int tdscnt,
2094 int mdrcnt,int mprcnt,
2095 char **rdata,char **rparam,
2096 int *rdata_len,int *rparam_len)
2098 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2099 char *str2 = skip_string(param,tpscnt,str1);
2100 char *p = skip_string(param,tpscnt,str2);
2101 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
2104 char *pathname = NULL;
2105 char *command, *cmdname;
2106 unsigned int offset;
2109 size_t converted_size;
2111 if (!str1 || !str2 || !p) {
2115 /* check it's a supported varient */
2116 if (!prefix_ok(str1,RAP_WShareAdd_REQ)) {
2119 if (!check_share_info(uLevel,str2)) {
2126 /* Do we have a string ? */
2127 if (skip_string(data,mdrcnt,data) == NULL) {
2130 pull_ascii_fstring(sharename,data);
2131 snum = find_service(sharename, sharename);
2132 if (snum >= 0) { /* already exists */
2141 /* only support disk share adds */
2142 if (SVAL(data,14)!=STYPE_DISKTREE) {
2146 offset = IVAL(data, 16);
2147 if (offset >= mdrcnt) {
2148 res = ERRinvalidparam;
2152 /* Do we have a string ? */
2153 if (skip_string(data,mdrcnt,data+offset) == NULL) {
2156 pull_ascii_fstring(comment, offset? (data+offset) : "");
2158 offset = IVAL(data, 26);
2160 if (offset >= mdrcnt) {
2161 res = ERRinvalidparam;
2165 /* Do we have a string ? */
2166 if (skip_string(data,mdrcnt,data+offset) == NULL) {
2170 if (!pull_ascii_talloc(talloc_tos(), &pathname,
2171 offset ? (data+offset) : "", &converted_size))
2173 DEBUG(0,("api_RNetShareAdd: pull_ascii_talloc failed: %s",
2181 string_replace(sharename, '"', ' ');
2182 string_replace(pathname, '"', ' ');
2183 string_replace(comment, '"', ' ');
2185 cmdname = lp_add_share_cmd();
2187 if (!cmdname || *cmdname == '\0') {
2191 if (asprintf(&command, "%s \"%s\" \"%s\" \"%s\" \"%s\"",
2192 lp_add_share_cmd(), get_dyn_CONFIGFILE(), sharename,
2193 pathname, comment) == -1) {
2197 DEBUG(10,("api_RNetShareAdd: Running [%s]\n", command ));
2199 if ((res = smbrun(command, NULL)) != 0) {
2200 DEBUG(1,("api_RNetShareAdd: Running [%s] returned (%d)\n",
2207 message_send_all(smbd_messaging_context(),
2208 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
2212 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2216 SSVAL(*rparam,0,NERR_Success);
2217 SSVAL(*rparam,2,0); /* converter word */
2218 SSVAL(*rparam,4,*rdata_len);
2226 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2231 SSVAL(*rparam,0,res);
2236 /****************************************************************************
2237 view list of groups available
2238 ****************************************************************************/
2240 static bool api_RNetGroupEnum(connection_struct *conn,uint16 vuid,
2241 char *param, int tpscnt,
2242 char *data, int tdscnt,
2243 int mdrcnt,int mprcnt,
2244 char **rdata,char **rparam,
2245 int *rdata_len,int *rparam_len)
2249 int resume_context, cli_buf_size;
2250 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2251 char *str2 = skip_string(param,tpscnt,str1);
2252 char *p = skip_string(param,tpscnt,str2);
2254 uint32_t num_groups;
2255 uint32_t resume_handle;
2256 struct rpc_pipe_client *samr_pipe;
2257 struct policy_handle samr_handle, domain_handle;
2260 if (!str1 || !str2 || !p) {
2264 if (strcmp(str1,"WrLeh") != 0) {
2269 * W-> resume context (number of users to skip)
2270 * r -> return parameter pointer to receive buffer
2271 * L -> length of receive buffer
2272 * e -> return parameter number of entries
2273 * h -> return parameter total number of users
2276 if (strcmp("B21",str2) != 0) {
2280 status = rpc_pipe_open_internal(
2281 talloc_tos(), &ndr_table_samr.syntax_id, rpc_samr_dispatch,
2282 conn->server_info, &samr_pipe);
2283 if (!NT_STATUS_IS_OK(status)) {
2284 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2285 nt_errstr(status)));
2289 status = rpccli_samr_Connect2(samr_pipe, talloc_tos(), global_myname(),
2290 SAMR_ACCESS_LOOKUP_DOMAIN, &samr_handle);
2291 if (!NT_STATUS_IS_OK(status)) {
2292 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2293 nt_errstr(status)));
2297 status = rpccli_samr_OpenDomain(samr_pipe, talloc_tos(), &samr_handle,
2298 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS,
2299 get_global_sam_sid(), &domain_handle);
2300 if (!NT_STATUS_IS_OK(status)) {
2301 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2302 nt_errstr(status)));
2303 rpccli_samr_Close(samr_pipe, talloc_tos(), &samr_handle);
2307 resume_context = get_safe_SVAL(param,tpscnt,p,0,-1);
2308 cli_buf_size= get_safe_SVAL(param,tpscnt,p,2,0);
2309 DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: "
2310 "%d\n", resume_context, cli_buf_size));
2312 *rdata_len = cli_buf_size;
2313 *rdata = smb_realloc_limit(*rdata,*rdata_len);
2320 errflags = NERR_Success;
2325 struct samr_SamArray *sam_entries;
2326 uint32_t num_entries;
2328 status = rpccli_samr_EnumDomainGroups(samr_pipe, talloc_tos(),
2333 if (!NT_STATUS_IS_OK(status)) {
2334 DEBUG(10, ("rpccli_samr_EnumDomainGroups returned "
2335 "%s\n", nt_errstr(status)));
2339 if (num_entries == 0) {
2340 DEBUG(10, ("rpccli_samr_EnumDomainGroups returned "
2341 "no entries -- done\n"));
2345 for(i=0; i<num_entries; i++) {
2348 name = sam_entries->entries[i].name.string;
2350 if( ((PTR_DIFF(p,*rdata)+21) > *rdata_len) ) {
2351 /* set overflow error */
2352 DEBUG(3,("overflow on entry %d group %s\n", i,
2358 /* truncate the name at 21 chars. */
2360 strlcpy(p, name, 21);
2361 DEBUG(10,("adding entry %d group %s\n", i, p));
2363 p += 5; /* Both NT4 and W2k3SP1 do padding here. No
2368 if (errflags != NERR_Success) {
2372 TALLOC_FREE(sam_entries);
2375 rpccli_samr_Close(samr_pipe, talloc_tos(), &domain_handle);
2376 rpccli_samr_Close(samr_pipe, talloc_tos(), &samr_handle);
2378 *rdata_len = PTR_DIFF(p,*rdata);
2381 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2385 SSVAL(*rparam, 0, errflags);
2386 SSVAL(*rparam, 2, 0); /* converter word */
2387 SSVAL(*rparam, 4, num_groups); /* is this right?? */
2388 SSVAL(*rparam, 6, resume_context+num_groups); /* is this right?? */
2393 /*******************************************************************
2394 Get groups that a user is a member of.
2395 ******************************************************************/
2397 static bool api_NetUserGetGroups(connection_struct *conn,uint16 vuid,
2398 char *param, int tpscnt,
2399 char *data, int tdscnt,
2400 int mdrcnt,int mprcnt,
2401 char **rdata,char **rparam,
2402 int *rdata_len,int *rparam_len)
2404 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2405 char *str2 = skip_string(param,tpscnt,str1);
2406 char *UserName = skip_string(param,tpscnt,str2);
2407 char *p = skip_string(param,tpscnt,UserName);
2408 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
2409 const char *level_string;
2415 struct rpc_pipe_client *samr_pipe;
2416 struct policy_handle samr_handle, domain_handle, user_handle;
2417 struct lsa_String name;
2418 struct lsa_Strings names;
2419 struct samr_Ids type, rid;
2420 struct samr_RidWithAttributeArray *rids;
2423 if (!str1 || !str2 || !UserName || !p) {
2428 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2433 /* check it's a supported varient */
2435 if ( strcmp(str1,"zWrLeh") != 0 )
2440 level_string = "B21";
2446 if (strcmp(level_string,str2) != 0)
2449 *rdata_len = mdrcnt + 1024;
2450 *rdata = smb_realloc_limit(*rdata,*rdata_len);
2455 SSVAL(*rparam,0,NERR_Success);
2456 SSVAL(*rparam,2,0); /* converter word */
2459 endp = *rdata + *rdata_len;
2461 status = rpc_pipe_open_internal(
2462 talloc_tos(), &ndr_table_samr.syntax_id, rpc_samr_dispatch,
2463 conn->server_info, &samr_pipe);
2464 if (!NT_STATUS_IS_OK(status)) {
2465 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2466 nt_errstr(status)));
2470 status = rpccli_samr_Connect2(samr_pipe, talloc_tos(), global_myname(),
2471 SAMR_ACCESS_LOOKUP_DOMAIN, &samr_handle);
2472 if (!NT_STATUS_IS_OK(status)) {
2473 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2474 nt_errstr(status)));
2478 status = rpccli_samr_OpenDomain(samr_pipe, talloc_tos(), &samr_handle,
2479 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
2480 get_global_sam_sid(), &domain_handle);
2481 if (!NT_STATUS_IS_OK(status)) {
2482 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2483 nt_errstr(status)));
2487 name.string = UserName;
2489 status = rpccli_samr_LookupNames(samr_pipe, talloc_tos(),
2490 &domain_handle, 1, &name,
2492 if (!NT_STATUS_IS_OK(status)) {
2493 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2494 nt_errstr(status)));
2498 if (type.ids[0] != SID_NAME_USER) {
2499 DEBUG(10, ("%s is a %s, not a user\n", UserName,
2500 sid_type_lookup(type.ids[0])));
2504 status = rpccli_samr_OpenUser(samr_pipe, talloc_tos(),
2506 SAMR_USER_ACCESS_GET_GROUPS,
2507 rid.ids[0], &user_handle);
2508 if (!NT_STATUS_IS_OK(status)) {
2509 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2510 nt_errstr(status)));
2514 status = rpccli_samr_GetGroupsForUser(samr_pipe, talloc_tos(),
2515 &user_handle, &rids);
2516 if (!NT_STATUS_IS_OK(status)) {
2517 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2518 nt_errstr(status)));
2522 for (i=0; i<rids->count; i++) {
2524 status = rpccli_samr_LookupRids(samr_pipe, talloc_tos(),
2526 1, &rids->rids[i].rid,
2528 if (NT_STATUS_IS_OK(status) && (names.count == 1)) {
2529 strlcpy(p, names.names[0].string, PTR_DIFF(endp,p));
2535 *rdata_len = PTR_DIFF(p,*rdata);
2537 SSVAL(*rparam,4,count); /* is this right?? */
2538 SSVAL(*rparam,6,count); /* is this right?? */
2543 rpccli_samr_Close(samr_pipe, talloc_tos(), &user_handle);
2545 rpccli_samr_Close(samr_pipe, talloc_tos(), &domain_handle);
2547 rpccli_samr_Close(samr_pipe, talloc_tos(), &samr_handle);
2552 /*******************************************************************
2554 ******************************************************************/
2556 static bool api_RNetUserEnum(connection_struct *conn, uint16 vuid,
2557 char *param, int tpscnt,
2558 char *data, int tdscnt,
2559 int mdrcnt,int mprcnt,
2560 char **rdata,char **rparam,
2561 int *rdata_len,int *rparam_len)
2566 int i, resume_context, cli_buf_size;
2567 uint32_t resume_handle;
2569 struct rpc_pipe_client *samr_pipe;
2570 struct policy_handle samr_handle, domain_handle;
2573 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2574 char *str2 = skip_string(param,tpscnt,str1);
2575 char *p = skip_string(param,tpscnt,str2);
2578 if (!str1 || !str2 || !p) {
2582 if (strcmp(str1,"WrLeh") != 0)
2585 * W-> resume context (number of users to skip)
2586 * r -> return parameter pointer to receive buffer
2587 * L -> length of receive buffer
2588 * e -> return parameter number of entries
2589 * h -> return parameter total number of users
2592 resume_context = get_safe_SVAL(param,tpscnt,p,0,-1);
2593 cli_buf_size= get_safe_SVAL(param,tpscnt,p,2,0);
2594 DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n",
2595 resume_context, cli_buf_size));
2598 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2603 /* check it's a supported varient */
2604 if (strcmp("B21",str2) != 0)
2607 *rdata_len = cli_buf_size;
2608 *rdata = smb_realloc_limit(*rdata,*rdata_len);
2614 endp = *rdata + *rdata_len;
2616 status = rpc_pipe_open_internal(
2617 talloc_tos(), &ndr_table_samr.syntax_id, rpc_samr_dispatch,
2618 conn->server_info, &samr_pipe);
2619 if (!NT_STATUS_IS_OK(status)) {
2620 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2621 nt_errstr(status)));
2625 status = rpccli_samr_Connect2(samr_pipe, talloc_tos(), global_myname(),
2626 SAMR_ACCESS_LOOKUP_DOMAIN, &samr_handle);
2627 if (!NT_STATUS_IS_OK(status)) {
2628 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2629 nt_errstr(status)));
2633 status = rpccli_samr_OpenDomain(samr_pipe, talloc_tos(), &samr_handle,
2634 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS,
2635 get_global_sam_sid(), &domain_handle);
2636 if (!NT_STATUS_IS_OK(status)) {
2637 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2638 nt_errstr(status)));
2639 rpccli_samr_Close(samr_pipe, talloc_tos(), &samr_handle);
2643 errflags=NERR_Success;
2648 struct samr_SamArray *sam_entries;
2649 uint32_t num_entries;
2651 status = rpccli_samr_EnumDomainUsers(samr_pipe, talloc_tos(),
2657 if (!NT_STATUS_IS_OK(status)) {
2658 DEBUG(10, ("rpccli_samr_EnumDomainUsers returned "
2659 "%s\n", nt_errstr(status)));
2663 if (num_entries == 0) {
2664 DEBUG(10, ("rpccli_samr_EnumDomainUsers returned "
2665 "no entries -- done\n"));
2669 for (i=0; i<num_entries; i++) {
2672 name = sam_entries->entries[i].name.string;
2674 if(((PTR_DIFF(p,*rdata)+21)<=*rdata_len)
2675 &&(strlen(name)<=21)) {
2676 strlcpy(p,name,PTR_DIFF(endp,p));
2677 DEBUG(10,("api_RNetUserEnum:adding entry %d "
2678 "username %s\n",count_sent,p));
2682 /* set overflow error */
2683 DEBUG(10,("api_RNetUserEnum:overflow on entry %d "
2684 "username %s\n",count_sent,name));
2690 if (errflags != NERR_Success) {
2694 TALLOC_FREE(sam_entries);
2697 rpccli_samr_Close(samr_pipe, talloc_tos(), &domain_handle);
2698 rpccli_samr_Close(samr_pipe, talloc_tos(), &samr_handle);
2700 *rdata_len = PTR_DIFF(p,*rdata);
2702 SSVAL(*rparam,0,errflags);
2703 SSVAL(*rparam,2,0); /* converter word */
2704 SSVAL(*rparam,4,count_sent); /* is this right?? */
2705 SSVAL(*rparam,6,num_users); /* is this right?? */
2710 /****************************************************************************
2711 Get the time of day info.
2712 ****************************************************************************/
2714 static bool api_NetRemoteTOD(connection_struct *conn,uint16 vuid,
2715 char *param, int tpscnt,
2716 char *data, int tdscnt,
2717 int mdrcnt,int mprcnt,
2718 char **rdata,char **rparam,
2719 int *rdata_len,int *rparam_len)
2722 time_t unixdate = time(NULL);
2726 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2732 *rdata = smb_realloc_limit(*rdata,*rdata_len);
2737 SSVAL(*rparam,0,NERR_Success);
2738 SSVAL(*rparam,2,0); /* converter word */
2742 srv_put_dos_date3(p,0,unixdate); /* this is the time that is looked at
2743 by NT in a "net time" operation,
2744 it seems to ignore the one below */
2746 /* the client expects to get localtime, not GMT, in this bit
2747 (I think, this needs testing) */
2748 t = localtime(&unixdate);
2753 SIVAL(p,4,0); /* msecs ? */
2754 SCVAL(p,8,t->tm_hour);
2755 SCVAL(p,9,t->tm_min);
2756 SCVAL(p,10,t->tm_sec);
2757 SCVAL(p,11,0); /* hundredths of seconds */
2758 SSVALS(p,12,get_time_zone(unixdate)/60); /* timezone in minutes from GMT */
2759 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
2760 SCVAL(p,16,t->tm_mday);
2761 SCVAL(p,17,t->tm_mon + 1);
2762 SSVAL(p,18,1900+t->tm_year);
2763 SCVAL(p,20,t->tm_wday);
2768 /****************************************************************************
2769 Set the user password.
2770 *****************************************************************************/
2772 static bool api_SetUserPassword(connection_struct *conn,uint16 vuid,
2773 char *param, int tpscnt,
2774 char *data, int tdscnt,
2775 int mdrcnt,int mprcnt,
2776 char **rdata,char **rparam,
2777 int *rdata_len,int *rparam_len)
2779 char *np = get_safe_str_ptr(param,tpscnt,param,2);
2782 fstring pass1,pass2;
2784 /* Skip 2 strings. */
2785 p = skip_string(param,tpscnt,np);
2786 p = skip_string(param,tpscnt,p);
2792 /* Do we have a string ? */
2793 if (skip_string(param,tpscnt,p) == NULL) {
2796 pull_ascii_fstring(user,p);
2798 p = skip_string(param,tpscnt,p);
2803 memset(pass1,'\0',sizeof(pass1));
2804 memset(pass2,'\0',sizeof(pass2));
2806 * We use 31 here not 32 as we're checking
2807 * the last byte we want to access is safe.
2809 if (!is_offset_safe(param,tpscnt,p,31)) {
2813 memcpy(pass2,p+16,16);
2816 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2823 SSVAL(*rparam,0,NERR_badpass);
2824 SSVAL(*rparam,2,0); /* converter word */
2826 DEBUG(3,("Set password for <%s>\n",user));
2829 * Attempt to verify the old password against smbpasswd entries
2830 * Win98 clients send old and new password in plaintext for this call.
2834 auth_serversupplied_info *server_info = NULL;
2835 DATA_BLOB password = data_blob(pass1, strlen(pass1)+1);
2837 if (NT_STATUS_IS_OK(check_plaintext_password(user,password,&server_info))) {
2840 if (NT_STATUS_IS_OK(change_oem_password(server_info->sam_account, pass1, pass2, False, NULL))) {
2841 SSVAL(*rparam,0,NERR_Success);
2845 TALLOC_FREE(server_info);
2847 data_blob_clear_free(&password);
2851 * If the plaintext change failed, attempt
2852 * the old encrypted method. NT will generate this
2853 * after trying the samr method. Note that this
2854 * method is done as a last resort as this
2855 * password change method loses the NT password hash
2856 * and cannot change the UNIX password as no plaintext
2860 if(SVAL(*rparam,0) != NERR_Success) {
2861 struct samu *hnd = NULL;
2863 if (check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &hnd)) {
2865 if (change_lanman_password(hnd,(uchar *)pass2)) {
2866 SSVAL(*rparam,0,NERR_Success);
2873 memset((char *)pass1,'\0',sizeof(fstring));
2874 memset((char *)pass2,'\0',sizeof(fstring));
2879 /****************************************************************************
2880 Set the user password (SamOEM version - gets plaintext).
2881 ****************************************************************************/
2883 static bool api_SamOEMChangePassword(connection_struct *conn,uint16 vuid,
2884 char *param, int tpscnt,
2885 char *data, int tdscnt,
2886 int mdrcnt,int mprcnt,
2887 char **rdata,char **rparam,
2888 int *rdata_len,int *rparam_len)
2890 struct smbd_server_connection *sconn = smbd_server_conn;
2892 char *p = get_safe_str_ptr(param,tpscnt,param,2);
2894 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2904 SSVAL(*rparam,0,NERR_badpass);
2907 * Check the parameter definition is correct.
2910 /* Do we have a string ? */
2911 if (skip_string(param,tpscnt,p) == 0) {
2914 if(!strequal(p, "zsT")) {
2915 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", p));
2918 p = skip_string(param, tpscnt, p);
2923 /* Do we have a string ? */
2924 if (skip_string(param,tpscnt,p) == 0) {
2927 if(!strequal(p, "B516B16")) {
2928 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p));
2931 p = skip_string(param,tpscnt,p);
2935 /* Do we have a string ? */
2936 if (skip_string(param,tpscnt,p) == 0) {
2939 p += pull_ascii_fstring(user,p);
2941 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user));
2944 * Pass the user through the NT -> unix user mapping
2948 (void)map_username(sconn, user);
2950 if (NT_STATUS_IS_OK(pass_oem_change(user, (uchar*) data, (uchar *)&data[516], NULL, NULL, NULL))) {
2951 SSVAL(*rparam,0,NERR_Success);
2957 /****************************************************************************
2960 ****************************************************************************/
2962 static bool api_RDosPrintJobDel(connection_struct *conn,uint16 vuid,
2963 char *param, int tpscnt,
2964 char *data, int tdscnt,
2965 int mdrcnt,int mprcnt,
2966 char **rdata,char **rparam,
2967 int *rdata_len,int *rparam_len)
2969 int function = get_safe_SVAL(param,tpscnt,param,0,0);
2970 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2971 char *str2 = skip_string(param,tpscnt,str1);
2972 char *p = skip_string(param,tpscnt,str2);
2977 WERROR werr = WERR_OK;
2979 if (!str1 || !str2 || !p) {
2983 * We use 1 here not 2 as we're checking
2984 * the last byte we want to access is safe.
2986 if (!is_offset_safe(param,tpscnt,p,1)) {
2989 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
2992 /* check it's a supported varient */
2993 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
2997 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3003 if (!print_job_exists(sharename, jobid)) {
3004 errcode = NERR_JobNotFound;
3008 snum = lp_servicenumber( sharename);
3010 errcode = NERR_DestNotFound;
3014 errcode = NERR_notsupported;
3017 case 81: /* delete */
3018 if (print_job_delete(conn->server_info, snum, jobid, &werr))
3019 errcode = NERR_Success;
3021 case 82: /* pause */
3022 if (print_job_pause(conn->server_info, snum, jobid, &werr))
3023 errcode = NERR_Success;
3025 case 83: /* resume */
3026 if (print_job_resume(conn->server_info, snum, jobid, &werr))
3027 errcode = NERR_Success;
3031 if (!W_ERROR_IS_OK(werr))
3032 errcode = W_ERROR_V(werr);
3035 SSVAL(*rparam,0,errcode);
3036 SSVAL(*rparam,2,0); /* converter word */
3041 /****************************************************************************
3042 Purge a print queue - or pause or resume it.
3043 ****************************************************************************/
3045 static bool api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid,
3046 char *param, int tpscnt,
3047 char *data, int tdscnt,
3048 int mdrcnt,int mprcnt,
3049 char **rdata,char **rparam,
3050 int *rdata_len,int *rparam_len)
3052 int function = get_safe_SVAL(param,tpscnt,param,0,0);
3053 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3054 char *str2 = skip_string(param,tpscnt,str1);
3055 char *QueueName = skip_string(param,tpscnt,str2);
3056 int errcode = NERR_notsupported;
3058 WERROR werr = WERR_OK;
3060 if (!str1 || !str2 || !QueueName) {
3064 /* check it's a supported varient */
3065 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
3069 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3075 if (skip_string(param,tpscnt,QueueName) == NULL) {
3078 snum = print_queue_snum(QueueName);
3081 errcode = NERR_JobNotFound;
3086 case 74: /* Pause queue */
3087 werr = print_queue_pause(conn->server_info, snum);
3089 case 75: /* Resume queue */
3090 werr = print_queue_resume(conn->server_info, snum);
3092 case 103: /* Purge */
3093 werr = print_queue_purge(conn->server_info, snum);
3096 werr = WERR_NOT_SUPPORTED;
3100 errcode = W_ERROR_V(werr);
3103 SSVAL(*rparam,0,errcode);
3104 SSVAL(*rparam,2,0); /* converter word */
3109 /****************************************************************************
3110 set the property of a print job (undocumented?)
3111 ? function = 0xb -> set name of print job
3112 ? function = 0x6 -> move print job up/down
3113 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
3114 or <WWsTP> <WB21BB16B10zWWzDDz>
3115 ****************************************************************************/
3117 static int check_printjob_info(struct pack_desc* desc,
3118 int uLevel, char* id)
3120 desc->subformat = NULL;
3122 case 0: desc->format = "W"; break;
3123 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
3124 case 2: desc->format = "WWzWWDDzz"; break;
3125 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
3126 case 4: desc->format = "WWzWWDDzzzzzDDDDDDD"; break;
3128 DEBUG(0,("check_printjob_info: invalid level %d\n",
3132 if (id == NULL || strcmp(desc->format,id) != 0) {
3133 DEBUG(0,("check_printjob_info: invalid format %s\n",
3134 id ? id : "<NULL>" ));
3140 static bool api_PrintJobInfo(connection_struct *conn, uint16 vuid,
3141 char *param, int tpscnt,
3142 char *data, int tdscnt,
3143 int mdrcnt,int mprcnt,
3144 char **rdata,char **rparam,
3145 int *rdata_len,int *rparam_len)
3147 struct pack_desc desc;
3148 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3149 char *str2 = skip_string(param,tpscnt,str1);
3150 char *p = skip_string(param,tpscnt,str2);
3153 int uLevel = get_safe_SVAL(param,tpscnt,p,2,-1);
3154 int function = get_safe_SVAL(param,tpscnt,p,4,-1);
3157 if (!str1 || !str2 || !p) {
3161 * We use 1 here not 2 as we're checking
3162 * the last byte we want to access is safe.
3164 if (!is_offset_safe(param,tpscnt,p,1)) {
3167 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
3170 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3175 if (!share_defined(sharename)) {
3176 DEBUG(0,("api_PrintJobInfo: sharen [%s] not defined\n",
3183 /* check it's a supported varient */
3184 if ((strcmp(str1,"WWsTP")) ||
3185 (!check_printjob_info(&desc,uLevel,str2)))
3188 if (!print_job_exists(sharename, jobid)) {
3189 errcode=NERR_JobNotFound;
3193 errcode = NERR_notsupported;
3197 /* change job place in the queue,
3198 data gives the new place */
3199 place = SVAL(data,0);
3200 if (print_job_set_place(sharename, jobid, place)) {
3201 errcode=NERR_Success;
3206 /* change print job name, data gives the name */
3207 if (print_job_set_name(sharename, jobid, data)) {
3208 errcode=NERR_Success;
3217 SSVALS(*rparam,0,errcode);
3218 SSVAL(*rparam,2,0); /* converter word */
3224 /****************************************************************************
3225 Get info about the server.
3226 ****************************************************************************/
3228 static bool api_RNetServerGetInfo(connection_struct *conn,uint16 vuid,
3229 char *param, int tpscnt,
3230 char *data, int tdscnt,
3231 int mdrcnt,int mprcnt,
3232 char **rdata,char **rparam,
3233 int *rdata_len,int *rparam_len)
3235 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3236 char *str2 = skip_string(param,tpscnt,str1);
3237 char *p = skip_string(param,tpscnt,str2);
3238 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
3242 if (!str1 || !str2 || !p) {
3246 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
3248 /* check it's a supported varient */
3249 if (!prefix_ok(str1,"WrLh")) {
3255 if (strcmp(str2,"B16") != 0) {
3261 if (strcmp(str2,"B16BBDz") != 0) {
3267 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")!= 0) {
3273 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz") != 0) {
3279 if (strcmp(str2,"DN") != 0) {
3285 if (strcmp(str2,"B16BBDzWWzzz") != 0) {
3294 *rdata_len = mdrcnt;
3295 *rdata = smb_realloc_limit(*rdata,*rdata_len);
3301 p2 = p + struct_len;
3303 srvstr_push(NULL, 0, p,global_myname(),16,
3304 STR_ASCII|STR_UPPER|STR_TERMINATE);
3308 struct srv_info_struct *servers=NULL;
3310 char *comment = NULL;
3311 TALLOC_CTX *ctx = talloc_tos();
3312 uint32 servertype= lp_default_server_announce();
3314 comment = talloc_strdup(ctx,lp_serverstring());
3319 if ((count=get_server_info(SV_TYPE_ALL,&servers,lp_workgroup()))>0) {
3320 for (i=0;i<count;i++) {
3321 if (strequal(servers[i].name,global_myname())) {
3322 servertype = servers[i].type;
3323 TALLOC_FREE(comment);
3324 comment = talloc_strdup(ctx,
3325 servers[i].comment);
3335 SCVAL(p,0,lp_major_announce_version());
3336 SCVAL(p,1,lp_minor_announce_version());
3337 SIVAL(p,2,servertype);
3339 if (mdrcnt == struct_len) {
3342 SIVAL(p,6,PTR_DIFF(p2,*rdata));
3343 comment = talloc_sub_advanced(
3345 lp_servicename(SNUM(conn)),
3346 conn->server_info->unix_name,
3348 conn->server_info->utok.gid,
3349 conn->server_info->sanitized_username,
3350 pdb_get_domain(conn->server_info->sam_account),
3355 if (mdrcnt - struct_len <= 0) {
3360 MIN(mdrcnt - struct_len,
3361 MAX_SERVER_STRING_LENGTH),
3363 p2 = skip_string(*rdata,*rdata_len,p2);
3371 return False; /* not yet implemented */
3374 *rdata_len = PTR_DIFF(p2,*rdata);
3377 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3381 SSVAL(*rparam,0,NERR_Success);
3382 SSVAL(*rparam,2,0); /* converter word */
3383 SSVAL(*rparam,4,*rdata_len);
3388 /****************************************************************************
3389 Get info about the server.
3390 ****************************************************************************/
3392 static bool api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid,
3393 char *param, int tpscnt,
3394 char *data, int tdscnt,
3395 int mdrcnt,int mprcnt,
3396 char **rdata,char **rparam,
3397 int *rdata_len,int *rparam_len)
3399 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3400 char *str2 = skip_string(param,tpscnt,str1);
3401 char *p = skip_string(param,tpscnt,str2);
3404 int level = get_safe_SVAL(param,tpscnt,p,0,-1);
3406 if (!str1 || !str2 || !p) {
3410 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
3413 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3418 /* check it's a supported varient */
3419 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz"))) {
3423 *rdata_len = mdrcnt + 1024;
3424 *rdata = smb_realloc_limit(*rdata,*rdata_len);
3429 SSVAL(*rparam,0,NERR_Success);
3430 SSVAL(*rparam,2,0); /* converter word */
3433 endp = *rdata + *rdata_len;
3435 p2 = get_safe_ptr(*rdata,*rdata_len,p,22);
3440 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
3441 strlcpy(p2,get_local_machine_name(),PTR_DIFF(endp,p2));
3443 p2 = skip_string(*rdata,*rdata_len,p2);
3449 SIVAL(p,0,PTR_DIFF(p2,*rdata));
3450 strlcpy(p2,conn->server_info->sanitized_username,PTR_DIFF(endp,p2));
3451 p2 = skip_string(*rdata,*rdata_len,p2);
3457 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
3458 strlcpy(p2,lp_workgroup(),PTR_DIFF(endp,p2));
3460 p2 = skip_string(*rdata,*rdata_len,p2);
3466 SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
3467 SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
3470 SIVAL(p,0,PTR_DIFF(p2,*rdata));
3471 strlcpy(p2,lp_workgroup(),PTR_DIFF(endp,p2)); /* don't know. login domain?? */
3472 p2 = skip_string(*rdata,*rdata_len,p2);
3478 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
3479 strlcpy(p2,"",PTR_DIFF(endp,p2));
3480 p2 = skip_string(*rdata,*rdata_len,p2);
3486 *rdata_len = PTR_DIFF(p2,*rdata);
3488 SSVAL(*rparam,4,*rdata_len);
3493 /****************************************************************************
3494 get info about a user
3496 struct user_info_11 {
3497 char usri11_name[21]; 0-20
3499 char *usri11_comment; 22-25
3500 char *usri11_usr_comment; 26-29
3501 unsigned short usri11_priv; 30-31
3502 unsigned long usri11_auth_flags; 32-35
3503 long usri11_password_age; 36-39
3504 char *usri11_homedir; 40-43
3505 char *usri11_parms; 44-47
3506 long usri11_last_logon; 48-51
3507 long usri11_last_logoff; 52-55
3508 unsigned short usri11_bad_pw_count; 56-57
3509 unsigned short usri11_num_logons; 58-59
3510 char *usri11_logon_server; 60-63
3511 unsigned short usri11_country_code; 64-65
3512 char *usri11_workstations; 66-69
3513 unsigned long usri11_max_storage; 70-73
3514 unsigned short usri11_units_per_week; 74-75
3515 unsigned char *usri11_logon_hours; 76-79
3516 unsigned short usri11_code_page; 80-81
3521 usri11_name specifies the user name for which information is retrieved
3523 usri11_pad aligns the next data structure element to a word boundary
3525 usri11_comment is a null terminated ASCII comment
3527 usri11_user_comment is a null terminated ASCII comment about the user
3529 usri11_priv specifies the level of the privilege assigned to the user.
3530 The possible values are:
3532 Name Value Description
3533 USER_PRIV_GUEST 0 Guest privilege
3534 USER_PRIV_USER 1 User privilege
3535 USER_PRV_ADMIN 2 Administrator privilege
3537 usri11_auth_flags specifies the account operator privileges. The
3538 possible values are:
3540 Name Value Description
3541 AF_OP_PRINT 0 Print operator
3544 Leach, Naik [Page 28]
3548 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
3551 AF_OP_COMM 1 Communications operator
3552 AF_OP_SERVER 2 Server operator
3553 AF_OP_ACCOUNTS 3 Accounts operator
3556 usri11_password_age specifies how many seconds have elapsed since the
3557 password was last changed.
3559 usri11_home_dir points to a null terminated ASCII string that contains
3560 the path name of the user's home directory.
3562 usri11_parms points to a null terminated ASCII string that is set
3563 aside for use by applications.
3565 usri11_last_logon specifies the time when the user last logged on.
3566 This value is stored as the number of seconds elapsed since
3567 00:00:00, January 1, 1970.
3569 usri11_last_logoff specifies the time when the user last logged off.
3570 This value is stored as the number of seconds elapsed since
3571 00:00:00, January 1, 1970. A value of 0 means the last logoff
3574 usri11_bad_pw_count specifies the number of incorrect passwords
3575 entered since the last successful logon.
3577 usri11_log1_num_logons specifies the number of times this user has
3578 logged on. A value of -1 means the number of logons is unknown.
3580 usri11_logon_server points to a null terminated ASCII string that
3581 contains the name of the server to which logon requests are sent.
3582 A null string indicates logon requests should be sent to the
3585 usri11_country_code specifies the country code for the user's language
3588 usri11_workstations points to a null terminated ASCII string that
3589 contains the names of workstations the user may log on from.
3590 There may be up to 8 workstations, with the names separated by
3591 commas. A null strings indicates there are no restrictions.
3593 usri11_max_storage specifies the maximum amount of disk space the user
3594 can occupy. A value of 0xffffffff indicates there are no
3597 usri11_units_per_week specifies the equal number of time units into
3598 which a week is divided. This value must be equal to 168.
3600 usri11_logon_hours points to a 21 byte (168 bits) string that
3601 specifies the time during which the user can log on. Each bit
3602 represents one unique hour in a week. The first bit (bit 0, word
3603 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
3607 Leach, Naik [Page 29]
3611 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
3614 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
3615 are no restrictions.
3617 usri11_code_page specifies the code page for the user's language of
3620 All of the pointers in this data structure need to be treated
3621 specially. The pointer is a 32 bit pointer. The higher 16 bits need
3622 to be ignored. The converter word returned in the parameters section
3623 needs to be subtracted from the lower 16 bits to calculate an offset
3624 into the return buffer where this ASCII string resides.
3626 There is no auxiliary data in the response.
3628 ****************************************************************************/
3630 #define usri11_name 0
3631 #define usri11_pad 21
3632 #define usri11_comment 22
3633 #define usri11_usr_comment 26
3634 #define usri11_full_name 30
3635 #define usri11_priv 34
3636 #define usri11_auth_flags 36
3637 #define usri11_password_age 40
3638 #define usri11_homedir 44
3639 #define usri11_parms 48
3640 #define usri11_last_logon 52
3641 #define usri11_last_logoff 56
3642 #define usri11_bad_pw_count 60
3643 #define usri11_num_logons 62
3644 #define usri11_logon_server 64
3645 #define usri11_country_code 68
3646 #define usri11_workstations 70
3647 #define usri11_max_storage 74
3648 #define usri11_units_per_week 78
3649 #define usri11_logon_hours 80
3650 #define usri11_code_page 84
3651 #define usri11_end 86
3653 #define USER_PRIV_GUEST 0
3654 #define USER_PRIV_USER 1
3655 #define USER_PRIV_ADMIN 2
3657 #define AF_OP_PRINT 0
3658 #define AF_OP_COMM 1
3659 #define AF_OP_SERVER 2
3660 #define AF_OP_ACCOUNTS 3
3663 static bool api_RNetUserGetInfo(connection_struct *conn, uint16 vuid,
3664 char *param, int tpscnt,
3665 char *data, int tdscnt,
3666 int mdrcnt,int mprcnt,
3667 char **rdata,char **rparam,
3668 int *rdata_len,int *rparam_len)
3670 struct smbd_server_connection *sconn = smbd_server_conn;
3671 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3672 char *str2 = skip_string(param,tpscnt,str1);
3673 char *UserName = skip_string(param,tpscnt,str2);
3674 char *p = skip_string(param,tpscnt,UserName);
3675 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
3678 const char *level_string;
3680 /* get NIS home of a previously validated user - simeon */
3681 /* With share level security vuid will always be zero.
3682 Don't depend on vuser being non-null !!. JRA */
3683 user_struct *vuser = get_valid_user_struct(sconn, vuid);
3685 DEBUG(3,(" Username of UID %d is %s\n",
3686 (int)vuser->server_info->utok.uid,
3687 vuser->server_info->unix_name));
3690 if (!str1 || !str2 || !UserName || !p) {
3695 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3700 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
3702 /* check it's a supported variant */
3703 if (strcmp(str1,"zWrLh") != 0) {
3707 case 0: level_string = "B21"; break;
3708 case 1: level_string = "B21BB16DWzzWz"; break;
3709 case 2: level_string = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
3710 case 10: level_string = "B21Bzzz"; break;
3711 case 11: level_string = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
3712 default: return False;
3715 if (strcmp(level_string,str2) != 0) {
3719 *rdata_len = mdrcnt + 1024;
3720 *rdata = smb_realloc_limit(*rdata,*rdata_len);
3725 SSVAL(*rparam,0,NERR_Success);
3726 SSVAL(*rparam,2,0); /* converter word */
3729 endp = *rdata + *rdata_len;
3730 p2 = get_safe_ptr(*rdata,*rdata_len,p,usri11_end);
3736 fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
3739 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
3744 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
3745 strlcpy(p2,"Comment",PTR_DIFF(endp,p2));
3746 p2 = skip_string(*rdata,*rdata_len,p2);
3751 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
3752 strlcpy(p2,"UserComment",PTR_DIFF(endp,p2));
3753 p2 = skip_string(*rdata,*rdata_len,p2);
3758 /* EEK! the cifsrap.txt doesn't have this in!!!! */
3759 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
3760 strlcpy(p2,((vuser != NULL)
3761 ? pdb_get_fullname(vuser->server_info->sam_account)
3762 : UserName),PTR_DIFF(endp,p2));
3763 p2 = skip_string(*rdata,*rdata_len,p2);
3770 const char *homedir = "";
3771 if (vuser != NULL) {
3772 homedir = pdb_get_homedir(
3773 vuser->server_info->sam_account);
3775 /* modelled after NTAS 3.51 reply */
3776 SSVAL(p,usri11_priv,conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
3777 SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
3778 SIVALS(p,usri11_password_age,-1); /* password age */
3779 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
3780 strlcpy(p2, homedir, PTR_DIFF(endp,p2));
3781 p2 = skip_string(*rdata,*rdata_len,p2);
3785 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
3786 strlcpy(p2,"",PTR_DIFF(endp,p2));
3787 p2 = skip_string(*rdata,*rdata_len,p2);
3791 SIVAL(p,usri11_last_logon,0); /* last logon */
3792 SIVAL(p,usri11_last_logoff,0); /* last logoff */
3793 SSVALS(p,usri11_bad_pw_count,-1); /* bad pw counts */
3794 SSVALS(p,usri11_num_logons,-1); /* num logons */
3795 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
3796 strlcpy(p2,"\\\\*",PTR_DIFF(endp,p2));
3797 p2 = skip_string(*rdata,*rdata_len,p2);
3801 SSVAL(p,usri11_country_code,0); /* country code */
3803 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
3804 strlcpy(p2,"",PTR_DIFF(endp,p2));
3805 p2 = skip_string(*rdata,*rdata_len,p2);
3810 SIVALS(p,usri11_max_storage,-1); /* max storage */
3811 SSVAL(p,usri11_units_per_week,168); /* units per week */
3812 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
3814 /* a simple way to get logon hours at all times. */
3816 SCVAL(p2,21,0); /* fix zero termination */
3817 p2 = skip_string(*rdata,*rdata_len,p2);
3822 SSVAL(p,usri11_code_page,0); /* code page */
3825 if (uLevel == 1 || uLevel == 2) {
3826 memset(p+22,' ',16); /* password */
3827 SIVALS(p,38,-1); /* password age */
3829 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
3830 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
3831 strlcpy(p2, vuser ? pdb_get_homedir(
3832 vuser->server_info->sam_account) : "",
3834 p2 = skip_string(*rdata,*rdata_len,p2);
3838 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
3840 SSVAL(p,52,0); /* flags */
3841 SIVAL(p,54,PTR_DIFF(p2,*rdata)); /* script_path */
3842 strlcpy(p2, vuser ? pdb_get_logon_script(
3843 vuser->server_info->sam_account) : "",
3845 p2 = skip_string(*rdata,*rdata_len,p2);
3850 SIVAL(p,60,0); /* auth_flags */
3851 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
3852 strlcpy(p2,((vuser != NULL)
3853 ? pdb_get_fullname(vuser->server_info->sam_account)
3854 : UserName),PTR_DIFF(endp,p2));
3855 p2 = skip_string(*rdata,*rdata_len,p2);
3859 SIVAL(p,68,0); /* urs_comment */
3860 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
3861 strlcpy(p2,"",PTR_DIFF(endp,p2));
3862 p2 = skip_string(*rdata,*rdata_len,p2);
3866 SIVAL(p,76,0); /* workstations */
3867 SIVAL(p,80,0); /* last_logon */
3868 SIVAL(p,84,0); /* last_logoff */
3869 SIVALS(p,88,-1); /* acct_expires */
3870 SIVALS(p,92,-1); /* max_storage */
3871 SSVAL(p,96,168); /* units_per_week */
3872 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
3875 SSVALS(p,102,-1); /* bad_pw_count */
3876 SSVALS(p,104,-1); /* num_logons */
3877 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
3879 TALLOC_CTX *ctx = talloc_tos();
3880 int space_rem = *rdata_len - (p2 - *rdata);
3883 if (space_rem <= 0) {
3886 tmp = talloc_strdup(ctx, "\\\\%L");
3890 tmp = talloc_sub_basic(ctx,
3903 p2 = skip_string(*rdata,*rdata_len,p2);
3907 SSVAL(p,110,49); /* country_code */
3908 SSVAL(p,112,860); /* code page */
3912 *rdata_len = PTR_DIFF(p2,*rdata);
3914 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
3919 static bool api_WWkstaUserLogon(connection_struct *conn,uint16 vuid,
3920 char *param, int tpscnt,
3921 char *data, int tdscnt,
3922 int mdrcnt,int mprcnt,
3923 char **rdata,char **rparam,
3924 int *rdata_len,int *rparam_len)
3926 struct smbd_server_connection *sconn = smbd_server_conn;
3927 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3928 char *str2 = skip_string(param,tpscnt,str1);
3929 char *p = skip_string(param,tpscnt,str2);
3931 struct pack_desc desc;
3933 /* With share level security vuid will always be zero.
3934 Don't depend on vuser being non-null !!. JRA */
3935 user_struct *vuser = get_valid_user_struct(sconn, vuid);
3937 if (!str1 || !str2 || !p) {
3942 DEBUG(3,(" Username of UID %d is %s\n",
3943 (int)vuser->server_info->utok.uid,
3944 vuser->server_info->unix_name));
3947 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
3948 name = get_safe_str_ptr(param,tpscnt,p,2);
3953 memset((char *)&desc,'\0',sizeof(desc));
3955 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
3957 /* check it's a supported varient */
3958 if (strcmp(str1,"OOWb54WrLh") != 0) {
3961 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) {
3965 *rdata = smb_realloc_limit(*rdata,mdrcnt);
3972 desc.buflen = mdrcnt;
3973 desc.subformat = NULL;
3976 if (init_package(&desc,1,0)) {
3977 PACKI(&desc,"W",0); /* code */
3978 PACKS(&desc,"B21",name); /* eff. name */
3979 PACKS(&desc,"B",""); /* pad */
3980 PACKI(&desc,"W", conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
3981 PACKI(&desc,"D",0); /* auth flags XXX */
3982 PACKI(&desc,"W",0); /* num logons */
3983 PACKI(&desc,"W",0); /* bad pw count */
3984 PACKI(&desc,"D",0); /* last logon */
3985 PACKI(&desc,"D",-1); /* last logoff */
3986 PACKI(&desc,"D",-1); /* logoff time */
3987 PACKI(&desc,"D",-1); /* kickoff time */
3988 PACKI(&desc,"D",0); /* password age */
3989 PACKI(&desc,"D",0); /* password can change */
3990 PACKI(&desc,"D",-1); /* password must change */
3994 fstrcpy(mypath,"\\\\");
3995 fstrcat(mypath,get_local_machine_name());
3997 PACKS(&desc,"z",mypath); /* computer */
4000 PACKS(&desc,"z",lp_workgroup());/* domain */
4001 PACKS(&desc,"z", vuser ? pdb_get_logon_script(
4002 vuser->server_info->sam_account) : ""); /* script path */
4003 PACKI(&desc,"D",0x00000000); /* reserved */
4006 *rdata_len = desc.usedlen;
4008 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4012 SSVALS(*rparam,0,desc.errcode);
4014 SSVAL(*rparam,4,desc.neededlen);
4016 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
4021 /****************************************************************************
4022 api_WAccessGetUserPerms
4023 ****************************************************************************/
4025 static bool api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid,
4026 char *param, int tpscnt,
4027 char *data, int tdscnt,
4028 int mdrcnt,int mprcnt,
4029 char **rdata,char **rparam,
4030 int *rdata_len,int *rparam_len)
4032 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4033 char *str2 = skip_string(param,tpscnt,str1);
4034 char *user = skip_string(param,tpscnt,str2);
4035 char *resource = skip_string(param,tpscnt,user);
4037 if (!str1 || !str2 || !user || !resource) {
4041 if (skip_string(param,tpscnt,resource) == NULL) {
4044 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
4046 /* check it's a supported varient */
4047 if (strcmp(str1,"zzh") != 0) {
4050 if (strcmp(str2,"") != 0) {
4055 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4059 SSVALS(*rparam,0,0); /* errorcode */
4060 SSVAL(*rparam,2,0); /* converter word */
4061 SSVAL(*rparam,4,0x7f); /* permission flags */
4066 /****************************************************************************
4067 api_WPrintJobEnumerate
4068 ****************************************************************************/
4070 static bool api_WPrintJobGetInfo(connection_struct *conn, uint16 vuid,
4071 char *param, int tpscnt,
4072 char *data, int tdscnt,
4073 int mdrcnt,int mprcnt,
4074 char **rdata,char **rparam,
4075 int *rdata_len,int *rparam_len)
4077 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4078 char *str2 = skip_string(param,tpscnt,str1);
4079 char *p = skip_string(param,tpscnt,str2);
4086 struct pack_desc desc;
4087 print_queue_struct *queue=NULL;
4088 print_status_struct status;
4091 if (!str1 || !str2 || !p) {
4095 uLevel = get_safe_SVAL(param,tpscnt,p,2,-1);
4097 memset((char *)&desc,'\0',sizeof(desc));
4098 memset((char *)&status,'\0',sizeof(status));
4100 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
4102 /* check it's a supported varient */
4103 if (strcmp(str1,"WWrLh") != 0) {
4106 if (!check_printjob_info(&desc,uLevel,str2)) {
4110 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid)) {
4114 snum = lp_servicenumber( sharename);
4115 if (snum < 0 || !VALID_SNUM(snum)) {
4119 count = print_queue_status(snum,&queue,&status);
4120 for (i = 0; i < count; i++) {
4121 if (queue[i].job == jobid) {
4127 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4132 desc.buflen = mdrcnt;
4135 * Don't return data but need to get correct length
4136 * init_package will return wrong size if buflen=0
4138 desc.buflen = getlen(desc.format);
4139 desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen );
4142 if (init_package(&desc,1,0)) {
4144 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
4145 *rdata_len = desc.usedlen;
4147 desc.errcode = NERR_JobNotFound;
4153 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4157 SSVALS(*rparam,0,desc.errcode);
4159 SSVAL(*rparam,4,desc.neededlen);
4164 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
4169 static bool api_WPrintJobEnumerate(connection_struct *conn, uint16 vuid,
4170 char *param, int tpscnt,
4171 char *data, int tdscnt,
4172 int mdrcnt,int mprcnt,
4173 char **rdata,char **rparam,
4174 int *rdata_len,int *rparam_len)
4176 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4177 char *str2 = skip_string(param,tpscnt,str1);
4178 char *p = skip_string(param,tpscnt,str2);
4184 struct pack_desc desc;
4185 print_queue_struct *queue=NULL;
4186 print_status_struct status;
4189 if (!str1 || !str2 || !p) {
4193 memset((char *)&desc,'\0',sizeof(desc));
4194 memset((char *)&status,'\0',sizeof(status));
4196 p = skip_string(param,tpscnt,p);
4200 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4202 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
4204 /* check it's a supported variant */
4205 if (strcmp(str1,"zWrLeh") != 0) {
4210 return False; /* defined only for uLevel 0,1,2 */
4213 if (!check_printjob_info(&desc,uLevel,str2)) {
4217 snum = find_service(name, share_name);
4218 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) ) {
4222 count = print_queue_status(snum,&queue,&status);
4224 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4230 desc.buflen = mdrcnt;
4232 if (init_package(&desc,count,0)) {
4234 for (i = 0; i < count; i++) {
4235 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
4236 if (desc.errcode == NERR_Success) {
4242 *rdata_len = desc.usedlen;
4245 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4249 SSVALS(*rparam,0,desc.errcode);
4251 SSVAL(*rparam,4,succnt);
4252 SSVAL(*rparam,6,count);
4256 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
4261 static int check_printdest_info(struct pack_desc* desc,
4262 int uLevel, char* id)
4264 desc->subformat = NULL;
4267 desc->format = "B9";
4270 desc->format = "B9B21WWzW";
4276 desc->format = "zzzWWzzzWW";
4279 DEBUG(0,("check_printdest_info: invalid level %d\n",
4283 if (id == NULL || strcmp(desc->format,id) != 0) {
4284 DEBUG(0,("check_printdest_info: invalid string %s\n",
4285 id ? id : "<NULL>" ));
4291 static void fill_printdest_info(connection_struct *conn, int snum, int uLevel,
4292 struct pack_desc* desc)
4296 strncpy(buf,SERVICE(snum),sizeof(buf)-1);
4297 buf[sizeof(buf)-1] = 0;
4301 PACKS(desc,"B9",buf); /* szName */
4303 PACKS(desc,"B21",""); /* szUserName */
4304 PACKI(desc,"W",0); /* uJobId */
4305 PACKI(desc,"W",0); /* fsStatus */
4306 PACKS(desc,"z",""); /* pszStatus */
4307 PACKI(desc,"W",0); /* time */
4311 if (uLevel == 2 || uLevel == 3) {
4312 PACKS(desc,"z",buf); /* pszPrinterName */
4314 PACKS(desc,"z",""); /* pszUserName */
4315 PACKS(desc,"z",""); /* pszLogAddr */
4316 PACKI(desc,"W",0); /* uJobId */
4317 PACKI(desc,"W",0); /* fsStatus */
4318 PACKS(desc,"z",""); /* pszStatus */
4319 PACKS(desc,"z",""); /* pszComment */
4320 PACKS(desc,"z","NULL"); /* pszDrivers */
4321 PACKI(desc,"W",0); /* time */
4322 PACKI(desc,"W",0); /* pad1 */
4327 static bool api_WPrintDestGetInfo(connection_struct *conn, uint16 vuid,
4328 char *param, int tpscnt,
4329 char *data, int tdscnt,
4330 int mdrcnt,int mprcnt,
4331 char **rdata,char **rparam,
4332 int *rdata_len,int *rparam_len)
4334 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4335 char *str2 = skip_string(param,tpscnt,str1);
4336 char *p = skip_string(param,tpscnt,str2);
4337 char* PrinterName = p;
4340 struct pack_desc desc;
4344 if (!str1 || !str2 || !p) {
4348 memset((char *)&desc,'\0',sizeof(desc));
4350 p = skip_string(param,tpscnt,p);
4354 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4356 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
4358 /* check it's a supported varient */
4359 if (strcmp(str1,"zWrLh") != 0) {
4362 if (!check_printdest_info(&desc,uLevel,str2)) {
4366 snum = find_service(PrinterName, share_name);
4367 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) ) {
4369 desc.errcode = NERR_DestNotFound;
4373 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4378 desc.buflen = mdrcnt;
4381 * Don't return data but need to get correct length
4382 * init_package will return wrong size if buflen=0
4384 desc.buflen = getlen(desc.format);
4385 desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen );
4387 if (init_package(&desc,1,0)) {
4388 fill_printdest_info(conn,snum,uLevel,&desc);
4390 *rdata_len = desc.usedlen;
4394 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4398 SSVALS(*rparam,0,desc.errcode);
4400 SSVAL(*rparam,4,desc.neededlen);
4402 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
4408 static bool api_WPrintDestEnum(connection_struct *conn, uint16 vuid,
4409 char *param, int tpscnt,
4410 char *data, int tdscnt,
4411 int mdrcnt,int mprcnt,
4412 char **rdata,char **rparam,
4413 int *rdata_len,int *rparam_len)
4415 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4416 char *str2 = skip_string(param,tpscnt,str1);
4417 char *p = skip_string(param,tpscnt,str2);
4421 struct pack_desc desc;
4422 int services = lp_numservices();
4424 if (!str1 || !str2 || !p) {
4428 memset((char *)&desc,'\0',sizeof(desc));
4430 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4432 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
4434 /* check it's a supported varient */
4435 if (strcmp(str1,"WrLeh") != 0) {
4438 if (!check_printdest_info(&desc,uLevel,str2)) {
4443 for (i = 0; i < services; i++) {
4444 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
4450 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4457 desc.buflen = mdrcnt;
4458 if (init_package(&desc,queuecnt,0)) {
4461 for (i = 0; i < services; i++) {
4462 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
4463 fill_printdest_info(conn,i,uLevel,&desc);
4465 if (desc.errcode == NERR_Success) {
4472 *rdata_len = desc.usedlen;
4475 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4479 SSVALS(*rparam,0,desc.errcode);
4481 SSVAL(*rparam,4,succnt);
4482 SSVAL(*rparam,6,queuecnt);
4484 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
4489 static bool api_WPrintDriverEnum(connection_struct *conn, uint16 vuid,
4490 char *param, int tpscnt,
4491 char *data, int tdscnt,
4492 int mdrcnt,int mprcnt,
4493 char **rdata,char **rparam,
4494 int *rdata_len,int *rparam_len)
4496 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4497 char *str2 = skip_string(param,tpscnt,str1);
4498 char *p = skip_string(param,tpscnt,str2);
4501 struct pack_desc desc;
4503 if (!str1 || !str2 || !p) {
4507 memset((char *)&desc,'\0',sizeof(desc));
4509 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4511 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
4513 /* check it's a supported varient */
4514 if (strcmp(str1,"WrLeh") != 0) {
4517 if (uLevel != 0 || strcmp(str2,"B41") != 0) {
4522 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4528 desc.buflen = mdrcnt;
4529 if (init_package(&desc,1,0)) {
4530 PACKS(&desc,"B41","NULL");
4533 succnt = (desc.errcode == NERR_Success ? 1 : 0);
4535 *rdata_len = desc.usedlen;
4538 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4542 SSVALS(*rparam,0,desc.errcode);
4544 SSVAL(*rparam,4,succnt);
4547 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
4552 static bool api_WPrintQProcEnum(connection_struct *conn, uint16 vuid,
4553 char *param, int tpscnt,
4554 char *data, int tdscnt,
4555 int mdrcnt,int mprcnt,
4556 char **rdata,char **rparam,
4557 int *rdata_len,int *rparam_len)
4559 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4560 char *str2 = skip_string(param,tpscnt,str1);
4561 char *p = skip_string(param,tpscnt,str2);
4564 struct pack_desc desc;
4566 if (!str1 || !str2 || !p) {
4569 memset((char *)&desc,'\0',sizeof(desc));
4571 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4573 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
4575 /* check it's a supported varient */
4576 if (strcmp(str1,"WrLeh") != 0) {
4579 if (uLevel != 0 || strcmp(str2,"B13") != 0) {
4584 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4590 desc.buflen = mdrcnt;
4592 if (init_package(&desc,1,0)) {
4593 PACKS(&desc,"B13","lpd");
4596 succnt = (desc.errcode == NERR_Success ? 1 : 0);
4598 *rdata_len = desc.usedlen;
4601 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4605 SSVALS(*rparam,0,desc.errcode);
4607 SSVAL(*rparam,4,succnt);
4610 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
4615 static bool api_WPrintPortEnum(connection_struct *conn, uint16 vuid,
4616 char *param, int tpscnt,
4617 char *data, int tdscnt,
4618 int mdrcnt,int mprcnt,
4619 char **rdata,char **rparam,
4620 int *rdata_len,int *rparam_len)
4622 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4623 char *str2 = skip_string(param,tpscnt,str1);
4624 char *p = skip_string(param,tpscnt,str2);
4627 struct pack_desc desc;
4629 if (!str1 || !str2 || !p) {
4633 memset((char *)&desc,'\0',sizeof(desc));
4635 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4637 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
4639 /* check it's a supported varient */
4640 if (strcmp(str1,"WrLeh") != 0) {
4643 if (uLevel != 0 || strcmp(str2,"B9") != 0) {
4648 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4653 memset((char *)&desc,'\0',sizeof(desc));
4655 desc.buflen = mdrcnt;
4657 if (init_package(&desc,1,0)) {
4658 PACKS(&desc,"B13","lp0");
4661 succnt = (desc.errcode == NERR_Success ? 1 : 0);
4663 *rdata_len = desc.usedlen;
4666 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4670 SSVALS(*rparam,0,desc.errcode);
4672 SSVAL(*rparam,4,succnt);
4675 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
4680 /****************************************************************************
4682 ****************************************************************************/
4684 static bool api_RNetSessionEnum(connection_struct *conn, uint16 vuid,
4685 char *param, int tpscnt,
4686 char *data, int tdscnt,
4687 int mdrcnt,int mprcnt,
4688 char **rdata,char **rparam,
4689 int *rdata_len,int *rparam_len)
4692 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4693 char *str2 = skip_string(param,tpscnt,str1);
4694 char *p = skip_string(param,tpscnt,str2);
4696 struct pack_desc desc;
4697 struct sessionid *session_list;
4698 int i, num_sessions;
4700 if (!str1 || !str2 || !p) {
4704 memset((char *)&desc,'\0',sizeof(desc));
4706 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4708 DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel));
4709 DEBUG(7,("RNetSessionEnum req string=%s\n",str1));
4710 DEBUG(7,("RNetSessionEnum ret string=%s\n",str2));
4712 /* check it's a supported varient */
4713 if (strcmp(str1,RAP_NetSessionEnum_REQ) != 0) {
4716 if (uLevel != 2 || strcmp(str2,RAP_SESSION_INFO_L2) != 0) {
4720 num_sessions = list_sessions(talloc_tos(), &session_list);
4723 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4728 memset((char *)&desc,'\0',sizeof(desc));
4730 desc.buflen = mdrcnt;
4732 if (!init_package(&desc,num_sessions,0)) {
4736 for(i=0; i<num_sessions; i++) {
4737 PACKS(&desc, "z", session_list[i].remote_machine);
4738 PACKS(&desc, "z", session_list[i].username);
4739 PACKI(&desc, "W", 1); /* num conns */
4740 PACKI(&desc, "W", 0); /* num opens */
4741 PACKI(&desc, "W", 1); /* num users */
4742 PACKI(&desc, "D", 0); /* session time */
4743 PACKI(&desc, "D", 0); /* idle time */
4744 PACKI(&desc, "D", 0); /* flags */
4745 PACKS(&desc, "z", "Unknown Client"); /* client type string */
4748 *rdata_len = desc.usedlen;
4751 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4755 SSVALS(*rparam,0,desc.errcode);
4756 SSVAL(*rparam,2,0); /* converter */
4757 SSVAL(*rparam,4,num_sessions); /* count */
4759 DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc.errcode));
4765 /****************************************************************************
4766 The buffer was too small.
4767 ****************************************************************************/
4769 static bool api_TooSmall(connection_struct *conn,uint16 vuid, char *param, char *data,
4770 int mdrcnt, int mprcnt,
4771 char **rdata, char **rparam,
4772 int *rdata_len, int *rparam_len)
4774 *rparam_len = MIN(*rparam_len,mprcnt);
4775 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4782 SSVAL(*rparam,0,NERR_BufTooSmall);
4784 DEBUG(3,("Supplied buffer too small in API command\n"));
4789 /****************************************************************************
4790 The request is not supported.
4791 ****************************************************************************/
4793 static bool api_Unsupported(connection_struct *conn, uint16 vuid,
4794 char *param, int tpscnt,
4795 char *data, int tdscnt,
4796 int mdrcnt, int mprcnt,
4797 char **rdata, char **rparam,
4798 int *rdata_len, int *rparam_len)
4801 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4808 SSVAL(*rparam,0,NERR_notsupported);
4809 SSVAL(*rparam,2,0); /* converter word */
4811 DEBUG(3,("Unsupported API command\n"));
4816 static const struct {
4819 bool (*fn)(connection_struct *, uint16,
4822 int,int,char **,char **,int *,int *);
4823 bool auth_user; /* Deny anonymous access? */
4824 } api_commands[] = {
4825 {"RNetShareEnum", RAP_WshareEnum, api_RNetShareEnum, True},
4826 {"RNetShareGetInfo", RAP_WshareGetInfo, api_RNetShareGetInfo},
4827 {"RNetShareAdd", RAP_WshareAdd, api_RNetShareAdd},
4828 {"RNetSessionEnum", RAP_WsessionEnum, api_RNetSessionEnum, True},
4829 {"RNetServerGetInfo", RAP_WserverGetInfo, api_RNetServerGetInfo},
4830 {"RNetGroupEnum", RAP_WGroupEnum, api_RNetGroupEnum, True},
4831 {"RNetGroupGetUsers", RAP_WGroupGetUsers, api_RNetGroupGetUsers, True},
4832 {"RNetUserEnum", RAP_WUserEnum, api_RNetUserEnum, True},
4833 {"RNetUserGetInfo", RAP_WUserGetInfo, api_RNetUserGetInfo},
4834 {"NetUserGetGroups", RAP_WUserGetGroups, api_NetUserGetGroups},
4835 {"NetWkstaGetInfo", RAP_WWkstaGetInfo, api_NetWkstaGetInfo},
4836 {"DosPrintQEnum", RAP_WPrintQEnum, api_DosPrintQEnum, True},
4837 {"DosPrintQGetInfo", RAP_WPrintQGetInfo, api_DosPrintQGetInfo},
4838 {"WPrintQueuePause", RAP_WPrintQPause, api_WPrintQueueCtrl},
4839 {"WPrintQueueResume", RAP_WPrintQContinue, api_WPrintQueueCtrl},
4840 {"WPrintJobEnumerate",RAP_WPrintJobEnum, api_WPrintJobEnumerate},
4841 {"WPrintJobGetInfo", RAP_WPrintJobGetInfo, api_WPrintJobGetInfo},
4842 {"RDosPrintJobDel", RAP_WPrintJobDel, api_RDosPrintJobDel},
4843 {"RDosPrintJobPause", RAP_WPrintJobPause, api_RDosPrintJobDel},
4844 {"RDosPrintJobResume",RAP_WPrintJobContinue, api_RDosPrintJobDel},
4845 {"WPrintDestEnum", RAP_WPrintDestEnum, api_WPrintDestEnum},
4846 {"WPrintDestGetInfo", RAP_WPrintDestGetInfo, api_WPrintDestGetInfo},
4847 {"NetRemoteTOD", RAP_NetRemoteTOD, api_NetRemoteTOD},
4848 {"WPrintQueuePurge", RAP_WPrintQPurge, api_WPrintQueueCtrl},
4849 {"NetServerEnum2", RAP_NetServerEnum2, api_RNetServerEnum2}, /* anon OK */
4850 {"NetServerEnum3", RAP_NetServerEnum3, api_RNetServerEnum3}, /* anon OK */
4851 {"WAccessGetUserPerms",RAP_WAccessGetUserPerms,api_WAccessGetUserPerms},
4852 {"SetUserPassword", RAP_WUserPasswordSet2, api_SetUserPassword},
4853 {"WWkstaUserLogon", RAP_WWkstaUserLogon, api_WWkstaUserLogon},
4854 {"PrintJobInfo", RAP_WPrintJobSetInfo, api_PrintJobInfo},
4855 {"WPrintDriverEnum", RAP_WPrintDriverEnum, api_WPrintDriverEnum},
4856 {"WPrintQProcEnum", RAP_WPrintQProcessorEnum,api_WPrintQProcEnum},
4857 {"WPrintPortEnum", RAP_WPrintPortEnum, api_WPrintPortEnum},
4858 {"SamOEMChangePassword",RAP_SamOEMChgPasswordUser2_P,api_SamOEMChangePassword}, /* anon OK */
4859 {NULL, -1, api_Unsupported}
4860 /* The following RAP calls are not implemented by Samba:
4862 RAP_WFileEnum2 - anon not OK
4867 /****************************************************************************
4868 Handle remote api calls.
4869 ****************************************************************************/
4871 void api_reply(connection_struct *conn, uint16 vuid,
4872 struct smb_request *req,
4873 char *data, char *params,
4874 int tdscnt, int tpscnt,
4875 int mdrcnt, int mprcnt)
4877 struct smbd_server_connection *sconn = smbd_server_conn;
4880 char *rparam = NULL;
4881 const char *name1 = NULL;
4882 const char *name2 = NULL;
4889 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
4890 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4895 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4898 api_command = SVAL(params,0);
4899 /* Is there a string at position params+2 ? */
4900 if (skip_string(params,tpscnt,params+2)) {
4905 name2 = skip_string(params,tpscnt,params+2);
4910 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
4914 tdscnt,tpscnt,mdrcnt,mprcnt));
4916 for (i=0;api_commands[i].name;i++) {
4917 if (api_commands[i].id == api_command && api_commands[i].fn) {
4918 DEBUG(3,("Doing %s\n",api_commands[i].name));
4923 /* Check whether this api call can be done anonymously */
4925 if (api_commands[i].auth_user && lp_restrict_anonymous()) {
4926 user_struct *user = get_valid_user_struct(sconn, vuid);
4928 if (!user || user->server_info->guest) {
4929 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4934 rdata = (char *)SMB_MALLOC(1024);
4936 memset(rdata,'\0',1024);
4939 rparam = (char *)SMB_MALLOC(1024);
4941 memset(rparam,'\0',1024);
4944 if(!rdata || !rparam) {
4945 DEBUG(0,("api_reply: malloc fail !\n"));
4948 reply_nterror(req, NT_STATUS_NO_MEMORY);
4952 reply = api_commands[i].fn(conn,
4954 params,tpscnt, /* params + length */
4955 data,tdscnt, /* data + length */
4957 &rdata,&rparam,&rdata_len,&rparam_len);
4960 if (rdata_len > mdrcnt || rparam_len > mprcnt) {
4961 reply = api_TooSmall(conn,vuid,params,data,mdrcnt,mprcnt,
4962 &rdata,&rparam,&rdata_len,&rparam_len);
4965 /* if we get False back then it's actually unsupported */
4967 reply = api_Unsupported(conn,vuid,params,tpscnt,data,tdscnt,mdrcnt,mprcnt,
4968 &rdata,&rparam,&rdata_len,&rparam_len);
4971 /* If api_Unsupported returns false we can't return anything. */
4973 send_trans_reply(conn, req, rparam, rparam_len,
4974 rdata, rdata_len, False);