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/cli_spoolss.h"
32 #include "../librpc/gen_ndr/srv_samr.h"
33 #include "../librpc/gen_ndr/srv_spoolss.h"
34 #include "../lib/util/binsearch.h"
41 #define NERR_Success 0
42 #define NERR_badpass 86
43 #define NERR_notsupported 50
45 #define NERR_BASE (2100)
46 #define NERR_BufTooSmall (NERR_BASE+23)
47 #define NERR_JobNotFound (NERR_BASE+51)
48 #define NERR_DestNotFound (NERR_BASE+52)
50 #define ACCESS_READ 0x01
51 #define ACCESS_WRITE 0x02
52 #define ACCESS_CREATE 0x04
54 #define SHPWLEN 8 /* share password length */
56 /* Limit size of ipc replies */
58 static char *smb_realloc_limit(void *ptr, size_t size)
62 size = MAX((size),4*1024);
63 val = (char *)SMB_REALLOC(ptr,size);
65 memset(val,'\0',size);
70 static bool api_Unsupported(connection_struct *conn, uint16 vuid,
71 char *param, int tpscnt,
72 char *data, int tdscnt,
73 int mdrcnt, int mprcnt,
74 char **rdata, char **rparam,
75 int *rdata_len, int *rparam_len);
77 static bool api_TooSmall(connection_struct *conn, uint16 vuid, char *param, char *data,
78 int mdrcnt, int mprcnt,
79 char **rdata, char **rparam,
80 int *rdata_len, int *rparam_len);
83 static int CopyExpanded(connection_struct *conn,
84 int snum, char **dst, char *src, int *p_space_remaining)
86 TALLOC_CTX *ctx = talloc_tos();
90 if (!src || !dst || !p_space_remaining || !(*dst) ||
91 *p_space_remaining <= 0) {
95 buf = talloc_strdup(ctx, src);
97 *p_space_remaining = 0;
100 buf = talloc_string_sub(ctx, buf,"%S",lp_servicename(snum));
102 *p_space_remaining = 0;
105 buf = talloc_sub_advanced(ctx,
106 lp_servicename(SNUM(conn)),
107 conn->server_info->unix_name,
109 conn->server_info->utok.gid,
110 conn->server_info->sanitized_username,
111 pdb_get_domain(conn->server_info->sam_account),
114 *p_space_remaining = 0;
117 l = push_ascii(*dst,buf,*p_space_remaining, STR_TERMINATE);
122 (*p_space_remaining) -= l;
126 static int CopyAndAdvance(char **dst, char *src, int *n)
129 if (!src || !dst || !n || !(*dst)) {
132 l = push_ascii(*dst,src,*n, STR_TERMINATE);
141 static int StrlenExpanded(connection_struct *conn, int snum, char *s)
143 TALLOC_CTX *ctx = talloc_tos();
148 buf = talloc_strdup(ctx,s);
152 buf = talloc_string_sub(ctx,buf,"%S",lp_servicename(snum));
156 buf = talloc_sub_advanced(ctx,
157 lp_servicename(SNUM(conn)),
158 conn->server_info->unix_name,
160 conn->server_info->utok.gid,
161 conn->server_info->sanitized_username,
162 pdb_get_domain(conn->server_info->sam_account),
167 return strlen(buf) + 1;
170 static char *Expand(connection_struct *conn, int snum, char *s)
172 TALLOC_CTX *ctx = talloc_tos();
178 buf = talloc_strdup(ctx,s);
182 buf = talloc_string_sub(ctx,buf,"%S",lp_servicename(snum));
186 return talloc_sub_advanced(ctx,
187 lp_servicename(SNUM(conn)),
188 conn->server_info->unix_name,
190 conn->server_info->utok.gid,
191 conn->server_info->sanitized_username,
192 pdb_get_domain(conn->server_info->sam_account),
196 /*******************************************************************
197 Check a API string for validity when we only need to check the prefix.
198 ******************************************************************/
200 static bool prefix_ok(const char *str, const char *prefix)
202 return(strncmp(str,prefix,strlen(prefix)) == 0);
206 const char *format; /* formatstring for structure */
207 const char *subformat; /* subformat for structure */
208 char *base; /* baseaddress of buffer */
209 int buflen; /* remaining size for fixed part; on init: length of base */
210 int subcount; /* count of substructures */
211 char *structbuf; /* pointer into buffer for remaining fixed part */
212 int stringlen; /* remaining size for variable part */
213 char *stringbuf; /* pointer into buffer for remaining variable part */
214 int neededlen; /* total needed size */
215 int usedlen; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
216 const char *curpos; /* current position; pointer into format or subformat */
220 static int get_counter(const char **p)
226 if (!isdigit((int)**p)) {
232 n = 10 * n + (i - '0');
240 static int getlen(const char *p)
249 case 'W': /* word (2 byte) */
252 case 'K': /* status word? (2 byte) */
255 case 'N': /* count of substructures (word) at end */
258 case 'D': /* double word (4 byte) */
259 case 'z': /* offset to zero terminated string (4 byte) */
260 case 'l': /* offset to user data (4 byte) */
263 case 'b': /* offset to data (with counter) (4 byte) */
267 case 'B': /* byte (with optional counter) */
268 n += get_counter(&p);
275 static bool init_package(struct pack_desc *p, int count, int subcount)
280 if (!p->format || !p->base) {
284 i = count * getlen(p->format);
286 i += subcount * getlen(p->subformat);
288 p->structbuf = p->base;
292 p->curpos = p->format;
298 * This is the old error code we used. Aparently
299 * WinNT/2k systems return ERRbuftoosmall (2123) and
300 * OS/2 needs this. I'm leaving this here so we can revert
303 p->errcode = ERRmoredata;
305 p->errcode = ERRbuftoosmall;
308 p->errcode = NERR_Success;
312 p->stringbuf = p->base + i;
314 return (p->errcode == NERR_Success);
317 static int package(struct pack_desc *p, ...)
320 int needed=0, stringneeded;
321 const char *str=NULL;
322 int is_string=0, stringused;
329 p->curpos = p->format;
331 p->curpos = p->subformat;
336 str = va_arg(args,char*);
337 SMB_ASSERT(strncmp(str,p->curpos,strlen(str)) == 0);
346 switch( *p->curpos++ ) {
347 case 'W': /* word (2 byte) */
349 temp = va_arg(args,int);
350 if (p->buflen >= needed) {
351 SSVAL(p->structbuf,0,temp);
354 case 'K': /* status word? (2 byte) */
356 temp = va_arg(args,int);
357 if (p->buflen >= needed) {
358 SSVAL(p->structbuf,0,temp);
361 case 'N': /* count of substructures (word) at end */
363 p->subcount = va_arg(args,int);
364 if (p->buflen >= needed) {
365 SSVAL(p->structbuf,0,p->subcount);
368 case 'D': /* double word (4 byte) */
370 temp = va_arg(args,int);
371 if (p->buflen >= needed) {
372 SIVAL(p->structbuf,0,temp);
375 case 'B': /* byte (with optional counter) */
376 needed = get_counter(&p->curpos);
378 char *s = va_arg(args,char*);
379 if (p->buflen >= needed) {
380 StrnCpy(p->structbuf,s?s:"",needed-1);
384 case 'z': /* offset to zero terminated string (4 byte) */
385 str = va_arg(args,char*);
386 stringneeded = (str ? strlen(str)+1 : 0);
389 case 'l': /* offset to user data (4 byte) */
390 str = va_arg(args,char*);
391 stringneeded = va_arg(args,int);
394 case 'b': /* offset to data (with counter) (4 byte) */
395 str = va_arg(args,char*);
396 stringneeded = get_counter(&p->curpos);
402 if (stringneeded >= 0) {
404 if (p->buflen >= needed) {
405 stringused = stringneeded;
406 if (stringused > p->stringlen) {
407 stringused = (is_string ? p->stringlen : 0);
408 if (p->errcode == NERR_Success) {
409 p->errcode = ERRmoredata;
413 SIVAL(p->structbuf,0,0);
415 SIVAL(p->structbuf,0,PTR_DIFF(p->stringbuf,p->base));
416 memcpy(p->stringbuf,str?str:"",stringused);
418 p->stringbuf[stringused-1] = '\0';
420 p->stringbuf += stringused;
421 p->stringlen -= stringused;
422 p->usedlen += stringused;
425 p->neededlen += stringneeded;
428 p->neededlen += needed;
429 if (p->buflen >= needed) {
430 p->structbuf += needed;
432 p->usedlen += needed;
434 if (p->errcode == NERR_Success) {
435 p->errcode = ERRmoredata;
442 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
443 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
445 #define PACK(desc,t,v) package(desc,v)
446 #define PACKl(desc,t,v,l) package(desc,v,l)
449 static void PACKI(struct pack_desc* desc, const char *t,int v)
454 static void PACKS(struct pack_desc* desc,const char *t,const char *v)
459 /****************************************************************************
461 ****************************************************************************/
463 static void PackDriverData(struct pack_desc* desc)
465 char drivdata[4+4+32];
466 SIVAL(drivdata,0,sizeof drivdata); /* cb */
467 SIVAL(drivdata,4,1000); /* lVersion */
468 memset(drivdata+8,0,32); /* szDeviceName */
469 push_ascii(drivdata+8,"NULL",32, STR_TERMINATE);
470 PACKl(desc,"l",drivdata,sizeof drivdata); /* pDriverData */
473 static int check_printq_info(struct pack_desc* desc,
474 unsigned int uLevel, char *id1, char *id2)
476 desc->subformat = NULL;
479 desc->format = "B13";
482 desc->format = "B13BWWWzzzzzWW";
485 desc->format = "B13BWWWzzzzzWN";
486 desc->subformat = "WB21BB16B10zWWzDDz";
489 desc->format = "zWWWWzzzzWWzzl";
492 desc->format = "zWWWWzzzzWNzzl";
493 desc->subformat = "WWzWWDDzz";
502 desc->format = "WzzzzzzzzN";
503 desc->subformat = "z";
506 DEBUG(0,("check_printq_info: invalid level %d\n",
510 if (id1 == NULL || strcmp(desc->format,id1) != 0) {
511 DEBUG(0,("check_printq_info: invalid format %s\n",
512 id1 ? id1 : "<NULL>" ));
515 if (desc->subformat && (id2 == NULL || strcmp(desc->subformat,id2) != 0)) {
516 DEBUG(0,("check_printq_info: invalid subformat %s\n",
517 id2 ? id2 : "<NULL>" ));
524 #define RAP_JOB_STATUS_QUEUED 0
525 #define RAP_JOB_STATUS_PAUSED 1
526 #define RAP_JOB_STATUS_SPOOLING 2
527 #define RAP_JOB_STATUS_PRINTING 3
528 #define RAP_JOB_STATUS_PRINTED 4
530 #define RAP_QUEUE_STATUS_PAUSED 1
531 #define RAP_QUEUE_STATUS_ERROR 2
533 /* turn a print job status into a on the wire status
535 static int printj_status(int v)
539 return RAP_JOB_STATUS_QUEUED;
541 return RAP_JOB_STATUS_PAUSED;
543 return RAP_JOB_STATUS_SPOOLING;
545 return RAP_JOB_STATUS_PRINTING;
550 /* turn a print queue status into a on the wire status
552 static int printq_status(int v)
558 return RAP_QUEUE_STATUS_PAUSED;
560 return RAP_QUEUE_STATUS_ERROR;
563 static void fill_printjob_info(connection_struct *conn, int snum, int uLevel,
564 struct pack_desc *desc,
565 print_queue_struct *queue, int n)
567 time_t t = queue->time;
569 /* the client expects localtime */
570 t -= get_time_zone(t);
572 PACKI(desc,"W",pjobid_to_rap(lp_const_servicename(snum),queue->job)); /* uJobId */
574 PACKS(desc,"B21",queue->fs_user); /* szUserName */
575 PACKS(desc,"B",""); /* pad */
576 PACKS(desc,"B16",""); /* szNotifyName */
577 PACKS(desc,"B10","PM_Q_RAW"); /* szDataType */
578 PACKS(desc,"z",""); /* pszParms */
579 PACKI(desc,"W",n+1); /* uPosition */
580 PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */
581 PACKS(desc,"z",""); /* pszStatus */
582 PACKI(desc,"D",t); /* ulSubmitted */
583 PACKI(desc,"D",queue->size); /* ulSize */
584 PACKS(desc,"z",queue->fs_file); /* pszComment */
586 if (uLevel == 2 || uLevel == 3 || uLevel == 4) {
587 PACKI(desc,"W",queue->priority); /* uPriority */
588 PACKS(desc,"z",queue->fs_user); /* pszUserName */
589 PACKI(desc,"W",n+1); /* uPosition */
590 PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */
591 PACKI(desc,"D",t); /* ulSubmitted */
592 PACKI(desc,"D",queue->size); /* ulSize */
593 PACKS(desc,"z","Samba"); /* pszComment */
594 PACKS(desc,"z",queue->fs_file); /* pszDocument */
596 PACKS(desc,"z",""); /* pszNotifyName */
597 PACKS(desc,"z","PM_Q_RAW"); /* pszDataType */
598 PACKS(desc,"z",""); /* pszParms */
599 PACKS(desc,"z",""); /* pszStatus */
600 PACKS(desc,"z",SERVICE(snum)); /* pszQueue */
601 PACKS(desc,"z","lpd"); /* pszQProcName */
602 PACKS(desc,"z",""); /* pszQProcParms */
603 PACKS(desc,"z","NULL"); /* pszDriverName */
604 PackDriverData(desc); /* pDriverData */
605 PACKS(desc,"z",""); /* pszPrinterName */
606 } else if (uLevel == 4) { /* OS2 */
607 PACKS(desc,"z",""); /* pszSpoolFileName */
608 PACKS(desc,"z",""); /* pszPortName */
609 PACKS(desc,"z",""); /* pszStatus */
610 PACKI(desc,"D",0); /* ulPagesSpooled */
611 PACKI(desc,"D",0); /* ulPagesSent */
612 PACKI(desc,"D",0); /* ulPagesPrinted */
613 PACKI(desc,"D",0); /* ulTimePrinted */
614 PACKI(desc,"D",0); /* ulExtendJobStatus */
615 PACKI(desc,"D",0); /* ulStartPage */
616 PACKI(desc,"D",0); /* ulEndPage */
621 /********************************************************************
622 Return a driver name given an snum.
623 Returns True if from tdb, False otherwise.
624 ********************************************************************/
626 static bool get_driver_name(int snum, char **pp_drivername)
628 NT_PRINTER_INFO_LEVEL *info = NULL;
631 get_a_printer (NULL, &info, 2, lp_servicename(snum));
633 *pp_drivername = talloc_strdup(talloc_tos(),
634 info->info_2->drivername);
636 free_a_printer(&info, 2);
637 if (!*pp_drivername) {
645 /********************************************************************
646 Respond to the DosPrintQInfo command with a level of 52
647 This is used to get printer driver information for Win9x clients
648 ********************************************************************/
649 static void fill_printq_info_52(connection_struct *conn, int snum,
650 struct pack_desc* desc, int count )
654 struct spoolss_DriverInfo8 *driver = NULL;
655 NT_PRINTER_INFO_LEVEL *printer = NULL;
657 if ( !W_ERROR_IS_OK(get_a_printer( NULL, &printer, 2, lp_servicename(snum))) ) {
658 DEBUG(3,("fill_printq_info_52: Failed to lookup printer [%s]\n",
659 lp_servicename(snum)));
663 if (!W_ERROR_IS_OK(get_a_printer_driver(talloc_tos(), &driver, printer->info_2->drivername,
666 DEBUG(3,("fill_printq_info_52: Failed to lookup driver [%s]\n",
667 printer->info_2->drivername));
671 trim_string((char *)driver->driver_path, "\\print$\\WIN40\\0\\", 0);
672 trim_string((char *)driver->data_file, "\\print$\\WIN40\\0\\", 0);
673 trim_string((char *)driver->help_file, "\\print$\\WIN40\\0\\", 0);
675 PACKI(desc, "W", 0x0400); /* don't know */
676 PACKS(desc, "z", driver->driver_name); /* long printer name */
677 PACKS(desc, "z", driver->driver_path); /* Driverfile Name */
678 PACKS(desc, "z", driver->data_file); /* Datafile name */
679 PACKS(desc, "z", driver->monitor_name); /* language monitor */
681 fstrcpy(location, "\\\\%L\\print$\\WIN40\\0");
682 standard_sub_basic( "", "", location, sizeof(location)-1 );
683 PACKS(desc,"z", location); /* share to retrieve files */
685 PACKS(desc,"z", driver->default_datatype); /* default data type */
686 PACKS(desc,"z", driver->help_file); /* helpfile name */
687 PACKS(desc,"z", driver->driver_path); /* driver name */
689 DEBUG(3,("Printer Driver Name: %s:\n",driver->driver_name));
690 DEBUG(3,("Driver: %s:\n",driver->driver_path));
691 DEBUG(3,("Data File: %s:\n",driver->data_file));
692 DEBUG(3,("Language Monitor: %s:\n",driver->monitor_name));
693 DEBUG(3,("Driver Location: %s:\n",location));
694 DEBUG(3,("Data Type: %s:\n",driver->default_datatype));
695 DEBUG(3,("Help File: %s:\n",driver->help_file));
696 PACKI(desc,"N",count); /* number of files to copy */
698 for ( i=0; i<count && driver->dependent_files && *driver->dependent_files[i]; i++)
700 trim_string((char *)driver->dependent_files[i], "\\print$\\WIN40\\0\\", 0);
701 PACKS(desc,"z",driver->dependent_files[i]); /* driver files to copy */
702 DEBUG(3,("Dependent File: %s:\n", driver->dependent_files[i]));
707 DEBUG(3,("fill_printq_info_52: file count specified by client [%d] != number of dependent files [%i]\n",
710 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n", SERVICE(snum),i));
712 desc->errcode=NERR_Success;
716 DEBUG(3,("fill_printq_info: Can't supply driver files\n"));
717 desc->errcode=NERR_notsupported;
721 free_a_printer( &printer, 2 );
723 free_a_printer_driver(driver);
727 static void fill_printq_info(connection_struct *conn, int snum, int uLevel,
728 struct pack_desc* desc,
729 int count, print_queue_struct* queue,
730 print_status_struct* status)
735 PACKS(desc,"B13",SERVICE(snum));
740 PACKS(desc,"z",Expand(conn,snum,SERVICE(snum)));
743 PACKI(desc,"K",printq_status(status->status));
747 if (uLevel == 1 || uLevel == 2) {
748 PACKS(desc,"B",""); /* alignment */
749 PACKI(desc,"W",5); /* priority */
750 PACKI(desc,"W",0); /* start time */
751 PACKI(desc,"W",0); /* until time */
752 PACKS(desc,"z",""); /* pSepFile */
753 PACKS(desc,"z","lpd"); /* pPrProc */
754 PACKS(desc,"z",SERVICE(snum)); /* pDestinations */
755 PACKS(desc,"z",""); /* pParms */
757 PACKS(desc,"z","UNKNOWN PRINTER");
758 PACKI(desc,"W",LPSTAT_ERROR);
760 else if (!status || !status->message[0]) {
761 PACKS(desc,"z",Expand(conn,snum,lp_comment(snum)));
762 PACKI(desc,"W",LPSTAT_OK); /* status */
764 PACKS(desc,"z",status->message);
765 PACKI(desc,"W",printq_status(status->status)); /* status */
767 PACKI(desc,(uLevel == 1 ? "W" : "N"),count);
770 if (uLevel == 3 || uLevel == 4) {
771 char *drivername = NULL;
773 PACKI(desc,"W",5); /* uPriority */
774 PACKI(desc,"W",0); /* uStarttime */
775 PACKI(desc,"W",0); /* uUntiltime */
776 PACKI(desc,"W",5); /* pad1 */
777 PACKS(desc,"z",""); /* pszSepFile */
778 PACKS(desc,"z","WinPrint"); /* pszPrProc */
779 PACKS(desc,"z",NULL); /* pszParms */
780 PACKS(desc,"z",NULL); /* pszComment - don't ask.... JRA */
781 /* "don't ask" that it's done this way to fix corrupted
782 Win9X/ME printer comments. */
784 PACKI(desc,"W",LPSTAT_OK); /* fsStatus */
786 PACKI(desc,"W",printq_status(status->status)); /* fsStatus */
788 PACKI(desc,(uLevel == 3 ? "W" : "N"),count); /* cJobs */
789 PACKS(desc,"z",SERVICE(snum)); /* pszPrinters */
790 get_driver_name(snum,&drivername);
794 PACKS(desc,"z",drivername); /* pszDriverName */
795 PackDriverData(desc); /* pDriverData */
798 if (uLevel == 2 || uLevel == 4) {
800 for (i=0;i<count;i++)
801 fill_printjob_info(conn,snum,uLevel == 2 ? 1 : 2,desc,&queue[i],i);
805 fill_printq_info_52( conn, snum, desc, count );
808 /* This function returns the number of files for a given driver */
809 static int get_printerdrivernumber(int snum)
812 struct spoolss_DriverInfo8 *driver;
813 NT_PRINTER_INFO_LEVEL *printer = NULL;
817 if ( !W_ERROR_IS_OK(get_a_printer( NULL, &printer, 2, lp_servicename(snum))) ) {
818 DEBUG(3,("get_printerdrivernumber: Failed to lookup printer [%s]\n",
819 lp_servicename(snum)));
823 if (!W_ERROR_IS_OK(get_a_printer_driver(talloc_tos(), &driver, printer->info_2->drivername,
826 DEBUG(3,("get_printerdrivernumber: Failed to lookup driver [%s]\n",
827 printer->info_2->drivername));
831 /* count the number of files */
832 while (driver->dependent_files && *driver->dependent_files[result])
836 free_a_printer( &printer, 2 );
838 free_a_printer_driver(driver);
843 static bool api_DosPrintQGetInfo(connection_struct *conn, uint16 vuid,
844 char *param, int tpscnt,
845 char *data, int tdscnt,
846 int mdrcnt,int mprcnt,
847 char **rdata,char **rparam,
848 int *rdata_len,int *rparam_len)
850 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
851 char *str2 = skip_string(param,tpscnt,str1);
852 char *p = skip_string(param,tpscnt,str2);
858 struct pack_desc desc;
859 print_queue_struct *queue=NULL;
860 print_status_struct status;
863 if (!str1 || !str2 || !p) {
866 memset((char *)&status,'\0',sizeof(status));
867 memset((char *)&desc,'\0',sizeof(desc));
869 p = skip_string(param,tpscnt,p);
873 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
874 str3 = get_safe_str_ptr(param,tpscnt,p,4);
875 /* str3 may be null here and is checked in check_printq_info(). */
877 /* remove any trailing username */
878 if ((p = strchr_m(QueueName,'%')))
881 DEBUG(3,("api_DosPrintQGetInfo uLevel=%d name=%s\n",uLevel,QueueName));
883 /* check it's a supported varient */
884 if (!prefix_ok(str1,"zWrLh"))
886 if (!check_printq_info(&desc,uLevel,str2,str3)) {
888 * Patch from Scott Moomaw <scott@bridgewater.edu>
889 * to return the 'invalid info level' error if an
890 * unknown level was requested.
894 *rparam = smb_realloc_limit(*rparam,*rparam_len);
898 SSVALS(*rparam,0,ERRunknownlevel);
904 snum = find_service(QueueName);
905 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
909 count = get_printerdrivernumber(snum);
910 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count));
912 count = print_queue_status(snum, &queue,&status);
916 *rdata = smb_realloc_limit(*rdata,mdrcnt);
922 desc.buflen = mdrcnt;
925 * Don't return data but need to get correct length
926 * init_package will return wrong size if buflen=0
928 desc.buflen = getlen(desc.format);
929 desc.base = tmpdata = (char *) SMB_MALLOC (desc.buflen);
932 if (init_package(&desc,1,count)) {
933 desc.subcount = count;
934 fill_printq_info(conn,snum,uLevel,&desc,count,queue,&status);
937 *rdata_len = desc.usedlen;
940 * We must set the return code to ERRbuftoosmall
941 * in order to support lanman style printing with Win NT/2k
944 if (!mdrcnt && lp_disable_spoolss())
945 desc.errcode = ERRbuftoosmall;
947 *rdata_len = desc.usedlen;
949 *rparam = smb_realloc_limit(*rparam,*rparam_len);
955 SSVALS(*rparam,0,desc.errcode);
957 SSVAL(*rparam,4,desc.neededlen);
959 DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode));
967 /****************************************************************************
968 View list of all print jobs on all queues.
969 ****************************************************************************/
971 static bool api_DosPrintQEnum(connection_struct *conn, uint16 vuid,
972 char *param, int tpscnt,
973 char *data, int tdscnt,
974 int mdrcnt, int mprcnt,
975 char **rdata, char** rparam,
976 int *rdata_len, int *rparam_len)
978 char *param_format = get_safe_str_ptr(param,tpscnt,param,2);
979 char *output_format1 = skip_string(param,tpscnt,param_format);
980 char *p = skip_string(param,tpscnt,output_format1);
981 unsigned int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
982 char *output_format2 = get_safe_str_ptr(param,tpscnt,p,4);
983 int services = lp_numservices();
985 struct pack_desc desc;
986 print_queue_struct **queue = NULL;
987 print_status_struct *status = NULL;
988 int *subcntarr = NULL;
989 int queuecnt = 0, subcnt = 0, succnt = 0;
991 if (!param_format || !output_format1 || !p) {
995 memset((char *)&desc,'\0',sizeof(desc));
997 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
999 if (!prefix_ok(param_format,"WrLeh")) {
1002 if (!check_printq_info(&desc,uLevel,output_format1,output_format2)) {
1004 * Patch from Scott Moomaw <scott@bridgewater.edu>
1005 * to return the 'invalid info level' error if an
1006 * unknown level was requested.
1010 *rparam = smb_realloc_limit(*rparam,*rparam_len);
1014 SSVALS(*rparam,0,ERRunknownlevel);
1020 for (i = 0; i < services; i++) {
1021 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
1026 if((queue = SMB_MALLOC_ARRAY(print_queue_struct*, queuecnt)) == NULL) {
1027 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
1030 memset(queue,0,queuecnt*sizeof(print_queue_struct*));
1031 if((status = SMB_MALLOC_ARRAY(print_status_struct,queuecnt)) == NULL) {
1032 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
1035 memset(status,0,queuecnt*sizeof(print_status_struct));
1036 if((subcntarr = SMB_MALLOC_ARRAY(int,queuecnt)) == NULL) {
1037 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
1043 for (i = 0; i < services; i++) {
1044 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
1045 subcntarr[n] = print_queue_status(i, &queue[n],&status[n]);
1046 subcnt += subcntarr[n];
1052 *rdata = smb_realloc_limit(*rdata,mdrcnt);
1058 desc.buflen = mdrcnt;
1060 if (init_package(&desc,queuecnt,subcnt)) {
1063 for (i = 0; i < services; i++) {
1064 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
1065 fill_printq_info(conn,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]);
1067 if (desc.errcode == NERR_Success) {
1074 SAFE_FREE(subcntarr);
1076 *rdata_len = desc.usedlen;
1078 *rparam = smb_realloc_limit(*rparam,*rparam_len);
1082 SSVALS(*rparam,0,desc.errcode);
1084 SSVAL(*rparam,4,succnt);
1085 SSVAL(*rparam,6,queuecnt);
1087 for (i = 0; i < queuecnt; i++) {
1089 SAFE_FREE(queue[i]);
1100 SAFE_FREE(subcntarr);
1101 for (i = 0; i < queuecnt; i++) {
1103 SAFE_FREE(queue[i]);
1112 /****************************************************************************
1113 Get info level for a server list query.
1114 ****************************************************************************/
1116 static bool check_server_info(int uLevel, char* id)
1120 if (strcmp(id,"B16") != 0) {
1125 if (strcmp(id,"B16BBDz") != 0) {
1135 struct srv_info_struct {
1143 /*******************************************************************
1144 Get server info lists from the files saved by nmbd. Return the
1146 ******************************************************************/
1148 static int get_server_info(uint32 servertype,
1149 struct srv_info_struct **servers,
1155 bool local_list_only;
1158 lines = file_lines_load(cache_path(SERVER_LIST), NULL, 0, NULL);
1160 DEBUG(4,("Can't open %s - %s\n",cache_path(SERVER_LIST),strerror(errno)));
1164 /* request for everything is code for request all servers */
1165 if (servertype == SV_TYPE_ALL) {
1166 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1169 local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY);
1171 DEBUG(4,("Servertype search: %8x\n",servertype));
1173 for (i=0;lines[i];i++) {
1175 struct srv_info_struct *s;
1176 const char *ptr = lines[i];
1178 TALLOC_CTX *frame = NULL;
1185 if (count == alloced) {
1187 *servers = SMB_REALLOC_ARRAY(*servers,struct srv_info_struct, alloced);
1189 DEBUG(0,("get_server_info: failed to enlarge servers info struct!\n"));
1193 memset((char *)((*servers)+count),'\0',sizeof(**servers)*(alloced-count));
1195 s = &(*servers)[count];
1197 frame = talloc_stackframe();
1199 if (!next_token_talloc(frame,&ptr,&p, NULL)) {
1203 fstrcpy(s->name, p);
1206 if (!next_token_talloc(frame,&ptr, &p, NULL)) {
1212 s->comment[0] = '\0';
1213 if (!next_token_talloc(frame,&ptr, &p, NULL)) {
1217 fstrcpy(s->comment, p);
1218 string_truncate(s->comment, MAX_SERVER_STRING_LENGTH);
1220 s->domain[0] = '\0';
1221 if (!next_token_talloc(frame,&ptr,&p, NULL)) {
1222 /* this allows us to cope with an old nmbd */
1223 fstrcpy(s->domain,lp_workgroup());
1225 fstrcpy(s->domain, p);
1229 if (sscanf(stype,"%X",&s->type) != 1) {
1230 DEBUG(4,("r:host file "));
1234 /* Filter the servers/domains we return based on what was asked for. */
1236 /* Check to see if we are being asked for a local list only. */
1237 if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) {
1238 DEBUG(4,("r: local list only"));
1242 /* doesn't match up: don't want it */
1243 if (!(servertype & s->type)) {
1244 DEBUG(4,("r:serv type "));
1248 if ((servertype & SV_TYPE_DOMAIN_ENUM) !=
1249 (s->type & SV_TYPE_DOMAIN_ENUM)) {
1250 DEBUG(4,("s: dom mismatch "));
1254 if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM)) {
1258 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1259 s->type &= ~SV_TYPE_LOCAL_LIST_ONLY;
1262 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1263 s->name, s->type, s->comment, s->domain));
1264 s->server_added = True;
1267 DEBUG(4,("%20s %8x %25s %15s\n",
1268 s->name, s->type, s->comment, s->domain));
1276 /*******************************************************************
1277 Fill in a server info structure.
1278 ******************************************************************/
1280 static int fill_srv_info(struct srv_info_struct *service,
1281 int uLevel, char **buf, int *buflen,
1282 char **stringbuf, int *stringspace, char *baseaddr)
1305 len = strlen(service->comment)+1;
1309 *buflen = struct_len;
1311 return struct_len + len;
1316 if (*buflen < struct_len) {
1323 p2 = p + struct_len;
1324 l2 = *buflen - struct_len;
1332 push_ascii(p,service->name, MAX_NETBIOSNAME_LEN, STR_TERMINATE);
1336 push_ascii(p,service->name,MAX_NETBIOSNAME_LEN, STR_TERMINATE);
1337 SIVAL(p,18,service->type);
1338 SIVAL(p,22,PTR_DIFF(p2,baseaddr));
1339 len += CopyAndAdvance(&p2,service->comment,&l2);
1344 *buf = p + struct_len;
1345 *buflen -= struct_len;
1356 static int srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
1358 return StrCaseCmp(s1->name,s2->name);
1361 /****************************************************************************
1362 View list of servers available (or possibly domains). The info is
1363 extracted from lists saved by nmbd on the local host.
1364 ****************************************************************************/
1366 static bool api_RNetServerEnum2(connection_struct *conn, uint16 vuid,
1367 char *param, int tpscnt,
1368 char *data, int tdscnt,
1369 int mdrcnt, int mprcnt, char **rdata,
1370 char **rparam, int *rdata_len, int *rparam_len)
1372 char *str1 = get_safe_str_ptr(param, tpscnt, param, 2);
1373 char *str2 = skip_string(param,tpscnt,str1);
1374 char *p = skip_string(param,tpscnt,str2);
1375 int uLevel = get_safe_SVAL(param, tpscnt, p, 0, -1);
1376 int buf_len = get_safe_SVAL(param,tpscnt, p, 2, 0);
1377 uint32 servertype = get_safe_IVAL(param,tpscnt,p,4, 0);
1379 int data_len, fixed_len, string_len;
1380 int f_len = 0, s_len = 0;
1381 struct srv_info_struct *servers=NULL;
1382 int counted=0,total=0;
1385 bool domain_request;
1388 if (!str1 || !str2 || !p) {
1392 /* If someone sets all the bits they don't really mean to set
1393 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1396 if (servertype == SV_TYPE_ALL) {
1397 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1400 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1401 any other bit (they may just set this bit on its own) they
1402 want all the locally seen servers. However this bit can be
1403 set on its own so set the requested servers to be
1404 ALL - DOMAIN_ENUM. */
1406 if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM)) {
1407 servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
1410 domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
1411 local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
1415 if (!prefix_ok(str1,"WrLehD")) {
1418 if (!check_server_info(uLevel,str2)) {
1422 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1423 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1424 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1426 if (strcmp(str1, "WrLehDz") == 0) {
1427 if (skip_string(param,tpscnt,p) == NULL) {
1430 pull_ascii_fstring(domain, p);
1432 fstrcpy(domain, lp_workgroup());
1435 DEBUG(4, ("domain [%s]\n", domain));
1437 if (lp_browse_list()) {
1438 total = get_server_info(servertype,&servers,domain);
1441 data_len = fixed_len = string_len = 0;
1444 TYPESAFE_QSORT(servers, total, srv_comp);
1447 char *lastname=NULL;
1449 for (i=0;i<total;i++) {
1450 struct srv_info_struct *s = &servers[i];
1452 if (lastname && strequal(lastname,s->name)) {
1456 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1457 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1458 i, s->name, s->type, s->comment, s->domain));
1460 if (data_len < buf_len) {
1463 string_len += s_len;
1470 *rdata_len = fixed_len + string_len;
1471 *rdata = smb_realloc_limit(*rdata,*rdata_len);
1476 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1482 char *lastname=NULL;
1483 int count2 = counted;
1485 for (i = 0; i < total && count2;i++) {
1486 struct srv_info_struct *s = &servers[i];
1488 if (lastname && strequal(lastname,s->name)) {
1492 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1493 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1494 i, s->name, s->type, s->comment, s->domain));
1500 *rparam = smb_realloc_limit(*rparam,*rparam_len);
1504 SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata));
1506 SSVAL(*rparam,4,counted);
1507 SSVAL(*rparam,6,counted+missed);
1511 DEBUG(3,("NetServerEnum2 domain = %s uLevel=%d counted=%d total=%d\n",
1512 domain,uLevel,counted,counted+missed));
1517 static int srv_name_match(const char *n1, const char *n2)
1520 * [MS-RAP] footnote <88> for Section 3.2.5.15 says:
1522 * In Windows, FirstNameToReturn need not be an exact match:
1523 * the server will return a list of servers that exist on
1524 * the network greater than or equal to the FirstNameToReturn.
1526 int ret = StrCaseCmp(n1, n2);
1535 static bool api_RNetServerEnum3(connection_struct *conn, uint16 vuid,
1536 char *param, int tpscnt,
1537 char *data, int tdscnt,
1538 int mdrcnt, int mprcnt, char **rdata,
1539 char **rparam, int *rdata_len, int *rparam_len)
1541 char *str1 = get_safe_str_ptr(param, tpscnt, param, 2);
1542 char *str2 = skip_string(param,tpscnt,str1);
1543 char *p = skip_string(param,tpscnt,str2);
1544 int uLevel = get_safe_SVAL(param, tpscnt, p, 0, -1);
1545 int buf_len = get_safe_SVAL(param,tpscnt, p, 2, 0);
1546 uint32 servertype = get_safe_IVAL(param,tpscnt,p,4, 0);
1548 int data_len, fixed_len, string_len;
1549 int f_len = 0, s_len = 0;
1550 struct srv_info_struct *servers=NULL;
1551 int counted=0,first=0,total=0;
1555 bool domain_request;
1558 if (!str1 || !str2 || !p) {
1562 /* If someone sets all the bits they don't really mean to set
1563 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1566 if (servertype == SV_TYPE_ALL) {
1567 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1570 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1571 any other bit (they may just set this bit on its own) they
1572 want all the locally seen servers. However this bit can be
1573 set on its own so set the requested servers to be
1574 ALL - DOMAIN_ENUM. */
1576 if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM)) {
1577 servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
1580 domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
1581 local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
1585 if (strcmp(str1, "WrLehDzz") != 0) {
1588 if (!check_server_info(uLevel,str2)) {
1592 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1593 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1594 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1596 if (skip_string(param,tpscnt,p) == NULL) {
1599 pull_ascii_fstring(domain, p);
1600 if (domain[0] == '\0') {
1601 fstrcpy(domain, lp_workgroup());
1603 p = skip_string(param,tpscnt,p);
1604 if (skip_string(param,tpscnt,p) == NULL) {
1607 pull_ascii_fstring(first_name, p);
1609 DEBUG(4, ("domain: '%s' first_name: '%s'\n",
1610 domain, first_name));
1612 if (lp_browse_list()) {
1613 total = get_server_info(servertype,&servers,domain);
1616 data_len = fixed_len = string_len = 0;
1619 TYPESAFE_QSORT(servers, total, srv_comp);
1621 if (first_name[0] != '\0') {
1622 struct srv_info_struct *first_server = NULL;
1624 BINARY_ARRAY_SEARCH(servers, total, name, first_name,
1625 srv_name_match, first_server);
1627 first = PTR_DIFF(first_server, servers) / sizeof(*servers);
1629 * The binary search may not find the exact match
1630 * so we need to search backward to find the first match
1632 * This implements the strange matching windows
1633 * implements. (see the comment in srv_name_match().
1637 ret = StrCaseCmp(first_name,
1638 servers[first-1].name);
1645 /* we should return no entries */
1651 char *lastname=NULL;
1653 for (i=first;i<total;i++) {
1654 struct srv_info_struct *s = &servers[i];
1656 if (lastname && strequal(lastname,s->name)) {
1660 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1661 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1662 i, s->name, s->type, s->comment, s->domain));
1664 if (data_len < buf_len) {
1667 string_len += s_len;
1674 *rdata_len = fixed_len + string_len;
1675 *rdata = smb_realloc_limit(*rdata,*rdata_len);
1680 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1686 char *lastname=NULL;
1687 int count2 = counted;
1689 for (i = first; i < total && count2;i++) {
1690 struct srv_info_struct *s = &servers[i];
1692 if (lastname && strequal(lastname,s->name)) {
1696 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1697 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1698 i, s->name, s->type, s->comment, s->domain));
1704 *rparam = smb_realloc_limit(*rparam,*rparam_len);
1708 SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata));
1710 SSVAL(*rparam,4,counted);
1711 SSVAL(*rparam,6,counted+missed);
1713 DEBUG(3,("NetServerEnum3 domain = %s uLevel=%d first=%d[%s => %s] counted=%d total=%d\n",
1714 domain,uLevel,first,first_name,
1715 first < total ? servers[first].name : "",
1716 counted,counted+missed));
1723 /****************************************************************************
1724 command 0x34 - suspected of being a "Lookup Names" stub api
1725 ****************************************************************************/
1727 static bool api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid,
1728 char *param, int tpscnt,
1729 char *data, int tdscnt,
1730 int mdrcnt, int mprcnt, char **rdata,
1731 char **rparam, int *rdata_len, int *rparam_len)
1733 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
1734 char *str2 = skip_string(param,tpscnt,str1);
1735 char *p = skip_string(param,tpscnt,str2);
1736 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
1737 int buf_len = get_safe_SVAL(param,tpscnt,p,2,0);
1741 if (!str1 || !str2 || !p) {
1745 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1746 str1, str2, p, uLevel, buf_len));
1748 if (!prefix_ok(str1,"zWrLeh")) {
1755 *rparam = smb_realloc_limit(*rparam,*rparam_len);
1760 SSVAL(*rparam,0,0x08AC); /* informational warning message */
1762 SSVAL(*rparam,4,counted);
1763 SSVAL(*rparam,6,counted+missed);
1768 /****************************************************************************
1769 get info about a share
1770 ****************************************************************************/
1772 static bool check_share_info(int uLevel, char* id)
1776 if (strcmp(id,"B13") != 0) {
1781 /* Level-2 descriptor is allowed (and ignored) */
1782 if (strcmp(id,"B13BWz") != 0 &&
1783 strcmp(id,"B13BWzWWWzB9B") != 0) {
1788 if (strcmp(id,"B13BWzWWWzB9B") != 0) {
1793 if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) {
1803 static int fill_share_info(connection_struct *conn, int snum, int uLevel,
1804 char** buf, int* buflen,
1805 char** stringbuf, int* stringspace, char* baseaddr)
1834 len += StrlenExpanded(conn,snum,lp_comment(snum));
1837 len += strlen(lp_pathname(snum)) + 1;
1840 *buflen = struct_len;
1845 return struct_len + len;
1850 if ((*buflen) < struct_len) {
1858 p2 = p + struct_len;
1859 l2 = (*buflen) - struct_len;
1866 push_ascii(p,lp_servicename(snum),13, STR_TERMINATE);
1872 type = STYPE_DISKTREE;
1873 if (lp_print_ok(snum)) {
1874 type = STYPE_PRINTQ;
1876 if (strequal("IPC",lp_fstype(snum))) {
1879 SSVAL(p,14,type); /* device type */
1880 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1881 len += CopyExpanded(conn,snum,&p2,lp_comment(snum),&l2);
1885 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1886 SSVALS(p,22,-1); /* max uses */
1887 SSVAL(p,24,1); /* current uses */
1888 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1889 len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1890 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1894 memset(p+40,0,SHPWLEN+2);
1905 (*buf) = p + struct_len;
1906 (*buflen) -= struct_len;
1908 (*stringspace) = l2;
1917 static bool api_RNetShareGetInfo(connection_struct *conn,uint16 vuid,
1918 char *param, int tpscnt,
1919 char *data, int tdscnt,
1920 int mdrcnt,int mprcnt,
1921 char **rdata,char **rparam,
1922 int *rdata_len,int *rparam_len)
1924 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
1925 char *str2 = skip_string(param,tpscnt,str1);
1926 char *netname = skip_string(param,tpscnt,str2);
1927 char *p = skip_string(param,tpscnt,netname);
1928 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
1931 if (!str1 || !str2 || !netname || !p) {
1935 snum = find_service(netname);
1940 /* check it's a supported varient */
1941 if (!prefix_ok(str1,"zWrLh")) {
1944 if (!check_share_info(uLevel,str2)) {
1948 *rdata = smb_realloc_limit(*rdata,mdrcnt);
1953 *rdata_len = fill_share_info(conn,snum,uLevel,&p,&mdrcnt,0,0,0);
1954 if (*rdata_len < 0) {
1959 *rparam = smb_realloc_limit(*rparam,*rparam_len);
1963 SSVAL(*rparam,0,NERR_Success);
1964 SSVAL(*rparam,2,0); /* converter word */
1965 SSVAL(*rparam,4,*rdata_len);
1970 /****************************************************************************
1971 View the list of available shares.
1973 This function is the server side of the NetShareEnum() RAP call.
1974 It fills the return buffer with share names and share comments.
1975 Note that the return buffer normally (in all known cases) allows only
1976 twelve byte strings for share names (plus one for a nul terminator).
1977 Share names longer than 12 bytes must be skipped.
1978 ****************************************************************************/
1980 static bool api_RNetShareEnum( connection_struct *conn, uint16 vuid,
1981 char *param, int tpscnt,
1982 char *data, int tdscnt,
1990 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
1991 char *str2 = skip_string(param,tpscnt,str1);
1992 char *p = skip_string(param,tpscnt,str2);
1993 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
1994 int buf_len = get_safe_SVAL(param,tpscnt,p,2,0);
1997 int total=0,counted=0;
1998 bool missed = False;
2000 int data_len, fixed_len, string_len;
2001 int f_len = 0, s_len = 0;
2003 if (!str1 || !str2 || !p) {
2007 if (!prefix_ok(str1,"WrLeh")) {
2010 if (!check_share_info(uLevel,str2)) {
2014 /* Ensure all the usershares are loaded. */
2016 load_registry_shares();
2017 count = load_usershare_shares();
2020 data_len = fixed_len = string_len = 0;
2021 for (i=0;i<count;i++) {
2022 fstring servicename_dos;
2023 if (!(lp_browseable(i) && lp_snum_ok(i))) {
2026 push_ascii_fstring(servicename_dos, lp_servicename(i));
2027 /* Maximum name length = 13. */
2028 if( lp_browseable( i ) && lp_snum_ok( i ) && (strlen(servicename_dos) < 13)) {
2030 data_len += fill_share_info(conn,i,uLevel,0,&f_len,0,&s_len,0);
2031 if (data_len < buf_len) {
2034 string_len += s_len;
2041 *rdata_len = fixed_len + string_len;
2042 *rdata = smb_realloc_limit(*rdata,*rdata_len);
2047 p2 = (*rdata) + fixed_len; /* auxiliary data (strings) will go here */
2052 for( i = 0; i < count; i++ ) {
2053 fstring servicename_dos;
2054 if (!(lp_browseable(i) && lp_snum_ok(i))) {
2058 push_ascii_fstring(servicename_dos, lp_servicename(i));
2059 if (lp_browseable(i) && lp_snum_ok(i) && (strlen(servicename_dos) < 13)) {
2060 if (fill_share_info( conn,i,uLevel,&p,&f_len,&p2,&s_len,*rdata ) < 0) {
2067 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2071 SSVAL(*rparam,0,missed ? ERRmoredata : NERR_Success);
2073 SSVAL(*rparam,4,counted);
2074 SSVAL(*rparam,6,total);
2076 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
2077 counted,total,uLevel,
2078 buf_len,*rdata_len,mdrcnt));
2083 /****************************************************************************
2085 ****************************************************************************/
2087 static bool api_RNetShareAdd(connection_struct *conn,uint16 vuid,
2088 char *param, int tpscnt,
2089 char *data, int tdscnt,
2090 int mdrcnt,int mprcnt,
2091 char **rdata,char **rparam,
2092 int *rdata_len,int *rparam_len)
2094 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2095 char *str2 = skip_string(param,tpscnt,str1);
2096 char *p = skip_string(param,tpscnt,str2);
2097 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
2100 char *pathname = NULL;
2101 char *command, *cmdname;
2102 unsigned int offset;
2105 size_t converted_size;
2107 if (!str1 || !str2 || !p) {
2111 /* check it's a supported varient */
2112 if (!prefix_ok(str1,RAP_WShareAdd_REQ)) {
2115 if (!check_share_info(uLevel,str2)) {
2122 /* Do we have a string ? */
2123 if (skip_string(data,mdrcnt,data) == NULL) {
2126 pull_ascii_fstring(sharename,data);
2127 snum = find_service(sharename);
2128 if (snum >= 0) { /* already exists */
2137 /* only support disk share adds */
2138 if (SVAL(data,14)!=STYPE_DISKTREE) {
2142 offset = IVAL(data, 16);
2143 if (offset >= mdrcnt) {
2144 res = ERRinvalidparam;
2148 /* Do we have a string ? */
2149 if (skip_string(data,mdrcnt,data+offset) == NULL) {
2152 pull_ascii_fstring(comment, offset? (data+offset) : "");
2154 offset = IVAL(data, 26);
2156 if (offset >= mdrcnt) {
2157 res = ERRinvalidparam;
2161 /* Do we have a string ? */
2162 if (skip_string(data,mdrcnt,data+offset) == NULL) {
2166 if (!pull_ascii_talloc(talloc_tos(), &pathname,
2167 offset ? (data+offset) : "", &converted_size))
2169 DEBUG(0,("api_RNetShareAdd: pull_ascii_talloc failed: %s",
2177 string_replace(sharename, '"', ' ');
2178 string_replace(pathname, '"', ' ');
2179 string_replace(comment, '"', ' ');
2181 cmdname = lp_add_share_cmd();
2183 if (!cmdname || *cmdname == '\0') {
2187 if (asprintf(&command, "%s \"%s\" \"%s\" \"%s\" \"%s\"",
2188 lp_add_share_cmd(), get_dyn_CONFIGFILE(), sharename,
2189 pathname, comment) == -1) {
2193 DEBUG(10,("api_RNetShareAdd: Running [%s]\n", command ));
2195 if ((res = smbrun(command, NULL)) != 0) {
2196 DEBUG(1,("api_RNetShareAdd: Running [%s] returned (%d)\n",
2203 message_send_all(smbd_messaging_context(),
2204 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
2208 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2212 SSVAL(*rparam,0,NERR_Success);
2213 SSVAL(*rparam,2,0); /* converter word */
2214 SSVAL(*rparam,4,*rdata_len);
2222 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2227 SSVAL(*rparam,0,res);
2232 /****************************************************************************
2233 view list of groups available
2234 ****************************************************************************/
2236 static bool api_RNetGroupEnum(connection_struct *conn,uint16 vuid,
2237 char *param, int tpscnt,
2238 char *data, int tdscnt,
2239 int mdrcnt,int mprcnt,
2240 char **rdata,char **rparam,
2241 int *rdata_len,int *rparam_len)
2245 int resume_context, cli_buf_size;
2246 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2247 char *str2 = skip_string(param,tpscnt,str1);
2248 char *p = skip_string(param,tpscnt,str2);
2250 uint32_t num_groups;
2251 uint32_t resume_handle;
2252 struct rpc_pipe_client *samr_pipe;
2253 struct policy_handle samr_handle, domain_handle;
2256 if (!str1 || !str2 || !p) {
2260 if (strcmp(str1,"WrLeh") != 0) {
2265 * W-> resume context (number of users to skip)
2266 * r -> return parameter pointer to receive buffer
2267 * L -> length of receive buffer
2268 * e -> return parameter number of entries
2269 * h -> return parameter total number of users
2272 if (strcmp("B21",str2) != 0) {
2276 status = rpc_pipe_open_internal(
2277 talloc_tos(), &ndr_table_samr.syntax_id, rpc_samr_dispatch,
2278 conn->server_info, &samr_pipe);
2279 if (!NT_STATUS_IS_OK(status)) {
2280 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2281 nt_errstr(status)));
2285 status = rpccli_samr_Connect2(samr_pipe, talloc_tos(), global_myname(),
2286 SAMR_ACCESS_LOOKUP_DOMAIN, &samr_handle);
2287 if (!NT_STATUS_IS_OK(status)) {
2288 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2289 nt_errstr(status)));
2293 status = rpccli_samr_OpenDomain(samr_pipe, talloc_tos(), &samr_handle,
2294 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS,
2295 get_global_sam_sid(), &domain_handle);
2296 if (!NT_STATUS_IS_OK(status)) {
2297 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2298 nt_errstr(status)));
2299 rpccli_samr_Close(samr_pipe, talloc_tos(), &samr_handle);
2303 resume_context = get_safe_SVAL(param,tpscnt,p,0,-1);
2304 cli_buf_size= get_safe_SVAL(param,tpscnt,p,2,0);
2305 DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: "
2306 "%d\n", resume_context, cli_buf_size));
2308 *rdata_len = cli_buf_size;
2309 *rdata = smb_realloc_limit(*rdata,*rdata_len);
2316 errflags = NERR_Success;
2321 struct samr_SamArray *sam_entries;
2322 uint32_t num_entries;
2324 status = rpccli_samr_EnumDomainGroups(samr_pipe, talloc_tos(),
2329 if (!NT_STATUS_IS_OK(status)) {
2330 DEBUG(10, ("rpccli_samr_EnumDomainGroups returned "
2331 "%s\n", nt_errstr(status)));
2335 if (num_entries == 0) {
2336 DEBUG(10, ("rpccli_samr_EnumDomainGroups returned "
2337 "no entries -- done\n"));
2341 for(i=0; i<num_entries; i++) {
2344 name = sam_entries->entries[i].name.string;
2346 if( ((PTR_DIFF(p,*rdata)+21) > *rdata_len) ) {
2347 /* set overflow error */
2348 DEBUG(3,("overflow on entry %d group %s\n", i,
2354 /* truncate the name at 21 chars. */
2356 strlcpy(p, name, 21);
2357 DEBUG(10,("adding entry %d group %s\n", i, p));
2359 p += 5; /* Both NT4 and W2k3SP1 do padding here. No
2364 if (errflags != NERR_Success) {
2368 TALLOC_FREE(sam_entries);
2371 rpccli_samr_Close(samr_pipe, talloc_tos(), &domain_handle);
2372 rpccli_samr_Close(samr_pipe, talloc_tos(), &samr_handle);
2374 *rdata_len = PTR_DIFF(p,*rdata);
2377 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2381 SSVAL(*rparam, 0, errflags);
2382 SSVAL(*rparam, 2, 0); /* converter word */
2383 SSVAL(*rparam, 4, num_groups); /* is this right?? */
2384 SSVAL(*rparam, 6, resume_context+num_groups); /* is this right?? */
2389 /*******************************************************************
2390 Get groups that a user is a member of.
2391 ******************************************************************/
2393 static bool api_NetUserGetGroups(connection_struct *conn,uint16 vuid,
2394 char *param, int tpscnt,
2395 char *data, int tdscnt,
2396 int mdrcnt,int mprcnt,
2397 char **rdata,char **rparam,
2398 int *rdata_len,int *rparam_len)
2400 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2401 char *str2 = skip_string(param,tpscnt,str1);
2402 char *UserName = skip_string(param,tpscnt,str2);
2403 char *p = skip_string(param,tpscnt,UserName);
2404 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
2405 const char *level_string;
2411 struct rpc_pipe_client *samr_pipe;
2412 struct policy_handle samr_handle, domain_handle, user_handle;
2413 struct lsa_String name;
2414 struct lsa_Strings names;
2415 struct samr_Ids type, rid;
2416 struct samr_RidWithAttributeArray *rids;
2419 if (!str1 || !str2 || !UserName || !p) {
2424 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2429 /* check it's a supported varient */
2431 if ( strcmp(str1,"zWrLeh") != 0 )
2436 level_string = "B21";
2442 if (strcmp(level_string,str2) != 0)
2445 *rdata_len = mdrcnt + 1024;
2446 *rdata = smb_realloc_limit(*rdata,*rdata_len);
2451 SSVAL(*rparam,0,NERR_Success);
2452 SSVAL(*rparam,2,0); /* converter word */
2455 endp = *rdata + *rdata_len;
2457 status = rpc_pipe_open_internal(
2458 talloc_tos(), &ndr_table_samr.syntax_id, rpc_samr_dispatch,
2459 conn->server_info, &samr_pipe);
2460 if (!NT_STATUS_IS_OK(status)) {
2461 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2462 nt_errstr(status)));
2466 status = rpccli_samr_Connect2(samr_pipe, talloc_tos(), global_myname(),
2467 SAMR_ACCESS_LOOKUP_DOMAIN, &samr_handle);
2468 if (!NT_STATUS_IS_OK(status)) {
2469 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2470 nt_errstr(status)));
2474 status = rpccli_samr_OpenDomain(samr_pipe, talloc_tos(), &samr_handle,
2475 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
2476 get_global_sam_sid(), &domain_handle);
2477 if (!NT_STATUS_IS_OK(status)) {
2478 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2479 nt_errstr(status)));
2483 name.string = UserName;
2485 status = rpccli_samr_LookupNames(samr_pipe, talloc_tos(),
2486 &domain_handle, 1, &name,
2488 if (!NT_STATUS_IS_OK(status)) {
2489 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2490 nt_errstr(status)));
2494 if (type.ids[0] != SID_NAME_USER) {
2495 DEBUG(10, ("%s is a %s, not a user\n", UserName,
2496 sid_type_lookup(type.ids[0])));
2500 status = rpccli_samr_OpenUser(samr_pipe, talloc_tos(),
2502 SAMR_USER_ACCESS_GET_GROUPS,
2503 rid.ids[0], &user_handle);
2504 if (!NT_STATUS_IS_OK(status)) {
2505 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2506 nt_errstr(status)));
2510 status = rpccli_samr_GetGroupsForUser(samr_pipe, talloc_tos(),
2511 &user_handle, &rids);
2512 if (!NT_STATUS_IS_OK(status)) {
2513 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2514 nt_errstr(status)));
2518 for (i=0; i<rids->count; i++) {
2520 status = rpccli_samr_LookupRids(samr_pipe, talloc_tos(),
2522 1, &rids->rids[i].rid,
2524 if (NT_STATUS_IS_OK(status) && (names.count == 1)) {
2525 strlcpy(p, names.names[0].string, PTR_DIFF(endp,p));
2531 *rdata_len = PTR_DIFF(p,*rdata);
2533 SSVAL(*rparam,4,count); /* is this right?? */
2534 SSVAL(*rparam,6,count); /* is this right?? */
2539 rpccli_samr_Close(samr_pipe, talloc_tos(), &user_handle);
2541 rpccli_samr_Close(samr_pipe, talloc_tos(), &domain_handle);
2543 rpccli_samr_Close(samr_pipe, talloc_tos(), &samr_handle);
2548 /*******************************************************************
2550 ******************************************************************/
2552 static bool api_RNetUserEnum(connection_struct *conn, uint16 vuid,
2553 char *param, int tpscnt,
2554 char *data, int tdscnt,
2555 int mdrcnt,int mprcnt,
2556 char **rdata,char **rparam,
2557 int *rdata_len,int *rparam_len)
2562 int i, resume_context, cli_buf_size;
2563 uint32_t resume_handle;
2565 struct rpc_pipe_client *samr_pipe;
2566 struct policy_handle samr_handle, domain_handle;
2569 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2570 char *str2 = skip_string(param,tpscnt,str1);
2571 char *p = skip_string(param,tpscnt,str2);
2574 if (!str1 || !str2 || !p) {
2578 if (strcmp(str1,"WrLeh") != 0)
2581 * W-> resume context (number of users to skip)
2582 * r -> return parameter pointer to receive buffer
2583 * L -> length of receive buffer
2584 * e -> return parameter number of entries
2585 * h -> return parameter total number of users
2588 resume_context = get_safe_SVAL(param,tpscnt,p,0,-1);
2589 cli_buf_size= get_safe_SVAL(param,tpscnt,p,2,0);
2590 DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n",
2591 resume_context, cli_buf_size));
2594 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2599 /* check it's a supported varient */
2600 if (strcmp("B21",str2) != 0)
2603 *rdata_len = cli_buf_size;
2604 *rdata = smb_realloc_limit(*rdata,*rdata_len);
2610 endp = *rdata + *rdata_len;
2612 status = rpc_pipe_open_internal(
2613 talloc_tos(), &ndr_table_samr.syntax_id, rpc_samr_dispatch,
2614 conn->server_info, &samr_pipe);
2615 if (!NT_STATUS_IS_OK(status)) {
2616 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2617 nt_errstr(status)));
2621 status = rpccli_samr_Connect2(samr_pipe, talloc_tos(), global_myname(),
2622 SAMR_ACCESS_LOOKUP_DOMAIN, &samr_handle);
2623 if (!NT_STATUS_IS_OK(status)) {
2624 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2625 nt_errstr(status)));
2629 status = rpccli_samr_OpenDomain(samr_pipe, talloc_tos(), &samr_handle,
2630 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS,
2631 get_global_sam_sid(), &domain_handle);
2632 if (!NT_STATUS_IS_OK(status)) {
2633 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2634 nt_errstr(status)));
2635 rpccli_samr_Close(samr_pipe, talloc_tos(), &samr_handle);
2639 errflags=NERR_Success;
2644 struct samr_SamArray *sam_entries;
2645 uint32_t num_entries;
2647 status = rpccli_samr_EnumDomainUsers(samr_pipe, talloc_tos(),
2653 if (!NT_STATUS_IS_OK(status)) {
2654 DEBUG(10, ("rpccli_samr_EnumDomainUsers returned "
2655 "%s\n", nt_errstr(status)));
2659 if (num_entries == 0) {
2660 DEBUG(10, ("rpccli_samr_EnumDomainUsers returned "
2661 "no entries -- done\n"));
2665 for (i=0; i<num_entries; i++) {
2668 name = sam_entries->entries[i].name.string;
2670 if(((PTR_DIFF(p,*rdata)+21)<=*rdata_len)
2671 &&(strlen(name)<=21)) {
2672 strlcpy(p,name,PTR_DIFF(endp,p));
2673 DEBUG(10,("api_RNetUserEnum:adding entry %d "
2674 "username %s\n",count_sent,p));
2678 /* set overflow error */
2679 DEBUG(10,("api_RNetUserEnum:overflow on entry %d "
2680 "username %s\n",count_sent,name));
2686 if (errflags != NERR_Success) {
2690 TALLOC_FREE(sam_entries);
2693 rpccli_samr_Close(samr_pipe, talloc_tos(), &domain_handle);
2694 rpccli_samr_Close(samr_pipe, talloc_tos(), &samr_handle);
2696 *rdata_len = PTR_DIFF(p,*rdata);
2698 SSVAL(*rparam,0,errflags);
2699 SSVAL(*rparam,2,0); /* converter word */
2700 SSVAL(*rparam,4,count_sent); /* is this right?? */
2701 SSVAL(*rparam,6,num_users); /* is this right?? */
2706 /****************************************************************************
2707 Get the time of day info.
2708 ****************************************************************************/
2710 static bool api_NetRemoteTOD(connection_struct *conn,uint16 vuid,
2711 char *param, int tpscnt,
2712 char *data, int tdscnt,
2713 int mdrcnt,int mprcnt,
2714 char **rdata,char **rparam,
2715 int *rdata_len,int *rparam_len)
2718 time_t unixdate = time(NULL);
2722 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2728 *rdata = smb_realloc_limit(*rdata,*rdata_len);
2733 SSVAL(*rparam,0,NERR_Success);
2734 SSVAL(*rparam,2,0); /* converter word */
2738 srv_put_dos_date3(p,0,unixdate); /* this is the time that is looked at
2739 by NT in a "net time" operation,
2740 it seems to ignore the one below */
2742 /* the client expects to get localtime, not GMT, in this bit
2743 (I think, this needs testing) */
2744 t = localtime(&unixdate);
2749 SIVAL(p,4,0); /* msecs ? */
2750 SCVAL(p,8,t->tm_hour);
2751 SCVAL(p,9,t->tm_min);
2752 SCVAL(p,10,t->tm_sec);
2753 SCVAL(p,11,0); /* hundredths of seconds */
2754 SSVALS(p,12,get_time_zone(unixdate)/60); /* timezone in minutes from GMT */
2755 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
2756 SCVAL(p,16,t->tm_mday);
2757 SCVAL(p,17,t->tm_mon + 1);
2758 SSVAL(p,18,1900+t->tm_year);
2759 SCVAL(p,20,t->tm_wday);
2764 /****************************************************************************
2765 Set the user password.
2766 *****************************************************************************/
2768 static bool api_SetUserPassword(connection_struct *conn,uint16 vuid,
2769 char *param, int tpscnt,
2770 char *data, int tdscnt,
2771 int mdrcnt,int mprcnt,
2772 char **rdata,char **rparam,
2773 int *rdata_len,int *rparam_len)
2775 char *np = get_safe_str_ptr(param,tpscnt,param,2);
2778 fstring pass1,pass2;
2780 /* Skip 2 strings. */
2781 p = skip_string(param,tpscnt,np);
2782 p = skip_string(param,tpscnt,p);
2788 /* Do we have a string ? */
2789 if (skip_string(param,tpscnt,p) == NULL) {
2792 pull_ascii_fstring(user,p);
2794 p = skip_string(param,tpscnt,p);
2799 memset(pass1,'\0',sizeof(pass1));
2800 memset(pass2,'\0',sizeof(pass2));
2802 * We use 31 here not 32 as we're checking
2803 * the last byte we want to access is safe.
2805 if (!is_offset_safe(param,tpscnt,p,31)) {
2809 memcpy(pass2,p+16,16);
2812 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2819 SSVAL(*rparam,0,NERR_badpass);
2820 SSVAL(*rparam,2,0); /* converter word */
2822 DEBUG(3,("Set password for <%s>\n",user));
2825 * Attempt to verify the old password against smbpasswd entries
2826 * Win98 clients send old and new password in plaintext for this call.
2830 struct auth_serversupplied_info *server_info = NULL;
2831 DATA_BLOB password = data_blob(pass1, strlen(pass1)+1);
2833 if (NT_STATUS_IS_OK(check_plaintext_password(user,password,&server_info))) {
2836 if (NT_STATUS_IS_OK(change_oem_password(server_info->sam_account, pass1, pass2, False, NULL))) {
2837 SSVAL(*rparam,0,NERR_Success);
2841 TALLOC_FREE(server_info);
2843 data_blob_clear_free(&password);
2847 * If the plaintext change failed, attempt
2848 * the old encrypted method. NT will generate this
2849 * after trying the samr method. Note that this
2850 * method is done as a last resort as this
2851 * password change method loses the NT password hash
2852 * and cannot change the UNIX password as no plaintext
2856 if(SVAL(*rparam,0) != NERR_Success) {
2857 struct samu *hnd = NULL;
2859 if (check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &hnd)) {
2861 if (change_lanman_password(hnd,(uchar *)pass2)) {
2862 SSVAL(*rparam,0,NERR_Success);
2869 memset((char *)pass1,'\0',sizeof(fstring));
2870 memset((char *)pass2,'\0',sizeof(fstring));
2875 /****************************************************************************
2876 Set the user password (SamOEM version - gets plaintext).
2877 ****************************************************************************/
2879 static bool api_SamOEMChangePassword(connection_struct *conn,uint16 vuid,
2880 char *param, int tpscnt,
2881 char *data, int tdscnt,
2882 int mdrcnt,int mprcnt,
2883 char **rdata,char **rparam,
2884 int *rdata_len,int *rparam_len)
2886 struct smbd_server_connection *sconn = smbd_server_conn;
2888 char *p = get_safe_str_ptr(param,tpscnt,param,2);
2890 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2900 SSVAL(*rparam,0,NERR_badpass);
2903 * Check the parameter definition is correct.
2906 /* Do we have a string ? */
2907 if (skip_string(param,tpscnt,p) == 0) {
2910 if(!strequal(p, "zsT")) {
2911 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", p));
2914 p = skip_string(param, tpscnt, p);
2919 /* Do we have a string ? */
2920 if (skip_string(param,tpscnt,p) == 0) {
2923 if(!strequal(p, "B516B16")) {
2924 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p));
2927 p = skip_string(param,tpscnt,p);
2931 /* Do we have a string ? */
2932 if (skip_string(param,tpscnt,p) == 0) {
2935 p += pull_ascii_fstring(user,p);
2937 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user));
2940 * Pass the user through the NT -> unix user mapping
2944 (void)map_username(sconn, user);
2946 if (NT_STATUS_IS_OK(pass_oem_change(user, (uchar*) data, (uchar *)&data[516], NULL, NULL, NULL))) {
2947 SSVAL(*rparam,0,NERR_Success);
2953 /****************************************************************************
2956 ****************************************************************************/
2958 static bool api_RDosPrintJobDel(connection_struct *conn,uint16 vuid,
2959 char *param, int tpscnt,
2960 char *data, int tdscnt,
2961 int mdrcnt,int mprcnt,
2962 char **rdata,char **rparam,
2963 int *rdata_len,int *rparam_len)
2965 int function = get_safe_SVAL(param,tpscnt,param,0,0);
2966 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2967 char *str2 = skip_string(param,tpscnt,str1);
2968 char *p = skip_string(param,tpscnt,str2);
2973 WERROR werr = WERR_OK;
2975 if (!str1 || !str2 || !p) {
2979 * We use 1 here not 2 as we're checking
2980 * the last byte we want to access is safe.
2982 if (!is_offset_safe(param,tpscnt,p,1)) {
2985 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
2988 /* check it's a supported varient */
2989 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
2993 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2999 if (!print_job_exists(sharename, jobid)) {
3000 errcode = NERR_JobNotFound;
3004 snum = lp_servicenumber( sharename);
3006 errcode = NERR_DestNotFound;
3010 errcode = NERR_notsupported;
3013 case 81: /* delete */
3014 if (print_job_delete(conn->server_info, snum, jobid, &werr))
3015 errcode = NERR_Success;
3017 case 82: /* pause */
3018 if (print_job_pause(conn->server_info, snum, jobid, &werr))
3019 errcode = NERR_Success;
3021 case 83: /* resume */
3022 if (print_job_resume(conn->server_info, snum, jobid, &werr))
3023 errcode = NERR_Success;
3027 if (!W_ERROR_IS_OK(werr))
3028 errcode = W_ERROR_V(werr);
3031 SSVAL(*rparam,0,errcode);
3032 SSVAL(*rparam,2,0); /* converter word */
3037 /****************************************************************************
3038 Purge a print queue - or pause or resume it.
3039 ****************************************************************************/
3041 static bool api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid,
3042 char *param, int tpscnt,
3043 char *data, int tdscnt,
3044 int mdrcnt,int mprcnt,
3045 char **rdata,char **rparam,
3046 int *rdata_len,int *rparam_len)
3048 int function = get_safe_SVAL(param,tpscnt,param,0,0);
3049 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3050 char *str2 = skip_string(param,tpscnt,str1);
3051 char *QueueName = skip_string(param,tpscnt,str2);
3052 int errcode = NERR_notsupported;
3053 WERROR werr = WERR_OK;
3056 TALLOC_CTX *mem_ctx = talloc_tos();
3057 struct rpc_pipe_client *cli = NULL;
3058 struct policy_handle handle;
3059 struct spoolss_SetPrinterInfoCtr info_ctr;
3060 struct spoolss_DevmodeContainer devmode_ctr;
3061 struct sec_desc_buf secdesc_ctr;
3062 enum spoolss_PrinterControl command;
3064 if (!str1 || !str2 || !QueueName) {
3068 /* check it's a supported varient */
3069 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
3073 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3079 if (skip_string(param,tpscnt,QueueName) == NULL) {
3083 ZERO_STRUCT(handle);
3085 status = rpc_pipe_open_internal(mem_ctx, &ndr_table_spoolss.syntax_id,
3086 rpc_spoolss_dispatch, conn->server_info,
3088 if (!NT_STATUS_IS_OK(status)) {
3089 DEBUG(0,("api_WPrintQueueCtrl: could not connect to spoolss: %s\n",
3090 nt_errstr(status)));
3091 errcode = W_ERROR_V(ntstatus_to_werror(status));
3095 ZERO_STRUCT(devmode_ctr);
3097 status = rpccli_spoolss_OpenPrinter(cli, mem_ctx,
3101 SEC_FLAG_MAXIMUM_ALLOWED,
3104 if (!NT_STATUS_IS_OK(status)) {
3105 errcode = W_ERROR_V(ntstatus_to_werror(status));
3108 if (!W_ERROR_IS_OK(werr)) {
3109 errcode = W_ERROR_V(werr);
3114 case 74: /* Pause queue */
3115 command = SPOOLSS_PRINTER_CONTROL_PAUSE;
3117 case 75: /* Resume queue */
3118 command = SPOOLSS_PRINTER_CONTROL_RESUME;
3120 case 103: /* Purge */
3121 command = SPOOLSS_PRINTER_CONTROL_PURGE;
3124 werr = WERR_NOT_SUPPORTED;
3128 if (!W_ERROR_IS_OK(werr)) {
3129 errcode = W_ERROR_V(werr);
3133 ZERO_STRUCT(info_ctr);
3134 ZERO_STRUCT(secdesc_ctr);
3136 status = rpccli_spoolss_SetPrinter(cli, mem_ctx,
3143 if (!NT_STATUS_IS_OK(status)) {
3144 errcode = W_ERROR_V(ntstatus_to_werror(status));
3147 if (!W_ERROR_IS_OK(werr)) {
3148 errcode = W_ERROR_V(werr);
3152 errcode = W_ERROR_V(werr);
3156 if (is_valid_policy_hnd(&handle)) {
3157 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
3160 SSVAL(*rparam,0,errcode);
3161 SSVAL(*rparam,2,0); /* converter word */
3166 /****************************************************************************
3167 set the property of a print job (undocumented?)
3168 ? function = 0xb -> set name of print job
3169 ? function = 0x6 -> move print job up/down
3170 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
3171 or <WWsTP> <WB21BB16B10zWWzDDz>
3172 ****************************************************************************/
3174 static int check_printjob_info(struct pack_desc* desc,
3175 int uLevel, char* id)
3177 desc->subformat = NULL;
3179 case 0: desc->format = "W"; break;
3180 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
3181 case 2: desc->format = "WWzWWDDzz"; break;
3182 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
3183 case 4: desc->format = "WWzWWDDzzzzzDDDDDDD"; break;
3185 DEBUG(0,("check_printjob_info: invalid level %d\n",
3189 if (id == NULL || strcmp(desc->format,id) != 0) {
3190 DEBUG(0,("check_printjob_info: invalid format %s\n",
3191 id ? id : "<NULL>" ));
3197 static bool api_PrintJobInfo(connection_struct *conn, uint16 vuid,
3198 char *param, int tpscnt,
3199 char *data, int tdscnt,
3200 int mdrcnt,int mprcnt,
3201 char **rdata,char **rparam,
3202 int *rdata_len,int *rparam_len)
3204 struct pack_desc desc;
3205 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3206 char *str2 = skip_string(param,tpscnt,str1);
3207 char *p = skip_string(param,tpscnt,str2);
3210 int uLevel = get_safe_SVAL(param,tpscnt,p,2,-1);
3211 int function = get_safe_SVAL(param,tpscnt,p,4,-1);
3214 if (!str1 || !str2 || !p) {
3218 * We use 1 here not 2 as we're checking
3219 * the last byte we want to access is safe.
3221 if (!is_offset_safe(param,tpscnt,p,1)) {
3224 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
3227 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3232 if (!share_defined(sharename)) {
3233 DEBUG(0,("api_PrintJobInfo: sharen [%s] not defined\n",
3240 /* check it's a supported varient */
3241 if ((strcmp(str1,"WWsTP")) ||
3242 (!check_printjob_info(&desc,uLevel,str2)))
3245 if (!print_job_exists(sharename, jobid)) {
3246 errcode=NERR_JobNotFound;
3250 errcode = NERR_notsupported;
3254 /* change job place in the queue,
3255 data gives the new place */
3256 place = SVAL(data,0);
3257 if (print_job_set_place(sharename, jobid, place)) {
3258 errcode=NERR_Success;
3263 /* change print job name, data gives the name */
3264 if (print_job_set_name(sharename, jobid, data)) {
3265 errcode=NERR_Success;
3274 SSVALS(*rparam,0,errcode);
3275 SSVAL(*rparam,2,0); /* converter word */
3281 /****************************************************************************
3282 Get info about the server.
3283 ****************************************************************************/
3285 static bool api_RNetServerGetInfo(connection_struct *conn,uint16 vuid,
3286 char *param, int tpscnt,
3287 char *data, int tdscnt,
3288 int mdrcnt,int mprcnt,
3289 char **rdata,char **rparam,
3290 int *rdata_len,int *rparam_len)
3292 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3293 char *str2 = skip_string(param,tpscnt,str1);
3294 char *p = skip_string(param,tpscnt,str2);
3295 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
3299 if (!str1 || !str2 || !p) {
3303 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
3305 /* check it's a supported varient */
3306 if (!prefix_ok(str1,"WrLh")) {
3312 if (strcmp(str2,"B16") != 0) {
3318 if (strcmp(str2,"B16BBDz") != 0) {
3324 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")!= 0) {
3330 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz") != 0) {
3336 if (strcmp(str2,"DN") != 0) {
3342 if (strcmp(str2,"B16BBDzWWzzz") != 0) {
3351 *rdata_len = mdrcnt;
3352 *rdata = smb_realloc_limit(*rdata,*rdata_len);
3358 p2 = p + struct_len;
3360 srvstr_push(NULL, 0, p,global_myname(),16,
3361 STR_ASCII|STR_UPPER|STR_TERMINATE);
3365 struct srv_info_struct *servers=NULL;
3367 char *comment = NULL;
3368 TALLOC_CTX *ctx = talloc_tos();
3369 uint32 servertype= lp_default_server_announce();
3371 comment = talloc_strdup(ctx,lp_serverstring());
3376 if ((count=get_server_info(SV_TYPE_ALL,&servers,lp_workgroup()))>0) {
3377 for (i=0;i<count;i++) {
3378 if (strequal(servers[i].name,global_myname())) {
3379 servertype = servers[i].type;
3380 TALLOC_FREE(comment);
3381 comment = talloc_strdup(ctx,
3382 servers[i].comment);
3392 SCVAL(p,0,lp_major_announce_version());
3393 SCVAL(p,1,lp_minor_announce_version());
3394 SIVAL(p,2,servertype);
3396 if (mdrcnt == struct_len) {
3399 SIVAL(p,6,PTR_DIFF(p2,*rdata));
3400 comment = talloc_sub_advanced(
3402 lp_servicename(SNUM(conn)),
3403 conn->server_info->unix_name,
3405 conn->server_info->utok.gid,
3406 conn->server_info->sanitized_username,
3407 pdb_get_domain(conn->server_info->sam_account),
3412 if (mdrcnt - struct_len <= 0) {
3417 MIN(mdrcnt - struct_len,
3418 MAX_SERVER_STRING_LENGTH),
3420 p2 = skip_string(*rdata,*rdata_len,p2);
3428 return False; /* not yet implemented */
3431 *rdata_len = PTR_DIFF(p2,*rdata);
3434 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3438 SSVAL(*rparam,0,NERR_Success);
3439 SSVAL(*rparam,2,0); /* converter word */
3440 SSVAL(*rparam,4,*rdata_len);
3445 /****************************************************************************
3446 Get info about the server.
3447 ****************************************************************************/
3449 static bool api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid,
3450 char *param, int tpscnt,
3451 char *data, int tdscnt,
3452 int mdrcnt,int mprcnt,
3453 char **rdata,char **rparam,
3454 int *rdata_len,int *rparam_len)
3456 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3457 char *str2 = skip_string(param,tpscnt,str1);
3458 char *p = skip_string(param,tpscnt,str2);
3461 int level = get_safe_SVAL(param,tpscnt,p,0,-1);
3463 if (!str1 || !str2 || !p) {
3467 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
3470 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3475 /* check it's a supported varient */
3476 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz"))) {
3480 *rdata_len = mdrcnt + 1024;
3481 *rdata = smb_realloc_limit(*rdata,*rdata_len);
3486 SSVAL(*rparam,0,NERR_Success);
3487 SSVAL(*rparam,2,0); /* converter word */
3490 endp = *rdata + *rdata_len;
3492 p2 = get_safe_ptr(*rdata,*rdata_len,p,22);
3497 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
3498 strlcpy(p2,get_local_machine_name(),PTR_DIFF(endp,p2));
3500 p2 = skip_string(*rdata,*rdata_len,p2);
3506 SIVAL(p,0,PTR_DIFF(p2,*rdata));
3507 strlcpy(p2,conn->server_info->sanitized_username,PTR_DIFF(endp,p2));
3508 p2 = skip_string(*rdata,*rdata_len,p2);
3514 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
3515 strlcpy(p2,lp_workgroup(),PTR_DIFF(endp,p2));
3517 p2 = skip_string(*rdata,*rdata_len,p2);
3523 SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
3524 SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
3527 SIVAL(p,0,PTR_DIFF(p2,*rdata));
3528 strlcpy(p2,lp_workgroup(),PTR_DIFF(endp,p2)); /* don't know. login domain?? */
3529 p2 = skip_string(*rdata,*rdata_len,p2);
3535 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
3536 strlcpy(p2,"",PTR_DIFF(endp,p2));
3537 p2 = skip_string(*rdata,*rdata_len,p2);
3543 *rdata_len = PTR_DIFF(p2,*rdata);
3545 SSVAL(*rparam,4,*rdata_len);
3550 /****************************************************************************
3551 get info about a user
3553 struct user_info_11 {
3554 char usri11_name[21]; 0-20
3556 char *usri11_comment; 22-25
3557 char *usri11_usr_comment; 26-29
3558 unsigned short usri11_priv; 30-31
3559 unsigned long usri11_auth_flags; 32-35
3560 long usri11_password_age; 36-39
3561 char *usri11_homedir; 40-43
3562 char *usri11_parms; 44-47
3563 long usri11_last_logon; 48-51
3564 long usri11_last_logoff; 52-55
3565 unsigned short usri11_bad_pw_count; 56-57
3566 unsigned short usri11_num_logons; 58-59
3567 char *usri11_logon_server; 60-63
3568 unsigned short usri11_country_code; 64-65
3569 char *usri11_workstations; 66-69
3570 unsigned long usri11_max_storage; 70-73
3571 unsigned short usri11_units_per_week; 74-75
3572 unsigned char *usri11_logon_hours; 76-79
3573 unsigned short usri11_code_page; 80-81
3578 usri11_name specifies the user name for which information is retrieved
3580 usri11_pad aligns the next data structure element to a word boundary
3582 usri11_comment is a null terminated ASCII comment
3584 usri11_user_comment is a null terminated ASCII comment about the user
3586 usri11_priv specifies the level of the privilege assigned to the user.
3587 The possible values are:
3589 Name Value Description
3590 USER_PRIV_GUEST 0 Guest privilege
3591 USER_PRIV_USER 1 User privilege
3592 USER_PRV_ADMIN 2 Administrator privilege
3594 usri11_auth_flags specifies the account operator privileges. The
3595 possible values are:
3597 Name Value Description
3598 AF_OP_PRINT 0 Print operator
3601 Leach, Naik [Page 28]
3605 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
3608 AF_OP_COMM 1 Communications operator
3609 AF_OP_SERVER 2 Server operator
3610 AF_OP_ACCOUNTS 3 Accounts operator
3613 usri11_password_age specifies how many seconds have elapsed since the
3614 password was last changed.
3616 usri11_home_dir points to a null terminated ASCII string that contains
3617 the path name of the user's home directory.
3619 usri11_parms points to a null terminated ASCII string that is set
3620 aside for use by applications.
3622 usri11_last_logon specifies the time when the user last logged on.
3623 This value is stored as the number of seconds elapsed since
3624 00:00:00, January 1, 1970.
3626 usri11_last_logoff specifies the time when the user last logged off.
3627 This value is stored as the number of seconds elapsed since
3628 00:00:00, January 1, 1970. A value of 0 means the last logoff
3631 usri11_bad_pw_count specifies the number of incorrect passwords
3632 entered since the last successful logon.
3634 usri11_log1_num_logons specifies the number of times this user has
3635 logged on. A value of -1 means the number of logons is unknown.
3637 usri11_logon_server points to a null terminated ASCII string that
3638 contains the name of the server to which logon requests are sent.
3639 A null string indicates logon requests should be sent to the
3642 usri11_country_code specifies the country code for the user's language
3645 usri11_workstations points to a null terminated ASCII string that
3646 contains the names of workstations the user may log on from.
3647 There may be up to 8 workstations, with the names separated by
3648 commas. A null strings indicates there are no restrictions.
3650 usri11_max_storage specifies the maximum amount of disk space the user
3651 can occupy. A value of 0xffffffff indicates there are no
3654 usri11_units_per_week specifies the equal number of time units into
3655 which a week is divided. This value must be equal to 168.
3657 usri11_logon_hours points to a 21 byte (168 bits) string that
3658 specifies the time during which the user can log on. Each bit
3659 represents one unique hour in a week. The first bit (bit 0, word
3660 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
3664 Leach, Naik [Page 29]
3668 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
3671 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
3672 are no restrictions.
3674 usri11_code_page specifies the code page for the user's language of
3677 All of the pointers in this data structure need to be treated
3678 specially. The pointer is a 32 bit pointer. The higher 16 bits need
3679 to be ignored. The converter word returned in the parameters section
3680 needs to be subtracted from the lower 16 bits to calculate an offset
3681 into the return buffer where this ASCII string resides.
3683 There is no auxiliary data in the response.
3685 ****************************************************************************/
3687 #define usri11_name 0
3688 #define usri11_pad 21
3689 #define usri11_comment 22
3690 #define usri11_usr_comment 26
3691 #define usri11_full_name 30
3692 #define usri11_priv 34
3693 #define usri11_auth_flags 36
3694 #define usri11_password_age 40
3695 #define usri11_homedir 44
3696 #define usri11_parms 48
3697 #define usri11_last_logon 52
3698 #define usri11_last_logoff 56
3699 #define usri11_bad_pw_count 60
3700 #define usri11_num_logons 62
3701 #define usri11_logon_server 64
3702 #define usri11_country_code 68
3703 #define usri11_workstations 70
3704 #define usri11_max_storage 74
3705 #define usri11_units_per_week 78
3706 #define usri11_logon_hours 80
3707 #define usri11_code_page 84
3708 #define usri11_end 86
3710 #define USER_PRIV_GUEST 0
3711 #define USER_PRIV_USER 1
3712 #define USER_PRIV_ADMIN 2
3714 #define AF_OP_PRINT 0
3715 #define AF_OP_COMM 1
3716 #define AF_OP_SERVER 2
3717 #define AF_OP_ACCOUNTS 3
3720 static bool api_RNetUserGetInfo(connection_struct *conn, uint16 vuid,
3721 char *param, int tpscnt,
3722 char *data, int tdscnt,
3723 int mdrcnt,int mprcnt,
3724 char **rdata,char **rparam,
3725 int *rdata_len,int *rparam_len)
3727 struct smbd_server_connection *sconn = smbd_server_conn;
3728 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3729 char *str2 = skip_string(param,tpscnt,str1);
3730 char *UserName = skip_string(param,tpscnt,str2);
3731 char *p = skip_string(param,tpscnt,UserName);
3732 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
3735 const char *level_string;
3737 /* get NIS home of a previously validated user - simeon */
3738 /* With share level security vuid will always be zero.
3739 Don't depend on vuser being non-null !!. JRA */
3740 user_struct *vuser = get_valid_user_struct(sconn, vuid);
3742 DEBUG(3,(" Username of UID %d is %s\n",
3743 (int)vuser->server_info->utok.uid,
3744 vuser->server_info->unix_name));
3747 if (!str1 || !str2 || !UserName || !p) {
3752 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3757 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
3759 /* check it's a supported variant */
3760 if (strcmp(str1,"zWrLh") != 0) {
3764 case 0: level_string = "B21"; break;
3765 case 1: level_string = "B21BB16DWzzWz"; break;
3766 case 2: level_string = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
3767 case 10: level_string = "B21Bzzz"; break;
3768 case 11: level_string = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
3769 default: return False;
3772 if (strcmp(level_string,str2) != 0) {
3776 *rdata_len = mdrcnt + 1024;
3777 *rdata = smb_realloc_limit(*rdata,*rdata_len);
3782 SSVAL(*rparam,0,NERR_Success);
3783 SSVAL(*rparam,2,0); /* converter word */
3786 endp = *rdata + *rdata_len;
3787 p2 = get_safe_ptr(*rdata,*rdata_len,p,usri11_end);
3793 fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
3796 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
3801 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
3802 strlcpy(p2,"Comment",PTR_DIFF(endp,p2));
3803 p2 = skip_string(*rdata,*rdata_len,p2);
3808 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
3809 strlcpy(p2,"UserComment",PTR_DIFF(endp,p2));
3810 p2 = skip_string(*rdata,*rdata_len,p2);
3815 /* EEK! the cifsrap.txt doesn't have this in!!!! */
3816 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
3817 strlcpy(p2,((vuser != NULL)
3818 ? pdb_get_fullname(vuser->server_info->sam_account)
3819 : UserName),PTR_DIFF(endp,p2));
3820 p2 = skip_string(*rdata,*rdata_len,p2);
3827 const char *homedir = "";
3828 if (vuser != NULL) {
3829 homedir = pdb_get_homedir(
3830 vuser->server_info->sam_account);
3832 /* modelled after NTAS 3.51 reply */
3833 SSVAL(p,usri11_priv,
3834 (get_current_uid(conn) == sec_initial_uid())?
3835 USER_PRIV_ADMIN:USER_PRIV_USER);
3836 SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
3837 SIVALS(p,usri11_password_age,-1); /* password age */
3838 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
3839 strlcpy(p2, homedir, PTR_DIFF(endp,p2));
3840 p2 = skip_string(*rdata,*rdata_len,p2);
3844 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
3845 strlcpy(p2,"",PTR_DIFF(endp,p2));
3846 p2 = skip_string(*rdata,*rdata_len,p2);
3850 SIVAL(p,usri11_last_logon,0); /* last logon */
3851 SIVAL(p,usri11_last_logoff,0); /* last logoff */
3852 SSVALS(p,usri11_bad_pw_count,-1); /* bad pw counts */
3853 SSVALS(p,usri11_num_logons,-1); /* num logons */
3854 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
3855 strlcpy(p2,"\\\\*",PTR_DIFF(endp,p2));
3856 p2 = skip_string(*rdata,*rdata_len,p2);
3860 SSVAL(p,usri11_country_code,0); /* country code */
3862 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
3863 strlcpy(p2,"",PTR_DIFF(endp,p2));
3864 p2 = skip_string(*rdata,*rdata_len,p2);
3869 SIVALS(p,usri11_max_storage,-1); /* max storage */
3870 SSVAL(p,usri11_units_per_week,168); /* units per week */
3871 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
3873 /* a simple way to get logon hours at all times. */
3875 SCVAL(p2,21,0); /* fix zero termination */
3876 p2 = skip_string(*rdata,*rdata_len,p2);
3881 SSVAL(p,usri11_code_page,0); /* code page */
3884 if (uLevel == 1 || uLevel == 2) {
3885 memset(p+22,' ',16); /* password */
3886 SIVALS(p,38,-1); /* password age */
3888 (get_current_uid(conn) == sec_initial_uid())?
3889 USER_PRIV_ADMIN:USER_PRIV_USER);
3890 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
3891 strlcpy(p2, vuser ? pdb_get_homedir(
3892 vuser->server_info->sam_account) : "",
3894 p2 = skip_string(*rdata,*rdata_len,p2);
3898 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
3900 SSVAL(p,52,0); /* flags */
3901 SIVAL(p,54,PTR_DIFF(p2,*rdata)); /* script_path */
3902 strlcpy(p2, vuser ? pdb_get_logon_script(
3903 vuser->server_info->sam_account) : "",
3905 p2 = skip_string(*rdata,*rdata_len,p2);
3910 SIVAL(p,60,0); /* auth_flags */
3911 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
3912 strlcpy(p2,((vuser != NULL)
3913 ? pdb_get_fullname(vuser->server_info->sam_account)
3914 : UserName),PTR_DIFF(endp,p2));
3915 p2 = skip_string(*rdata,*rdata_len,p2);
3919 SIVAL(p,68,0); /* urs_comment */
3920 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
3921 strlcpy(p2,"",PTR_DIFF(endp,p2));
3922 p2 = skip_string(*rdata,*rdata_len,p2);
3926 SIVAL(p,76,0); /* workstations */
3927 SIVAL(p,80,0); /* last_logon */
3928 SIVAL(p,84,0); /* last_logoff */
3929 SIVALS(p,88,-1); /* acct_expires */
3930 SIVALS(p,92,-1); /* max_storage */
3931 SSVAL(p,96,168); /* units_per_week */
3932 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
3935 SSVALS(p,102,-1); /* bad_pw_count */
3936 SSVALS(p,104,-1); /* num_logons */
3937 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
3939 TALLOC_CTX *ctx = talloc_tos();
3940 int space_rem = *rdata_len - (p2 - *rdata);
3943 if (space_rem <= 0) {
3946 tmp = talloc_strdup(ctx, "\\\\%L");
3950 tmp = talloc_sub_basic(ctx,
3963 p2 = skip_string(*rdata,*rdata_len,p2);
3967 SSVAL(p,110,49); /* country_code */
3968 SSVAL(p,112,860); /* code page */
3972 *rdata_len = PTR_DIFF(p2,*rdata);
3974 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
3979 static bool api_WWkstaUserLogon(connection_struct *conn,uint16 vuid,
3980 char *param, int tpscnt,
3981 char *data, int tdscnt,
3982 int mdrcnt,int mprcnt,
3983 char **rdata,char **rparam,
3984 int *rdata_len,int *rparam_len)
3986 struct smbd_server_connection *sconn = smbd_server_conn;
3987 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3988 char *str2 = skip_string(param,tpscnt,str1);
3989 char *p = skip_string(param,tpscnt,str2);
3991 struct pack_desc desc;
3993 /* With share level security vuid will always be zero.
3994 Don't depend on vuser being non-null !!. JRA */
3995 user_struct *vuser = get_valid_user_struct(sconn, vuid);
3997 if (!str1 || !str2 || !p) {
4002 DEBUG(3,(" Username of UID %d is %s\n",
4003 (int)vuser->server_info->utok.uid,
4004 vuser->server_info->unix_name));
4007 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4008 name = get_safe_str_ptr(param,tpscnt,p,2);
4013 memset((char *)&desc,'\0',sizeof(desc));
4015 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
4017 /* check it's a supported varient */
4018 if (strcmp(str1,"OOWb54WrLh") != 0) {
4021 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) {
4025 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4032 desc.buflen = mdrcnt;
4033 desc.subformat = NULL;
4036 if (init_package(&desc,1,0)) {
4037 PACKI(&desc,"W",0); /* code */
4038 PACKS(&desc,"B21",name); /* eff. name */
4039 PACKS(&desc,"B",""); /* pad */
4041 (get_current_uid(conn) == sec_initial_uid())?
4042 USER_PRIV_ADMIN:USER_PRIV_USER);
4043 PACKI(&desc,"D",0); /* auth flags XXX */
4044 PACKI(&desc,"W",0); /* num logons */
4045 PACKI(&desc,"W",0); /* bad pw count */
4046 PACKI(&desc,"D",0); /* last logon */
4047 PACKI(&desc,"D",-1); /* last logoff */
4048 PACKI(&desc,"D",-1); /* logoff time */
4049 PACKI(&desc,"D",-1); /* kickoff time */
4050 PACKI(&desc,"D",0); /* password age */
4051 PACKI(&desc,"D",0); /* password can change */
4052 PACKI(&desc,"D",-1); /* password must change */
4056 fstrcpy(mypath,"\\\\");
4057 fstrcat(mypath,get_local_machine_name());
4059 PACKS(&desc,"z",mypath); /* computer */
4062 PACKS(&desc,"z",lp_workgroup());/* domain */
4063 PACKS(&desc,"z", vuser ? pdb_get_logon_script(
4064 vuser->server_info->sam_account) : ""); /* script path */
4065 PACKI(&desc,"D",0x00000000); /* reserved */
4068 *rdata_len = desc.usedlen;
4070 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4074 SSVALS(*rparam,0,desc.errcode);
4076 SSVAL(*rparam,4,desc.neededlen);
4078 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
4083 /****************************************************************************
4084 api_WAccessGetUserPerms
4085 ****************************************************************************/
4087 static bool api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid,
4088 char *param, int tpscnt,
4089 char *data, int tdscnt,
4090 int mdrcnt,int mprcnt,
4091 char **rdata,char **rparam,
4092 int *rdata_len,int *rparam_len)
4094 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4095 char *str2 = skip_string(param,tpscnt,str1);
4096 char *user = skip_string(param,tpscnt,str2);
4097 char *resource = skip_string(param,tpscnt,user);
4099 if (!str1 || !str2 || !user || !resource) {
4103 if (skip_string(param,tpscnt,resource) == NULL) {
4106 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
4108 /* check it's a supported varient */
4109 if (strcmp(str1,"zzh") != 0) {
4112 if (strcmp(str2,"") != 0) {
4117 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4121 SSVALS(*rparam,0,0); /* errorcode */
4122 SSVAL(*rparam,2,0); /* converter word */
4123 SSVAL(*rparam,4,0x7f); /* permission flags */
4128 /****************************************************************************
4129 api_WPrintJobEnumerate
4130 ****************************************************************************/
4132 static bool api_WPrintJobGetInfo(connection_struct *conn, uint16 vuid,
4133 char *param, int tpscnt,
4134 char *data, int tdscnt,
4135 int mdrcnt,int mprcnt,
4136 char **rdata,char **rparam,
4137 int *rdata_len,int *rparam_len)
4139 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4140 char *str2 = skip_string(param,tpscnt,str1);
4141 char *p = skip_string(param,tpscnt,str2);
4148 struct pack_desc desc;
4149 print_queue_struct *queue=NULL;
4150 print_status_struct status;
4153 if (!str1 || !str2 || !p) {
4157 uLevel = get_safe_SVAL(param,tpscnt,p,2,-1);
4159 memset((char *)&desc,'\0',sizeof(desc));
4160 memset((char *)&status,'\0',sizeof(status));
4162 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
4164 /* check it's a supported varient */
4165 if (strcmp(str1,"WWrLh") != 0) {
4168 if (!check_printjob_info(&desc,uLevel,str2)) {
4172 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid)) {
4176 snum = lp_servicenumber( sharename);
4177 if (snum < 0 || !VALID_SNUM(snum)) {
4181 count = print_queue_status(snum,&queue,&status);
4182 for (i = 0; i < count; i++) {
4183 if (queue[i].job == jobid) {
4189 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4194 desc.buflen = mdrcnt;
4197 * Don't return data but need to get correct length
4198 * init_package will return wrong size if buflen=0
4200 desc.buflen = getlen(desc.format);
4201 desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen );
4204 if (init_package(&desc,1,0)) {
4206 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
4207 *rdata_len = desc.usedlen;
4209 desc.errcode = NERR_JobNotFound;
4215 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4219 SSVALS(*rparam,0,desc.errcode);
4221 SSVAL(*rparam,4,desc.neededlen);
4226 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
4231 static bool api_WPrintJobEnumerate(connection_struct *conn, uint16 vuid,
4232 char *param, int tpscnt,
4233 char *data, int tdscnt,
4234 int mdrcnt,int mprcnt,
4235 char **rdata,char **rparam,
4236 int *rdata_len,int *rparam_len)
4238 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4239 char *str2 = skip_string(param,tpscnt,str1);
4240 char *p = skip_string(param,tpscnt,str2);
4246 struct pack_desc desc;
4247 print_queue_struct *queue=NULL;
4248 print_status_struct status;
4250 if (!str1 || !str2 || !p) {
4254 memset((char *)&desc,'\0',sizeof(desc));
4255 memset((char *)&status,'\0',sizeof(status));
4257 p = skip_string(param,tpscnt,p);
4261 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4263 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
4265 /* check it's a supported variant */
4266 if (strcmp(str1,"zWrLeh") != 0) {
4271 return False; /* defined only for uLevel 0,1,2 */
4274 if (!check_printjob_info(&desc,uLevel,str2)) {
4278 snum = find_service(name);
4279 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) ) {
4283 count = print_queue_status(snum,&queue,&status);
4285 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4291 desc.buflen = mdrcnt;
4293 if (init_package(&desc,count,0)) {
4295 for (i = 0; i < count; i++) {
4296 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
4297 if (desc.errcode == NERR_Success) {
4303 *rdata_len = desc.usedlen;
4306 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4310 SSVALS(*rparam,0,desc.errcode);
4312 SSVAL(*rparam,4,succnt);
4313 SSVAL(*rparam,6,count);
4317 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
4322 static int check_printdest_info(struct pack_desc* desc,
4323 int uLevel, char* id)
4325 desc->subformat = NULL;
4328 desc->format = "B9";
4331 desc->format = "B9B21WWzW";
4337 desc->format = "zzzWWzzzWW";
4340 DEBUG(0,("check_printdest_info: invalid level %d\n",
4344 if (id == NULL || strcmp(desc->format,id) != 0) {
4345 DEBUG(0,("check_printdest_info: invalid string %s\n",
4346 id ? id : "<NULL>" ));
4352 static void fill_printdest_info(connection_struct *conn, int snum, int uLevel,
4353 struct pack_desc* desc)
4357 strncpy(buf,SERVICE(snum),sizeof(buf)-1);
4358 buf[sizeof(buf)-1] = 0;
4362 PACKS(desc,"B9",buf); /* szName */
4364 PACKS(desc,"B21",""); /* szUserName */
4365 PACKI(desc,"W",0); /* uJobId */
4366 PACKI(desc,"W",0); /* fsStatus */
4367 PACKS(desc,"z",""); /* pszStatus */
4368 PACKI(desc,"W",0); /* time */
4372 if (uLevel == 2 || uLevel == 3) {
4373 PACKS(desc,"z",buf); /* pszPrinterName */
4375 PACKS(desc,"z",""); /* pszUserName */
4376 PACKS(desc,"z",""); /* pszLogAddr */
4377 PACKI(desc,"W",0); /* uJobId */
4378 PACKI(desc,"W",0); /* fsStatus */
4379 PACKS(desc,"z",""); /* pszStatus */
4380 PACKS(desc,"z",""); /* pszComment */
4381 PACKS(desc,"z","NULL"); /* pszDrivers */
4382 PACKI(desc,"W",0); /* time */
4383 PACKI(desc,"W",0); /* pad1 */
4388 static bool api_WPrintDestGetInfo(connection_struct *conn, uint16 vuid,
4389 char *param, int tpscnt,
4390 char *data, int tdscnt,
4391 int mdrcnt,int mprcnt,
4392 char **rdata,char **rparam,
4393 int *rdata_len,int *rparam_len)
4395 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4396 char *str2 = skip_string(param,tpscnt,str1);
4397 char *p = skip_string(param,tpscnt,str2);
4398 char* PrinterName = p;
4400 struct pack_desc desc;
4404 if (!str1 || !str2 || !p) {
4408 memset((char *)&desc,'\0',sizeof(desc));
4410 p = skip_string(param,tpscnt,p);
4414 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4416 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
4418 /* check it's a supported varient */
4419 if (strcmp(str1,"zWrLh") != 0) {
4422 if (!check_printdest_info(&desc,uLevel,str2)) {
4426 snum = find_service(PrinterName);
4427 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) ) {
4429 desc.errcode = NERR_DestNotFound;
4433 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4438 desc.buflen = mdrcnt;
4441 * Don't return data but need to get correct length
4442 * init_package will return wrong size if buflen=0
4444 desc.buflen = getlen(desc.format);
4445 desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen );
4447 if (init_package(&desc,1,0)) {
4448 fill_printdest_info(conn,snum,uLevel,&desc);
4450 *rdata_len = desc.usedlen;
4454 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4458 SSVALS(*rparam,0,desc.errcode);
4460 SSVAL(*rparam,4,desc.neededlen);
4462 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
4468 static bool api_WPrintDestEnum(connection_struct *conn, uint16 vuid,
4469 char *param, int tpscnt,
4470 char *data, int tdscnt,
4471 int mdrcnt,int mprcnt,
4472 char **rdata,char **rparam,
4473 int *rdata_len,int *rparam_len)
4475 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4476 char *str2 = skip_string(param,tpscnt,str1);
4477 char *p = skip_string(param,tpscnt,str2);
4481 struct pack_desc desc;
4482 int services = lp_numservices();
4484 if (!str1 || !str2 || !p) {
4488 memset((char *)&desc,'\0',sizeof(desc));
4490 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4492 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
4494 /* check it's a supported varient */
4495 if (strcmp(str1,"WrLeh") != 0) {
4498 if (!check_printdest_info(&desc,uLevel,str2)) {
4503 for (i = 0; i < services; i++) {
4504 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
4510 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4517 desc.buflen = mdrcnt;
4518 if (init_package(&desc,queuecnt,0)) {
4521 for (i = 0; i < services; i++) {
4522 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
4523 fill_printdest_info(conn,i,uLevel,&desc);
4525 if (desc.errcode == NERR_Success) {
4532 *rdata_len = desc.usedlen;
4535 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4539 SSVALS(*rparam,0,desc.errcode);
4541 SSVAL(*rparam,4,succnt);
4542 SSVAL(*rparam,6,queuecnt);
4544 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
4549 static bool api_WPrintDriverEnum(connection_struct *conn, uint16 vuid,
4550 char *param, int tpscnt,
4551 char *data, int tdscnt,
4552 int mdrcnt,int mprcnt,
4553 char **rdata,char **rparam,
4554 int *rdata_len,int *rparam_len)
4556 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4557 char *str2 = skip_string(param,tpscnt,str1);
4558 char *p = skip_string(param,tpscnt,str2);
4561 struct pack_desc desc;
4563 if (!str1 || !str2 || !p) {
4567 memset((char *)&desc,'\0',sizeof(desc));
4569 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4571 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
4573 /* check it's a supported varient */
4574 if (strcmp(str1,"WrLeh") != 0) {
4577 if (uLevel != 0 || strcmp(str2,"B41") != 0) {
4582 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4588 desc.buflen = mdrcnt;
4589 if (init_package(&desc,1,0)) {
4590 PACKS(&desc,"B41","NULL");
4593 succnt = (desc.errcode == NERR_Success ? 1 : 0);
4595 *rdata_len = desc.usedlen;
4598 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4602 SSVALS(*rparam,0,desc.errcode);
4604 SSVAL(*rparam,4,succnt);
4607 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
4612 static bool api_WPrintQProcEnum(connection_struct *conn, uint16 vuid,
4613 char *param, int tpscnt,
4614 char *data, int tdscnt,
4615 int mdrcnt,int mprcnt,
4616 char **rdata,char **rparam,
4617 int *rdata_len,int *rparam_len)
4619 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4620 char *str2 = skip_string(param,tpscnt,str1);
4621 char *p = skip_string(param,tpscnt,str2);
4624 struct pack_desc desc;
4626 if (!str1 || !str2 || !p) {
4629 memset((char *)&desc,'\0',sizeof(desc));
4631 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4633 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
4635 /* check it's a supported varient */
4636 if (strcmp(str1,"WrLeh") != 0) {
4639 if (uLevel != 0 || strcmp(str2,"B13") != 0) {
4644 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4650 desc.buflen = mdrcnt;
4652 if (init_package(&desc,1,0)) {
4653 PACKS(&desc,"B13","lpd");
4656 succnt = (desc.errcode == NERR_Success ? 1 : 0);
4658 *rdata_len = desc.usedlen;
4661 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4665 SSVALS(*rparam,0,desc.errcode);
4667 SSVAL(*rparam,4,succnt);
4670 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
4675 static bool api_WPrintPortEnum(connection_struct *conn, uint16 vuid,
4676 char *param, int tpscnt,
4677 char *data, int tdscnt,
4678 int mdrcnt,int mprcnt,
4679 char **rdata,char **rparam,
4680 int *rdata_len,int *rparam_len)
4682 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4683 char *str2 = skip_string(param,tpscnt,str1);
4684 char *p = skip_string(param,tpscnt,str2);
4687 struct pack_desc desc;
4689 if (!str1 || !str2 || !p) {
4693 memset((char *)&desc,'\0',sizeof(desc));
4695 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4697 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
4699 /* check it's a supported varient */
4700 if (strcmp(str1,"WrLeh") != 0) {
4703 if (uLevel != 0 || strcmp(str2,"B9") != 0) {
4708 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4713 memset((char *)&desc,'\0',sizeof(desc));
4715 desc.buflen = mdrcnt;
4717 if (init_package(&desc,1,0)) {
4718 PACKS(&desc,"B13","lp0");
4721 succnt = (desc.errcode == NERR_Success ? 1 : 0);
4723 *rdata_len = desc.usedlen;
4726 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4730 SSVALS(*rparam,0,desc.errcode);
4732 SSVAL(*rparam,4,succnt);
4735 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
4740 /****************************************************************************
4742 ****************************************************************************/
4744 static bool api_RNetSessionEnum(connection_struct *conn, uint16 vuid,
4745 char *param, int tpscnt,
4746 char *data, int tdscnt,
4747 int mdrcnt,int mprcnt,
4748 char **rdata,char **rparam,
4749 int *rdata_len,int *rparam_len)
4752 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4753 char *str2 = skip_string(param,tpscnt,str1);
4754 char *p = skip_string(param,tpscnt,str2);
4756 struct pack_desc desc;
4757 struct sessionid *session_list;
4758 int i, num_sessions;
4760 if (!str1 || !str2 || !p) {
4764 memset((char *)&desc,'\0',sizeof(desc));
4766 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4768 DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel));
4769 DEBUG(7,("RNetSessionEnum req string=%s\n",str1));
4770 DEBUG(7,("RNetSessionEnum ret string=%s\n",str2));
4772 /* check it's a supported varient */
4773 if (strcmp(str1,RAP_NetSessionEnum_REQ) != 0) {
4776 if (uLevel != 2 || strcmp(str2,RAP_SESSION_INFO_L2) != 0) {
4780 num_sessions = list_sessions(talloc_tos(), &session_list);
4783 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4788 memset((char *)&desc,'\0',sizeof(desc));
4790 desc.buflen = mdrcnt;
4792 if (!init_package(&desc,num_sessions,0)) {
4796 for(i=0; i<num_sessions; i++) {
4797 PACKS(&desc, "z", session_list[i].remote_machine);
4798 PACKS(&desc, "z", session_list[i].username);
4799 PACKI(&desc, "W", 1); /* num conns */
4800 PACKI(&desc, "W", 0); /* num opens */
4801 PACKI(&desc, "W", 1); /* num users */
4802 PACKI(&desc, "D", 0); /* session time */
4803 PACKI(&desc, "D", 0); /* idle time */
4804 PACKI(&desc, "D", 0); /* flags */
4805 PACKS(&desc, "z", "Unknown Client"); /* client type string */
4808 *rdata_len = desc.usedlen;
4811 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4815 SSVALS(*rparam,0,desc.errcode);
4816 SSVAL(*rparam,2,0); /* converter */
4817 SSVAL(*rparam,4,num_sessions); /* count */
4819 DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc.errcode));
4825 /****************************************************************************
4826 The buffer was too small.
4827 ****************************************************************************/
4829 static bool api_TooSmall(connection_struct *conn,uint16 vuid, char *param, char *data,
4830 int mdrcnt, int mprcnt,
4831 char **rdata, char **rparam,
4832 int *rdata_len, int *rparam_len)
4834 *rparam_len = MIN(*rparam_len,mprcnt);
4835 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4842 SSVAL(*rparam,0,NERR_BufTooSmall);
4844 DEBUG(3,("Supplied buffer too small in API command\n"));
4849 /****************************************************************************
4850 The request is not supported.
4851 ****************************************************************************/
4853 static bool api_Unsupported(connection_struct *conn, uint16 vuid,
4854 char *param, int tpscnt,
4855 char *data, int tdscnt,
4856 int mdrcnt, int mprcnt,
4857 char **rdata, char **rparam,
4858 int *rdata_len, int *rparam_len)
4861 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4868 SSVAL(*rparam,0,NERR_notsupported);
4869 SSVAL(*rparam,2,0); /* converter word */
4871 DEBUG(3,("Unsupported API command\n"));
4876 static const struct {
4879 bool (*fn)(connection_struct *, uint16,
4882 int,int,char **,char **,int *,int *);
4883 bool auth_user; /* Deny anonymous access? */
4884 } api_commands[] = {
4885 {"RNetShareEnum", RAP_WshareEnum, api_RNetShareEnum, True},
4886 {"RNetShareGetInfo", RAP_WshareGetInfo, api_RNetShareGetInfo},
4887 {"RNetShareAdd", RAP_WshareAdd, api_RNetShareAdd},
4888 {"RNetSessionEnum", RAP_WsessionEnum, api_RNetSessionEnum, True},
4889 {"RNetServerGetInfo", RAP_WserverGetInfo, api_RNetServerGetInfo},
4890 {"RNetGroupEnum", RAP_WGroupEnum, api_RNetGroupEnum, True},
4891 {"RNetGroupGetUsers", RAP_WGroupGetUsers, api_RNetGroupGetUsers, True},
4892 {"RNetUserEnum", RAP_WUserEnum, api_RNetUserEnum, True},
4893 {"RNetUserGetInfo", RAP_WUserGetInfo, api_RNetUserGetInfo},
4894 {"NetUserGetGroups", RAP_WUserGetGroups, api_NetUserGetGroups},
4895 {"NetWkstaGetInfo", RAP_WWkstaGetInfo, api_NetWkstaGetInfo},
4896 {"DosPrintQEnum", RAP_WPrintQEnum, api_DosPrintQEnum, True},
4897 {"DosPrintQGetInfo", RAP_WPrintQGetInfo, api_DosPrintQGetInfo},
4898 {"WPrintQueuePause", RAP_WPrintQPause, api_WPrintQueueCtrl},
4899 {"WPrintQueueResume", RAP_WPrintQContinue, api_WPrintQueueCtrl},
4900 {"WPrintJobEnumerate",RAP_WPrintJobEnum, api_WPrintJobEnumerate},
4901 {"WPrintJobGetInfo", RAP_WPrintJobGetInfo, api_WPrintJobGetInfo},
4902 {"RDosPrintJobDel", RAP_WPrintJobDel, api_RDosPrintJobDel},
4903 {"RDosPrintJobPause", RAP_WPrintJobPause, api_RDosPrintJobDel},
4904 {"RDosPrintJobResume",RAP_WPrintJobContinue, api_RDosPrintJobDel},
4905 {"WPrintDestEnum", RAP_WPrintDestEnum, api_WPrintDestEnum},
4906 {"WPrintDestGetInfo", RAP_WPrintDestGetInfo, api_WPrintDestGetInfo},
4907 {"NetRemoteTOD", RAP_NetRemoteTOD, api_NetRemoteTOD},
4908 {"WPrintQueuePurge", RAP_WPrintQPurge, api_WPrintQueueCtrl},
4909 {"NetServerEnum2", RAP_NetServerEnum2, api_RNetServerEnum2}, /* anon OK */
4910 {"NetServerEnum3", RAP_NetServerEnum3, api_RNetServerEnum3}, /* anon OK */
4911 {"WAccessGetUserPerms",RAP_WAccessGetUserPerms,api_WAccessGetUserPerms},
4912 {"SetUserPassword", RAP_WUserPasswordSet2, api_SetUserPassword},
4913 {"WWkstaUserLogon", RAP_WWkstaUserLogon, api_WWkstaUserLogon},
4914 {"PrintJobInfo", RAP_WPrintJobSetInfo, api_PrintJobInfo},
4915 {"WPrintDriverEnum", RAP_WPrintDriverEnum, api_WPrintDriverEnum},
4916 {"WPrintQProcEnum", RAP_WPrintQProcessorEnum,api_WPrintQProcEnum},
4917 {"WPrintPortEnum", RAP_WPrintPortEnum, api_WPrintPortEnum},
4918 {"SamOEMChangePassword",RAP_SamOEMChgPasswordUser2_P,api_SamOEMChangePassword}, /* anon OK */
4919 {NULL, -1, api_Unsupported}
4920 /* The following RAP calls are not implemented by Samba:
4922 RAP_WFileEnum2 - anon not OK
4927 /****************************************************************************
4928 Handle remote api calls.
4929 ****************************************************************************/
4931 void api_reply(connection_struct *conn, uint16 vuid,
4932 struct smb_request *req,
4933 char *data, char *params,
4934 int tdscnt, int tpscnt,
4935 int mdrcnt, int mprcnt)
4937 struct smbd_server_connection *sconn = smbd_server_conn;
4940 char *rparam = NULL;
4941 const char *name1 = NULL;
4942 const char *name2 = NULL;
4949 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
4950 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4955 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4958 api_command = SVAL(params,0);
4959 /* Is there a string at position params+2 ? */
4960 if (skip_string(params,tpscnt,params+2)) {
4965 name2 = skip_string(params,tpscnt,params+2);
4970 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
4974 tdscnt,tpscnt,mdrcnt,mprcnt));
4976 for (i=0;api_commands[i].name;i++) {
4977 if (api_commands[i].id == api_command && api_commands[i].fn) {
4978 DEBUG(3,("Doing %s\n",api_commands[i].name));
4983 /* Check whether this api call can be done anonymously */
4985 if (api_commands[i].auth_user && lp_restrict_anonymous()) {
4986 user_struct *user = get_valid_user_struct(sconn, vuid);
4988 if (!user || user->server_info->guest) {
4989 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4994 rdata = (char *)SMB_MALLOC(1024);
4996 memset(rdata,'\0',1024);
4999 rparam = (char *)SMB_MALLOC(1024);
5001 memset(rparam,'\0',1024);
5004 if(!rdata || !rparam) {
5005 DEBUG(0,("api_reply: malloc fail !\n"));
5008 reply_nterror(req, NT_STATUS_NO_MEMORY);
5012 reply = api_commands[i].fn(conn,
5014 params,tpscnt, /* params + length */
5015 data,tdscnt, /* data + length */
5017 &rdata,&rparam,&rdata_len,&rparam_len);
5020 if (rdata_len > mdrcnt || rparam_len > mprcnt) {
5021 reply = api_TooSmall(conn,vuid,params,data,mdrcnt,mprcnt,
5022 &rdata,&rparam,&rdata_len,&rparam_len);
5025 /* if we get False back then it's actually unsupported */
5027 reply = api_Unsupported(conn,vuid,params,tpscnt,data,tdscnt,mdrcnt,mprcnt,
5028 &rdata,&rparam,&rdata_len,&rparam_len);
5031 /* If api_Unsupported returns false we can't return anything. */
5033 send_trans_reply(conn, req, rparam, rparam_len,
5034 rdata, rdata_len, False);