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/ndr_spoolss_c.h"
32 #include "rpc_client/cli_spoolss.h"
33 #include "rpc_client/init_spoolss.h"
34 #include "../librpc/gen_ndr/ndr_srvsvc_c.h"
35 #include "../librpc/gen_ndr/srv_samr.h"
36 #include "../librpc/gen_ndr/srv_srvsvc.h"
37 #include "../librpc/gen_ndr/rap.h"
38 #include "../lib/util/binsearch.h"
39 #include "../libcli/auth/libcli_auth.h"
40 #include "rpc_client/init_lsa.h"
41 #include "rpc_server/rpc_ncacn_np.h"
42 #include "../libcli/security/security.h"
49 #define NERR_Success 0
50 #define NERR_badpass 86
51 #define NERR_notsupported 50
53 #define NERR_BASE (2100)
54 #define NERR_BufTooSmall (NERR_BASE+23)
55 #define NERR_JobNotFound (NERR_BASE+51)
56 #define NERR_DestNotFound (NERR_BASE+52)
58 #define ACCESS_READ 0x01
59 #define ACCESS_WRITE 0x02
60 #define ACCESS_CREATE 0x04
62 #define SHPWLEN 8 /* share password length */
64 /* Limit size of ipc replies */
66 static char *smb_realloc_limit(void *ptr, size_t size)
70 size = MAX((size),4*1024);
71 val = (char *)SMB_REALLOC(ptr,size);
73 memset(val,'\0',size);
78 static bool api_Unsupported(struct smbd_server_connection *sconn,
79 connection_struct *conn, uint16 vuid,
80 char *param, int tpscnt,
81 char *data, int tdscnt,
82 int mdrcnt, int mprcnt,
83 char **rdata, char **rparam,
84 int *rdata_len, int *rparam_len);
86 static bool api_TooSmall(struct smbd_server_connection *sconn,
87 connection_struct *conn, uint16 vuid, char *param, char *data,
88 int mdrcnt, int mprcnt,
89 char **rdata, char **rparam,
90 int *rdata_len, int *rparam_len);
93 static int CopyExpanded(connection_struct *conn,
94 int snum, char **dst, char *src, int *p_space_remaining)
96 TALLOC_CTX *ctx = talloc_tos();
100 if (!src || !dst || !p_space_remaining || !(*dst) ||
101 *p_space_remaining <= 0) {
105 buf = talloc_strdup(ctx, src);
107 *p_space_remaining = 0;
110 buf = talloc_string_sub(ctx, buf,"%S",lp_servicename(snum));
112 *p_space_remaining = 0;
115 buf = talloc_sub_advanced(ctx,
116 lp_servicename(SNUM(conn)),
117 conn->server_info->unix_name,
119 conn->server_info->utok.gid,
120 conn->server_info->sanitized_username,
121 conn->server_info->info3->base.domain.string,
124 *p_space_remaining = 0;
127 l = push_ascii(*dst,buf,*p_space_remaining, STR_TERMINATE);
132 (*p_space_remaining) -= l;
136 static int CopyAndAdvance(char **dst, char *src, int *n)
139 if (!src || !dst || !n || !(*dst)) {
142 l = push_ascii(*dst,src,*n, STR_TERMINATE);
151 static int StrlenExpanded(connection_struct *conn, int snum, char *s)
153 TALLOC_CTX *ctx = talloc_tos();
158 buf = talloc_strdup(ctx,s);
162 buf = talloc_string_sub(ctx,buf,"%S",lp_servicename(snum));
166 buf = talloc_sub_advanced(ctx,
167 lp_servicename(SNUM(conn)),
168 conn->server_info->unix_name,
170 conn->server_info->utok.gid,
171 conn->server_info->sanitized_username,
172 conn->server_info->info3->base.domain.string,
177 return strlen(buf) + 1;
180 /*******************************************************************
181 Check a API string for validity when we only need to check the prefix.
182 ******************************************************************/
184 static bool prefix_ok(const char *str, const char *prefix)
186 return(strncmp(str,prefix,strlen(prefix)) == 0);
190 const char *format; /* formatstring for structure */
191 const char *subformat; /* subformat for structure */
192 char *base; /* baseaddress of buffer */
193 int buflen; /* remaining size for fixed part; on init: length of base */
194 int subcount; /* count of substructures */
195 char *structbuf; /* pointer into buffer for remaining fixed part */
196 int stringlen; /* remaining size for variable part */
197 char *stringbuf; /* pointer into buffer for remaining variable part */
198 int neededlen; /* total needed size */
199 int usedlen; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
200 const char *curpos; /* current position; pointer into format or subformat */
204 static int get_counter(const char **p)
210 if (!isdigit((int)**p)) {
216 n = 10 * n + (i - '0');
224 static int getlen(const char *p)
233 case 'W': /* word (2 byte) */
236 case 'K': /* status word? (2 byte) */
239 case 'N': /* count of substructures (word) at end */
242 case 'D': /* double word (4 byte) */
243 case 'z': /* offset to zero terminated string (4 byte) */
244 case 'l': /* offset to user data (4 byte) */
247 case 'b': /* offset to data (with counter) (4 byte) */
251 case 'B': /* byte (with optional counter) */
252 n += get_counter(&p);
259 static bool init_package(struct pack_desc *p, int count, int subcount)
264 if (!p->format || !p->base) {
268 i = count * getlen(p->format);
270 i += subcount * getlen(p->subformat);
272 p->structbuf = p->base;
276 p->curpos = p->format;
282 * This is the old error code we used. Aparently
283 * WinNT/2k systems return ERRbuftoosmall (2123) and
284 * OS/2 needs this. I'm leaving this here so we can revert
287 p->errcode = ERRmoredata;
289 p->errcode = ERRbuftoosmall;
292 p->errcode = NERR_Success;
296 p->stringbuf = p->base + i;
298 return (p->errcode == NERR_Success);
301 static int package(struct pack_desc *p, ...)
304 int needed=0, stringneeded;
305 const char *str=NULL;
306 int is_string=0, stringused;
313 p->curpos = p->format;
315 p->curpos = p->subformat;
320 str = va_arg(args,char*);
321 SMB_ASSERT(strncmp(str,p->curpos,strlen(str)) == 0);
330 switch( *p->curpos++ ) {
331 case 'W': /* word (2 byte) */
333 temp = va_arg(args,int);
334 if (p->buflen >= needed) {
335 SSVAL(p->structbuf,0,temp);
338 case 'K': /* status word? (2 byte) */
340 temp = va_arg(args,int);
341 if (p->buflen >= needed) {
342 SSVAL(p->structbuf,0,temp);
345 case 'N': /* count of substructures (word) at end */
347 p->subcount = va_arg(args,int);
348 if (p->buflen >= needed) {
349 SSVAL(p->structbuf,0,p->subcount);
352 case 'D': /* double word (4 byte) */
354 temp = va_arg(args,int);
355 if (p->buflen >= needed) {
356 SIVAL(p->structbuf,0,temp);
359 case 'B': /* byte (with optional counter) */
360 needed = get_counter(&p->curpos);
362 char *s = va_arg(args,char*);
363 if (p->buflen >= needed) {
364 StrnCpy(p->structbuf,s?s:"",needed-1);
368 case 'z': /* offset to zero terminated string (4 byte) */
369 str = va_arg(args,char*);
370 stringneeded = (str ? strlen(str)+1 : 0);
373 case 'l': /* offset to user data (4 byte) */
374 str = va_arg(args,char*);
375 stringneeded = va_arg(args,int);
378 case 'b': /* offset to data (with counter) (4 byte) */
379 str = va_arg(args,char*);
380 stringneeded = get_counter(&p->curpos);
386 if (stringneeded >= 0) {
388 if (p->buflen >= needed) {
389 stringused = stringneeded;
390 if (stringused > p->stringlen) {
391 stringused = (is_string ? p->stringlen : 0);
392 if (p->errcode == NERR_Success) {
393 p->errcode = ERRmoredata;
397 SIVAL(p->structbuf,0,0);
399 SIVAL(p->structbuf,0,PTR_DIFF(p->stringbuf,p->base));
400 memcpy(p->stringbuf,str?str:"",stringused);
402 p->stringbuf[stringused-1] = '\0';
404 p->stringbuf += stringused;
405 p->stringlen -= stringused;
406 p->usedlen += stringused;
409 p->neededlen += stringneeded;
412 p->neededlen += needed;
413 if (p->buflen >= needed) {
414 p->structbuf += needed;
416 p->usedlen += needed;
418 if (p->errcode == NERR_Success) {
419 p->errcode = ERRmoredata;
426 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
427 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
429 #define PACK(desc,t,v) package(desc,v)
430 #define PACKl(desc,t,v,l) package(desc,v,l)
433 static void PACKI(struct pack_desc* desc, const char *t,int v)
438 static void PACKS(struct pack_desc* desc,const char *t,const char *v)
443 /****************************************************************************
445 ****************************************************************************/
447 static void PackDriverData(struct pack_desc* desc)
449 char drivdata[4+4+32];
450 SIVAL(drivdata,0,sizeof drivdata); /* cb */
451 SIVAL(drivdata,4,1000); /* lVersion */
452 memset(drivdata+8,0,32); /* szDeviceName */
453 push_ascii(drivdata+8,"NULL",32, STR_TERMINATE);
454 PACKl(desc,"l",drivdata,sizeof drivdata); /* pDriverData */
457 static int check_printq_info(struct pack_desc* desc,
458 unsigned int uLevel, char *id1, char *id2)
460 desc->subformat = NULL;
463 desc->format = "B13";
466 desc->format = "B13BWWWzzzzzWW";
469 desc->format = "B13BWWWzzzzzWN";
470 desc->subformat = "WB21BB16B10zWWzDDz";
473 desc->format = "zWWWWzzzzWWzzl";
476 desc->format = "zWWWWzzzzWNzzl";
477 desc->subformat = "WWzWWDDzz";
486 desc->format = "WzzzzzzzzN";
487 desc->subformat = "z";
490 DEBUG(0,("check_printq_info: invalid level %d\n",
494 if (id1 == NULL || strcmp(desc->format,id1) != 0) {
495 DEBUG(0,("check_printq_info: invalid format %s\n",
496 id1 ? id1 : "<NULL>" ));
499 if (desc->subformat && (id2 == NULL || strcmp(desc->subformat,id2) != 0)) {
500 DEBUG(0,("check_printq_info: invalid subformat %s\n",
501 id2 ? id2 : "<NULL>" ));
508 #define RAP_JOB_STATUS_QUEUED 0
509 #define RAP_JOB_STATUS_PAUSED 1
510 #define RAP_JOB_STATUS_SPOOLING 2
511 #define RAP_JOB_STATUS_PRINTING 3
512 #define RAP_JOB_STATUS_PRINTED 4
514 #define RAP_QUEUE_STATUS_PAUSED 1
515 #define RAP_QUEUE_STATUS_ERROR 2
517 /* turn a print job status into a on the wire status
519 static int printj_spoolss_status(int v)
521 if (v == JOB_STATUS_QUEUED)
522 return RAP_JOB_STATUS_QUEUED;
523 if (v & JOB_STATUS_PAUSED)
524 return RAP_JOB_STATUS_PAUSED;
525 if (v & JOB_STATUS_SPOOLING)
526 return RAP_JOB_STATUS_SPOOLING;
527 if (v & JOB_STATUS_PRINTING)
528 return RAP_JOB_STATUS_PRINTING;
532 /* turn a print queue status into a on the wire status
534 static int printq_spoolss_status(int v)
536 if (v == PRINTER_STATUS_OK)
538 if (v & PRINTER_STATUS_PAUSED)
539 return RAP_QUEUE_STATUS_PAUSED;
540 return RAP_QUEUE_STATUS_ERROR;
543 static void fill_spoolss_printjob_info(int uLevel,
544 struct pack_desc *desc,
545 struct spoolss_JobInfo2 *info2,
548 time_t t = spoolss_Time_to_time_t(&info2->submitted);
550 /* the client expects localtime */
551 t -= get_time_zone(t);
553 PACKI(desc,"W",pjobid_to_rap(info2->printer_name, info2->job_id)); /* uJobId */
555 PACKS(desc,"B21", info2->user_name); /* szUserName */
556 PACKS(desc,"B",""); /* pad */
557 PACKS(desc,"B16",""); /* szNotifyName */
558 PACKS(desc,"B10","PM_Q_RAW"); /* szDataType */
559 PACKS(desc,"z",""); /* pszParms */
560 PACKI(desc,"W",n+1); /* uPosition */
561 PACKI(desc,"W", printj_spoolss_status(info2->status)); /* fsStatus */
562 PACKS(desc,"z",""); /* pszStatus */
563 PACKI(desc,"D", t); /* ulSubmitted */
564 PACKI(desc,"D", info2->size); /* ulSize */
565 PACKS(desc,"z", info2->document_name); /* pszComment */
567 if (uLevel == 2 || uLevel == 3 || uLevel == 4) {
568 PACKI(desc,"W", info2->priority); /* uPriority */
569 PACKS(desc,"z", info2->user_name); /* pszUserName */
570 PACKI(desc,"W",n+1); /* uPosition */
571 PACKI(desc,"W", printj_spoolss_status(info2->status)); /* fsStatus */
572 PACKI(desc,"D",t); /* ulSubmitted */
573 PACKI(desc,"D", info2->size); /* ulSize */
574 PACKS(desc,"z","Samba"); /* pszComment */
575 PACKS(desc,"z", info2->document_name); /* pszDocument */
577 PACKS(desc,"z",""); /* pszNotifyName */
578 PACKS(desc,"z","PM_Q_RAW"); /* pszDataType */
579 PACKS(desc,"z",""); /* pszParms */
580 PACKS(desc,"z",""); /* pszStatus */
581 PACKS(desc,"z", info2->printer_name); /* pszQueue */
582 PACKS(desc,"z","lpd"); /* pszQProcName */
583 PACKS(desc,"z",""); /* pszQProcParms */
584 PACKS(desc,"z","NULL"); /* pszDriverName */
585 PackDriverData(desc); /* pDriverData */
586 PACKS(desc,"z",""); /* pszPrinterName */
587 } else if (uLevel == 4) { /* OS2 */
588 PACKS(desc,"z",""); /* pszSpoolFileName */
589 PACKS(desc,"z",""); /* pszPortName */
590 PACKS(desc,"z",""); /* pszStatus */
591 PACKI(desc,"D",0); /* ulPagesSpooled */
592 PACKI(desc,"D",0); /* ulPagesSent */
593 PACKI(desc,"D",0); /* ulPagesPrinted */
594 PACKI(desc,"D",0); /* ulTimePrinted */
595 PACKI(desc,"D",0); /* ulExtendJobStatus */
596 PACKI(desc,"D",0); /* ulStartPage */
597 PACKI(desc,"D",0); /* ulEndPage */
602 /********************************************************************
603 Respond to the DosPrintQInfo command with a level of 52
604 This is used to get printer driver information for Win9x clients
605 ********************************************************************/
606 static void fill_printq_info_52(struct spoolss_DriverInfo3 *driver,
607 struct pack_desc* desc, int count,
608 const char *printer_name)
612 trim_string((char *)driver->driver_path, "\\print$\\WIN40\\0\\", 0);
613 trim_string((char *)driver->data_file, "\\print$\\WIN40\\0\\", 0);
614 trim_string((char *)driver->help_file, "\\print$\\WIN40\\0\\", 0);
616 PACKI(desc, "W", 0x0400); /* don't know */
617 PACKS(desc, "z", driver->driver_name); /* long printer name */
618 PACKS(desc, "z", driver->driver_path); /* Driverfile Name */
619 PACKS(desc, "z", driver->data_file); /* Datafile name */
620 PACKS(desc, "z", driver->monitor_name); /* language monitor */
622 fstrcpy(location, "\\\\%L\\print$\\WIN40\\0");
623 standard_sub_basic( "", "", location, sizeof(location)-1 );
624 PACKS(desc,"z", location); /* share to retrieve files */
626 PACKS(desc,"z", driver->default_datatype); /* default data type */
627 PACKS(desc,"z", driver->help_file); /* helpfile name */
628 PACKS(desc,"z", driver->driver_path); /* driver name */
630 DEBUG(3,("Printer Driver Name: %s:\n",driver->driver_name));
631 DEBUG(3,("Driver: %s:\n",driver->driver_path));
632 DEBUG(3,("Data File: %s:\n",driver->data_file));
633 DEBUG(3,("Language Monitor: %s:\n",driver->monitor_name));
634 DEBUG(3,("Driver Location: %s:\n",location));
635 DEBUG(3,("Data Type: %s:\n",driver->default_datatype));
636 DEBUG(3,("Help File: %s:\n",driver->help_file));
637 PACKI(desc,"N",count); /* number of files to copy */
639 for ( i=0; i<count && driver->dependent_files && *driver->dependent_files[i]; i++)
641 trim_string((char *)driver->dependent_files[i], "\\print$\\WIN40\\0\\", 0);
642 PACKS(desc,"z",driver->dependent_files[i]); /* driver files to copy */
643 DEBUG(3,("Dependent File: %s:\n", driver->dependent_files[i]));
648 DEBUG(3,("fill_printq_info_52: file count specified by client [%d] != number of dependent files [%i]\n",
651 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n", printer_name, i));
653 desc->errcode=NERR_Success;
657 static const char *strip_unc(const char *unc)
665 if ((p = strrchr(unc, '\\')) != NULL) {
672 static void fill_printq_info(int uLevel,
673 struct pack_desc* desc,
675 union spoolss_JobInfo *job_info,
676 struct spoolss_DriverInfo3 *driver_info,
677 struct spoolss_PrinterInfo2 *printer_info)
683 PACKS(desc,"B13", strip_unc(printer_info->printername));
688 PACKS(desc,"z", strip_unc(printer_info->printername));
691 PACKI(desc,"K", printq_spoolss_status(printer_info->status));
695 if (uLevel == 1 || uLevel == 2) {
696 PACKS(desc,"B",""); /* alignment */
697 PACKI(desc,"W",5); /* priority */
698 PACKI(desc,"W",0); /* start time */
699 PACKI(desc,"W",0); /* until time */
700 PACKS(desc,"z",""); /* pSepFile */
701 PACKS(desc,"z","lpd"); /* pPrProc */
702 PACKS(desc,"z", strip_unc(printer_info->printername)); /* pDestinations */
703 PACKS(desc,"z",""); /* pParms */
704 if (printer_info->printername == NULL) {
705 PACKS(desc,"z","UNKNOWN PRINTER");
706 PACKI(desc,"W",LPSTAT_ERROR);
708 PACKS(desc,"z", printer_info->comment);
709 PACKI(desc,"W", printq_spoolss_status(printer_info->status)); /* status */
711 PACKI(desc,(uLevel == 1 ? "W" : "N"),count);
714 if (uLevel == 3 || uLevel == 4) {
715 PACKI(desc,"W",5); /* uPriority */
716 PACKI(desc,"W",0); /* uStarttime */
717 PACKI(desc,"W",0); /* uUntiltime */
718 PACKI(desc,"W",5); /* pad1 */
719 PACKS(desc,"z",""); /* pszSepFile */
720 PACKS(desc,"z","WinPrint"); /* pszPrProc */
721 PACKS(desc,"z",NULL); /* pszParms */
722 PACKS(desc,"z",NULL); /* pszComment - don't ask.... JRA */
723 /* "don't ask" that it's done this way to fix corrupted
724 Win9X/ME printer comments. */
725 PACKI(desc,"W", printq_spoolss_status(printer_info->status)); /* fsStatus */
726 PACKI(desc,(uLevel == 3 ? "W" : "N"),count); /* cJobs */
727 PACKS(desc,"z", strip_unc(printer_info->printername)); /* pszPrinters */
728 PACKS(desc,"z", printer_info->drivername); /* pszDriverName */
729 PackDriverData(desc); /* pDriverData */
732 if (uLevel == 2 || uLevel == 4) {
734 for (i = 0; i < count; i++) {
735 fill_spoolss_printjob_info(uLevel == 2 ? 1 : 2, desc, &job_info[i].info2, i);
740 fill_printq_info_52(driver_info, desc, count, printer_info->printername);
743 /* This function returns the number of files for a given driver */
744 static int get_printerdrivernumber(const struct spoolss_DriverInfo3 *driver)
748 /* count the number of files */
749 while (driver->dependent_files && *driver->dependent_files[result])
755 static bool api_DosPrintQGetInfo(struct smbd_server_connection *sconn,
756 connection_struct *conn, uint16 vuid,
757 char *param, int tpscnt,
758 char *data, int tdscnt,
759 int mdrcnt,int mprcnt,
760 char **rdata,char **rparam,
761 int *rdata_len,int *rparam_len)
763 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
764 char *str2 = skip_string(param,tpscnt,str1);
765 char *p = skip_string(param,tpscnt,str2);
770 struct pack_desc desc;
773 WERROR werr = WERR_OK;
774 TALLOC_CTX *mem_ctx = talloc_tos();
776 struct rpc_pipe_client *cli = NULL;
777 struct dcerpc_binding_handle *b = NULL;
778 struct policy_handle handle;
779 struct spoolss_DevmodeContainer devmode_ctr;
780 union spoolss_DriverInfo driver_info;
781 union spoolss_JobInfo *job_info = NULL;
782 union spoolss_PrinterInfo printer_info;
784 if (!str1 || !str2 || !p) {
787 memset((char *)&desc,'\0',sizeof(desc));
789 p = skip_string(param,tpscnt,p);
793 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
794 str3 = get_safe_str_ptr(param,tpscnt,p,4);
795 /* str3 may be null here and is checked in check_printq_info(). */
797 /* remove any trailing username */
798 if ((p = strchr_m(QueueName,'%')))
801 DEBUG(3,("api_DosPrintQGetInfo uLevel=%d name=%s\n",uLevel,QueueName));
803 /* check it's a supported varient */
804 if (!prefix_ok(str1,"zWrLh"))
806 if (!check_printq_info(&desc,uLevel,str2,str3)) {
808 * Patch from Scott Moomaw <scott@bridgewater.edu>
809 * to return the 'invalid info level' error if an
810 * unknown level was requested.
814 *rparam = smb_realloc_limit(*rparam,*rparam_len);
818 SSVALS(*rparam,0,ERRunknownlevel);
826 if (QueueName == NULL || (strlen(QueueName) < 1)) {
827 desc.errcode = W_ERROR_V(WERR_INVALID_PARAM);
831 status = rpc_pipe_open_interface(conn,
832 &ndr_table_spoolss.syntax_id,
834 &conn->sconn->client_id,
835 conn->sconn->msg_ctx,
837 if (!NT_STATUS_IS_OK(status)) {
838 DEBUG(0,("api_DosPrintQGetInfo: could not connect to spoolss: %s\n",
840 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
843 b = cli->binding_handle;
845 ZERO_STRUCT(devmode_ctr);
847 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
854 if (!NT_STATUS_IS_OK(status)) {
855 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
858 if (!W_ERROR_IS_OK(werr)) {
859 desc.errcode = W_ERROR_V(werr);
863 werr = rpccli_spoolss_getprinter(cli, mem_ctx,
868 if (!W_ERROR_IS_OK(werr)) {
869 desc.errcode = W_ERROR_V(werr);
874 uint32_t server_major_version;
875 uint32_t server_minor_version;
877 werr = rpccli_spoolss_getprinterdriver2(cli, mem_ctx,
885 &server_major_version,
886 &server_minor_version);
887 if (!W_ERROR_IS_OK(werr)) {
888 desc.errcode = W_ERROR_V(werr);
892 count = get_printerdrivernumber(&driver_info.info3);
893 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count));
896 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
904 if (!W_ERROR_IS_OK(werr)) {
905 desc.errcode = W_ERROR_V(werr);
913 *rdata = smb_realloc_limit(*rdata,mdrcnt);
918 desc.buflen = mdrcnt;
921 * Don't return data but need to get correct length
922 * init_package will return wrong size if buflen=0
924 desc.buflen = getlen(desc.format);
925 desc.base = tmpdata = (char *) SMB_MALLOC (desc.buflen);
928 if (init_package(&desc,1,count)) {
929 desc.subcount = count;
930 fill_printq_info(uLevel,&desc,count, job_info, &driver_info.info3, &printer_info.info2);
933 *rdata_len = desc.usedlen;
936 * We must set the return code to ERRbuftoosmall
937 * in order to support lanman style printing with Win NT/2k
940 if (!mdrcnt && lp_disable_spoolss())
941 desc.errcode = ERRbuftoosmall;
944 if (b && is_valid_policy_hnd(&handle)) {
945 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
948 *rdata_len = desc.usedlen;
950 *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));
966 /****************************************************************************
967 View list of all print jobs on all queues.
968 ****************************************************************************/
970 static bool api_DosPrintQEnum(struct smbd_server_connection *sconn,
971 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);
984 struct pack_desc desc;
985 int *subcntarr = NULL;
986 int queuecnt = 0, subcnt = 0, succnt = 0;
988 WERROR werr = WERR_OK;
989 TALLOC_CTX *mem_ctx = talloc_tos();
991 struct rpc_pipe_client *cli = NULL;
992 struct dcerpc_binding_handle *b = NULL;
993 struct spoolss_DevmodeContainer devmode_ctr;
994 uint32_t num_printers;
995 union spoolss_PrinterInfo *printer_info;
996 union spoolss_DriverInfo *driver_info;
997 union spoolss_JobInfo **job_info;
999 if (!param_format || !output_format1 || !p) {
1003 memset((char *)&desc,'\0',sizeof(desc));
1005 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
1007 if (!prefix_ok(param_format,"WrLeh")) {
1010 if (!check_printq_info(&desc,uLevel,output_format1,output_format2)) {
1012 * Patch from Scott Moomaw <scott@bridgewater.edu>
1013 * to return the 'invalid info level' error if an
1014 * unknown level was requested.
1018 *rparam = smb_realloc_limit(*rparam,*rparam_len);
1022 SSVALS(*rparam,0,ERRunknownlevel);
1028 status = rpc_pipe_open_interface(conn,
1029 &ndr_table_spoolss.syntax_id,
1031 &conn->sconn->client_id,
1032 conn->sconn->msg_ctx,
1034 if (!NT_STATUS_IS_OK(status)) {
1035 DEBUG(0,("api_DosPrintQEnum: could not connect to spoolss: %s\n",
1036 nt_errstr(status)));
1037 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
1040 b = cli->binding_handle;
1042 werr = rpccli_spoolss_enumprinters(cli, mem_ctx,
1044 cli->srv_name_slash,
1049 if (!W_ERROR_IS_OK(werr)) {
1050 desc.errcode = W_ERROR_V(werr);
1054 queuecnt = num_printers;
1056 job_info = talloc_array(mem_ctx, union spoolss_JobInfo *, num_printers);
1057 if (job_info == NULL) {
1061 driver_info = talloc_array(mem_ctx, union spoolss_DriverInfo, num_printers);
1062 if (driver_info == NULL) {
1066 if((subcntarr = SMB_MALLOC_ARRAY(int,queuecnt)) == NULL) {
1067 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
1072 *rdata = smb_realloc_limit(*rdata,mdrcnt);
1078 desc.buflen = mdrcnt;
1081 for (i = 0; i < num_printers; i++) {
1084 struct policy_handle handle;
1085 const char *printername;
1087 printername = talloc_strdup(mem_ctx, printer_info[i].info2.printername);
1088 if (printername == NULL) {
1092 ZERO_STRUCT(handle);
1093 ZERO_STRUCT(devmode_ctr);
1095 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
1102 if (!NT_STATUS_IS_OK(status)) {
1103 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
1106 if (!W_ERROR_IS_OK(werr)) {
1107 desc.errcode = W_ERROR_V(werr);
1111 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
1119 if (!W_ERROR_IS_OK(werr)) {
1120 desc.errcode = W_ERROR_V(werr);
1125 uint32_t server_major_version;
1126 uint32_t server_minor_version;
1128 werr = rpccli_spoolss_getprinterdriver2(cli, mem_ctx,
1136 &server_major_version,
1137 &server_minor_version);
1138 if (!W_ERROR_IS_OK(werr)) {
1139 desc.errcode = W_ERROR_V(werr);
1144 subcntarr[i] = num_jobs;
1145 subcnt += subcntarr[i];
1147 if (b && is_valid_policy_hnd(&handle)) {
1148 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
1152 if (init_package(&desc,queuecnt,subcnt)) {
1153 for (i = 0; i < num_printers; i++) {
1154 fill_printq_info(uLevel,&desc,subcntarr[i], job_info[i], &driver_info[i].info3, &printer_info[i].info2);
1155 if (desc.errcode == NERR_Success) {
1161 SAFE_FREE(subcntarr);
1163 *rdata_len = desc.usedlen;
1165 *rparam = smb_realloc_limit(*rparam,*rparam_len);
1169 SSVALS(*rparam,0,desc.errcode);
1171 SSVAL(*rparam,4,succnt);
1172 SSVAL(*rparam,6,queuecnt);
1178 SAFE_FREE(subcntarr);
1183 /****************************************************************************
1184 Get info level for a server list query.
1185 ****************************************************************************/
1187 static bool check_server_info(int uLevel, char* id)
1191 if (strcmp(id,"B16") != 0) {
1196 if (strcmp(id,"B16BBDz") != 0) {
1206 struct srv_info_struct {
1214 /*******************************************************************
1215 Get server info lists from the files saved by nmbd. Return the
1217 ******************************************************************/
1219 static int get_server_info(uint32 servertype,
1220 struct srv_info_struct **servers,
1226 bool local_list_only;
1229 lines = file_lines_load(cache_path(SERVER_LIST), NULL, 0, NULL);
1231 DEBUG(4,("Can't open %s - %s\n",cache_path(SERVER_LIST),strerror(errno)));
1235 /* request for everything is code for request all servers */
1236 if (servertype == SV_TYPE_ALL) {
1237 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1240 local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY);
1242 DEBUG(4,("Servertype search: %8x\n",servertype));
1244 for (i=0;lines[i];i++) {
1246 struct srv_info_struct *s;
1247 const char *ptr = lines[i];
1249 TALLOC_CTX *frame = NULL;
1256 if (count == alloced) {
1258 *servers = SMB_REALLOC_ARRAY(*servers,struct srv_info_struct, alloced);
1260 DEBUG(0,("get_server_info: failed to enlarge servers info struct!\n"));
1264 memset((char *)((*servers)+count),'\0',sizeof(**servers)*(alloced-count));
1266 s = &(*servers)[count];
1268 frame = talloc_stackframe();
1270 if (!next_token_talloc(frame,&ptr,&p, NULL)) {
1274 fstrcpy(s->name, p);
1277 if (!next_token_talloc(frame,&ptr, &p, NULL)) {
1283 s->comment[0] = '\0';
1284 if (!next_token_talloc(frame,&ptr, &p, NULL)) {
1288 fstrcpy(s->comment, p);
1289 string_truncate(s->comment, MAX_SERVER_STRING_LENGTH);
1291 s->domain[0] = '\0';
1292 if (!next_token_talloc(frame,&ptr,&p, NULL)) {
1293 /* this allows us to cope with an old nmbd */
1294 fstrcpy(s->domain,lp_workgroup());
1296 fstrcpy(s->domain, p);
1300 if (sscanf(stype,"%X",&s->type) != 1) {
1301 DEBUG(4,("r:host file "));
1305 /* Filter the servers/domains we return based on what was asked for. */
1307 /* Check to see if we are being asked for a local list only. */
1308 if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) {
1309 DEBUG(4,("r: local list only"));
1313 /* doesn't match up: don't want it */
1314 if (!(servertype & s->type)) {
1315 DEBUG(4,("r:serv type "));
1319 if ((servertype & SV_TYPE_DOMAIN_ENUM) !=
1320 (s->type & SV_TYPE_DOMAIN_ENUM)) {
1321 DEBUG(4,("s: dom mismatch "));
1325 if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM)) {
1329 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1330 s->type &= ~SV_TYPE_LOCAL_LIST_ONLY;
1333 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1334 s->name, s->type, s->comment, s->domain));
1335 s->server_added = True;
1338 DEBUG(4,("%20s %8x %25s %15s\n",
1339 s->name, s->type, s->comment, s->domain));
1347 /*******************************************************************
1348 Fill in a server info structure.
1349 ******************************************************************/
1351 static int fill_srv_info(struct srv_info_struct *service,
1352 int uLevel, char **buf, int *buflen,
1353 char **stringbuf, int *stringspace, char *baseaddr)
1376 len = strlen(service->comment)+1;
1380 *buflen = struct_len;
1382 return struct_len + len;
1387 if (*buflen < struct_len) {
1394 p2 = p + struct_len;
1395 l2 = *buflen - struct_len;
1403 push_ascii(p,service->name, MAX_NETBIOSNAME_LEN, STR_TERMINATE);
1407 push_ascii(p,service->name,MAX_NETBIOSNAME_LEN, STR_TERMINATE);
1408 SIVAL(p,18,service->type);
1409 SIVAL(p,22,PTR_DIFF(p2,baseaddr));
1410 len += CopyAndAdvance(&p2,service->comment,&l2);
1415 *buf = p + struct_len;
1416 *buflen -= struct_len;
1427 static int srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
1429 return StrCaseCmp(s1->name,s2->name);
1432 /****************************************************************************
1433 View list of servers available (or possibly domains). The info is
1434 extracted from lists saved by nmbd on the local host.
1435 ****************************************************************************/
1437 static bool api_RNetServerEnum2(struct smbd_server_connection *sconn,
1438 connection_struct *conn, uint16 vuid,
1439 char *param, int tpscnt,
1440 char *data, int tdscnt,
1441 int mdrcnt, int mprcnt, char **rdata,
1442 char **rparam, int *rdata_len, int *rparam_len)
1444 char *str1 = get_safe_str_ptr(param, tpscnt, param, 2);
1445 char *str2 = skip_string(param,tpscnt,str1);
1446 char *p = skip_string(param,tpscnt,str2);
1447 int uLevel = get_safe_SVAL(param, tpscnt, p, 0, -1);
1448 int buf_len = get_safe_SVAL(param,tpscnt, p, 2, 0);
1449 uint32 servertype = get_safe_IVAL(param,tpscnt,p,4, 0);
1451 int data_len, fixed_len, string_len;
1452 int f_len = 0, s_len = 0;
1453 struct srv_info_struct *servers=NULL;
1454 int counted=0,total=0;
1457 bool domain_request;
1460 if (!str1 || !str2 || !p) {
1464 /* If someone sets all the bits they don't really mean to set
1465 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1468 if (servertype == SV_TYPE_ALL) {
1469 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1472 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1473 any other bit (they may just set this bit on its own) they
1474 want all the locally seen servers. However this bit can be
1475 set on its own so set the requested servers to be
1476 ALL - DOMAIN_ENUM. */
1478 if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM)) {
1479 servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
1482 domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
1483 local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
1487 if (!prefix_ok(str1,"WrLehD")) {
1490 if (!check_server_info(uLevel,str2)) {
1494 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1495 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1496 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1498 if (strcmp(str1, "WrLehDz") == 0) {
1499 if (skip_string(param,tpscnt,p) == NULL) {
1502 pull_ascii_fstring(domain, p);
1504 fstrcpy(domain, lp_workgroup());
1507 DEBUG(4, ("domain [%s]\n", domain));
1509 if (lp_browse_list()) {
1510 total = get_server_info(servertype,&servers,domain);
1513 data_len = fixed_len = string_len = 0;
1516 TYPESAFE_QSORT(servers, total, srv_comp);
1519 char *lastname=NULL;
1521 for (i=0;i<total;i++) {
1522 struct srv_info_struct *s = &servers[i];
1524 if (lastname && strequal(lastname,s->name)) {
1528 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1529 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1530 i, s->name, s->type, s->comment, s->domain));
1532 if (data_len < buf_len) {
1535 string_len += s_len;
1542 *rdata_len = fixed_len + string_len;
1543 *rdata = smb_realloc_limit(*rdata,*rdata_len);
1548 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1554 char *lastname=NULL;
1555 int count2 = counted;
1557 for (i = 0; i < total && count2;i++) {
1558 struct srv_info_struct *s = &servers[i];
1560 if (lastname && strequal(lastname,s->name)) {
1564 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1565 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1566 i, s->name, s->type, s->comment, s->domain));
1572 *rparam = smb_realloc_limit(*rparam,*rparam_len);
1576 SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata));
1578 SSVAL(*rparam,4,counted);
1579 SSVAL(*rparam,6,counted+missed);
1583 DEBUG(3,("NetServerEnum2 domain = %s uLevel=%d counted=%d total=%d\n",
1584 domain,uLevel,counted,counted+missed));
1589 static int srv_name_match(const char *n1, const char *n2)
1592 * [MS-RAP] footnote <88> for Section 3.2.5.15 says:
1594 * In Windows, FirstNameToReturn need not be an exact match:
1595 * the server will return a list of servers that exist on
1596 * the network greater than or equal to the FirstNameToReturn.
1598 int ret = StrCaseCmp(n1, n2);
1607 static bool api_RNetServerEnum3(struct smbd_server_connection *sconn,
1608 connection_struct *conn, uint16 vuid,
1609 char *param, int tpscnt,
1610 char *data, int tdscnt,
1611 int mdrcnt, int mprcnt, char **rdata,
1612 char **rparam, int *rdata_len, int *rparam_len)
1614 char *str1 = get_safe_str_ptr(param, tpscnt, param, 2);
1615 char *str2 = skip_string(param,tpscnt,str1);
1616 char *p = skip_string(param,tpscnt,str2);
1617 int uLevel = get_safe_SVAL(param, tpscnt, p, 0, -1);
1618 int buf_len = get_safe_SVAL(param,tpscnt, p, 2, 0);
1619 uint32 servertype = get_safe_IVAL(param,tpscnt,p,4, 0);
1621 int data_len, fixed_len, string_len;
1622 int f_len = 0, s_len = 0;
1623 struct srv_info_struct *servers=NULL;
1624 int counted=0,first=0,total=0;
1628 bool domain_request;
1631 if (!str1 || !str2 || !p) {
1635 /* If someone sets all the bits they don't really mean to set
1636 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1639 if (servertype == SV_TYPE_ALL) {
1640 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1643 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1644 any other bit (they may just set this bit on its own) they
1645 want all the locally seen servers. However this bit can be
1646 set on its own so set the requested servers to be
1647 ALL - DOMAIN_ENUM. */
1649 if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM)) {
1650 servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
1653 domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
1654 local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
1658 if (strcmp(str1, "WrLehDzz") != 0) {
1661 if (!check_server_info(uLevel,str2)) {
1665 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1666 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1667 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1669 if (skip_string(param,tpscnt,p) == NULL) {
1672 pull_ascii_fstring(domain, p);
1673 if (domain[0] == '\0') {
1674 fstrcpy(domain, lp_workgroup());
1676 p = skip_string(param,tpscnt,p);
1677 if (skip_string(param,tpscnt,p) == NULL) {
1680 pull_ascii_fstring(first_name, p);
1682 DEBUG(4, ("domain: '%s' first_name: '%s'\n",
1683 domain, first_name));
1685 if (lp_browse_list()) {
1686 total = get_server_info(servertype,&servers,domain);
1689 data_len = fixed_len = string_len = 0;
1692 TYPESAFE_QSORT(servers, total, srv_comp);
1694 if (first_name[0] != '\0') {
1695 struct srv_info_struct *first_server = NULL;
1697 BINARY_ARRAY_SEARCH(servers, total, name, first_name,
1698 srv_name_match, first_server);
1700 first = PTR_DIFF(first_server, servers) / sizeof(*servers);
1702 * The binary search may not find the exact match
1703 * so we need to search backward to find the first match
1705 * This implements the strange matching windows
1706 * implements. (see the comment in srv_name_match().
1710 ret = StrCaseCmp(first_name,
1711 servers[first-1].name);
1718 /* we should return no entries */
1724 char *lastname=NULL;
1726 for (i=first;i<total;i++) {
1727 struct srv_info_struct *s = &servers[i];
1729 if (lastname && strequal(lastname,s->name)) {
1733 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1734 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1735 i, s->name, s->type, s->comment, s->domain));
1737 if (data_len < buf_len) {
1740 string_len += s_len;
1747 *rdata_len = fixed_len + string_len;
1748 *rdata = smb_realloc_limit(*rdata,*rdata_len);
1753 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1759 char *lastname=NULL;
1760 int count2 = counted;
1762 for (i = first; i < total && count2;i++) {
1763 struct srv_info_struct *s = &servers[i];
1765 if (lastname && strequal(lastname,s->name)) {
1769 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1770 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1771 i, s->name, s->type, s->comment, s->domain));
1777 *rparam = smb_realloc_limit(*rparam,*rparam_len);
1781 SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata));
1783 SSVAL(*rparam,4,counted);
1784 SSVAL(*rparam,6,counted+missed);
1786 DEBUG(3,("NetServerEnum3 domain = %s uLevel=%d first=%d[%s => %s] counted=%d total=%d\n",
1787 domain,uLevel,first,first_name,
1788 first < total ? servers[first].name : "",
1789 counted,counted+missed));
1796 /****************************************************************************
1797 command 0x34 - suspected of being a "Lookup Names" stub api
1798 ****************************************************************************/
1800 static bool api_RNetGroupGetUsers(struct smbd_server_connection *sconn,
1801 connection_struct *conn, uint16 vuid,
1802 char *param, int tpscnt,
1803 char *data, int tdscnt,
1804 int mdrcnt, int mprcnt, char **rdata,
1805 char **rparam, int *rdata_len, int *rparam_len)
1807 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
1808 char *str2 = skip_string(param,tpscnt,str1);
1809 char *p = skip_string(param,tpscnt,str2);
1810 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
1811 int buf_len = get_safe_SVAL(param,tpscnt,p,2,0);
1815 if (!str1 || !str2 || !p) {
1819 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1820 str1, str2, p, uLevel, buf_len));
1822 if (!prefix_ok(str1,"zWrLeh")) {
1829 *rparam = smb_realloc_limit(*rparam,*rparam_len);
1834 SSVAL(*rparam,0,0x08AC); /* informational warning message */
1836 SSVAL(*rparam,4,counted);
1837 SSVAL(*rparam,6,counted+missed);
1842 /****************************************************************************
1843 get info about a share
1844 ****************************************************************************/
1846 static bool check_share_info(int uLevel, char* id)
1850 if (strcmp(id,"B13") != 0) {
1855 /* Level-2 descriptor is allowed (and ignored) */
1856 if (strcmp(id,"B13BWz") != 0 &&
1857 strcmp(id,"B13BWzWWWzB9B") != 0) {
1862 if (strcmp(id,"B13BWzWWWzB9B") != 0) {
1867 if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) {
1877 static int fill_share_info(connection_struct *conn, int snum, int uLevel,
1878 char** buf, int* buflen,
1879 char** stringbuf, int* stringspace, char* baseaddr)
1908 len += StrlenExpanded(conn,snum,lp_comment(snum));
1911 len += strlen(lp_pathname(snum)) + 1;
1914 *buflen = struct_len;
1919 return struct_len + len;
1924 if ((*buflen) < struct_len) {
1932 p2 = p + struct_len;
1933 l2 = (*buflen) - struct_len;
1940 push_ascii(p,lp_servicename(snum),13, STR_TERMINATE);
1946 type = STYPE_DISKTREE;
1947 if (lp_print_ok(snum)) {
1948 type = STYPE_PRINTQ;
1950 if (strequal("IPC",lp_fstype(snum))) {
1953 SSVAL(p,14,type); /* device type */
1954 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1955 len += CopyExpanded(conn,snum,&p2,lp_comment(snum),&l2);
1959 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1960 SSVALS(p,22,-1); /* max uses */
1961 SSVAL(p,24,1); /* current uses */
1962 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1963 len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1964 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1968 memset(p+40,0,SHPWLEN+2);
1979 (*buf) = p + struct_len;
1980 (*buflen) -= struct_len;
1982 (*stringspace) = l2;
1991 static bool api_RNetShareGetInfo(struct smbd_server_connection *sconn,
1992 connection_struct *conn,uint16 vuid,
1993 char *param, int tpscnt,
1994 char *data, int tdscnt,
1995 int mdrcnt,int mprcnt,
1996 char **rdata,char **rparam,
1997 int *rdata_len,int *rparam_len)
1999 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2000 char *str2 = skip_string(param,tpscnt,str1);
2001 char *netname_in = skip_string(param,tpscnt,str2);
2002 char *netname = NULL;
2003 char *p = skip_string(param,tpscnt,netname);
2004 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
2007 if (!str1 || !str2 || !netname || !p) {
2011 snum = find_service(talloc_tos(), netname_in, &netname);
2012 if (snum < 0 || !netname) {
2016 /* check it's a supported varient */
2017 if (!prefix_ok(str1,"zWrLh")) {
2020 if (!check_share_info(uLevel,str2)) {
2024 *rdata = smb_realloc_limit(*rdata,mdrcnt);
2029 *rdata_len = fill_share_info(conn,snum,uLevel,&p,&mdrcnt,0,0,0);
2030 if (*rdata_len < 0) {
2035 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2039 SSVAL(*rparam,0,NERR_Success);
2040 SSVAL(*rparam,2,0); /* converter word */
2041 SSVAL(*rparam,4,*rdata_len);
2046 /****************************************************************************
2047 View the list of available shares.
2049 This function is the server side of the NetShareEnum() RAP call.
2050 It fills the return buffer with share names and share comments.
2051 Note that the return buffer normally (in all known cases) allows only
2052 twelve byte strings for share names (plus one for a nul terminator).
2053 Share names longer than 12 bytes must be skipped.
2054 ****************************************************************************/
2056 static bool api_RNetShareEnum(struct smbd_server_connection *sconn,
2057 connection_struct *conn, uint16 vuid,
2058 char *param, int tpscnt,
2059 char *data, int tdscnt,
2067 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2068 char *str2 = skip_string(param,tpscnt,str1);
2069 char *p = skip_string(param,tpscnt,str2);
2070 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
2071 int buf_len = get_safe_SVAL(param,tpscnt,p,2,0);
2074 int total=0,counted=0;
2075 bool missed = False;
2077 int data_len, fixed_len, string_len;
2078 int f_len = 0, s_len = 0;
2080 if (!str1 || !str2 || !p) {
2084 if (!prefix_ok(str1,"WrLeh")) {
2087 if (!check_share_info(uLevel,str2)) {
2091 /* Ensure all the usershares are loaded. */
2093 load_registry_shares();
2094 count = load_usershare_shares();
2097 data_len = fixed_len = string_len = 0;
2098 for (i=0;i<count;i++) {
2099 fstring servicename_dos;
2100 if (!(lp_browseable(i) && lp_snum_ok(i))) {
2103 push_ascii_fstring(servicename_dos, lp_servicename(i));
2104 /* Maximum name length = 13. */
2105 if( lp_browseable( i ) && lp_snum_ok( i ) && (strlen(servicename_dos) < 13)) {
2107 data_len += fill_share_info(conn,i,uLevel,0,&f_len,0,&s_len,0);
2108 if (data_len < buf_len) {
2111 string_len += s_len;
2118 *rdata_len = fixed_len + string_len;
2119 *rdata = smb_realloc_limit(*rdata,*rdata_len);
2124 p2 = (*rdata) + fixed_len; /* auxiliary data (strings) will go here */
2129 for( i = 0; i < count; i++ ) {
2130 fstring servicename_dos;
2131 if (!(lp_browseable(i) && lp_snum_ok(i))) {
2135 push_ascii_fstring(servicename_dos, lp_servicename(i));
2136 if (lp_browseable(i) && lp_snum_ok(i) && (strlen(servicename_dos) < 13)) {
2137 if (fill_share_info( conn,i,uLevel,&p,&f_len,&p2,&s_len,*rdata ) < 0) {
2144 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2148 SSVAL(*rparam,0,missed ? ERRmoredata : NERR_Success);
2150 SSVAL(*rparam,4,counted);
2151 SSVAL(*rparam,6,total);
2153 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
2154 counted,total,uLevel,
2155 buf_len,*rdata_len,mdrcnt));
2160 /****************************************************************************
2162 ****************************************************************************/
2164 static bool api_RNetShareAdd(struct smbd_server_connection *sconn,
2165 connection_struct *conn,uint16 vuid,
2166 char *param, int tpscnt,
2167 char *data, int tdscnt,
2168 int mdrcnt,int mprcnt,
2169 char **rdata,char **rparam,
2170 int *rdata_len,int *rparam_len)
2172 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2173 char *str2 = skip_string(param,tpscnt,str1);
2174 char *p = skip_string(param,tpscnt,str2);
2175 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
2178 char *pathname = NULL;
2179 unsigned int offset;
2181 size_t converted_size;
2183 WERROR werr = WERR_OK;
2184 TALLOC_CTX *mem_ctx = talloc_tos();
2186 struct rpc_pipe_client *cli = NULL;
2187 union srvsvc_NetShareInfo info;
2188 struct srvsvc_NetShareInfo2 info2;
2189 struct dcerpc_binding_handle *b;
2191 if (!str1 || !str2 || !p) {
2195 /* check it's a supported varient */
2196 if (!prefix_ok(str1,RAP_WShareAdd_REQ)) {
2199 if (!check_share_info(uLevel,str2)) {
2206 /* Do we have a string ? */
2207 if (skip_string(data,mdrcnt,data) == NULL) {
2210 pull_ascii_fstring(sharename,data);
2216 /* only support disk share adds */
2217 if (SVAL(data,14)!=STYPE_DISKTREE) {
2221 offset = IVAL(data, 16);
2222 if (offset >= mdrcnt) {
2223 res = ERRinvalidparam;
2227 /* Do we have a string ? */
2228 if (skip_string(data,mdrcnt,data+offset) == NULL) {
2231 pull_ascii_fstring(comment, offset? (data+offset) : "");
2233 offset = IVAL(data, 26);
2235 if (offset >= mdrcnt) {
2236 res = ERRinvalidparam;
2240 /* Do we have a string ? */
2241 if (skip_string(data,mdrcnt,data+offset) == NULL) {
2245 if (!pull_ascii_talloc(talloc_tos(), &pathname,
2246 offset ? (data+offset) : "", &converted_size))
2248 DEBUG(0,("api_RNetShareAdd: pull_ascii_talloc failed: %s",
2256 status = rpc_pipe_open_internal(mem_ctx, &ndr_table_srvsvc.syntax_id,
2258 &conn->sconn->client_id,
2259 conn->sconn->msg_ctx,
2261 if (!NT_STATUS_IS_OK(status)) {
2262 DEBUG(0,("api_RNetShareAdd: could not connect to srvsvc: %s\n",
2263 nt_errstr(status)));
2264 res = W_ERROR_V(ntstatus_to_werror(status));
2268 b = cli->binding_handle;
2270 info2.name = sharename;
2271 info2.type = STYPE_DISKTREE;
2272 info2.comment = comment;
2273 info2.permissions = 0;
2274 info2.max_users = 0;
2275 info2.current_users = 0;
2276 info2.path = pathname;
2277 info2.password = NULL;
2279 info.info2 = &info2;
2281 status = dcerpc_srvsvc_NetShareAdd(b, mem_ctx,
2282 cli->srv_name_slash,
2287 if (!NT_STATUS_IS_OK(status)) {
2288 res = W_ERROR_V(ntstatus_to_werror(status));
2291 if (!W_ERROR_IS_OK(werr)) {
2292 res = W_ERROR_V(werr);
2297 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2301 SSVAL(*rparam,0,NERR_Success);
2302 SSVAL(*rparam,2,0); /* converter word */
2303 SSVAL(*rparam,4,*rdata_len);
2311 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2316 SSVAL(*rparam,0,res);
2321 /****************************************************************************
2322 view list of groups available
2323 ****************************************************************************/
2325 static bool api_RNetGroupEnum(struct smbd_server_connection *sconn,
2326 connection_struct *conn,uint16 vuid,
2327 char *param, int tpscnt,
2328 char *data, int tdscnt,
2329 int mdrcnt,int mprcnt,
2330 char **rdata,char **rparam,
2331 int *rdata_len,int *rparam_len)
2335 int resume_context, cli_buf_size;
2336 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2337 char *str2 = skip_string(param,tpscnt,str1);
2338 char *p = skip_string(param,tpscnt,str2);
2340 uint32_t num_groups;
2341 uint32_t resume_handle;
2342 struct rpc_pipe_client *samr_pipe;
2343 struct policy_handle samr_handle, domain_handle;
2346 if (!str1 || !str2 || !p) {
2350 if (strcmp(str1,"WrLeh") != 0) {
2355 * W-> resume context (number of users to skip)
2356 * r -> return parameter pointer to receive buffer
2357 * L -> length of receive buffer
2358 * e -> return parameter number of entries
2359 * h -> return parameter total number of users
2362 if (strcmp("B21",str2) != 0) {
2366 status = rpc_pipe_open_internal(
2367 talloc_tos(), &ndr_table_samr.syntax_id,
2368 conn->server_info, &conn->sconn->client_id,
2369 conn->sconn->msg_ctx, &samr_pipe);
2370 if (!NT_STATUS_IS_OK(status)) {
2371 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2372 nt_errstr(status)));
2376 status = rpccli_samr_Connect2(samr_pipe, talloc_tos(), global_myname(),
2377 SAMR_ACCESS_LOOKUP_DOMAIN, &samr_handle);
2378 if (!NT_STATUS_IS_OK(status)) {
2379 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2380 nt_errstr(status)));
2384 status = rpccli_samr_OpenDomain(samr_pipe, talloc_tos(), &samr_handle,
2385 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS,
2386 get_global_sam_sid(), &domain_handle);
2387 if (!NT_STATUS_IS_OK(status)) {
2388 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2389 nt_errstr(status)));
2390 rpccli_samr_Close(samr_pipe, talloc_tos(), &samr_handle);
2394 resume_context = get_safe_SVAL(param,tpscnt,p,0,-1);
2395 cli_buf_size= get_safe_SVAL(param,tpscnt,p,2,0);
2396 DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: "
2397 "%d\n", resume_context, cli_buf_size));
2399 *rdata_len = cli_buf_size;
2400 *rdata = smb_realloc_limit(*rdata,*rdata_len);
2407 errflags = NERR_Success;
2412 struct samr_SamArray *sam_entries;
2413 uint32_t num_entries;
2415 status = rpccli_samr_EnumDomainGroups(samr_pipe, talloc_tos(),
2420 if (!NT_STATUS_IS_OK(status)) {
2421 DEBUG(10, ("rpccli_samr_EnumDomainGroups returned "
2422 "%s\n", nt_errstr(status)));
2426 if (num_entries == 0) {
2427 DEBUG(10, ("rpccli_samr_EnumDomainGroups returned "
2428 "no entries -- done\n"));
2432 for(i=0; i<num_entries; i++) {
2435 name = sam_entries->entries[i].name.string;
2437 if( ((PTR_DIFF(p,*rdata)+21) > *rdata_len) ) {
2438 /* set overflow error */
2439 DEBUG(3,("overflow on entry %d group %s\n", i,
2445 /* truncate the name at 21 chars. */
2447 strlcpy(p, name, 21);
2448 DEBUG(10,("adding entry %d group %s\n", i, p));
2450 p += 5; /* Both NT4 and W2k3SP1 do padding here. No
2455 if (errflags != NERR_Success) {
2459 TALLOC_FREE(sam_entries);
2462 rpccli_samr_Close(samr_pipe, talloc_tos(), &domain_handle);
2463 rpccli_samr_Close(samr_pipe, talloc_tos(), &samr_handle);
2465 *rdata_len = PTR_DIFF(p,*rdata);
2468 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2472 SSVAL(*rparam, 0, errflags);
2473 SSVAL(*rparam, 2, 0); /* converter word */
2474 SSVAL(*rparam, 4, num_groups); /* is this right?? */
2475 SSVAL(*rparam, 6, resume_context+num_groups); /* is this right?? */
2480 /*******************************************************************
2481 Get groups that a user is a member of.
2482 ******************************************************************/
2484 static bool api_NetUserGetGroups(struct smbd_server_connection *sconn,
2485 connection_struct *conn,uint16 vuid,
2486 char *param, int tpscnt,
2487 char *data, int tdscnt,
2488 int mdrcnt,int mprcnt,
2489 char **rdata,char **rparam,
2490 int *rdata_len,int *rparam_len)
2492 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2493 char *str2 = skip_string(param,tpscnt,str1);
2494 char *UserName = skip_string(param,tpscnt,str2);
2495 char *p = skip_string(param,tpscnt,UserName);
2496 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
2497 const char *level_string;
2503 struct rpc_pipe_client *samr_pipe;
2504 struct policy_handle samr_handle, domain_handle, user_handle;
2505 struct lsa_String name;
2506 struct lsa_Strings names;
2507 struct samr_Ids type, rid;
2508 struct samr_RidWithAttributeArray *rids;
2511 if (!str1 || !str2 || !UserName || !p) {
2516 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2521 /* check it's a supported varient */
2523 if ( strcmp(str1,"zWrLeh") != 0 )
2528 level_string = "B21";
2534 if (strcmp(level_string,str2) != 0)
2537 *rdata_len = mdrcnt + 1024;
2538 *rdata = smb_realloc_limit(*rdata,*rdata_len);
2543 SSVAL(*rparam,0,NERR_Success);
2544 SSVAL(*rparam,2,0); /* converter word */
2547 endp = *rdata + *rdata_len;
2549 status = rpc_pipe_open_internal(
2550 talloc_tos(), &ndr_table_samr.syntax_id,
2551 conn->server_info, &conn->sconn->client_id,
2552 conn->sconn->msg_ctx, &samr_pipe);
2553 if (!NT_STATUS_IS_OK(status)) {
2554 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2555 nt_errstr(status)));
2559 status = rpccli_samr_Connect2(samr_pipe, talloc_tos(), global_myname(),
2560 SAMR_ACCESS_LOOKUP_DOMAIN, &samr_handle);
2561 if (!NT_STATUS_IS_OK(status)) {
2562 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2563 nt_errstr(status)));
2567 status = rpccli_samr_OpenDomain(samr_pipe, talloc_tos(), &samr_handle,
2568 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
2569 get_global_sam_sid(), &domain_handle);
2570 if (!NT_STATUS_IS_OK(status)) {
2571 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2572 nt_errstr(status)));
2576 name.string = UserName;
2578 status = rpccli_samr_LookupNames(samr_pipe, talloc_tos(),
2579 &domain_handle, 1, &name,
2581 if (!NT_STATUS_IS_OK(status)) {
2582 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2583 nt_errstr(status)));
2587 if (type.ids[0] != SID_NAME_USER) {
2588 DEBUG(10, ("%s is a %s, not a user\n", UserName,
2589 sid_type_lookup(type.ids[0])));
2593 status = rpccli_samr_OpenUser(samr_pipe, talloc_tos(),
2595 SAMR_USER_ACCESS_GET_GROUPS,
2596 rid.ids[0], &user_handle);
2597 if (!NT_STATUS_IS_OK(status)) {
2598 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2599 nt_errstr(status)));
2603 status = rpccli_samr_GetGroupsForUser(samr_pipe, talloc_tos(),
2604 &user_handle, &rids);
2605 if (!NT_STATUS_IS_OK(status)) {
2606 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2607 nt_errstr(status)));
2611 for (i=0; i<rids->count; i++) {
2613 status = rpccli_samr_LookupRids(samr_pipe, talloc_tos(),
2615 1, &rids->rids[i].rid,
2617 if (NT_STATUS_IS_OK(status) && (names.count == 1)) {
2618 strlcpy(p, names.names[0].string, PTR_DIFF(endp,p));
2624 *rdata_len = PTR_DIFF(p,*rdata);
2626 SSVAL(*rparam,4,count); /* is this right?? */
2627 SSVAL(*rparam,6,count); /* is this right?? */
2632 rpccli_samr_Close(samr_pipe, talloc_tos(), &user_handle);
2634 rpccli_samr_Close(samr_pipe, talloc_tos(), &domain_handle);
2636 rpccli_samr_Close(samr_pipe, talloc_tos(), &samr_handle);
2641 /*******************************************************************
2643 ******************************************************************/
2645 static bool api_RNetUserEnum(struct smbd_server_connection *sconn,
2646 connection_struct *conn, uint16 vuid,
2647 char *param, int tpscnt,
2648 char *data, int tdscnt,
2649 int mdrcnt,int mprcnt,
2650 char **rdata,char **rparam,
2651 int *rdata_len,int *rparam_len)
2656 int i, resume_context, cli_buf_size;
2657 uint32_t resume_handle;
2659 struct rpc_pipe_client *samr_pipe;
2660 struct policy_handle samr_handle, domain_handle;
2663 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2664 char *str2 = skip_string(param,tpscnt,str1);
2665 char *p = skip_string(param,tpscnt,str2);
2668 if (!str1 || !str2 || !p) {
2672 if (strcmp(str1,"WrLeh") != 0)
2675 * W-> resume context (number of users to skip)
2676 * r -> return parameter pointer to receive buffer
2677 * L -> length of receive buffer
2678 * e -> return parameter number of entries
2679 * h -> return parameter total number of users
2682 resume_context = get_safe_SVAL(param,tpscnt,p,0,-1);
2683 cli_buf_size= get_safe_SVAL(param,tpscnt,p,2,0);
2684 DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n",
2685 resume_context, cli_buf_size));
2688 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2693 /* check it's a supported varient */
2694 if (strcmp("B21",str2) != 0)
2697 *rdata_len = cli_buf_size;
2698 *rdata = smb_realloc_limit(*rdata,*rdata_len);
2704 endp = *rdata + *rdata_len;
2706 status = rpc_pipe_open_internal(
2707 talloc_tos(), &ndr_table_samr.syntax_id,
2708 conn->server_info, &conn->sconn->client_id,
2709 conn->sconn->msg_ctx, &samr_pipe);
2710 if (!NT_STATUS_IS_OK(status)) {
2711 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2712 nt_errstr(status)));
2716 status = rpccli_samr_Connect2(samr_pipe, talloc_tos(), global_myname(),
2717 SAMR_ACCESS_LOOKUP_DOMAIN, &samr_handle);
2718 if (!NT_STATUS_IS_OK(status)) {
2719 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2720 nt_errstr(status)));
2724 status = rpccli_samr_OpenDomain(samr_pipe, talloc_tos(), &samr_handle,
2725 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS,
2726 get_global_sam_sid(), &domain_handle);
2727 if (!NT_STATUS_IS_OK(status)) {
2728 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2729 nt_errstr(status)));
2730 rpccli_samr_Close(samr_pipe, talloc_tos(), &samr_handle);
2734 errflags=NERR_Success;
2739 struct samr_SamArray *sam_entries;
2740 uint32_t num_entries;
2742 status = rpccli_samr_EnumDomainUsers(samr_pipe, talloc_tos(),
2748 if (!NT_STATUS_IS_OK(status)) {
2749 DEBUG(10, ("rpccli_samr_EnumDomainUsers returned "
2750 "%s\n", nt_errstr(status)));
2754 if (num_entries == 0) {
2755 DEBUG(10, ("rpccli_samr_EnumDomainUsers returned "
2756 "no entries -- done\n"));
2760 for (i=0; i<num_entries; i++) {
2763 name = sam_entries->entries[i].name.string;
2765 if(((PTR_DIFF(p,*rdata)+21)<=*rdata_len)
2766 &&(strlen(name)<=21)) {
2767 strlcpy(p,name,PTR_DIFF(endp,p));
2768 DEBUG(10,("api_RNetUserEnum:adding entry %d "
2769 "username %s\n",count_sent,p));
2773 /* set overflow error */
2774 DEBUG(10,("api_RNetUserEnum:overflow on entry %d "
2775 "username %s\n",count_sent,name));
2781 if (errflags != NERR_Success) {
2785 TALLOC_FREE(sam_entries);
2788 rpccli_samr_Close(samr_pipe, talloc_tos(), &domain_handle);
2789 rpccli_samr_Close(samr_pipe, talloc_tos(), &samr_handle);
2791 *rdata_len = PTR_DIFF(p,*rdata);
2793 SSVAL(*rparam,0,errflags);
2794 SSVAL(*rparam,2,0); /* converter word */
2795 SSVAL(*rparam,4,count_sent); /* is this right?? */
2796 SSVAL(*rparam,6,num_users); /* is this right?? */
2801 /****************************************************************************
2802 Get the time of day info.
2803 ****************************************************************************/
2805 static bool api_NetRemoteTOD(struct smbd_server_connection *sconn,
2806 connection_struct *conn,uint16 vuid,
2807 char *param, int tpscnt,
2808 char *data, int tdscnt,
2809 int mdrcnt,int mprcnt,
2810 char **rdata,char **rparam,
2811 int *rdata_len,int *rparam_len)
2814 time_t unixdate = time(NULL);
2818 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2824 *rdata = smb_realloc_limit(*rdata,*rdata_len);
2829 SSVAL(*rparam,0,NERR_Success);
2830 SSVAL(*rparam,2,0); /* converter word */
2834 srv_put_dos_date3(p,0,unixdate); /* this is the time that is looked at
2835 by NT in a "net time" operation,
2836 it seems to ignore the one below */
2838 /* the client expects to get localtime, not GMT, in this bit
2839 (I think, this needs testing) */
2840 t = localtime(&unixdate);
2845 SIVAL(p,4,0); /* msecs ? */
2846 SCVAL(p,8,t->tm_hour);
2847 SCVAL(p,9,t->tm_min);
2848 SCVAL(p,10,t->tm_sec);
2849 SCVAL(p,11,0); /* hundredths of seconds */
2850 SSVALS(p,12,get_time_zone(unixdate)/60); /* timezone in minutes from GMT */
2851 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
2852 SCVAL(p,16,t->tm_mday);
2853 SCVAL(p,17,t->tm_mon + 1);
2854 SSVAL(p,18,1900+t->tm_year);
2855 SCVAL(p,20,t->tm_wday);
2860 /****************************************************************************
2861 Set the user password.
2862 *****************************************************************************/
2864 static bool api_SetUserPassword(struct smbd_server_connection *sconn,
2865 connection_struct *conn,uint16 vuid,
2866 char *param, int tpscnt,
2867 char *data, int tdscnt,
2868 int mdrcnt,int mprcnt,
2869 char **rdata,char **rparam,
2870 int *rdata_len,int *rparam_len)
2872 char *np = get_safe_str_ptr(param,tpscnt,param,2);
2875 fstring pass1,pass2;
2876 TALLOC_CTX *mem_ctx = talloc_tos();
2878 struct rpc_pipe_client *cli = NULL;
2879 struct policy_handle connect_handle, domain_handle, user_handle;
2880 struct lsa_String domain_name;
2881 struct dom_sid2 *domain_sid;
2882 struct lsa_String names;
2883 struct samr_Ids rids;
2884 struct samr_Ids types;
2885 struct samr_Password old_lm_hash;
2886 struct samr_Password new_lm_hash;
2887 int errcode = NERR_badpass;
2892 /* Skip 2 strings. */
2893 p = skip_string(param,tpscnt,np);
2894 p = skip_string(param,tpscnt,p);
2900 /* Do we have a string ? */
2901 if (skip_string(param,tpscnt,p) == NULL) {
2904 pull_ascii_fstring(user,p);
2906 p = skip_string(param,tpscnt,p);
2911 memset(pass1,'\0',sizeof(pass1));
2912 memset(pass2,'\0',sizeof(pass2));
2914 * We use 31 here not 32 as we're checking
2915 * the last byte we want to access is safe.
2917 if (!is_offset_safe(param,tpscnt,p,31)) {
2921 memcpy(pass2,p+16,16);
2923 encrypted = get_safe_SVAL(param,tpscnt,p+32,0,-1);
2924 if (encrypted == -1) {
2925 errcode = W_ERROR_V(WERR_INVALID_PARAM);
2929 min_pwd_length = get_safe_SVAL(param,tpscnt,p+34,0,-1);
2930 if (min_pwd_length == -1) {
2931 errcode = W_ERROR_V(WERR_INVALID_PARAM);
2936 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2943 DEBUG(3,("Set password for <%s> (encrypted: %d, min_pwd_length: %d)\n",
2944 user, encrypted, min_pwd_length));
2946 ZERO_STRUCT(connect_handle);
2947 ZERO_STRUCT(domain_handle);
2948 ZERO_STRUCT(user_handle);
2950 status = rpc_pipe_open_internal(mem_ctx, &ndr_table_samr.syntax_id,
2952 &conn->sconn->client_id,
2953 conn->sconn->msg_ctx,
2955 if (!NT_STATUS_IS_OK(status)) {
2956 DEBUG(0,("api_SetUserPassword: could not connect to samr: %s\n",
2957 nt_errstr(status)));
2958 errcode = W_ERROR_V(ntstatus_to_werror(status));
2962 status = rpccli_samr_Connect2(cli, mem_ctx,
2964 SAMR_ACCESS_CONNECT_TO_SERVER |
2965 SAMR_ACCESS_ENUM_DOMAINS |
2966 SAMR_ACCESS_LOOKUP_DOMAIN,
2968 if (!NT_STATUS_IS_OK(status)) {
2969 errcode = W_ERROR_V(ntstatus_to_werror(status));
2973 init_lsa_String(&domain_name, get_global_sam_name());
2975 status = rpccli_samr_LookupDomain(cli, mem_ctx,
2979 if (!NT_STATUS_IS_OK(status)) {
2980 errcode = W_ERROR_V(ntstatus_to_werror(status));
2984 status = rpccli_samr_OpenDomain(cli, mem_ctx,
2986 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
2989 if (!NT_STATUS_IS_OK(status)) {
2990 errcode = W_ERROR_V(ntstatus_to_werror(status));
2994 init_lsa_String(&names, user);
2996 status = rpccli_samr_LookupNames(cli, mem_ctx,
3002 if (!NT_STATUS_IS_OK(status)) {
3003 errcode = W_ERROR_V(ntstatus_to_werror(status));
3007 if (rids.count != 1) {
3008 errcode = W_ERROR_V(WERR_NO_SUCH_USER);
3011 if (rids.count != types.count) {
3012 errcode = W_ERROR_V(WERR_INVALID_PARAM);
3015 if (types.ids[0] != SID_NAME_USER) {
3016 errcode = W_ERROR_V(WERR_INVALID_PARAM);
3022 status = rpccli_samr_OpenUser(cli, mem_ctx,
3024 SAMR_USER_ACCESS_CHANGE_PASSWORD,
3027 if (!NT_STATUS_IS_OK(status)) {
3028 errcode = W_ERROR_V(ntstatus_to_werror(status));
3032 if (encrypted == 0) {
3033 E_deshash(pass1, old_lm_hash.hash);
3034 E_deshash(pass2, new_lm_hash.hash);
3036 ZERO_STRUCT(old_lm_hash);
3037 ZERO_STRUCT(new_lm_hash);
3038 memcpy(old_lm_hash.hash, pass1, MIN(strlen(pass1), 16));
3039 memcpy(new_lm_hash.hash, pass1, MIN(strlen(pass2), 16));
3042 status = rpccli_samr_ChangePasswordUser(cli, mem_ctx,
3044 true, /* lm_present */
3047 false, /* nt_present */
3048 NULL, /* old_nt_crypted */
3049 NULL, /* new_nt_crypted */
3050 false, /* cross1_present */
3051 NULL, /* nt_cross */
3052 false, /* cross2_present */
3053 NULL); /* lm_cross */
3054 if (!NT_STATUS_IS_OK(status)) {
3055 errcode = W_ERROR_V(ntstatus_to_werror(status));
3059 errcode = NERR_Success;
3062 if (cli && is_valid_policy_hnd(&user_handle)) {
3063 rpccli_samr_Close(cli, mem_ctx, &user_handle);
3065 if (cli && is_valid_policy_hnd(&domain_handle)) {
3066 rpccli_samr_Close(cli, mem_ctx, &domain_handle);
3068 if (cli && is_valid_policy_hnd(&connect_handle)) {
3069 rpccli_samr_Close(cli, mem_ctx, &connect_handle);
3072 memset((char *)pass1,'\0',sizeof(fstring));
3073 memset((char *)pass2,'\0',sizeof(fstring));
3075 SSVAL(*rparam,0,errcode);
3076 SSVAL(*rparam,2,0); /* converter word */
3080 /****************************************************************************
3081 Set the user password (SamOEM version - gets plaintext).
3082 ****************************************************************************/
3084 static bool api_SamOEMChangePassword(struct smbd_server_connection *sconn,
3085 connection_struct *conn,uint16 vuid,
3086 char *param, int tpscnt,
3087 char *data, int tdscnt,
3088 int mdrcnt,int mprcnt,
3089 char **rdata,char **rparam,
3090 int *rdata_len,int *rparam_len)
3093 char *p = get_safe_str_ptr(param,tpscnt,param,2);
3095 TALLOC_CTX *mem_ctx = talloc_tos();
3097 struct rpc_pipe_client *cli = NULL;
3098 struct lsa_AsciiString server, account;
3099 struct samr_CryptPassword password;
3100 struct samr_Password hash;
3101 int errcode = NERR_badpass;
3105 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3115 SSVAL(*rparam,0,NERR_badpass);
3118 * Check the parameter definition is correct.
3121 /* Do we have a string ? */
3122 if (skip_string(param,tpscnt,p) == 0) {
3125 if(!strequal(p, "zsT")) {
3126 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", p));
3129 p = skip_string(param, tpscnt, p);
3134 /* Do we have a string ? */
3135 if (skip_string(param,tpscnt,p) == 0) {
3138 if(!strequal(p, "B516B16")) {
3139 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p));
3142 p = skip_string(param,tpscnt,p);
3146 /* Do we have a string ? */
3147 if (skip_string(param,tpscnt,p) == 0) {
3150 p += pull_ascii_fstring(user,p);
3152 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user));
3154 if (tdscnt != 532) {
3155 errcode = W_ERROR_V(WERR_INVALID_PARAM);
3159 bufsize = get_safe_SVAL(param,tpscnt,p,0,-1);
3160 if (bufsize != 532) {
3161 errcode = W_ERROR_V(WERR_INVALID_PARAM);
3165 memcpy(password.data, data, 516);
3166 memcpy(hash.hash, data+516, 16);
3168 status = rpc_pipe_open_internal(mem_ctx, &ndr_table_samr.syntax_id,
3170 &conn->sconn->client_id,
3171 conn->sconn->msg_ctx,
3173 if (!NT_STATUS_IS_OK(status)) {
3174 DEBUG(0,("api_SamOEMChangePassword: could not connect to samr: %s\n",
3175 nt_errstr(status)));
3176 errcode = W_ERROR_V(ntstatus_to_werror(status));
3180 init_lsa_AsciiString(&server, global_myname());
3181 init_lsa_AsciiString(&account, user);
3183 status = rpccli_samr_OemChangePasswordUser2(cli, mem_ctx,
3188 if (!NT_STATUS_IS_OK(status)) {
3189 errcode = W_ERROR_V(ntstatus_to_werror(status));
3193 errcode = NERR_Success;
3195 SSVAL(*rparam,0,errcode);
3196 SSVAL(*rparam,2,0); /* converter word */
3201 /****************************************************************************
3204 ****************************************************************************/
3206 static bool api_RDosPrintJobDel(struct smbd_server_connection *sconn,
3207 connection_struct *conn,uint16 vuid,
3208 char *param, int tpscnt,
3209 char *data, int tdscnt,
3210 int mdrcnt,int mprcnt,
3211 char **rdata,char **rparam,
3212 int *rdata_len,int *rparam_len)
3214 int function = get_safe_SVAL(param,tpscnt,param,0,0);
3215 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3216 char *str2 = skip_string(param,tpscnt,str1);
3217 char *p = skip_string(param,tpscnt,str2);
3221 WERROR werr = WERR_OK;
3223 TALLOC_CTX *mem_ctx = talloc_tos();
3225 struct rpc_pipe_client *cli = NULL;
3226 struct dcerpc_binding_handle *b = NULL;
3227 struct policy_handle handle;
3228 struct spoolss_DevmodeContainer devmode_ctr;
3229 enum spoolss_JobControl command;
3231 if (!str1 || !str2 || !p) {
3235 * We use 1 here not 2 as we're checking
3236 * the last byte we want to access is safe.
3238 if (!is_offset_safe(param,tpscnt,p,1)) {
3241 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
3244 /* check it's a supported varient */
3245 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
3249 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3255 ZERO_STRUCT(handle);
3257 status = rpc_pipe_open_interface(conn,
3258 &ndr_table_spoolss.syntax_id,
3260 &conn->sconn->client_id,
3261 conn->sconn->msg_ctx,
3263 if (!NT_STATUS_IS_OK(status)) {
3264 DEBUG(0,("api_RDosPrintJobDel: could not connect to spoolss: %s\n",
3265 nt_errstr(status)));
3266 errcode = W_ERROR_V(ntstatus_to_werror(status));
3269 b = cli->binding_handle;
3271 ZERO_STRUCT(devmode_ctr);
3273 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
3277 JOB_ACCESS_ADMINISTER,
3280 if (!NT_STATUS_IS_OK(status)) {
3281 errcode = W_ERROR_V(ntstatus_to_werror(status));
3284 if (!W_ERROR_IS_OK(werr)) {
3285 errcode = W_ERROR_V(werr);
3289 /* FIXME: formerly NERR_JobNotFound was returned if job did not exist
3290 * and NERR_DestNotFound if share did not exist */
3292 errcode = NERR_Success;
3295 case 81: /* delete */
3296 command = SPOOLSS_JOB_CONTROL_DELETE;
3298 case 82: /* pause */
3299 command = SPOOLSS_JOB_CONTROL_PAUSE;
3301 case 83: /* resume */
3302 command = SPOOLSS_JOB_CONTROL_RESUME;
3305 errcode = NERR_notsupported;
3309 status = dcerpc_spoolss_SetJob(b, mem_ctx,
3312 NULL, /* unique ptr ctr */
3315 if (!NT_STATUS_IS_OK(status)) {
3316 errcode = W_ERROR_V(ntstatus_to_werror(status));
3319 if (!W_ERROR_IS_OK(werr)) {
3320 errcode = W_ERROR_V(werr);
3325 if (b && is_valid_policy_hnd(&handle)) {
3326 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
3329 SSVAL(*rparam,0,errcode);
3330 SSVAL(*rparam,2,0); /* converter word */
3335 /****************************************************************************
3336 Purge a print queue - or pause or resume it.
3337 ****************************************************************************/
3339 static bool api_WPrintQueueCtrl(struct smbd_server_connection *sconn,
3340 connection_struct *conn,uint16 vuid,
3341 char *param, int tpscnt,
3342 char *data, int tdscnt,
3343 int mdrcnt,int mprcnt,
3344 char **rdata,char **rparam,
3345 int *rdata_len,int *rparam_len)
3347 int function = get_safe_SVAL(param,tpscnt,param,0,0);
3348 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3349 char *str2 = skip_string(param,tpscnt,str1);
3350 char *QueueName = skip_string(param,tpscnt,str2);
3351 int errcode = NERR_notsupported;
3352 WERROR werr = WERR_OK;
3355 TALLOC_CTX *mem_ctx = talloc_tos();
3356 struct rpc_pipe_client *cli = NULL;
3357 struct dcerpc_binding_handle *b = NULL;
3358 struct policy_handle handle;
3359 struct spoolss_SetPrinterInfoCtr info_ctr;
3360 struct spoolss_DevmodeContainer devmode_ctr;
3361 struct sec_desc_buf secdesc_ctr;
3362 enum spoolss_PrinterControl command;
3364 if (!str1 || !str2 || !QueueName) {
3368 /* check it's a supported varient */
3369 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
3373 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3379 if (skip_string(param,tpscnt,QueueName) == NULL) {
3383 ZERO_STRUCT(handle);
3385 status = rpc_pipe_open_interface(conn,
3386 &ndr_table_spoolss.syntax_id,
3388 &conn->sconn->client_id,
3389 conn->sconn->msg_ctx,
3391 if (!NT_STATUS_IS_OK(status)) {
3392 DEBUG(0,("api_WPrintQueueCtrl: could not connect to spoolss: %s\n",
3393 nt_errstr(status)));
3394 errcode = W_ERROR_V(ntstatus_to_werror(status));
3397 b = cli->binding_handle;
3399 ZERO_STRUCT(devmode_ctr);
3401 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
3405 SEC_FLAG_MAXIMUM_ALLOWED,
3408 if (!NT_STATUS_IS_OK(status)) {
3409 errcode = W_ERROR_V(ntstatus_to_werror(status));
3412 if (!W_ERROR_IS_OK(werr)) {
3413 errcode = W_ERROR_V(werr);
3418 case 74: /* Pause queue */
3419 command = SPOOLSS_PRINTER_CONTROL_PAUSE;
3421 case 75: /* Resume queue */
3422 command = SPOOLSS_PRINTER_CONTROL_RESUME;
3424 case 103: /* Purge */
3425 command = SPOOLSS_PRINTER_CONTROL_PURGE;
3428 werr = WERR_NOT_SUPPORTED;
3432 if (!W_ERROR_IS_OK(werr)) {
3433 errcode = W_ERROR_V(werr);
3437 ZERO_STRUCT(info_ctr);
3438 ZERO_STRUCT(secdesc_ctr);
3440 status = dcerpc_spoolss_SetPrinter(b, mem_ctx,
3447 if (!NT_STATUS_IS_OK(status)) {
3448 errcode = W_ERROR_V(ntstatus_to_werror(status));
3451 if (!W_ERROR_IS_OK(werr)) {
3452 errcode = W_ERROR_V(werr);
3456 errcode = W_ERROR_V(werr);
3460 if (b && is_valid_policy_hnd(&handle)) {
3461 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
3464 SSVAL(*rparam,0,errcode);
3465 SSVAL(*rparam,2,0); /* converter word */
3470 /****************************************************************************
3471 set the property of a print job (undocumented?)
3472 ? function = 0xb -> set name of print job
3473 ? function = 0x6 -> move print job up/down
3474 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
3475 or <WWsTP> <WB21BB16B10zWWzDDz>
3476 ****************************************************************************/
3478 static int check_printjob_info(struct pack_desc* desc,
3479 int uLevel, char* id)
3481 desc->subformat = NULL;
3483 case 0: desc->format = "W"; break;
3484 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
3485 case 2: desc->format = "WWzWWDDzz"; break;
3486 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
3487 case 4: desc->format = "WWzWWDDzzzzzDDDDDDD"; break;
3489 DEBUG(0,("check_printjob_info: invalid level %d\n",
3493 if (id == NULL || strcmp(desc->format,id) != 0) {
3494 DEBUG(0,("check_printjob_info: invalid format %s\n",
3495 id ? id : "<NULL>" ));
3501 static bool api_PrintJobInfo(struct smbd_server_connection *sconn,
3502 connection_struct *conn, uint16 vuid,
3503 char *param, int tpscnt,
3504 char *data, int tdscnt,
3505 int mdrcnt,int mprcnt,
3506 char **rdata,char **rparam,
3507 int *rdata_len,int *rparam_len)
3509 struct pack_desc desc;
3510 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3511 char *str2 = skip_string(param,tpscnt,str1);
3512 char *p = skip_string(param,tpscnt,str2);
3515 int uLevel = get_safe_SVAL(param,tpscnt,p,2,-1);
3516 int function = get_safe_SVAL(param,tpscnt,p,4,-1);
3519 TALLOC_CTX *mem_ctx = talloc_tos();
3522 struct rpc_pipe_client *cli = NULL;
3523 struct dcerpc_binding_handle *b = NULL;
3524 struct policy_handle handle;
3525 struct spoolss_DevmodeContainer devmode_ctr;
3526 struct spoolss_JobInfoContainer ctr;
3527 union spoolss_JobInfo info;
3528 struct spoolss_SetJobInfo1 info1;
3530 if (!str1 || !str2 || !p) {
3534 * We use 1 here not 2 as we're checking
3535 * the last byte we want to access is safe.
3537 if (!is_offset_safe(param,tpscnt,p,1)) {
3540 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
3543 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3550 /* check it's a supported varient */
3551 if ((strcmp(str1,"WWsTP")) ||
3552 (!check_printjob_info(&desc,uLevel,str2)))
3555 errcode = NERR_notsupported;
3559 /* change print job name, data gives the name */
3565 ZERO_STRUCT(handle);
3567 status = rpc_pipe_open_interface(conn,
3568 &ndr_table_spoolss.syntax_id,
3570 &conn->sconn->client_id,
3571 conn->sconn->msg_ctx,
3573 if (!NT_STATUS_IS_OK(status)) {
3574 DEBUG(0,("api_PrintJobInfo: could not connect to spoolss: %s\n",
3575 nt_errstr(status)));
3576 errcode = W_ERROR_V(ntstatus_to_werror(status));
3579 b = cli->binding_handle;
3581 ZERO_STRUCT(devmode_ctr);
3583 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
3590 if (!NT_STATUS_IS_OK(status)) {
3591 errcode = W_ERROR_V(ntstatus_to_werror(status));
3594 if (!W_ERROR_IS_OK(werr)) {
3595 errcode = W_ERROR_V(werr);
3599 werr = rpccli_spoolss_getjob(cli, mem_ctx,
3605 if (!W_ERROR_IS_OK(werr)) {
3606 errcode = W_ERROR_V(werr);
3612 info1.job_id = info.info1.job_id;
3613 info1.printer_name = info.info1.printer_name;
3614 info1.user_name = info.info1.user_name;
3615 info1.document_name = data;
3616 info1.data_type = info.info1.data_type;
3617 info1.text_status = info.info1.text_status;
3618 info1.status = info.info1.status;
3619 info1.priority = info.info1.priority;
3620 info1.position = info.info1.position;
3621 info1.total_pages = info.info1.total_pages;
3622 info1.pages_printed = info.info1.pages_printed;
3623 info1.submitted = info.info1.submitted;
3626 ctr.info.info1 = &info1;
3628 status = dcerpc_spoolss_SetJob(b, mem_ctx,
3634 if (!NT_STATUS_IS_OK(status)) {
3635 errcode = W_ERROR_V(ntstatus_to_werror(status));
3638 if (!W_ERROR_IS_OK(werr)) {
3639 errcode = W_ERROR_V(werr);
3643 errcode = NERR_Success;
3646 if (b && is_valid_policy_hnd(&handle)) {
3647 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
3650 SSVALS(*rparam,0,errcode);
3651 SSVAL(*rparam,2,0); /* converter word */
3657 /****************************************************************************
3658 Get info about the server.
3659 ****************************************************************************/
3661 static bool api_RNetServerGetInfo(struct smbd_server_connection *sconn,
3662 connection_struct *conn,uint16 vuid,
3663 char *param, int tpscnt,
3664 char *data, int tdscnt,
3665 int mdrcnt,int mprcnt,
3666 char **rdata,char **rparam,
3667 int *rdata_len,int *rparam_len)
3669 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3670 char *str2 = skip_string(param,tpscnt,str1);
3671 char *p = skip_string(param,tpscnt,str2);
3672 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
3678 TALLOC_CTX *mem_ctx = talloc_tos();
3679 struct rpc_pipe_client *cli = NULL;
3680 union srvsvc_NetSrvInfo info;
3682 struct dcerpc_binding_handle *b;
3684 if (!str1 || !str2 || !p) {
3688 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
3690 /* check it's a supported varient */
3691 if (!prefix_ok(str1,"WrLh")) {
3697 if (strcmp(str2,"B16") != 0) {
3703 if (strcmp(str2,"B16BBDz") != 0) {
3709 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")!= 0) {
3715 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz") != 0) {
3721 if (strcmp(str2,"DN") != 0) {
3727 if (strcmp(str2,"B16BBDzWWzzz") != 0) {
3736 *rdata_len = mdrcnt;
3737 *rdata = smb_realloc_limit(*rdata,*rdata_len);
3743 p2 = p + struct_len;
3745 status = rpc_pipe_open_internal(mem_ctx, &ndr_table_srvsvc.syntax_id,
3747 &conn->sconn->client_id,
3748 conn->sconn->msg_ctx,
3750 if (!NT_STATUS_IS_OK(status)) {
3751 DEBUG(0,("api_RNetServerGetInfo: could not connect to srvsvc: %s\n",
3752 nt_errstr(status)));
3753 errcode = W_ERROR_V(ntstatus_to_werror(status));
3757 b = cli->binding_handle;
3759 status = dcerpc_srvsvc_NetSrvGetInfo(b, mem_ctx,
3764 if (!NT_STATUS_IS_OK(status)) {
3765 errcode = W_ERROR_V(ntstatus_to_werror(status));
3768 if (!W_ERROR_IS_OK(werr)) {
3769 errcode = W_ERROR_V(werr);
3773 if (info.info101 == NULL) {
3774 errcode = W_ERROR_V(WERR_INVALID_PARAM);
3779 srvstr_push(NULL, 0, p, info.info101->server_name, 16,
3780 STR_ASCII|STR_UPPER|STR_TERMINATE);
3784 SCVAL(p,0,info.info101->version_major);
3785 SCVAL(p,1,info.info101->version_minor);
3786 SIVAL(p,2,info.info101->server_type);
3788 if (mdrcnt == struct_len) {
3791 SIVAL(p,6,PTR_DIFF(p2,*rdata));
3792 if (mdrcnt - struct_len <= 0) {
3796 info.info101->comment,
3797 MIN(mdrcnt - struct_len,
3798 MAX_SERVER_STRING_LENGTH),
3800 p2 = skip_string(*rdata,*rdata_len,p2);
3808 return False; /* not yet implemented */
3811 errcode = NERR_Success;
3815 *rdata_len = PTR_DIFF(p2,*rdata);
3818 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3822 SSVAL(*rparam,0,errcode);
3823 SSVAL(*rparam,2,0); /* converter word */
3824 SSVAL(*rparam,4,*rdata_len);
3829 /****************************************************************************
3830 Get info about the server.
3831 ****************************************************************************/
3833 static bool api_NetWkstaGetInfo(struct smbd_server_connection *sconn,
3834 connection_struct *conn,uint16 vuid,
3835 char *param, int tpscnt,
3836 char *data, int tdscnt,
3837 int mdrcnt,int mprcnt,
3838 char **rdata,char **rparam,
3839 int *rdata_len,int *rparam_len)
3841 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3842 char *str2 = skip_string(param,tpscnt,str1);
3843 char *p = skip_string(param,tpscnt,str2);
3846 int level = get_safe_SVAL(param,tpscnt,p,0,-1);
3848 if (!str1 || !str2 || !p) {
3852 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
3855 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3860 /* check it's a supported varient */
3861 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz"))) {
3865 *rdata_len = mdrcnt + 1024;
3866 *rdata = smb_realloc_limit(*rdata,*rdata_len);
3871 SSVAL(*rparam,0,NERR_Success);
3872 SSVAL(*rparam,2,0); /* converter word */
3875 endp = *rdata + *rdata_len;
3877 p2 = get_safe_ptr(*rdata,*rdata_len,p,22);
3882 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
3883 strlcpy(p2,get_local_machine_name(),PTR_DIFF(endp,p2));
3885 p2 = skip_string(*rdata,*rdata_len,p2);
3891 SIVAL(p,0,PTR_DIFF(p2,*rdata));
3892 strlcpy(p2,conn->server_info->sanitized_username,PTR_DIFF(endp,p2));
3893 p2 = skip_string(*rdata,*rdata_len,p2);
3899 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
3900 strlcpy(p2,lp_workgroup(),PTR_DIFF(endp,p2));
3902 p2 = skip_string(*rdata,*rdata_len,p2);
3908 SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
3909 SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
3912 SIVAL(p,0,PTR_DIFF(p2,*rdata));
3913 strlcpy(p2,lp_workgroup(),PTR_DIFF(endp,p2)); /* don't know. login domain?? */
3914 p2 = skip_string(*rdata,*rdata_len,p2);
3920 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
3921 strlcpy(p2,"",PTR_DIFF(endp,p2));
3922 p2 = skip_string(*rdata,*rdata_len,p2);
3928 *rdata_len = PTR_DIFF(p2,*rdata);
3930 SSVAL(*rparam,4,*rdata_len);
3935 /****************************************************************************
3936 get info about a user
3938 struct user_info_11 {
3939 char usri11_name[21]; 0-20
3941 char *usri11_comment; 22-25
3942 char *usri11_usr_comment; 26-29
3943 unsigned short usri11_priv; 30-31
3944 unsigned long usri11_auth_flags; 32-35
3945 long usri11_password_age; 36-39
3946 char *usri11_homedir; 40-43
3947 char *usri11_parms; 44-47
3948 long usri11_last_logon; 48-51
3949 long usri11_last_logoff; 52-55
3950 unsigned short usri11_bad_pw_count; 56-57
3951 unsigned short usri11_num_logons; 58-59
3952 char *usri11_logon_server; 60-63
3953 unsigned short usri11_country_code; 64-65
3954 char *usri11_workstations; 66-69
3955 unsigned long usri11_max_storage; 70-73
3956 unsigned short usri11_units_per_week; 74-75
3957 unsigned char *usri11_logon_hours; 76-79
3958 unsigned short usri11_code_page; 80-81
3963 usri11_name specifies the user name for which information is retrieved
3965 usri11_pad aligns the next data structure element to a word boundary
3967 usri11_comment is a null terminated ASCII comment
3969 usri11_user_comment is a null terminated ASCII comment about the user
3971 usri11_priv specifies the level of the privilege assigned to the user.
3972 The possible values are:
3974 Name Value Description
3975 USER_PRIV_GUEST 0 Guest privilege
3976 USER_PRIV_USER 1 User privilege
3977 USER_PRV_ADMIN 2 Administrator privilege
3979 usri11_auth_flags specifies the account operator privileges. The
3980 possible values are:
3982 Name Value Description
3983 AF_OP_PRINT 0 Print operator
3986 Leach, Naik [Page 28]
3990 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
3993 AF_OP_COMM 1 Communications operator
3994 AF_OP_SERVER 2 Server operator
3995 AF_OP_ACCOUNTS 3 Accounts operator
3998 usri11_password_age specifies how many seconds have elapsed since the
3999 password was last changed.
4001 usri11_home_dir points to a null terminated ASCII string that contains
4002 the path name of the user's home directory.
4004 usri11_parms points to a null terminated ASCII string that is set
4005 aside for use by applications.
4007 usri11_last_logon specifies the time when the user last logged on.
4008 This value is stored as the number of seconds elapsed since
4009 00:00:00, January 1, 1970.
4011 usri11_last_logoff specifies the time when the user last logged off.
4012 This value is stored as the number of seconds elapsed since
4013 00:00:00, January 1, 1970. A value of 0 means the last logoff
4016 usri11_bad_pw_count specifies the number of incorrect passwords
4017 entered since the last successful logon.
4019 usri11_log1_num_logons specifies the number of times this user has
4020 logged on. A value of -1 means the number of logons is unknown.
4022 usri11_logon_server points to a null terminated ASCII string that
4023 contains the name of the server to which logon requests are sent.
4024 A null string indicates logon requests should be sent to the
4027 usri11_country_code specifies the country code for the user's language
4030 usri11_workstations points to a null terminated ASCII string that
4031 contains the names of workstations the user may log on from.
4032 There may be up to 8 workstations, with the names separated by
4033 commas. A null strings indicates there are no restrictions.
4035 usri11_max_storage specifies the maximum amount of disk space the user
4036 can occupy. A value of 0xffffffff indicates there are no
4039 usri11_units_per_week specifies the equal number of time units into
4040 which a week is divided. This value must be equal to 168.
4042 usri11_logon_hours points to a 21 byte (168 bits) string that
4043 specifies the time during which the user can log on. Each bit
4044 represents one unique hour in a week. The first bit (bit 0, word
4045 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
4049 Leach, Naik [Page 29]
4053 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
4056 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
4057 are no restrictions.
4059 usri11_code_page specifies the code page for the user's language of
4062 All of the pointers in this data structure need to be treated
4063 specially. The pointer is a 32 bit pointer. The higher 16 bits need
4064 to be ignored. The converter word returned in the parameters section
4065 needs to be subtracted from the lower 16 bits to calculate an offset
4066 into the return buffer where this ASCII string resides.
4068 There is no auxiliary data in the response.
4070 ****************************************************************************/
4072 #define usri11_name 0
4073 #define usri11_pad 21
4074 #define usri11_comment 22
4075 #define usri11_usr_comment 26
4076 #define usri11_full_name 30
4077 #define usri11_priv 34
4078 #define usri11_auth_flags 36
4079 #define usri11_password_age 40
4080 #define usri11_homedir 44
4081 #define usri11_parms 48
4082 #define usri11_last_logon 52
4083 #define usri11_last_logoff 56
4084 #define usri11_bad_pw_count 60
4085 #define usri11_num_logons 62
4086 #define usri11_logon_server 64
4087 #define usri11_country_code 68
4088 #define usri11_workstations 70
4089 #define usri11_max_storage 74
4090 #define usri11_units_per_week 78
4091 #define usri11_logon_hours 80
4092 #define usri11_code_page 84
4093 #define usri11_end 86
4095 static bool api_RNetUserGetInfo(struct smbd_server_connection *sconn,
4096 connection_struct *conn, uint16 vuid,
4097 char *param, int tpscnt,
4098 char *data, int tdscnt,
4099 int mdrcnt,int mprcnt,
4100 char **rdata,char **rparam,
4101 int *rdata_len,int *rparam_len)
4103 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4104 char *str2 = skip_string(param,tpscnt,str1);
4105 char *UserName = skip_string(param,tpscnt,str2);
4106 char *p = skip_string(param,tpscnt,UserName);
4107 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4110 const char *level_string;
4112 TALLOC_CTX *mem_ctx = talloc_tos();
4114 struct rpc_pipe_client *cli = NULL;
4115 struct policy_handle connect_handle, domain_handle, user_handle;
4116 struct lsa_String domain_name;
4117 struct dom_sid2 *domain_sid;
4118 struct lsa_String names;
4119 struct samr_Ids rids;
4120 struct samr_Ids types;
4121 int errcode = W_ERROR_V(WERR_USER_NOT_FOUND);
4123 union samr_UserInfo *info;
4125 if (!str1 || !str2 || !UserName || !p) {
4130 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4135 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
4137 /* check it's a supported variant */
4138 if (strcmp(str1,"zWrLh") != 0) {
4142 case 0: level_string = "B21"; break;
4143 case 1: level_string = "B21BB16DWzzWz"; break;
4144 case 2: level_string = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
4145 case 10: level_string = "B21Bzzz"; break;
4146 case 11: level_string = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
4147 default: return False;
4150 if (strcmp(level_string,str2) != 0) {
4154 *rdata_len = mdrcnt + 1024;
4155 *rdata = smb_realloc_limit(*rdata,*rdata_len);
4161 endp = *rdata + *rdata_len;
4162 p2 = get_safe_ptr(*rdata,*rdata_len,p,usri11_end);
4167 ZERO_STRUCT(connect_handle);
4168 ZERO_STRUCT(domain_handle);
4169 ZERO_STRUCT(user_handle);
4171 status = rpc_pipe_open_internal(mem_ctx, &ndr_table_samr.syntax_id,
4173 &conn->sconn->client_id,
4174 conn->sconn->msg_ctx,
4176 if (!NT_STATUS_IS_OK(status)) {
4177 DEBUG(0,("api_RNetUserGetInfo: could not connect to samr: %s\n",
4178 nt_errstr(status)));
4179 errcode = W_ERROR_V(ntstatus_to_werror(status));
4183 status = rpccli_samr_Connect2(cli, mem_ctx,
4185 SAMR_ACCESS_CONNECT_TO_SERVER |
4186 SAMR_ACCESS_ENUM_DOMAINS |
4187 SAMR_ACCESS_LOOKUP_DOMAIN,
4189 if (!NT_STATUS_IS_OK(status)) {
4190 errcode = W_ERROR_V(ntstatus_to_werror(status));
4194 init_lsa_String(&domain_name, get_global_sam_name());
4196 status = rpccli_samr_LookupDomain(cli, mem_ctx,
4200 if (!NT_STATUS_IS_OK(status)) {
4201 errcode = W_ERROR_V(ntstatus_to_werror(status));
4205 status = rpccli_samr_OpenDomain(cli, mem_ctx,
4207 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
4210 if (!NT_STATUS_IS_OK(status)) {
4211 errcode = W_ERROR_V(ntstatus_to_werror(status));
4215 init_lsa_String(&names, UserName);
4217 status = rpccli_samr_LookupNames(cli, mem_ctx,
4223 if (!NT_STATUS_IS_OK(status)) {
4224 errcode = W_ERROR_V(ntstatus_to_werror(status));
4228 if (rids.count != 1) {
4229 errcode = W_ERROR_V(WERR_NO_SUCH_USER);
4232 if (rids.count != types.count) {
4233 errcode = W_ERROR_V(WERR_INVALID_PARAM);
4236 if (types.ids[0] != SID_NAME_USER) {
4237 errcode = W_ERROR_V(WERR_INVALID_PARAM);
4243 status = rpccli_samr_OpenUser(cli, mem_ctx,
4245 SAMR_USER_ACCESS_GET_LOCALE |
4246 SAMR_USER_ACCESS_GET_LOGONINFO |
4247 SAMR_USER_ACCESS_GET_ATTRIBUTES |
4248 SAMR_USER_ACCESS_GET_GROUPS |
4249 SAMR_USER_ACCESS_GET_GROUP_MEMBERSHIP |
4250 SEC_STD_READ_CONTROL,
4253 if (!NT_STATUS_IS_OK(status)) {
4254 errcode = W_ERROR_V(ntstatus_to_werror(status));
4258 status = rpccli_samr_QueryUserInfo2(cli, mem_ctx,
4262 if (!NT_STATUS_IS_OK(status)) {
4263 errcode = W_ERROR_V(ntstatus_to_werror(status));
4268 fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
4271 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
4276 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
4277 strlcpy(p2,"Comment",PTR_DIFF(endp,p2));
4278 p2 = skip_string(*rdata,*rdata_len,p2);
4283 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
4284 strlcpy(p2,"UserComment",PTR_DIFF(endp,p2));
4285 p2 = skip_string(*rdata,*rdata_len,p2);
4290 /* EEK! the cifsrap.txt doesn't have this in!!!! */
4291 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
4292 strlcpy(p2,info->info21.full_name.string,PTR_DIFF(endp,p2));
4293 p2 = skip_string(*rdata,*rdata_len,p2);
4300 const char *homedir = info->info21.home_directory.string;
4301 /* modelled after NTAS 3.51 reply */
4302 SSVAL(p,usri11_priv,
4303 (get_current_uid(conn) == sec_initial_uid())?
4304 USER_PRIV_ADMIN:USER_PRIV_USER);
4305 SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
4306 SIVALS(p,usri11_password_age,-1); /* password age */
4307 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
4308 strlcpy(p2, homedir, PTR_DIFF(endp,p2));
4309 p2 = skip_string(*rdata,*rdata_len,p2);
4313 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
4314 strlcpy(p2,"",PTR_DIFF(endp,p2));
4315 p2 = skip_string(*rdata,*rdata_len,p2);
4319 SIVAL(p,usri11_last_logon,0); /* last logon */
4320 SIVAL(p,usri11_last_logoff,0); /* last logoff */
4321 SSVALS(p,usri11_bad_pw_count,-1); /* bad pw counts */
4322 SSVALS(p,usri11_num_logons,-1); /* num logons */
4323 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
4324 strlcpy(p2,"\\\\*",PTR_DIFF(endp,p2));
4325 p2 = skip_string(*rdata,*rdata_len,p2);
4329 SSVAL(p,usri11_country_code,0); /* country code */
4331 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
4332 strlcpy(p2,"",PTR_DIFF(endp,p2));
4333 p2 = skip_string(*rdata,*rdata_len,p2);
4338 SIVALS(p,usri11_max_storage,-1); /* max storage */
4339 SSVAL(p,usri11_units_per_week,168); /* units per week */
4340 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
4342 /* a simple way to get logon hours at all times. */
4344 SCVAL(p2,21,0); /* fix zero termination */
4345 p2 = skip_string(*rdata,*rdata_len,p2);
4350 SSVAL(p,usri11_code_page,0); /* code page */
4353 if (uLevel == 1 || uLevel == 2) {
4354 memset(p+22,' ',16); /* password */
4355 SIVALS(p,38,-1); /* password age */
4357 (get_current_uid(conn) == sec_initial_uid())?
4358 USER_PRIV_ADMIN:USER_PRIV_USER);
4359 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
4360 strlcpy(p2, info->info21.home_directory.string,
4362 p2 = skip_string(*rdata,*rdata_len,p2);
4366 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
4368 SSVAL(p,52,0); /* flags */
4369 SIVAL(p,54,PTR_DIFF(p2,*rdata)); /* script_path */
4370 strlcpy(p2, info->info21.logon_script.string,
4372 p2 = skip_string(*rdata,*rdata_len,p2);
4377 SIVAL(p,58,0); /* auth_flags */
4378 SIVAL(p,62,PTR_DIFF(p2,*rdata)); /* full_name */
4379 strlcpy(p2,info->info21.full_name.string,PTR_DIFF(endp,p2));
4380 p2 = skip_string(*rdata,*rdata_len,p2);
4384 SIVAL(p,66,0); /* urs_comment */
4385 SIVAL(p,70,PTR_DIFF(p2,*rdata)); /* parms */
4386 strlcpy(p2,"",PTR_DIFF(endp,p2));
4387 p2 = skip_string(*rdata,*rdata_len,p2);
4391 SIVAL(p,74,0); /* workstations */
4392 SIVAL(p,78,0); /* last_logon */
4393 SIVAL(p,82,0); /* last_logoff */
4394 SIVALS(p,86,-1); /* acct_expires */
4395 SIVALS(p,90,-1); /* max_storage */
4396 SSVAL(p,94,168); /* units_per_week */
4397 SIVAL(p,96,PTR_DIFF(p2,*rdata)); /* logon_hours */
4400 SSVALS(p,100,-1); /* bad_pw_count */
4401 SSVALS(p,102,-1); /* num_logons */
4402 SIVAL(p,104,PTR_DIFF(p2,*rdata)); /* logon_server */
4404 TALLOC_CTX *ctx = talloc_tos();
4405 int space_rem = *rdata_len - (p2 - *rdata);
4408 if (space_rem <= 0) {
4411 tmp = talloc_strdup(ctx, "\\\\%L");
4415 tmp = talloc_sub_basic(ctx,
4428 p2 = skip_string(*rdata,*rdata_len,p2);
4432 SSVAL(p,108,49); /* country_code */
4433 SSVAL(p,110,860); /* code page */
4437 errcode = NERR_Success;
4440 *rdata_len = PTR_DIFF(p2,*rdata);
4442 if (cli && is_valid_policy_hnd(&user_handle)) {
4443 rpccli_samr_Close(cli, mem_ctx, &user_handle);
4445 if (cli && is_valid_policy_hnd(&domain_handle)) {
4446 rpccli_samr_Close(cli, mem_ctx, &domain_handle);
4448 if (cli && is_valid_policy_hnd(&connect_handle)) {
4449 rpccli_samr_Close(cli, mem_ctx, &connect_handle);
4452 SSVAL(*rparam,0,errcode);
4453 SSVAL(*rparam,2,0); /* converter word */
4454 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
4459 static bool api_WWkstaUserLogon(struct smbd_server_connection *sconn,
4460 connection_struct *conn,uint16 vuid,
4461 char *param, int tpscnt,
4462 char *data, int tdscnt,
4463 int mdrcnt,int mprcnt,
4464 char **rdata,char **rparam,
4465 int *rdata_len,int *rparam_len)
4467 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4468 char *str2 = skip_string(param,tpscnt,str1);
4469 char *p = skip_string(param,tpscnt,str2);
4471 struct pack_desc desc;
4473 /* With share level security vuid will always be zero.
4474 Don't depend on vuser being non-null !!. JRA */
4475 user_struct *vuser = get_valid_user_struct(sconn, vuid);
4477 if (!str1 || !str2 || !p) {
4482 DEBUG(3,(" Username of UID %d is %s\n",
4483 (int)vuser->server_info->utok.uid,
4484 vuser->server_info->unix_name));
4487 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4488 name = get_safe_str_ptr(param,tpscnt,p,2);
4493 memset((char *)&desc,'\0',sizeof(desc));
4495 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
4497 /* check it's a supported varient */
4498 if (strcmp(str1,"OOWb54WrLh") != 0) {
4501 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) {
4505 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4512 desc.buflen = mdrcnt;
4513 desc.subformat = NULL;
4516 if (init_package(&desc,1,0)) {
4517 PACKI(&desc,"W",0); /* code */
4518 PACKS(&desc,"B21",name); /* eff. name */
4519 PACKS(&desc,"B",""); /* pad */
4521 (get_current_uid(conn) == sec_initial_uid())?
4522 USER_PRIV_ADMIN:USER_PRIV_USER);
4523 PACKI(&desc,"D",0); /* auth flags XXX */
4524 PACKI(&desc,"W",0); /* num logons */
4525 PACKI(&desc,"W",0); /* bad pw count */
4526 PACKI(&desc,"D",0); /* last logon */
4527 PACKI(&desc,"D",-1); /* last logoff */
4528 PACKI(&desc,"D",-1); /* logoff time */
4529 PACKI(&desc,"D",-1); /* kickoff time */
4530 PACKI(&desc,"D",0); /* password age */
4531 PACKI(&desc,"D",0); /* password can change */
4532 PACKI(&desc,"D",-1); /* password must change */
4536 fstrcpy(mypath,"\\\\");
4537 fstrcat(mypath,get_local_machine_name());
4539 PACKS(&desc,"z",mypath); /* computer */
4542 PACKS(&desc,"z",lp_workgroup());/* domain */
4543 PACKS(&desc,"z", vuser ?
4544 vuser->server_info->info3->base.logon_script.string
4545 : ""); /* script path */
4546 PACKI(&desc,"D",0x00000000); /* reserved */
4549 *rdata_len = desc.usedlen;
4551 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4555 SSVALS(*rparam,0,desc.errcode);
4557 SSVAL(*rparam,4,desc.neededlen);
4559 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
4564 /****************************************************************************
4565 api_WAccessGetUserPerms
4566 ****************************************************************************/
4568 static bool api_WAccessGetUserPerms(struct smbd_server_connection *sconn,
4569 connection_struct *conn,uint16 vuid,
4570 char *param, int tpscnt,
4571 char *data, int tdscnt,
4572 int mdrcnt,int mprcnt,
4573 char **rdata,char **rparam,
4574 int *rdata_len,int *rparam_len)
4576 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4577 char *str2 = skip_string(param,tpscnt,str1);
4578 char *user = skip_string(param,tpscnt,str2);
4579 char *resource = skip_string(param,tpscnt,user);
4581 if (!str1 || !str2 || !user || !resource) {
4585 if (skip_string(param,tpscnt,resource) == NULL) {
4588 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
4590 /* check it's a supported varient */
4591 if (strcmp(str1,"zzh") != 0) {
4594 if (strcmp(str2,"") != 0) {
4599 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4603 SSVALS(*rparam,0,0); /* errorcode */
4604 SSVAL(*rparam,2,0); /* converter word */
4605 SSVAL(*rparam,4,0x7f); /* permission flags */
4610 /****************************************************************************
4611 api_WPrintJobEnumerate
4612 ****************************************************************************/
4614 static bool api_WPrintJobGetInfo(struct smbd_server_connection *sconn,
4615 connection_struct *conn, uint16 vuid,
4616 char *param, int tpscnt,
4617 char *data, int tdscnt,
4618 int mdrcnt,int mprcnt,
4619 char **rdata,char **rparam,
4620 int *rdata_len,int *rparam_len)
4622 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4623 char *str2 = skip_string(param,tpscnt,str1);
4624 char *p = skip_string(param,tpscnt,str2);
4628 struct pack_desc desc;
4631 TALLOC_CTX *mem_ctx = talloc_tos();
4634 struct rpc_pipe_client *cli = NULL;
4635 struct dcerpc_binding_handle *b = NULL;
4636 struct policy_handle handle;
4637 struct spoolss_DevmodeContainer devmode_ctr;
4638 union spoolss_JobInfo info;
4640 if (!str1 || !str2 || !p) {
4644 uLevel = get_safe_SVAL(param,tpscnt,p,2,-1);
4646 memset((char *)&desc,'\0',sizeof(desc));
4647 memset((char *)&status,'\0',sizeof(status));
4649 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
4651 /* check it's a supported varient */
4652 if (strcmp(str1,"WWrLh") != 0) {
4655 if (!check_printjob_info(&desc,uLevel,str2)) {
4659 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid)) {
4663 ZERO_STRUCT(handle);
4665 status = rpc_pipe_open_interface(conn,
4666 &ndr_table_spoolss.syntax_id,
4668 &conn->sconn->client_id,
4669 conn->sconn->msg_ctx,
4671 if (!NT_STATUS_IS_OK(status)) {
4672 DEBUG(0,("api_WPrintJobGetInfo: could not connect to spoolss: %s\n",
4673 nt_errstr(status)));
4674 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
4677 b = cli->binding_handle;
4679 ZERO_STRUCT(devmode_ctr);
4681 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
4688 if (!NT_STATUS_IS_OK(status)) {
4689 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
4692 if (!W_ERROR_IS_OK(werr)) {
4693 desc.errcode = W_ERROR_V(werr);
4697 werr = rpccli_spoolss_getjob(cli, mem_ctx,
4703 if (!W_ERROR_IS_OK(werr)) {
4704 desc.errcode = W_ERROR_V(werr);
4709 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4714 desc.buflen = mdrcnt;
4717 * Don't return data but need to get correct length
4718 * init_package will return wrong size if buflen=0
4720 desc.buflen = getlen(desc.format);
4721 desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen );
4724 if (init_package(&desc,1,0)) {
4725 fill_spoolss_printjob_info(uLevel, &desc, &info.info2, info.info2.position);
4726 *rdata_len = desc.usedlen;
4728 desc.errcode = NERR_JobNotFound;
4732 if (b && is_valid_policy_hnd(&handle)) {
4733 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
4737 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4741 SSVALS(*rparam,0,desc.errcode);
4743 SSVAL(*rparam,4,desc.neededlen);
4747 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
4752 static bool api_WPrintJobEnumerate(struct smbd_server_connection *sconn,
4753 connection_struct *conn, uint16 vuid,
4754 char *param, int tpscnt,
4755 char *data, int tdscnt,
4756 int mdrcnt,int mprcnt,
4757 char **rdata,char **rparam,
4758 int *rdata_len,int *rparam_len)
4760 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4761 char *str2 = skip_string(param,tpscnt,str1);
4762 char *p = skip_string(param,tpscnt,str2);
4766 struct pack_desc desc;
4768 TALLOC_CTX *mem_ctx = talloc_tos();
4771 struct rpc_pipe_client *cli = NULL;
4772 struct dcerpc_binding_handle *b = NULL;
4773 struct policy_handle handle;
4774 struct spoolss_DevmodeContainer devmode_ctr;
4776 union spoolss_JobInfo *info;
4778 if (!str1 || !str2 || !p) {
4782 memset((char *)&desc,'\0',sizeof(desc));
4784 p = skip_string(param,tpscnt,p);
4788 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4790 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
4792 /* check it's a supported variant */
4793 if (strcmp(str1,"zWrLeh") != 0) {
4798 return False; /* defined only for uLevel 0,1,2 */
4801 if (!check_printjob_info(&desc,uLevel,str2)) {
4805 ZERO_STRUCT(handle);
4807 status = rpc_pipe_open_interface(conn,
4808 &ndr_table_spoolss.syntax_id,
4810 &conn->sconn->client_id,
4811 conn->sconn->msg_ctx,
4813 if (!NT_STATUS_IS_OK(status)) {
4814 DEBUG(0,("api_WPrintJobEnumerate: could not connect to spoolss: %s\n",
4815 nt_errstr(status)));
4816 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
4819 b = cli->binding_handle;
4821 ZERO_STRUCT(devmode_ctr);
4823 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
4827 SEC_FLAG_MAXIMUM_ALLOWED,
4830 if (!NT_STATUS_IS_OK(status)) {
4831 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
4834 if (!W_ERROR_IS_OK(werr)) {
4835 desc.errcode = W_ERROR_V(werr);
4839 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
4847 if (!W_ERROR_IS_OK(werr)) {
4848 desc.errcode = W_ERROR_V(werr);
4853 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4859 desc.buflen = mdrcnt;
4861 if (init_package(&desc,count,0)) {
4863 for (i = 0; i < count; i++) {
4864 fill_spoolss_printjob_info(uLevel, &desc, &info[i].info2, i);
4865 if (desc.errcode == NERR_Success) {
4871 if (b && is_valid_policy_hnd(&handle)) {
4872 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
4875 *rdata_len = desc.usedlen;
4878 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4882 SSVALS(*rparam,0,desc.errcode);
4884 SSVAL(*rparam,4,succnt);
4885 SSVAL(*rparam,6,count);
4887 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
4892 static int check_printdest_info(struct pack_desc* desc,
4893 int uLevel, char* id)
4895 desc->subformat = NULL;
4898 desc->format = "B9";
4901 desc->format = "B9B21WWzW";
4907 desc->format = "zzzWWzzzWW";
4910 DEBUG(0,("check_printdest_info: invalid level %d\n",
4914 if (id == NULL || strcmp(desc->format,id) != 0) {
4915 DEBUG(0,("check_printdest_info: invalid string %s\n",
4916 id ? id : "<NULL>" ));
4922 static void fill_printdest_info(struct spoolss_PrinterInfo2 *info2, int uLevel,
4923 struct pack_desc* desc)
4927 strncpy(buf, info2->printername, sizeof(buf)-1);
4928 buf[sizeof(buf)-1] = 0;
4932 PACKS(desc,"B9",buf); /* szName */
4934 PACKS(desc,"B21",""); /* szUserName */
4935 PACKI(desc,"W",0); /* uJobId */
4936 PACKI(desc,"W",0); /* fsStatus */
4937 PACKS(desc,"z",""); /* pszStatus */
4938 PACKI(desc,"W",0); /* time */
4942 if (uLevel == 2 || uLevel == 3) {
4943 PACKS(desc,"z",buf); /* pszPrinterName */
4945 PACKS(desc,"z",""); /* pszUserName */
4946 PACKS(desc,"z",""); /* pszLogAddr */
4947 PACKI(desc,"W",0); /* uJobId */
4948 PACKI(desc,"W",0); /* fsStatus */
4949 PACKS(desc,"z",""); /* pszStatus */
4950 PACKS(desc,"z",""); /* pszComment */
4951 PACKS(desc,"z","NULL"); /* pszDrivers */
4952 PACKI(desc,"W",0); /* time */
4953 PACKI(desc,"W",0); /* pad1 */
4958 static bool api_WPrintDestGetInfo(struct smbd_server_connection *sconn,
4959 connection_struct *conn, uint16 vuid,
4960 char *param, int tpscnt,
4961 char *data, int tdscnt,
4962 int mdrcnt,int mprcnt,
4963 char **rdata,char **rparam,
4964 int *rdata_len,int *rparam_len)
4966 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4967 char *str2 = skip_string(param,tpscnt,str1);
4968 char *p = skip_string(param,tpscnt,str2);
4969 char* PrinterName = p;
4971 struct pack_desc desc;
4974 TALLOC_CTX *mem_ctx = talloc_tos();
4977 struct rpc_pipe_client *cli = NULL;
4978 struct dcerpc_binding_handle *b = NULL;
4979 struct policy_handle handle;
4980 struct spoolss_DevmodeContainer devmode_ctr;
4981 union spoolss_PrinterInfo info;
4983 if (!str1 || !str2 || !p) {
4987 memset((char *)&desc,'\0',sizeof(desc));
4989 p = skip_string(param,tpscnt,p);
4993 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4995 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
4997 /* check it's a supported varient */
4998 if (strcmp(str1,"zWrLh") != 0) {
5001 if (!check_printdest_info(&desc,uLevel,str2)) {
5005 ZERO_STRUCT(handle);
5007 status = rpc_pipe_open_interface(conn,
5008 &ndr_table_spoolss.syntax_id,
5010 &conn->sconn->client_id,
5011 conn->sconn->msg_ctx,
5013 if (!NT_STATUS_IS_OK(status)) {
5014 DEBUG(0,("api_WPrintDestGetInfo: could not connect to spoolss: %s\n",
5015 nt_errstr(status)));
5016 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
5019 b = cli->binding_handle;
5021 ZERO_STRUCT(devmode_ctr);
5023 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
5027 SEC_FLAG_MAXIMUM_ALLOWED,
5030 if (!NT_STATUS_IS_OK(status)) {
5032 desc.errcode = NERR_DestNotFound;
5036 if (!W_ERROR_IS_OK(werr)) {
5038 desc.errcode = NERR_DestNotFound;
5043 werr = rpccli_spoolss_getprinter(cli, mem_ctx,
5048 if (!W_ERROR_IS_OK(werr)) {
5050 desc.errcode = NERR_DestNotFound;
5056 *rdata = smb_realloc_limit(*rdata,mdrcnt);
5061 desc.buflen = mdrcnt;
5064 * Don't return data but need to get correct length
5065 * init_package will return wrong size if buflen=0
5067 desc.buflen = getlen(desc.format);
5068 desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen );
5070 if (init_package(&desc,1,0)) {
5071 fill_printdest_info(&info.info2, uLevel,&desc);
5075 if (b && is_valid_policy_hnd(&handle)) {
5076 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
5079 *rdata_len = desc.usedlen;
5082 *rparam = smb_realloc_limit(*rparam,*rparam_len);
5086 SSVALS(*rparam,0,desc.errcode);
5088 SSVAL(*rparam,4,desc.neededlen);
5090 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
5096 static bool api_WPrintDestEnum(struct smbd_server_connection *sconn,
5097 connection_struct *conn, uint16 vuid,
5098 char *param, int tpscnt,
5099 char *data, int tdscnt,
5100 int mdrcnt,int mprcnt,
5101 char **rdata,char **rparam,
5102 int *rdata_len,int *rparam_len)
5104 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
5105 char *str2 = skip_string(param,tpscnt,str1);
5106 char *p = skip_string(param,tpscnt,str2);
5110 struct pack_desc desc;
5112 TALLOC_CTX *mem_ctx = talloc_tos();
5115 struct rpc_pipe_client *cli = NULL;
5116 union spoolss_PrinterInfo *info;
5119 if (!str1 || !str2 || !p) {
5123 memset((char *)&desc,'\0',sizeof(desc));
5125 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
5127 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
5129 /* check it's a supported varient */
5130 if (strcmp(str1,"WrLeh") != 0) {
5133 if (!check_printdest_info(&desc,uLevel,str2)) {
5139 status = rpc_pipe_open_interface(conn,
5140 &ndr_table_spoolss.syntax_id,
5142 &conn->sconn->client_id,
5143 conn->sconn->msg_ctx,
5145 if (!NT_STATUS_IS_OK(status)) {
5146 DEBUG(0,("api_WPrintDestEnum: could not connect to spoolss: %s\n",
5147 nt_errstr(status)));
5148 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
5152 werr = rpccli_spoolss_enumprinters(cli, mem_ctx,
5154 cli->srv_name_slash,
5159 if (!W_ERROR_IS_OK(werr)) {
5160 desc.errcode = W_ERROR_V(werr);
5162 desc.errcode = NERR_DestNotFound;
5170 *rdata = smb_realloc_limit(*rdata,mdrcnt);
5177 desc.buflen = mdrcnt;
5178 if (init_package(&desc,queuecnt,0)) {
5181 for (i = 0; i < count; i++) {
5182 fill_printdest_info(&info[i].info2, uLevel,&desc);
5184 if (desc.errcode == NERR_Success) {
5190 *rdata_len = desc.usedlen;
5193 *rparam = smb_realloc_limit(*rparam,*rparam_len);
5197 SSVALS(*rparam,0,desc.errcode);
5199 SSVAL(*rparam,4,succnt);
5200 SSVAL(*rparam,6,queuecnt);
5202 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
5207 static bool api_WPrintDriverEnum(struct smbd_server_connection *sconn,
5208 connection_struct *conn, uint16 vuid,
5209 char *param, int tpscnt,
5210 char *data, int tdscnt,
5211 int mdrcnt,int mprcnt,
5212 char **rdata,char **rparam,
5213 int *rdata_len,int *rparam_len)
5215 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
5216 char *str2 = skip_string(param,tpscnt,str1);
5217 char *p = skip_string(param,tpscnt,str2);
5220 struct pack_desc desc;
5222 if (!str1 || !str2 || !p) {
5226 memset((char *)&desc,'\0',sizeof(desc));
5228 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
5230 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
5232 /* check it's a supported varient */
5233 if (strcmp(str1,"WrLeh") != 0) {
5236 if (uLevel != 0 || strcmp(str2,"B41") != 0) {
5241 *rdata = smb_realloc_limit(*rdata,mdrcnt);
5247 desc.buflen = mdrcnt;
5248 if (init_package(&desc,1,0)) {
5249 PACKS(&desc,"B41","NULL");
5252 succnt = (desc.errcode == NERR_Success ? 1 : 0);
5254 *rdata_len = desc.usedlen;
5257 *rparam = smb_realloc_limit(*rparam,*rparam_len);
5261 SSVALS(*rparam,0,desc.errcode);
5263 SSVAL(*rparam,4,succnt);
5266 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
5271 static bool api_WPrintQProcEnum(struct smbd_server_connection *sconn,
5272 connection_struct *conn, uint16 vuid,
5273 char *param, int tpscnt,
5274 char *data, int tdscnt,
5275 int mdrcnt,int mprcnt,
5276 char **rdata,char **rparam,
5277 int *rdata_len,int *rparam_len)
5279 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
5280 char *str2 = skip_string(param,tpscnt,str1);
5281 char *p = skip_string(param,tpscnt,str2);
5284 struct pack_desc desc;
5286 if (!str1 || !str2 || !p) {
5289 memset((char *)&desc,'\0',sizeof(desc));
5291 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
5293 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
5295 /* check it's a supported varient */
5296 if (strcmp(str1,"WrLeh") != 0) {
5299 if (uLevel != 0 || strcmp(str2,"B13") != 0) {
5304 *rdata = smb_realloc_limit(*rdata,mdrcnt);
5310 desc.buflen = mdrcnt;
5312 if (init_package(&desc,1,0)) {
5313 PACKS(&desc,"B13","lpd");
5316 succnt = (desc.errcode == NERR_Success ? 1 : 0);
5318 *rdata_len = desc.usedlen;
5321 *rparam = smb_realloc_limit(*rparam,*rparam_len);
5325 SSVALS(*rparam,0,desc.errcode);
5327 SSVAL(*rparam,4,succnt);
5330 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
5335 static bool api_WPrintPortEnum(struct smbd_server_connection *sconn,
5336 connection_struct *conn, uint16 vuid,
5337 char *param, int tpscnt,
5338 char *data, int tdscnt,
5339 int mdrcnt,int mprcnt,
5340 char **rdata,char **rparam,
5341 int *rdata_len,int *rparam_len)
5343 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
5344 char *str2 = skip_string(param,tpscnt,str1);
5345 char *p = skip_string(param,tpscnt,str2);
5348 struct pack_desc desc;
5350 if (!str1 || !str2 || !p) {
5354 memset((char *)&desc,'\0',sizeof(desc));
5356 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
5358 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
5360 /* check it's a supported varient */
5361 if (strcmp(str1,"WrLeh") != 0) {
5364 if (uLevel != 0 || strcmp(str2,"B9") != 0) {
5369 *rdata = smb_realloc_limit(*rdata,mdrcnt);
5374 memset((char *)&desc,'\0',sizeof(desc));
5376 desc.buflen = mdrcnt;
5378 if (init_package(&desc,1,0)) {
5379 PACKS(&desc,"B13","lp0");
5382 succnt = (desc.errcode == NERR_Success ? 1 : 0);
5384 *rdata_len = desc.usedlen;
5387 *rparam = smb_realloc_limit(*rparam,*rparam_len);
5391 SSVALS(*rparam,0,desc.errcode);
5393 SSVAL(*rparam,4,succnt);
5396 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
5401 /****************************************************************************
5403 ****************************************************************************/
5405 static bool api_RNetSessionEnum(struct smbd_server_connection *sconn,
5406 connection_struct *conn, uint16 vuid,
5407 char *param, int tpscnt,
5408 char *data, int tdscnt,
5409 int mdrcnt,int mprcnt,
5410 char **rdata,char **rparam,
5411 int *rdata_len,int *rparam_len)
5414 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
5415 char *str2 = skip_string(param,tpscnt,str1);
5416 char *p = skip_string(param,tpscnt,str2);
5418 struct pack_desc desc;
5419 struct sessionid *session_list;
5420 int i, num_sessions;
5422 if (!str1 || !str2 || !p) {
5426 memset((char *)&desc,'\0',sizeof(desc));
5428 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
5430 DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel));
5431 DEBUG(7,("RNetSessionEnum req string=%s\n",str1));
5432 DEBUG(7,("RNetSessionEnum ret string=%s\n",str2));
5434 /* check it's a supported varient */
5435 if (strcmp(str1,RAP_NetSessionEnum_REQ) != 0) {
5438 if (uLevel != 2 || strcmp(str2,RAP_SESSION_INFO_L2) != 0) {
5442 num_sessions = list_sessions(talloc_tos(), &session_list);
5445 *rdata = smb_realloc_limit(*rdata,mdrcnt);
5450 memset((char *)&desc,'\0',sizeof(desc));
5452 desc.buflen = mdrcnt;
5454 if (!init_package(&desc,num_sessions,0)) {
5458 for(i=0; i<num_sessions; i++) {
5459 PACKS(&desc, "z", session_list[i].remote_machine);
5460 PACKS(&desc, "z", session_list[i].username);
5461 PACKI(&desc, "W", 1); /* num conns */
5462 PACKI(&desc, "W", 0); /* num opens */
5463 PACKI(&desc, "W", 1); /* num users */
5464 PACKI(&desc, "D", 0); /* session time */
5465 PACKI(&desc, "D", 0); /* idle time */
5466 PACKI(&desc, "D", 0); /* flags */
5467 PACKS(&desc, "z", "Unknown Client"); /* client type string */
5470 *rdata_len = desc.usedlen;
5473 *rparam = smb_realloc_limit(*rparam,*rparam_len);
5477 SSVALS(*rparam,0,desc.errcode);
5478 SSVAL(*rparam,2,0); /* converter */
5479 SSVAL(*rparam,4,num_sessions); /* count */
5481 DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc.errcode));
5487 /****************************************************************************
5488 The buffer was too small.
5489 ****************************************************************************/
5491 static bool api_TooSmall(struct smbd_server_connection *sconn,
5492 connection_struct *conn,uint16 vuid, char *param, char *data,
5493 int mdrcnt, int mprcnt,
5494 char **rdata, char **rparam,
5495 int *rdata_len, int *rparam_len)
5497 *rparam_len = MIN(*rparam_len,mprcnt);
5498 *rparam = smb_realloc_limit(*rparam,*rparam_len);
5505 SSVAL(*rparam,0,NERR_BufTooSmall);
5507 DEBUG(3,("Supplied buffer too small in API command\n"));
5512 /****************************************************************************
5513 The request is not supported.
5514 ****************************************************************************/
5516 static bool api_Unsupported(struct smbd_server_connection *sconn,
5517 connection_struct *conn, uint16 vuid,
5518 char *param, int tpscnt,
5519 char *data, int tdscnt,
5520 int mdrcnt, int mprcnt,
5521 char **rdata, char **rparam,
5522 int *rdata_len, int *rparam_len)
5525 *rparam = smb_realloc_limit(*rparam,*rparam_len);
5532 SSVAL(*rparam,0,NERR_notsupported);
5533 SSVAL(*rparam,2,0); /* converter word */
5535 DEBUG(3,("Unsupported API command\n"));
5540 static const struct {
5543 bool (*fn)(struct smbd_server_connection *sconn,
5544 connection_struct *, uint16,
5547 int,int,char **,char **,int *,int *);
5548 bool auth_user; /* Deny anonymous access? */
5549 } api_commands[] = {
5550 {"RNetShareEnum", RAP_WshareEnum, api_RNetShareEnum, True},
5551 {"RNetShareGetInfo", RAP_WshareGetInfo, api_RNetShareGetInfo},
5552 {"RNetShareAdd", RAP_WshareAdd, api_RNetShareAdd},
5553 {"RNetSessionEnum", RAP_WsessionEnum, api_RNetSessionEnum, True},
5554 {"RNetServerGetInfo", RAP_WserverGetInfo, api_RNetServerGetInfo},
5555 {"RNetGroupEnum", RAP_WGroupEnum, api_RNetGroupEnum, True},
5556 {"RNetGroupGetUsers", RAP_WGroupGetUsers, api_RNetGroupGetUsers, True},
5557 {"RNetUserEnum", RAP_WUserEnum, api_RNetUserEnum, True},
5558 {"RNetUserGetInfo", RAP_WUserGetInfo, api_RNetUserGetInfo},
5559 {"NetUserGetGroups", RAP_WUserGetGroups, api_NetUserGetGroups},
5560 {"NetWkstaGetInfo", RAP_WWkstaGetInfo, api_NetWkstaGetInfo},
5561 {"DosPrintQEnum", RAP_WPrintQEnum, api_DosPrintQEnum, True},
5562 {"DosPrintQGetInfo", RAP_WPrintQGetInfo, api_DosPrintQGetInfo},
5563 {"WPrintQueuePause", RAP_WPrintQPause, api_WPrintQueueCtrl},
5564 {"WPrintQueueResume", RAP_WPrintQContinue, api_WPrintQueueCtrl},
5565 {"WPrintJobEnumerate",RAP_WPrintJobEnum, api_WPrintJobEnumerate},
5566 {"WPrintJobGetInfo", RAP_WPrintJobGetInfo, api_WPrintJobGetInfo},
5567 {"RDosPrintJobDel", RAP_WPrintJobDel, api_RDosPrintJobDel},
5568 {"RDosPrintJobPause", RAP_WPrintJobPause, api_RDosPrintJobDel},
5569 {"RDosPrintJobResume",RAP_WPrintJobContinue, api_RDosPrintJobDel},
5570 {"WPrintDestEnum", RAP_WPrintDestEnum, api_WPrintDestEnum},
5571 {"WPrintDestGetInfo", RAP_WPrintDestGetInfo, api_WPrintDestGetInfo},
5572 {"NetRemoteTOD", RAP_NetRemoteTOD, api_NetRemoteTOD},
5573 {"WPrintQueuePurge", RAP_WPrintQPurge, api_WPrintQueueCtrl},
5574 {"NetServerEnum2", RAP_NetServerEnum2, api_RNetServerEnum2}, /* anon OK */
5575 {"NetServerEnum3", RAP_NetServerEnum3, api_RNetServerEnum3}, /* anon OK */
5576 {"WAccessGetUserPerms",RAP_WAccessGetUserPerms,api_WAccessGetUserPerms},
5577 {"SetUserPassword", RAP_WUserPasswordSet2, api_SetUserPassword},
5578 {"WWkstaUserLogon", RAP_WWkstaUserLogon, api_WWkstaUserLogon},
5579 {"PrintJobInfo", RAP_WPrintJobSetInfo, api_PrintJobInfo},
5580 {"WPrintDriverEnum", RAP_WPrintDriverEnum, api_WPrintDriverEnum},
5581 {"WPrintQProcEnum", RAP_WPrintQProcessorEnum,api_WPrintQProcEnum},
5582 {"WPrintPortEnum", RAP_WPrintPortEnum, api_WPrintPortEnum},
5583 {"SamOEMChangePassword",RAP_SamOEMChgPasswordUser2_P,api_SamOEMChangePassword}, /* anon OK */
5584 {NULL, -1, api_Unsupported}
5585 /* The following RAP calls are not implemented by Samba:
5587 RAP_WFileEnum2 - anon not OK
5592 /****************************************************************************
5593 Handle remote api calls.
5594 ****************************************************************************/
5596 void api_reply(connection_struct *conn, uint16 vuid,
5597 struct smb_request *req,
5598 char *data, char *params,
5599 int tdscnt, int tpscnt,
5600 int mdrcnt, int mprcnt)
5604 char *rparam = NULL;
5605 const char *name1 = NULL;
5606 const char *name2 = NULL;
5613 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
5614 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5619 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5622 api_command = SVAL(params,0);
5623 /* Is there a string at position params+2 ? */
5624 if (skip_string(params,tpscnt,params+2)) {
5629 name2 = skip_string(params,tpscnt,params+2);
5634 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
5638 tdscnt,tpscnt,mdrcnt,mprcnt));
5640 for (i=0;api_commands[i].name;i++) {
5641 if (api_commands[i].id == api_command && api_commands[i].fn) {
5642 DEBUG(3,("Doing %s\n",api_commands[i].name));
5647 /* Check whether this api call can be done anonymously */
5649 if (api_commands[i].auth_user && lp_restrict_anonymous()) {
5650 user_struct *user = get_valid_user_struct(req->sconn, vuid);
5652 if (!user || user->server_info->guest) {
5653 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5658 rdata = (char *)SMB_MALLOC(1024);
5660 memset(rdata,'\0',1024);
5663 rparam = (char *)SMB_MALLOC(1024);
5665 memset(rparam,'\0',1024);
5668 if(!rdata || !rparam) {
5669 DEBUG(0,("api_reply: malloc fail !\n"));
5672 reply_nterror(req, NT_STATUS_NO_MEMORY);
5676 reply = api_commands[i].fn(req->sconn, conn,
5678 params,tpscnt, /* params + length */
5679 data,tdscnt, /* data + length */
5681 &rdata,&rparam,&rdata_len,&rparam_len);
5684 if (rdata_len > mdrcnt || rparam_len > mprcnt) {
5685 reply = api_TooSmall(req->sconn,conn,vuid,params,data,
5687 &rdata,&rparam,&rdata_len,&rparam_len);
5690 /* if we get False back then it's actually unsupported */
5692 reply = api_Unsupported(req->sconn,conn,vuid,params,tpscnt,
5694 tdscnt,mdrcnt,mprcnt,
5695 &rdata,&rparam,&rdata_len,&rparam_len);
5698 /* If api_Unsupported returns false we can't return anything. */
5700 send_trans_reply(conn, req, rparam, rparam_len,
5701 rdata, rdata_len, False);