2 Unix SMB/CIFS implementation.
3 Inter-process communication and named pipe handling
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Jeremy Allison 2007.
8 Copyright (C) John H Terpstra 1995-1998
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 This file handles the named pipe and mailslot calls
25 in the SMBtrans protocol
29 #include "smbd/globals.h"
30 #include "../librpc/gen_ndr/cli_samr.h"
31 #include "../librpc/gen_ndr/cli_spoolss.h"
32 #include "rpc_client/cli_spoolss.h"
33 #include "rpc_client/init_spoolss.h"
34 #include "../librpc/gen_ndr/cli_srvsvc.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 policy_handle handle;
778 struct spoolss_DevmodeContainer devmode_ctr;
779 union spoolss_DriverInfo driver_info;
780 union spoolss_JobInfo *job_info = NULL;
781 union spoolss_PrinterInfo printer_info;
783 if (!str1 || !str2 || !p) {
786 memset((char *)&desc,'\0',sizeof(desc));
788 p = skip_string(param,tpscnt,p);
792 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
793 str3 = get_safe_str_ptr(param,tpscnt,p,4);
794 /* str3 may be null here and is checked in check_printq_info(). */
796 /* remove any trailing username */
797 if ((p = strchr_m(QueueName,'%')))
800 DEBUG(3,("api_DosPrintQGetInfo uLevel=%d name=%s\n",uLevel,QueueName));
802 /* check it's a supported varient */
803 if (!prefix_ok(str1,"zWrLh"))
805 if (!check_printq_info(&desc,uLevel,str2,str3)) {
807 * Patch from Scott Moomaw <scott@bridgewater.edu>
808 * to return the 'invalid info level' error if an
809 * unknown level was requested.
813 *rparam = smb_realloc_limit(*rparam,*rparam_len);
817 SSVALS(*rparam,0,ERRunknownlevel);
825 if (QueueName == NULL || (strlen(QueueName) < 1)) {
826 desc.errcode = W_ERROR_V(WERR_INVALID_PARAM);
830 status = rpc_pipe_open_interface(conn,
831 &ndr_table_spoolss.syntax_id,
833 &conn->sconn->client_id,
834 conn->sconn->msg_ctx,
836 if (!NT_STATUS_IS_OK(status)) {
837 DEBUG(0,("api_DosPrintQGetInfo: could not connect to spoolss: %s\n",
839 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
843 ZERO_STRUCT(devmode_ctr);
845 status = rpccli_spoolss_OpenPrinter(cli, mem_ctx,
852 if (!NT_STATUS_IS_OK(status)) {
853 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
856 if (!W_ERROR_IS_OK(werr)) {
857 desc.errcode = W_ERROR_V(werr);
861 werr = rpccli_spoolss_getprinter(cli, mem_ctx,
866 if (!W_ERROR_IS_OK(werr)) {
867 desc.errcode = W_ERROR_V(werr);
872 uint32_t server_major_version;
873 uint32_t server_minor_version;
875 werr = rpccli_spoolss_getprinterdriver2(cli, mem_ctx,
883 &server_major_version,
884 &server_minor_version);
885 if (!W_ERROR_IS_OK(werr)) {
886 desc.errcode = W_ERROR_V(werr);
890 count = get_printerdrivernumber(&driver_info.info3);
891 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count));
894 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
902 if (!W_ERROR_IS_OK(werr)) {
903 desc.errcode = W_ERROR_V(werr);
911 *rdata = smb_realloc_limit(*rdata,mdrcnt);
916 desc.buflen = mdrcnt;
919 * Don't return data but need to get correct length
920 * init_package will return wrong size if buflen=0
922 desc.buflen = getlen(desc.format);
923 desc.base = tmpdata = (char *) SMB_MALLOC (desc.buflen);
926 if (init_package(&desc,1,count)) {
927 desc.subcount = count;
928 fill_printq_info(uLevel,&desc,count, job_info, &driver_info.info3, &printer_info.info2);
931 *rdata_len = desc.usedlen;
934 * We must set the return code to ERRbuftoosmall
935 * in order to support lanman style printing with Win NT/2k
938 if (!mdrcnt && lp_disable_spoolss())
939 desc.errcode = ERRbuftoosmall;
942 if (cli && is_valid_policy_hnd(&handle)) {
943 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
946 *rdata_len = desc.usedlen;
948 *rparam = smb_realloc_limit(*rparam,*rparam_len);
953 SSVALS(*rparam,0,desc.errcode);
955 SSVAL(*rparam,4,desc.neededlen);
957 DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode));
964 /****************************************************************************
965 View list of all print jobs on all queues.
966 ****************************************************************************/
968 static bool api_DosPrintQEnum(struct smbd_server_connection *sconn,
969 connection_struct *conn, uint16 vuid,
970 char *param, int tpscnt,
971 char *data, int tdscnt,
972 int mdrcnt, int mprcnt,
973 char **rdata, char** rparam,
974 int *rdata_len, int *rparam_len)
976 char *param_format = get_safe_str_ptr(param,tpscnt,param,2);
977 char *output_format1 = skip_string(param,tpscnt,param_format);
978 char *p = skip_string(param,tpscnt,output_format1);
979 unsigned int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
980 char *output_format2 = get_safe_str_ptr(param,tpscnt,p,4);
982 struct pack_desc desc;
983 int *subcntarr = NULL;
984 int queuecnt = 0, subcnt = 0, succnt = 0;
986 WERROR werr = WERR_OK;
987 TALLOC_CTX *mem_ctx = talloc_tos();
989 struct rpc_pipe_client *cli = NULL;
990 struct spoolss_DevmodeContainer devmode_ctr;
991 uint32_t num_printers;
992 union spoolss_PrinterInfo *printer_info;
993 union spoolss_DriverInfo *driver_info;
994 union spoolss_JobInfo **job_info;
996 if (!param_format || !output_format1 || !p) {
1000 memset((char *)&desc,'\0',sizeof(desc));
1002 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
1004 if (!prefix_ok(param_format,"WrLeh")) {
1007 if (!check_printq_info(&desc,uLevel,output_format1,output_format2)) {
1009 * Patch from Scott Moomaw <scott@bridgewater.edu>
1010 * to return the 'invalid info level' error if an
1011 * unknown level was requested.
1015 *rparam = smb_realloc_limit(*rparam,*rparam_len);
1019 SSVALS(*rparam,0,ERRunknownlevel);
1025 status = rpc_pipe_open_interface(conn,
1026 &ndr_table_spoolss.syntax_id,
1028 &conn->sconn->client_id,
1029 conn->sconn->msg_ctx,
1031 if (!NT_STATUS_IS_OK(status)) {
1032 DEBUG(0,("api_DosPrintQEnum: could not connect to spoolss: %s\n",
1033 nt_errstr(status)));
1034 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
1038 werr = rpccli_spoolss_enumprinters(cli, mem_ctx,
1040 cli->srv_name_slash,
1045 if (!W_ERROR_IS_OK(werr)) {
1046 desc.errcode = W_ERROR_V(werr);
1050 queuecnt = num_printers;
1052 job_info = talloc_array(mem_ctx, union spoolss_JobInfo *, num_printers);
1053 if (job_info == NULL) {
1057 driver_info = talloc_array(mem_ctx, union spoolss_DriverInfo, num_printers);
1058 if (driver_info == NULL) {
1062 if((subcntarr = SMB_MALLOC_ARRAY(int,queuecnt)) == NULL) {
1063 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
1068 *rdata = smb_realloc_limit(*rdata,mdrcnt);
1074 desc.buflen = mdrcnt;
1077 for (i = 0; i < num_printers; i++) {
1080 struct policy_handle handle;
1081 const char *printername;
1083 printername = talloc_strdup(mem_ctx, printer_info[i].info2.printername);
1084 if (printername == NULL) {
1088 ZERO_STRUCT(handle);
1089 ZERO_STRUCT(devmode_ctr);
1091 status = rpccli_spoolss_OpenPrinter(cli, mem_ctx,
1098 if (!NT_STATUS_IS_OK(status)) {
1099 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
1102 if (!W_ERROR_IS_OK(werr)) {
1103 desc.errcode = W_ERROR_V(werr);
1107 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
1115 if (!W_ERROR_IS_OK(werr)) {
1116 desc.errcode = W_ERROR_V(werr);
1121 uint32_t server_major_version;
1122 uint32_t server_minor_version;
1124 werr = rpccli_spoolss_getprinterdriver2(cli, mem_ctx,
1132 &server_major_version,
1133 &server_minor_version);
1134 if (!W_ERROR_IS_OK(werr)) {
1135 desc.errcode = W_ERROR_V(werr);
1140 subcntarr[i] = num_jobs;
1141 subcnt += subcntarr[i];
1143 if (cli && is_valid_policy_hnd(&handle)) {
1144 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
1148 if (init_package(&desc,queuecnt,subcnt)) {
1149 for (i = 0; i < num_printers; i++) {
1150 fill_printq_info(uLevel,&desc,subcntarr[i], job_info[i], &driver_info[i].info3, &printer_info[i].info2);
1151 if (desc.errcode == NERR_Success) {
1157 SAFE_FREE(subcntarr);
1159 *rdata_len = desc.usedlen;
1161 *rparam = smb_realloc_limit(*rparam,*rparam_len);
1165 SSVALS(*rparam,0,desc.errcode);
1167 SSVAL(*rparam,4,succnt);
1168 SSVAL(*rparam,6,queuecnt);
1174 SAFE_FREE(subcntarr);
1179 /****************************************************************************
1180 Get info level for a server list query.
1181 ****************************************************************************/
1183 static bool check_server_info(int uLevel, char* id)
1187 if (strcmp(id,"B16") != 0) {
1192 if (strcmp(id,"B16BBDz") != 0) {
1202 struct srv_info_struct {
1210 /*******************************************************************
1211 Get server info lists from the files saved by nmbd. Return the
1213 ******************************************************************/
1215 static int get_server_info(uint32 servertype,
1216 struct srv_info_struct **servers,
1222 bool local_list_only;
1225 lines = file_lines_load(cache_path(SERVER_LIST), NULL, 0, NULL);
1227 DEBUG(4,("Can't open %s - %s\n",cache_path(SERVER_LIST),strerror(errno)));
1231 /* request for everything is code for request all servers */
1232 if (servertype == SV_TYPE_ALL) {
1233 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1236 local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY);
1238 DEBUG(4,("Servertype search: %8x\n",servertype));
1240 for (i=0;lines[i];i++) {
1242 struct srv_info_struct *s;
1243 const char *ptr = lines[i];
1245 TALLOC_CTX *frame = NULL;
1252 if (count == alloced) {
1254 *servers = SMB_REALLOC_ARRAY(*servers,struct srv_info_struct, alloced);
1256 DEBUG(0,("get_server_info: failed to enlarge servers info struct!\n"));
1260 memset((char *)((*servers)+count),'\0',sizeof(**servers)*(alloced-count));
1262 s = &(*servers)[count];
1264 frame = talloc_stackframe();
1266 if (!next_token_talloc(frame,&ptr,&p, NULL)) {
1270 fstrcpy(s->name, p);
1273 if (!next_token_talloc(frame,&ptr, &p, NULL)) {
1279 s->comment[0] = '\0';
1280 if (!next_token_talloc(frame,&ptr, &p, NULL)) {
1284 fstrcpy(s->comment, p);
1285 string_truncate(s->comment, MAX_SERVER_STRING_LENGTH);
1287 s->domain[0] = '\0';
1288 if (!next_token_talloc(frame,&ptr,&p, NULL)) {
1289 /* this allows us to cope with an old nmbd */
1290 fstrcpy(s->domain,lp_workgroup());
1292 fstrcpy(s->domain, p);
1296 if (sscanf(stype,"%X",&s->type) != 1) {
1297 DEBUG(4,("r:host file "));
1301 /* Filter the servers/domains we return based on what was asked for. */
1303 /* Check to see if we are being asked for a local list only. */
1304 if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) {
1305 DEBUG(4,("r: local list only"));
1309 /* doesn't match up: don't want it */
1310 if (!(servertype & s->type)) {
1311 DEBUG(4,("r:serv type "));
1315 if ((servertype & SV_TYPE_DOMAIN_ENUM) !=
1316 (s->type & SV_TYPE_DOMAIN_ENUM)) {
1317 DEBUG(4,("s: dom mismatch "));
1321 if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM)) {
1325 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1326 s->type &= ~SV_TYPE_LOCAL_LIST_ONLY;
1329 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1330 s->name, s->type, s->comment, s->domain));
1331 s->server_added = True;
1334 DEBUG(4,("%20s %8x %25s %15s\n",
1335 s->name, s->type, s->comment, s->domain));
1343 /*******************************************************************
1344 Fill in a server info structure.
1345 ******************************************************************/
1347 static int fill_srv_info(struct srv_info_struct *service,
1348 int uLevel, char **buf, int *buflen,
1349 char **stringbuf, int *stringspace, char *baseaddr)
1372 len = strlen(service->comment)+1;
1376 *buflen = struct_len;
1378 return struct_len + len;
1383 if (*buflen < struct_len) {
1390 p2 = p + struct_len;
1391 l2 = *buflen - struct_len;
1399 push_ascii(p,service->name, MAX_NETBIOSNAME_LEN, STR_TERMINATE);
1403 push_ascii(p,service->name,MAX_NETBIOSNAME_LEN, STR_TERMINATE);
1404 SIVAL(p,18,service->type);
1405 SIVAL(p,22,PTR_DIFF(p2,baseaddr));
1406 len += CopyAndAdvance(&p2,service->comment,&l2);
1411 *buf = p + struct_len;
1412 *buflen -= struct_len;
1423 static int srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
1425 return StrCaseCmp(s1->name,s2->name);
1428 /****************************************************************************
1429 View list of servers available (or possibly domains). The info is
1430 extracted from lists saved by nmbd on the local host.
1431 ****************************************************************************/
1433 static bool api_RNetServerEnum2(struct smbd_server_connection *sconn,
1434 connection_struct *conn, uint16 vuid,
1435 char *param, int tpscnt,
1436 char *data, int tdscnt,
1437 int mdrcnt, int mprcnt, char **rdata,
1438 char **rparam, int *rdata_len, int *rparam_len)
1440 char *str1 = get_safe_str_ptr(param, tpscnt, param, 2);
1441 char *str2 = skip_string(param,tpscnt,str1);
1442 char *p = skip_string(param,tpscnt,str2);
1443 int uLevel = get_safe_SVAL(param, tpscnt, p, 0, -1);
1444 int buf_len = get_safe_SVAL(param,tpscnt, p, 2, 0);
1445 uint32 servertype = get_safe_IVAL(param,tpscnt,p,4, 0);
1447 int data_len, fixed_len, string_len;
1448 int f_len = 0, s_len = 0;
1449 struct srv_info_struct *servers=NULL;
1450 int counted=0,total=0;
1453 bool domain_request;
1456 if (!str1 || !str2 || !p) {
1460 /* If someone sets all the bits they don't really mean to set
1461 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1464 if (servertype == SV_TYPE_ALL) {
1465 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1468 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1469 any other bit (they may just set this bit on its own) they
1470 want all the locally seen servers. However this bit can be
1471 set on its own so set the requested servers to be
1472 ALL - DOMAIN_ENUM. */
1474 if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM)) {
1475 servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
1478 domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
1479 local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
1483 if (!prefix_ok(str1,"WrLehD")) {
1486 if (!check_server_info(uLevel,str2)) {
1490 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1491 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1492 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1494 if (strcmp(str1, "WrLehDz") == 0) {
1495 if (skip_string(param,tpscnt,p) == NULL) {
1498 pull_ascii_fstring(domain, p);
1500 fstrcpy(domain, lp_workgroup());
1503 DEBUG(4, ("domain [%s]\n", domain));
1505 if (lp_browse_list()) {
1506 total = get_server_info(servertype,&servers,domain);
1509 data_len = fixed_len = string_len = 0;
1512 TYPESAFE_QSORT(servers, total, srv_comp);
1515 char *lastname=NULL;
1517 for (i=0;i<total;i++) {
1518 struct srv_info_struct *s = &servers[i];
1520 if (lastname && strequal(lastname,s->name)) {
1524 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1525 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1526 i, s->name, s->type, s->comment, s->domain));
1528 if (data_len < buf_len) {
1531 string_len += s_len;
1538 *rdata_len = fixed_len + string_len;
1539 *rdata = smb_realloc_limit(*rdata,*rdata_len);
1544 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1550 char *lastname=NULL;
1551 int count2 = counted;
1553 for (i = 0; i < total && count2;i++) {
1554 struct srv_info_struct *s = &servers[i];
1556 if (lastname && strequal(lastname,s->name)) {
1560 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1561 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1562 i, s->name, s->type, s->comment, s->domain));
1568 *rparam = smb_realloc_limit(*rparam,*rparam_len);
1572 SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata));
1574 SSVAL(*rparam,4,counted);
1575 SSVAL(*rparam,6,counted+missed);
1579 DEBUG(3,("NetServerEnum2 domain = %s uLevel=%d counted=%d total=%d\n",
1580 domain,uLevel,counted,counted+missed));
1585 static int srv_name_match(const char *n1, const char *n2)
1588 * [MS-RAP] footnote <88> for Section 3.2.5.15 says:
1590 * In Windows, FirstNameToReturn need not be an exact match:
1591 * the server will return a list of servers that exist on
1592 * the network greater than or equal to the FirstNameToReturn.
1594 int ret = StrCaseCmp(n1, n2);
1603 static bool api_RNetServerEnum3(struct smbd_server_connection *sconn,
1604 connection_struct *conn, uint16 vuid,
1605 char *param, int tpscnt,
1606 char *data, int tdscnt,
1607 int mdrcnt, int mprcnt, char **rdata,
1608 char **rparam, int *rdata_len, int *rparam_len)
1610 char *str1 = get_safe_str_ptr(param, tpscnt, param, 2);
1611 char *str2 = skip_string(param,tpscnt,str1);
1612 char *p = skip_string(param,tpscnt,str2);
1613 int uLevel = get_safe_SVAL(param, tpscnt, p, 0, -1);
1614 int buf_len = get_safe_SVAL(param,tpscnt, p, 2, 0);
1615 uint32 servertype = get_safe_IVAL(param,tpscnt,p,4, 0);
1617 int data_len, fixed_len, string_len;
1618 int f_len = 0, s_len = 0;
1619 struct srv_info_struct *servers=NULL;
1620 int counted=0,first=0,total=0;
1624 bool domain_request;
1627 if (!str1 || !str2 || !p) {
1631 /* If someone sets all the bits they don't really mean to set
1632 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1635 if (servertype == SV_TYPE_ALL) {
1636 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1639 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1640 any other bit (they may just set this bit on its own) they
1641 want all the locally seen servers. However this bit can be
1642 set on its own so set the requested servers to be
1643 ALL - DOMAIN_ENUM. */
1645 if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM)) {
1646 servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
1649 domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
1650 local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
1654 if (strcmp(str1, "WrLehDzz") != 0) {
1657 if (!check_server_info(uLevel,str2)) {
1661 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1662 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1663 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1665 if (skip_string(param,tpscnt,p) == NULL) {
1668 pull_ascii_fstring(domain, p);
1669 if (domain[0] == '\0') {
1670 fstrcpy(domain, lp_workgroup());
1672 p = skip_string(param,tpscnt,p);
1673 if (skip_string(param,tpscnt,p) == NULL) {
1676 pull_ascii_fstring(first_name, p);
1678 DEBUG(4, ("domain: '%s' first_name: '%s'\n",
1679 domain, first_name));
1681 if (lp_browse_list()) {
1682 total = get_server_info(servertype,&servers,domain);
1685 data_len = fixed_len = string_len = 0;
1688 TYPESAFE_QSORT(servers, total, srv_comp);
1690 if (first_name[0] != '\0') {
1691 struct srv_info_struct *first_server = NULL;
1693 BINARY_ARRAY_SEARCH(servers, total, name, first_name,
1694 srv_name_match, first_server);
1696 first = PTR_DIFF(first_server, servers) / sizeof(*servers);
1698 * The binary search may not find the exact match
1699 * so we need to search backward to find the first match
1701 * This implements the strange matching windows
1702 * implements. (see the comment in srv_name_match().
1706 ret = StrCaseCmp(first_name,
1707 servers[first-1].name);
1714 /* we should return no entries */
1720 char *lastname=NULL;
1722 for (i=first;i<total;i++) {
1723 struct srv_info_struct *s = &servers[i];
1725 if (lastname && strequal(lastname,s->name)) {
1729 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1730 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1731 i, s->name, s->type, s->comment, s->domain));
1733 if (data_len < buf_len) {
1736 string_len += s_len;
1743 *rdata_len = fixed_len + string_len;
1744 *rdata = smb_realloc_limit(*rdata,*rdata_len);
1749 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1755 char *lastname=NULL;
1756 int count2 = counted;
1758 for (i = first; i < total && count2;i++) {
1759 struct srv_info_struct *s = &servers[i];
1761 if (lastname && strequal(lastname,s->name)) {
1765 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1766 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1767 i, s->name, s->type, s->comment, s->domain));
1773 *rparam = smb_realloc_limit(*rparam,*rparam_len);
1777 SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata));
1779 SSVAL(*rparam,4,counted);
1780 SSVAL(*rparam,6,counted+missed);
1782 DEBUG(3,("NetServerEnum3 domain = %s uLevel=%d first=%d[%s => %s] counted=%d total=%d\n",
1783 domain,uLevel,first,first_name,
1784 first < total ? servers[first].name : "",
1785 counted,counted+missed));
1792 /****************************************************************************
1793 command 0x34 - suspected of being a "Lookup Names" stub api
1794 ****************************************************************************/
1796 static bool api_RNetGroupGetUsers(struct smbd_server_connection *sconn,
1797 connection_struct *conn, uint16 vuid,
1798 char *param, int tpscnt,
1799 char *data, int tdscnt,
1800 int mdrcnt, int mprcnt, char **rdata,
1801 char **rparam, int *rdata_len, int *rparam_len)
1803 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
1804 char *str2 = skip_string(param,tpscnt,str1);
1805 char *p = skip_string(param,tpscnt,str2);
1806 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
1807 int buf_len = get_safe_SVAL(param,tpscnt,p,2,0);
1811 if (!str1 || !str2 || !p) {
1815 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1816 str1, str2, p, uLevel, buf_len));
1818 if (!prefix_ok(str1,"zWrLeh")) {
1825 *rparam = smb_realloc_limit(*rparam,*rparam_len);
1830 SSVAL(*rparam,0,0x08AC); /* informational warning message */
1832 SSVAL(*rparam,4,counted);
1833 SSVAL(*rparam,6,counted+missed);
1838 /****************************************************************************
1839 get info about a share
1840 ****************************************************************************/
1842 static bool check_share_info(int uLevel, char* id)
1846 if (strcmp(id,"B13") != 0) {
1851 /* Level-2 descriptor is allowed (and ignored) */
1852 if (strcmp(id,"B13BWz") != 0 &&
1853 strcmp(id,"B13BWzWWWzB9B") != 0) {
1858 if (strcmp(id,"B13BWzWWWzB9B") != 0) {
1863 if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) {
1873 static int fill_share_info(connection_struct *conn, int snum, int uLevel,
1874 char** buf, int* buflen,
1875 char** stringbuf, int* stringspace, char* baseaddr)
1904 len += StrlenExpanded(conn,snum,lp_comment(snum));
1907 len += strlen(lp_pathname(snum)) + 1;
1910 *buflen = struct_len;
1915 return struct_len + len;
1920 if ((*buflen) < struct_len) {
1928 p2 = p + struct_len;
1929 l2 = (*buflen) - struct_len;
1936 push_ascii(p,lp_servicename(snum),13, STR_TERMINATE);
1942 type = STYPE_DISKTREE;
1943 if (lp_print_ok(snum)) {
1944 type = STYPE_PRINTQ;
1946 if (strequal("IPC",lp_fstype(snum))) {
1949 SSVAL(p,14,type); /* device type */
1950 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1951 len += CopyExpanded(conn,snum,&p2,lp_comment(snum),&l2);
1955 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1956 SSVALS(p,22,-1); /* max uses */
1957 SSVAL(p,24,1); /* current uses */
1958 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1959 len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1960 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1964 memset(p+40,0,SHPWLEN+2);
1975 (*buf) = p + struct_len;
1976 (*buflen) -= struct_len;
1978 (*stringspace) = l2;
1987 static bool api_RNetShareGetInfo(struct smbd_server_connection *sconn,
1988 connection_struct *conn,uint16 vuid,
1989 char *param, int tpscnt,
1990 char *data, int tdscnt,
1991 int mdrcnt,int mprcnt,
1992 char **rdata,char **rparam,
1993 int *rdata_len,int *rparam_len)
1995 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
1996 char *str2 = skip_string(param,tpscnt,str1);
1997 char *netname = skip_string(param,tpscnt,str2);
1998 char *p = skip_string(param,tpscnt,netname);
1999 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
2002 if (!str1 || !str2 || !netname || !p) {
2006 snum = find_service(netname);
2011 /* check it's a supported varient */
2012 if (!prefix_ok(str1,"zWrLh")) {
2015 if (!check_share_info(uLevel,str2)) {
2019 *rdata = smb_realloc_limit(*rdata,mdrcnt);
2024 *rdata_len = fill_share_info(conn,snum,uLevel,&p,&mdrcnt,0,0,0);
2025 if (*rdata_len < 0) {
2030 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2034 SSVAL(*rparam,0,NERR_Success);
2035 SSVAL(*rparam,2,0); /* converter word */
2036 SSVAL(*rparam,4,*rdata_len);
2041 /****************************************************************************
2042 View the list of available shares.
2044 This function is the server side of the NetShareEnum() RAP call.
2045 It fills the return buffer with share names and share comments.
2046 Note that the return buffer normally (in all known cases) allows only
2047 twelve byte strings for share names (plus one for a nul terminator).
2048 Share names longer than 12 bytes must be skipped.
2049 ****************************************************************************/
2051 static bool api_RNetShareEnum(struct smbd_server_connection *sconn,
2052 connection_struct *conn, uint16 vuid,
2053 char *param, int tpscnt,
2054 char *data, int tdscnt,
2062 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2063 char *str2 = skip_string(param,tpscnt,str1);
2064 char *p = skip_string(param,tpscnt,str2);
2065 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
2066 int buf_len = get_safe_SVAL(param,tpscnt,p,2,0);
2069 int total=0,counted=0;
2070 bool missed = False;
2072 int data_len, fixed_len, string_len;
2073 int f_len = 0, s_len = 0;
2075 if (!str1 || !str2 || !p) {
2079 if (!prefix_ok(str1,"WrLeh")) {
2082 if (!check_share_info(uLevel,str2)) {
2086 /* Ensure all the usershares are loaded. */
2088 load_registry_shares();
2089 count = load_usershare_shares();
2092 data_len = fixed_len = string_len = 0;
2093 for (i=0;i<count;i++) {
2094 fstring servicename_dos;
2095 if (!(lp_browseable(i) && lp_snum_ok(i))) {
2098 push_ascii_fstring(servicename_dos, lp_servicename(i));
2099 /* Maximum name length = 13. */
2100 if( lp_browseable( i ) && lp_snum_ok( i ) && (strlen(servicename_dos) < 13)) {
2102 data_len += fill_share_info(conn,i,uLevel,0,&f_len,0,&s_len,0);
2103 if (data_len < buf_len) {
2106 string_len += s_len;
2113 *rdata_len = fixed_len + string_len;
2114 *rdata = smb_realloc_limit(*rdata,*rdata_len);
2119 p2 = (*rdata) + fixed_len; /* auxiliary data (strings) will go here */
2124 for( i = 0; i < count; i++ ) {
2125 fstring servicename_dos;
2126 if (!(lp_browseable(i) && lp_snum_ok(i))) {
2130 push_ascii_fstring(servicename_dos, lp_servicename(i));
2131 if (lp_browseable(i) && lp_snum_ok(i) && (strlen(servicename_dos) < 13)) {
2132 if (fill_share_info( conn,i,uLevel,&p,&f_len,&p2,&s_len,*rdata ) < 0) {
2139 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2143 SSVAL(*rparam,0,missed ? ERRmoredata : NERR_Success);
2145 SSVAL(*rparam,4,counted);
2146 SSVAL(*rparam,6,total);
2148 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
2149 counted,total,uLevel,
2150 buf_len,*rdata_len,mdrcnt));
2155 /****************************************************************************
2157 ****************************************************************************/
2159 static bool api_RNetShareAdd(struct smbd_server_connection *sconn,
2160 connection_struct *conn,uint16 vuid,
2161 char *param, int tpscnt,
2162 char *data, int tdscnt,
2163 int mdrcnt,int mprcnt,
2164 char **rdata,char **rparam,
2165 int *rdata_len,int *rparam_len)
2167 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2168 char *str2 = skip_string(param,tpscnt,str1);
2169 char *p = skip_string(param,tpscnt,str2);
2170 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
2173 char *pathname = NULL;
2174 unsigned int offset;
2176 size_t converted_size;
2178 WERROR werr = WERR_OK;
2179 TALLOC_CTX *mem_ctx = talloc_tos();
2181 struct rpc_pipe_client *cli = NULL;
2182 union srvsvc_NetShareInfo info;
2183 struct srvsvc_NetShareInfo2 info2;
2185 if (!str1 || !str2 || !p) {
2189 /* check it's a supported varient */
2190 if (!prefix_ok(str1,RAP_WShareAdd_REQ)) {
2193 if (!check_share_info(uLevel,str2)) {
2200 /* Do we have a string ? */
2201 if (skip_string(data,mdrcnt,data) == NULL) {
2204 pull_ascii_fstring(sharename,data);
2210 /* only support disk share adds */
2211 if (SVAL(data,14)!=STYPE_DISKTREE) {
2215 offset = IVAL(data, 16);
2216 if (offset >= mdrcnt) {
2217 res = ERRinvalidparam;
2221 /* Do we have a string ? */
2222 if (skip_string(data,mdrcnt,data+offset) == NULL) {
2225 pull_ascii_fstring(comment, offset? (data+offset) : "");
2227 offset = IVAL(data, 26);
2229 if (offset >= mdrcnt) {
2230 res = ERRinvalidparam;
2234 /* Do we have a string ? */
2235 if (skip_string(data,mdrcnt,data+offset) == NULL) {
2239 if (!pull_ascii_talloc(talloc_tos(), &pathname,
2240 offset ? (data+offset) : "", &converted_size))
2242 DEBUG(0,("api_RNetShareAdd: pull_ascii_talloc failed: %s",
2250 status = rpc_pipe_open_internal(mem_ctx, &ndr_table_srvsvc.syntax_id,
2252 &conn->sconn->client_id,
2253 conn->sconn->msg_ctx,
2255 if (!NT_STATUS_IS_OK(status)) {
2256 DEBUG(0,("api_RNetShareAdd: could not connect to srvsvc: %s\n",
2257 nt_errstr(status)));
2258 res = W_ERROR_V(ntstatus_to_werror(status));
2262 info2.name = sharename;
2263 info2.type = STYPE_DISKTREE;
2264 info2.comment = comment;
2265 info2.permissions = 0;
2266 info2.max_users = 0;
2267 info2.current_users = 0;
2268 info2.path = pathname;
2269 info2.password = NULL;
2271 info.info2 = &info2;
2273 status = rpccli_srvsvc_NetShareAdd(cli, mem_ctx,
2274 cli->srv_name_slash,
2279 if (!NT_STATUS_IS_OK(status)) {
2280 res = W_ERROR_V(ntstatus_to_werror(status));
2283 if (!W_ERROR_IS_OK(werr)) {
2284 res = W_ERROR_V(werr);
2289 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2293 SSVAL(*rparam,0,NERR_Success);
2294 SSVAL(*rparam,2,0); /* converter word */
2295 SSVAL(*rparam,4,*rdata_len);
2303 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2308 SSVAL(*rparam,0,res);
2313 /****************************************************************************
2314 view list of groups available
2315 ****************************************************************************/
2317 static bool api_RNetGroupEnum(struct smbd_server_connection *sconn,
2318 connection_struct *conn,uint16 vuid,
2319 char *param, int tpscnt,
2320 char *data, int tdscnt,
2321 int mdrcnt,int mprcnt,
2322 char **rdata,char **rparam,
2323 int *rdata_len,int *rparam_len)
2327 int resume_context, cli_buf_size;
2328 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2329 char *str2 = skip_string(param,tpscnt,str1);
2330 char *p = skip_string(param,tpscnt,str2);
2332 uint32_t num_groups;
2333 uint32_t resume_handle;
2334 struct rpc_pipe_client *samr_pipe;
2335 struct policy_handle samr_handle, domain_handle;
2338 if (!str1 || !str2 || !p) {
2342 if (strcmp(str1,"WrLeh") != 0) {
2347 * W-> resume context (number of users to skip)
2348 * r -> return parameter pointer to receive buffer
2349 * L -> length of receive buffer
2350 * e -> return parameter number of entries
2351 * h -> return parameter total number of users
2354 if (strcmp("B21",str2) != 0) {
2358 status = rpc_pipe_open_internal(
2359 talloc_tos(), &ndr_table_samr.syntax_id,
2360 conn->server_info, &conn->sconn->client_id,
2361 conn->sconn->msg_ctx, &samr_pipe);
2362 if (!NT_STATUS_IS_OK(status)) {
2363 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2364 nt_errstr(status)));
2368 status = rpccli_samr_Connect2(samr_pipe, talloc_tos(), global_myname(),
2369 SAMR_ACCESS_LOOKUP_DOMAIN, &samr_handle);
2370 if (!NT_STATUS_IS_OK(status)) {
2371 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2372 nt_errstr(status)));
2376 status = rpccli_samr_OpenDomain(samr_pipe, talloc_tos(), &samr_handle,
2377 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS,
2378 get_global_sam_sid(), &domain_handle);
2379 if (!NT_STATUS_IS_OK(status)) {
2380 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2381 nt_errstr(status)));
2382 rpccli_samr_Close(samr_pipe, talloc_tos(), &samr_handle);
2386 resume_context = get_safe_SVAL(param,tpscnt,p,0,-1);
2387 cli_buf_size= get_safe_SVAL(param,tpscnt,p,2,0);
2388 DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: "
2389 "%d\n", resume_context, cli_buf_size));
2391 *rdata_len = cli_buf_size;
2392 *rdata = smb_realloc_limit(*rdata,*rdata_len);
2399 errflags = NERR_Success;
2404 struct samr_SamArray *sam_entries;
2405 uint32_t num_entries;
2407 status = rpccli_samr_EnumDomainGroups(samr_pipe, talloc_tos(),
2412 if (!NT_STATUS_IS_OK(status)) {
2413 DEBUG(10, ("rpccli_samr_EnumDomainGroups returned "
2414 "%s\n", nt_errstr(status)));
2418 if (num_entries == 0) {
2419 DEBUG(10, ("rpccli_samr_EnumDomainGroups returned "
2420 "no entries -- done\n"));
2424 for(i=0; i<num_entries; i++) {
2427 name = sam_entries->entries[i].name.string;
2429 if( ((PTR_DIFF(p,*rdata)+21) > *rdata_len) ) {
2430 /* set overflow error */
2431 DEBUG(3,("overflow on entry %d group %s\n", i,
2437 /* truncate the name at 21 chars. */
2439 strlcpy(p, name, 21);
2440 DEBUG(10,("adding entry %d group %s\n", i, p));
2442 p += 5; /* Both NT4 and W2k3SP1 do padding here. No
2447 if (errflags != NERR_Success) {
2451 TALLOC_FREE(sam_entries);
2454 rpccli_samr_Close(samr_pipe, talloc_tos(), &domain_handle);
2455 rpccli_samr_Close(samr_pipe, talloc_tos(), &samr_handle);
2457 *rdata_len = PTR_DIFF(p,*rdata);
2460 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2464 SSVAL(*rparam, 0, errflags);
2465 SSVAL(*rparam, 2, 0); /* converter word */
2466 SSVAL(*rparam, 4, num_groups); /* is this right?? */
2467 SSVAL(*rparam, 6, resume_context+num_groups); /* is this right?? */
2472 /*******************************************************************
2473 Get groups that a user is a member of.
2474 ******************************************************************/
2476 static bool api_NetUserGetGroups(struct smbd_server_connection *sconn,
2477 connection_struct *conn,uint16 vuid,
2478 char *param, int tpscnt,
2479 char *data, int tdscnt,
2480 int mdrcnt,int mprcnt,
2481 char **rdata,char **rparam,
2482 int *rdata_len,int *rparam_len)
2484 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2485 char *str2 = skip_string(param,tpscnt,str1);
2486 char *UserName = skip_string(param,tpscnt,str2);
2487 char *p = skip_string(param,tpscnt,UserName);
2488 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
2489 const char *level_string;
2495 struct rpc_pipe_client *samr_pipe;
2496 struct policy_handle samr_handle, domain_handle, user_handle;
2497 struct lsa_String name;
2498 struct lsa_Strings names;
2499 struct samr_Ids type, rid;
2500 struct samr_RidWithAttributeArray *rids;
2503 if (!str1 || !str2 || !UserName || !p) {
2508 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2513 /* check it's a supported varient */
2515 if ( strcmp(str1,"zWrLeh") != 0 )
2520 level_string = "B21";
2526 if (strcmp(level_string,str2) != 0)
2529 *rdata_len = mdrcnt + 1024;
2530 *rdata = smb_realloc_limit(*rdata,*rdata_len);
2535 SSVAL(*rparam,0,NERR_Success);
2536 SSVAL(*rparam,2,0); /* converter word */
2539 endp = *rdata + *rdata_len;
2541 status = rpc_pipe_open_internal(
2542 talloc_tos(), &ndr_table_samr.syntax_id,
2543 conn->server_info, &conn->sconn->client_id,
2544 conn->sconn->msg_ctx, &samr_pipe);
2545 if (!NT_STATUS_IS_OK(status)) {
2546 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2547 nt_errstr(status)));
2551 status = rpccli_samr_Connect2(samr_pipe, talloc_tos(), global_myname(),
2552 SAMR_ACCESS_LOOKUP_DOMAIN, &samr_handle);
2553 if (!NT_STATUS_IS_OK(status)) {
2554 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2555 nt_errstr(status)));
2559 status = rpccli_samr_OpenDomain(samr_pipe, talloc_tos(), &samr_handle,
2560 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
2561 get_global_sam_sid(), &domain_handle);
2562 if (!NT_STATUS_IS_OK(status)) {
2563 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2564 nt_errstr(status)));
2568 name.string = UserName;
2570 status = rpccli_samr_LookupNames(samr_pipe, talloc_tos(),
2571 &domain_handle, 1, &name,
2573 if (!NT_STATUS_IS_OK(status)) {
2574 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2575 nt_errstr(status)));
2579 if (type.ids[0] != SID_NAME_USER) {
2580 DEBUG(10, ("%s is a %s, not a user\n", UserName,
2581 sid_type_lookup(type.ids[0])));
2585 status = rpccli_samr_OpenUser(samr_pipe, talloc_tos(),
2587 SAMR_USER_ACCESS_GET_GROUPS,
2588 rid.ids[0], &user_handle);
2589 if (!NT_STATUS_IS_OK(status)) {
2590 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2591 nt_errstr(status)));
2595 status = rpccli_samr_GetGroupsForUser(samr_pipe, talloc_tos(),
2596 &user_handle, &rids);
2597 if (!NT_STATUS_IS_OK(status)) {
2598 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2599 nt_errstr(status)));
2603 for (i=0; i<rids->count; i++) {
2605 status = rpccli_samr_LookupRids(samr_pipe, talloc_tos(),
2607 1, &rids->rids[i].rid,
2609 if (NT_STATUS_IS_OK(status) && (names.count == 1)) {
2610 strlcpy(p, names.names[0].string, PTR_DIFF(endp,p));
2616 *rdata_len = PTR_DIFF(p,*rdata);
2618 SSVAL(*rparam,4,count); /* is this right?? */
2619 SSVAL(*rparam,6,count); /* is this right?? */
2624 rpccli_samr_Close(samr_pipe, talloc_tos(), &user_handle);
2626 rpccli_samr_Close(samr_pipe, talloc_tos(), &domain_handle);
2628 rpccli_samr_Close(samr_pipe, talloc_tos(), &samr_handle);
2633 /*******************************************************************
2635 ******************************************************************/
2637 static bool api_RNetUserEnum(struct smbd_server_connection *sconn,
2638 connection_struct *conn, uint16 vuid,
2639 char *param, int tpscnt,
2640 char *data, int tdscnt,
2641 int mdrcnt,int mprcnt,
2642 char **rdata,char **rparam,
2643 int *rdata_len,int *rparam_len)
2648 int i, resume_context, cli_buf_size;
2649 uint32_t resume_handle;
2651 struct rpc_pipe_client *samr_pipe;
2652 struct policy_handle samr_handle, domain_handle;
2655 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2656 char *str2 = skip_string(param,tpscnt,str1);
2657 char *p = skip_string(param,tpscnt,str2);
2660 if (!str1 || !str2 || !p) {
2664 if (strcmp(str1,"WrLeh") != 0)
2667 * W-> resume context (number of users to skip)
2668 * r -> return parameter pointer to receive buffer
2669 * L -> length of receive buffer
2670 * e -> return parameter number of entries
2671 * h -> return parameter total number of users
2674 resume_context = get_safe_SVAL(param,tpscnt,p,0,-1);
2675 cli_buf_size= get_safe_SVAL(param,tpscnt,p,2,0);
2676 DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n",
2677 resume_context, cli_buf_size));
2680 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2685 /* check it's a supported varient */
2686 if (strcmp("B21",str2) != 0)
2689 *rdata_len = cli_buf_size;
2690 *rdata = smb_realloc_limit(*rdata,*rdata_len);
2696 endp = *rdata + *rdata_len;
2698 status = rpc_pipe_open_internal(
2699 talloc_tos(), &ndr_table_samr.syntax_id,
2700 conn->server_info, &conn->sconn->client_id,
2701 conn->sconn->msg_ctx, &samr_pipe);
2702 if (!NT_STATUS_IS_OK(status)) {
2703 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2704 nt_errstr(status)));
2708 status = rpccli_samr_Connect2(samr_pipe, talloc_tos(), global_myname(),
2709 SAMR_ACCESS_LOOKUP_DOMAIN, &samr_handle);
2710 if (!NT_STATUS_IS_OK(status)) {
2711 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2712 nt_errstr(status)));
2716 status = rpccli_samr_OpenDomain(samr_pipe, talloc_tos(), &samr_handle,
2717 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS,
2718 get_global_sam_sid(), &domain_handle);
2719 if (!NT_STATUS_IS_OK(status)) {
2720 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2721 nt_errstr(status)));
2722 rpccli_samr_Close(samr_pipe, talloc_tos(), &samr_handle);
2726 errflags=NERR_Success;
2731 struct samr_SamArray *sam_entries;
2732 uint32_t num_entries;
2734 status = rpccli_samr_EnumDomainUsers(samr_pipe, talloc_tos(),
2740 if (!NT_STATUS_IS_OK(status)) {
2741 DEBUG(10, ("rpccli_samr_EnumDomainUsers returned "
2742 "%s\n", nt_errstr(status)));
2746 if (num_entries == 0) {
2747 DEBUG(10, ("rpccli_samr_EnumDomainUsers returned "
2748 "no entries -- done\n"));
2752 for (i=0; i<num_entries; i++) {
2755 name = sam_entries->entries[i].name.string;
2757 if(((PTR_DIFF(p,*rdata)+21)<=*rdata_len)
2758 &&(strlen(name)<=21)) {
2759 strlcpy(p,name,PTR_DIFF(endp,p));
2760 DEBUG(10,("api_RNetUserEnum:adding entry %d "
2761 "username %s\n",count_sent,p));
2765 /* set overflow error */
2766 DEBUG(10,("api_RNetUserEnum:overflow on entry %d "
2767 "username %s\n",count_sent,name));
2773 if (errflags != NERR_Success) {
2777 TALLOC_FREE(sam_entries);
2780 rpccli_samr_Close(samr_pipe, talloc_tos(), &domain_handle);
2781 rpccli_samr_Close(samr_pipe, talloc_tos(), &samr_handle);
2783 *rdata_len = PTR_DIFF(p,*rdata);
2785 SSVAL(*rparam,0,errflags);
2786 SSVAL(*rparam,2,0); /* converter word */
2787 SSVAL(*rparam,4,count_sent); /* is this right?? */
2788 SSVAL(*rparam,6,num_users); /* is this right?? */
2793 /****************************************************************************
2794 Get the time of day info.
2795 ****************************************************************************/
2797 static bool api_NetRemoteTOD(struct smbd_server_connection *sconn,
2798 connection_struct *conn,uint16 vuid,
2799 char *param, int tpscnt,
2800 char *data, int tdscnt,
2801 int mdrcnt,int mprcnt,
2802 char **rdata,char **rparam,
2803 int *rdata_len,int *rparam_len)
2806 time_t unixdate = time(NULL);
2810 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2816 *rdata = smb_realloc_limit(*rdata,*rdata_len);
2821 SSVAL(*rparam,0,NERR_Success);
2822 SSVAL(*rparam,2,0); /* converter word */
2826 srv_put_dos_date3(p,0,unixdate); /* this is the time that is looked at
2827 by NT in a "net time" operation,
2828 it seems to ignore the one below */
2830 /* the client expects to get localtime, not GMT, in this bit
2831 (I think, this needs testing) */
2832 t = localtime(&unixdate);
2837 SIVAL(p,4,0); /* msecs ? */
2838 SCVAL(p,8,t->tm_hour);
2839 SCVAL(p,9,t->tm_min);
2840 SCVAL(p,10,t->tm_sec);
2841 SCVAL(p,11,0); /* hundredths of seconds */
2842 SSVALS(p,12,get_time_zone(unixdate)/60); /* timezone in minutes from GMT */
2843 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
2844 SCVAL(p,16,t->tm_mday);
2845 SCVAL(p,17,t->tm_mon + 1);
2846 SSVAL(p,18,1900+t->tm_year);
2847 SCVAL(p,20,t->tm_wday);
2852 /****************************************************************************
2853 Set the user password.
2854 *****************************************************************************/
2856 static bool api_SetUserPassword(struct smbd_server_connection *sconn,
2857 connection_struct *conn,uint16 vuid,
2858 char *param, int tpscnt,
2859 char *data, int tdscnt,
2860 int mdrcnt,int mprcnt,
2861 char **rdata,char **rparam,
2862 int *rdata_len,int *rparam_len)
2864 char *np = get_safe_str_ptr(param,tpscnt,param,2);
2867 fstring pass1,pass2;
2868 TALLOC_CTX *mem_ctx = talloc_tos();
2870 struct rpc_pipe_client *cli = NULL;
2871 struct policy_handle connect_handle, domain_handle, user_handle;
2872 struct lsa_String domain_name;
2873 struct dom_sid2 *domain_sid;
2874 struct lsa_String names;
2875 struct samr_Ids rids;
2876 struct samr_Ids types;
2877 struct samr_Password old_lm_hash;
2878 struct samr_Password new_lm_hash;
2879 int errcode = NERR_badpass;
2884 /* Skip 2 strings. */
2885 p = skip_string(param,tpscnt,np);
2886 p = skip_string(param,tpscnt,p);
2892 /* Do we have a string ? */
2893 if (skip_string(param,tpscnt,p) == NULL) {
2896 pull_ascii_fstring(user,p);
2898 p = skip_string(param,tpscnt,p);
2903 memset(pass1,'\0',sizeof(pass1));
2904 memset(pass2,'\0',sizeof(pass2));
2906 * We use 31 here not 32 as we're checking
2907 * the last byte we want to access is safe.
2909 if (!is_offset_safe(param,tpscnt,p,31)) {
2913 memcpy(pass2,p+16,16);
2915 encrypted = get_safe_SVAL(param,tpscnt,p+32,0,-1);
2916 if (encrypted == -1) {
2917 errcode = W_ERROR_V(WERR_INVALID_PARAM);
2921 min_pwd_length = get_safe_SVAL(param,tpscnt,p+34,0,-1);
2922 if (min_pwd_length == -1) {
2923 errcode = W_ERROR_V(WERR_INVALID_PARAM);
2928 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2935 DEBUG(3,("Set password for <%s> (encrypted: %d, min_pwd_length: %d)\n",
2936 user, encrypted, min_pwd_length));
2938 ZERO_STRUCT(connect_handle);
2939 ZERO_STRUCT(domain_handle);
2940 ZERO_STRUCT(user_handle);
2942 status = rpc_pipe_open_internal(mem_ctx, &ndr_table_samr.syntax_id,
2944 &conn->sconn->client_id,
2945 conn->sconn->msg_ctx,
2947 if (!NT_STATUS_IS_OK(status)) {
2948 DEBUG(0,("api_SetUserPassword: could not connect to samr: %s\n",
2949 nt_errstr(status)));
2950 errcode = W_ERROR_V(ntstatus_to_werror(status));
2954 status = rpccli_samr_Connect2(cli, mem_ctx,
2956 SAMR_ACCESS_CONNECT_TO_SERVER |
2957 SAMR_ACCESS_ENUM_DOMAINS |
2958 SAMR_ACCESS_LOOKUP_DOMAIN,
2960 if (!NT_STATUS_IS_OK(status)) {
2961 errcode = W_ERROR_V(ntstatus_to_werror(status));
2965 init_lsa_String(&domain_name, get_global_sam_name());
2967 status = rpccli_samr_LookupDomain(cli, mem_ctx,
2971 if (!NT_STATUS_IS_OK(status)) {
2972 errcode = W_ERROR_V(ntstatus_to_werror(status));
2976 status = rpccli_samr_OpenDomain(cli, mem_ctx,
2978 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
2981 if (!NT_STATUS_IS_OK(status)) {
2982 errcode = W_ERROR_V(ntstatus_to_werror(status));
2986 init_lsa_String(&names, user);
2988 status = rpccli_samr_LookupNames(cli, mem_ctx,
2994 if (!NT_STATUS_IS_OK(status)) {
2995 errcode = W_ERROR_V(ntstatus_to_werror(status));
2999 if (rids.count != 1) {
3000 errcode = W_ERROR_V(WERR_NO_SUCH_USER);
3003 if (rids.count != types.count) {
3004 errcode = W_ERROR_V(WERR_INVALID_PARAM);
3007 if (types.ids[0] != SID_NAME_USER) {
3008 errcode = W_ERROR_V(WERR_INVALID_PARAM);
3014 status = rpccli_samr_OpenUser(cli, mem_ctx,
3016 SAMR_USER_ACCESS_CHANGE_PASSWORD,
3019 if (!NT_STATUS_IS_OK(status)) {
3020 errcode = W_ERROR_V(ntstatus_to_werror(status));
3024 if (encrypted == 0) {
3025 E_deshash(pass1, old_lm_hash.hash);
3026 E_deshash(pass2, new_lm_hash.hash);
3028 ZERO_STRUCT(old_lm_hash);
3029 ZERO_STRUCT(new_lm_hash);
3030 memcpy(old_lm_hash.hash, pass1, MIN(strlen(pass1), 16));
3031 memcpy(new_lm_hash.hash, pass1, MIN(strlen(pass2), 16));
3034 status = rpccli_samr_ChangePasswordUser(cli, mem_ctx,
3036 true, /* lm_present */
3039 false, /* nt_present */
3040 NULL, /* old_nt_crypted */
3041 NULL, /* new_nt_crypted */
3042 false, /* cross1_present */
3043 NULL, /* nt_cross */
3044 false, /* cross2_present */
3045 NULL); /* lm_cross */
3046 if (!NT_STATUS_IS_OK(status)) {
3047 errcode = W_ERROR_V(ntstatus_to_werror(status));
3051 errcode = NERR_Success;
3054 if (cli && is_valid_policy_hnd(&user_handle)) {
3055 rpccli_samr_Close(cli, mem_ctx, &user_handle);
3057 if (cli && is_valid_policy_hnd(&domain_handle)) {
3058 rpccli_samr_Close(cli, mem_ctx, &domain_handle);
3060 if (cli && is_valid_policy_hnd(&connect_handle)) {
3061 rpccli_samr_Close(cli, mem_ctx, &connect_handle);
3064 memset((char *)pass1,'\0',sizeof(fstring));
3065 memset((char *)pass2,'\0',sizeof(fstring));
3067 SSVAL(*rparam,0,errcode);
3068 SSVAL(*rparam,2,0); /* converter word */
3072 /****************************************************************************
3073 Set the user password (SamOEM version - gets plaintext).
3074 ****************************************************************************/
3076 static bool api_SamOEMChangePassword(struct smbd_server_connection *sconn,
3077 connection_struct *conn,uint16 vuid,
3078 char *param, int tpscnt,
3079 char *data, int tdscnt,
3080 int mdrcnt,int mprcnt,
3081 char **rdata,char **rparam,
3082 int *rdata_len,int *rparam_len)
3085 char *p = get_safe_str_ptr(param,tpscnt,param,2);
3087 TALLOC_CTX *mem_ctx = talloc_tos();
3089 struct rpc_pipe_client *cli = NULL;
3090 struct lsa_AsciiString server, account;
3091 struct samr_CryptPassword password;
3092 struct samr_Password hash;
3093 int errcode = NERR_badpass;
3097 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3107 SSVAL(*rparam,0,NERR_badpass);
3110 * Check the parameter definition is correct.
3113 /* Do we have a string ? */
3114 if (skip_string(param,tpscnt,p) == 0) {
3117 if(!strequal(p, "zsT")) {
3118 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", p));
3121 p = skip_string(param, tpscnt, p);
3126 /* Do we have a string ? */
3127 if (skip_string(param,tpscnt,p) == 0) {
3130 if(!strequal(p, "B516B16")) {
3131 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p));
3134 p = skip_string(param,tpscnt,p);
3138 /* Do we have a string ? */
3139 if (skip_string(param,tpscnt,p) == 0) {
3142 p += pull_ascii_fstring(user,p);
3144 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user));
3146 if (tdscnt != 532) {
3147 errcode = W_ERROR_V(WERR_INVALID_PARAM);
3151 bufsize = get_safe_SVAL(param,tpscnt,p,0,-1);
3152 if (bufsize != 532) {
3153 errcode = W_ERROR_V(WERR_INVALID_PARAM);
3157 memcpy(password.data, data, 516);
3158 memcpy(hash.hash, data+516, 16);
3160 status = rpc_pipe_open_internal(mem_ctx, &ndr_table_samr.syntax_id,
3162 &conn->sconn->client_id,
3163 conn->sconn->msg_ctx,
3165 if (!NT_STATUS_IS_OK(status)) {
3166 DEBUG(0,("api_SamOEMChangePassword: could not connect to samr: %s\n",
3167 nt_errstr(status)));
3168 errcode = W_ERROR_V(ntstatus_to_werror(status));
3172 init_lsa_AsciiString(&server, global_myname());
3173 init_lsa_AsciiString(&account, user);
3175 status = rpccli_samr_OemChangePasswordUser2(cli, mem_ctx,
3180 if (!NT_STATUS_IS_OK(status)) {
3181 errcode = W_ERROR_V(ntstatus_to_werror(status));
3185 errcode = NERR_Success;
3187 SSVAL(*rparam,0,errcode);
3188 SSVAL(*rparam,2,0); /* converter word */
3193 /****************************************************************************
3196 ****************************************************************************/
3198 static bool api_RDosPrintJobDel(struct smbd_server_connection *sconn,
3199 connection_struct *conn,uint16 vuid,
3200 char *param, int tpscnt,
3201 char *data, int tdscnt,
3202 int mdrcnt,int mprcnt,
3203 char **rdata,char **rparam,
3204 int *rdata_len,int *rparam_len)
3206 int function = get_safe_SVAL(param,tpscnt,param,0,0);
3207 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3208 char *str2 = skip_string(param,tpscnt,str1);
3209 char *p = skip_string(param,tpscnt,str2);
3213 WERROR werr = WERR_OK;
3215 TALLOC_CTX *mem_ctx = talloc_tos();
3217 struct rpc_pipe_client *cli = NULL;
3218 struct policy_handle handle;
3219 struct spoolss_DevmodeContainer devmode_ctr;
3220 enum spoolss_JobControl command;
3222 if (!str1 || !str2 || !p) {
3226 * We use 1 here not 2 as we're checking
3227 * the last byte we want to access is safe.
3229 if (!is_offset_safe(param,tpscnt,p,1)) {
3232 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
3235 /* check it's a supported varient */
3236 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
3240 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3246 ZERO_STRUCT(handle);
3248 status = rpc_pipe_open_interface(conn,
3249 &ndr_table_spoolss.syntax_id,
3251 &conn->sconn->client_id,
3252 conn->sconn->msg_ctx,
3254 if (!NT_STATUS_IS_OK(status)) {
3255 DEBUG(0,("api_RDosPrintJobDel: could not connect to spoolss: %s\n",
3256 nt_errstr(status)));
3257 errcode = W_ERROR_V(ntstatus_to_werror(status));
3261 ZERO_STRUCT(devmode_ctr);
3263 status = rpccli_spoolss_OpenPrinter(cli, mem_ctx,
3267 JOB_ACCESS_ADMINISTER,
3270 if (!NT_STATUS_IS_OK(status)) {
3271 errcode = W_ERROR_V(ntstatus_to_werror(status));
3274 if (!W_ERROR_IS_OK(werr)) {
3275 errcode = W_ERROR_V(werr);
3279 /* FIXME: formerly NERR_JobNotFound was returned if job did not exist
3280 * and NERR_DestNotFound if share did not exist */
3282 errcode = NERR_Success;
3285 case 81: /* delete */
3286 command = SPOOLSS_JOB_CONTROL_DELETE;
3288 case 82: /* pause */
3289 command = SPOOLSS_JOB_CONTROL_PAUSE;
3291 case 83: /* resume */
3292 command = SPOOLSS_JOB_CONTROL_RESUME;
3295 errcode = NERR_notsupported;
3299 status = rpccli_spoolss_SetJob(cli, mem_ctx,
3302 NULL, /* unique ptr ctr */
3305 if (!NT_STATUS_IS_OK(status)) {
3306 errcode = W_ERROR_V(ntstatus_to_werror(status));
3309 if (!W_ERROR_IS_OK(werr)) {
3310 errcode = W_ERROR_V(werr);
3315 if (cli && is_valid_policy_hnd(&handle)) {
3316 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
3319 SSVAL(*rparam,0,errcode);
3320 SSVAL(*rparam,2,0); /* converter word */
3325 /****************************************************************************
3326 Purge a print queue - or pause or resume it.
3327 ****************************************************************************/
3329 static bool api_WPrintQueueCtrl(struct smbd_server_connection *sconn,
3330 connection_struct *conn,uint16 vuid,
3331 char *param, int tpscnt,
3332 char *data, int tdscnt,
3333 int mdrcnt,int mprcnt,
3334 char **rdata,char **rparam,
3335 int *rdata_len,int *rparam_len)
3337 int function = get_safe_SVAL(param,tpscnt,param,0,0);
3338 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3339 char *str2 = skip_string(param,tpscnt,str1);
3340 char *QueueName = skip_string(param,tpscnt,str2);
3341 int errcode = NERR_notsupported;
3342 WERROR werr = WERR_OK;
3345 TALLOC_CTX *mem_ctx = talloc_tos();
3346 struct rpc_pipe_client *cli = NULL;
3347 struct policy_handle handle;
3348 struct spoolss_SetPrinterInfoCtr info_ctr;
3349 struct spoolss_DevmodeContainer devmode_ctr;
3350 struct sec_desc_buf secdesc_ctr;
3351 enum spoolss_PrinterControl command;
3353 if (!str1 || !str2 || !QueueName) {
3357 /* check it's a supported varient */
3358 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
3362 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3368 if (skip_string(param,tpscnt,QueueName) == NULL) {
3372 ZERO_STRUCT(handle);
3374 status = rpc_pipe_open_interface(conn,
3375 &ndr_table_spoolss.syntax_id,
3377 &conn->sconn->client_id,
3378 conn->sconn->msg_ctx,
3380 if (!NT_STATUS_IS_OK(status)) {
3381 DEBUG(0,("api_WPrintQueueCtrl: could not connect to spoolss: %s\n",
3382 nt_errstr(status)));
3383 errcode = W_ERROR_V(ntstatus_to_werror(status));
3387 ZERO_STRUCT(devmode_ctr);
3389 status = rpccli_spoolss_OpenPrinter(cli, mem_ctx,
3393 SEC_FLAG_MAXIMUM_ALLOWED,
3396 if (!NT_STATUS_IS_OK(status)) {
3397 errcode = W_ERROR_V(ntstatus_to_werror(status));
3400 if (!W_ERROR_IS_OK(werr)) {
3401 errcode = W_ERROR_V(werr);
3406 case 74: /* Pause queue */
3407 command = SPOOLSS_PRINTER_CONTROL_PAUSE;
3409 case 75: /* Resume queue */
3410 command = SPOOLSS_PRINTER_CONTROL_RESUME;
3412 case 103: /* Purge */
3413 command = SPOOLSS_PRINTER_CONTROL_PURGE;
3416 werr = WERR_NOT_SUPPORTED;
3420 if (!W_ERROR_IS_OK(werr)) {
3421 errcode = W_ERROR_V(werr);
3425 ZERO_STRUCT(info_ctr);
3426 ZERO_STRUCT(secdesc_ctr);
3428 status = rpccli_spoolss_SetPrinter(cli, mem_ctx,
3435 if (!NT_STATUS_IS_OK(status)) {
3436 errcode = W_ERROR_V(ntstatus_to_werror(status));
3439 if (!W_ERROR_IS_OK(werr)) {
3440 errcode = W_ERROR_V(werr);
3444 errcode = W_ERROR_V(werr);
3448 if (cli && is_valid_policy_hnd(&handle)) {
3449 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
3452 SSVAL(*rparam,0,errcode);
3453 SSVAL(*rparam,2,0); /* converter word */
3458 /****************************************************************************
3459 set the property of a print job (undocumented?)
3460 ? function = 0xb -> set name of print job
3461 ? function = 0x6 -> move print job up/down
3462 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
3463 or <WWsTP> <WB21BB16B10zWWzDDz>
3464 ****************************************************************************/
3466 static int check_printjob_info(struct pack_desc* desc,
3467 int uLevel, char* id)
3469 desc->subformat = NULL;
3471 case 0: desc->format = "W"; break;
3472 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
3473 case 2: desc->format = "WWzWWDDzz"; break;
3474 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
3475 case 4: desc->format = "WWzWWDDzzzzzDDDDDDD"; break;
3477 DEBUG(0,("check_printjob_info: invalid level %d\n",
3481 if (id == NULL || strcmp(desc->format,id) != 0) {
3482 DEBUG(0,("check_printjob_info: invalid format %s\n",
3483 id ? id : "<NULL>" ));
3489 static bool api_PrintJobInfo(struct smbd_server_connection *sconn,
3490 connection_struct *conn, uint16 vuid,
3491 char *param, int tpscnt,
3492 char *data, int tdscnt,
3493 int mdrcnt,int mprcnt,
3494 char **rdata,char **rparam,
3495 int *rdata_len,int *rparam_len)
3497 struct pack_desc desc;
3498 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3499 char *str2 = skip_string(param,tpscnt,str1);
3500 char *p = skip_string(param,tpscnt,str2);
3503 int uLevel = get_safe_SVAL(param,tpscnt,p,2,-1);
3504 int function = get_safe_SVAL(param,tpscnt,p,4,-1);
3507 TALLOC_CTX *mem_ctx = talloc_tos();
3510 struct rpc_pipe_client *cli = NULL;
3511 struct policy_handle handle;
3512 struct spoolss_DevmodeContainer devmode_ctr;
3513 struct spoolss_JobInfoContainer ctr;
3514 union spoolss_JobInfo info;
3515 struct spoolss_SetJobInfo1 info1;
3517 if (!str1 || !str2 || !p) {
3521 * We use 1 here not 2 as we're checking
3522 * the last byte we want to access is safe.
3524 if (!is_offset_safe(param,tpscnt,p,1)) {
3527 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
3530 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3537 /* check it's a supported varient */
3538 if ((strcmp(str1,"WWsTP")) ||
3539 (!check_printjob_info(&desc,uLevel,str2)))
3542 errcode = NERR_notsupported;
3546 /* change print job name, data gives the name */
3552 ZERO_STRUCT(handle);
3554 status = rpc_pipe_open_interface(conn,
3555 &ndr_table_spoolss.syntax_id,
3557 &conn->sconn->client_id,
3558 conn->sconn->msg_ctx,
3560 if (!NT_STATUS_IS_OK(status)) {
3561 DEBUG(0,("api_PrintJobInfo: could not connect to spoolss: %s\n",
3562 nt_errstr(status)));
3563 errcode = W_ERROR_V(ntstatus_to_werror(status));
3567 ZERO_STRUCT(devmode_ctr);
3569 status = rpccli_spoolss_OpenPrinter(cli, mem_ctx,
3576 if (!NT_STATUS_IS_OK(status)) {
3577 errcode = W_ERROR_V(ntstatus_to_werror(status));
3580 if (!W_ERROR_IS_OK(werr)) {
3581 errcode = W_ERROR_V(werr);
3585 werr = rpccli_spoolss_getjob(cli, mem_ctx,
3591 if (!W_ERROR_IS_OK(werr)) {
3592 errcode = W_ERROR_V(werr);
3598 info1.job_id = info.info1.job_id;
3599 info1.printer_name = info.info1.printer_name;
3600 info1.user_name = info.info1.user_name;
3601 info1.document_name = data;
3602 info1.data_type = info.info1.data_type;
3603 info1.text_status = info.info1.text_status;
3604 info1.status = info.info1.status;
3605 info1.priority = info.info1.priority;
3606 info1.position = info.info1.position;
3607 info1.total_pages = info.info1.total_pages;
3608 info1.pages_printed = info.info1.pages_printed;
3609 info1.submitted = info.info1.submitted;
3612 ctr.info.info1 = &info1;
3614 status = rpccli_spoolss_SetJob(cli, mem_ctx,
3620 if (!NT_STATUS_IS_OK(status)) {
3621 errcode = W_ERROR_V(ntstatus_to_werror(status));
3624 if (!W_ERROR_IS_OK(werr)) {
3625 errcode = W_ERROR_V(werr);
3629 errcode = NERR_Success;
3632 if (cli && is_valid_policy_hnd(&handle)) {
3633 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
3636 SSVALS(*rparam,0,errcode);
3637 SSVAL(*rparam,2,0); /* converter word */
3643 /****************************************************************************
3644 Get info about the server.
3645 ****************************************************************************/
3647 static bool api_RNetServerGetInfo(struct smbd_server_connection *sconn,
3648 connection_struct *conn,uint16 vuid,
3649 char *param, int tpscnt,
3650 char *data, int tdscnt,
3651 int mdrcnt,int mprcnt,
3652 char **rdata,char **rparam,
3653 int *rdata_len,int *rparam_len)
3655 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3656 char *str2 = skip_string(param,tpscnt,str1);
3657 char *p = skip_string(param,tpscnt,str2);
3658 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
3664 TALLOC_CTX *mem_ctx = talloc_tos();
3665 struct rpc_pipe_client *cli = NULL;
3666 union srvsvc_NetSrvInfo info;
3669 if (!str1 || !str2 || !p) {
3673 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
3675 /* check it's a supported varient */
3676 if (!prefix_ok(str1,"WrLh")) {
3682 if (strcmp(str2,"B16") != 0) {
3688 if (strcmp(str2,"B16BBDz") != 0) {
3694 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")!= 0) {
3700 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz") != 0) {
3706 if (strcmp(str2,"DN") != 0) {
3712 if (strcmp(str2,"B16BBDzWWzzz") != 0) {
3721 *rdata_len = mdrcnt;
3722 *rdata = smb_realloc_limit(*rdata,*rdata_len);
3728 p2 = p + struct_len;
3730 status = rpc_pipe_open_internal(mem_ctx, &ndr_table_srvsvc.syntax_id,
3732 &conn->sconn->client_id,
3733 conn->sconn->msg_ctx,
3735 if (!NT_STATUS_IS_OK(status)) {
3736 DEBUG(0,("api_RNetServerGetInfo: could not connect to srvsvc: %s\n",
3737 nt_errstr(status)));
3738 errcode = W_ERROR_V(ntstatus_to_werror(status));
3742 status = rpccli_srvsvc_NetSrvGetInfo(cli, mem_ctx,
3747 if (!NT_STATUS_IS_OK(status)) {
3748 errcode = W_ERROR_V(ntstatus_to_werror(status));
3751 if (!W_ERROR_IS_OK(werr)) {
3752 errcode = W_ERROR_V(werr);
3756 if (info.info101 == NULL) {
3757 errcode = W_ERROR_V(WERR_INVALID_PARAM);
3762 srvstr_push(NULL, 0, p, info.info101->server_name, 16,
3763 STR_ASCII|STR_UPPER|STR_TERMINATE);
3767 SCVAL(p,0,info.info101->version_major);
3768 SCVAL(p,1,info.info101->version_minor);
3769 SIVAL(p,2,info.info101->server_type);
3771 if (mdrcnt == struct_len) {
3774 SIVAL(p,6,PTR_DIFF(p2,*rdata));
3775 if (mdrcnt - struct_len <= 0) {
3779 info.info101->comment,
3780 MIN(mdrcnt - struct_len,
3781 MAX_SERVER_STRING_LENGTH),
3783 p2 = skip_string(*rdata,*rdata_len,p2);
3791 return False; /* not yet implemented */
3794 errcode = NERR_Success;
3798 *rdata_len = PTR_DIFF(p2,*rdata);
3801 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3805 SSVAL(*rparam,0,errcode);
3806 SSVAL(*rparam,2,0); /* converter word */
3807 SSVAL(*rparam,4,*rdata_len);
3812 /****************************************************************************
3813 Get info about the server.
3814 ****************************************************************************/
3816 static bool api_NetWkstaGetInfo(struct smbd_server_connection *sconn,
3817 connection_struct *conn,uint16 vuid,
3818 char *param, int tpscnt,
3819 char *data, int tdscnt,
3820 int mdrcnt,int mprcnt,
3821 char **rdata,char **rparam,
3822 int *rdata_len,int *rparam_len)
3824 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3825 char *str2 = skip_string(param,tpscnt,str1);
3826 char *p = skip_string(param,tpscnt,str2);
3829 int level = get_safe_SVAL(param,tpscnt,p,0,-1);
3831 if (!str1 || !str2 || !p) {
3835 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
3838 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3843 /* check it's a supported varient */
3844 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz"))) {
3848 *rdata_len = mdrcnt + 1024;
3849 *rdata = smb_realloc_limit(*rdata,*rdata_len);
3854 SSVAL(*rparam,0,NERR_Success);
3855 SSVAL(*rparam,2,0); /* converter word */
3858 endp = *rdata + *rdata_len;
3860 p2 = get_safe_ptr(*rdata,*rdata_len,p,22);
3865 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
3866 strlcpy(p2,get_local_machine_name(),PTR_DIFF(endp,p2));
3868 p2 = skip_string(*rdata,*rdata_len,p2);
3874 SIVAL(p,0,PTR_DIFF(p2,*rdata));
3875 strlcpy(p2,conn->server_info->sanitized_username,PTR_DIFF(endp,p2));
3876 p2 = skip_string(*rdata,*rdata_len,p2);
3882 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
3883 strlcpy(p2,lp_workgroup(),PTR_DIFF(endp,p2));
3885 p2 = skip_string(*rdata,*rdata_len,p2);
3891 SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
3892 SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
3895 SIVAL(p,0,PTR_DIFF(p2,*rdata));
3896 strlcpy(p2,lp_workgroup(),PTR_DIFF(endp,p2)); /* don't know. login domain?? */
3897 p2 = skip_string(*rdata,*rdata_len,p2);
3903 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
3904 strlcpy(p2,"",PTR_DIFF(endp,p2));
3905 p2 = skip_string(*rdata,*rdata_len,p2);
3911 *rdata_len = PTR_DIFF(p2,*rdata);
3913 SSVAL(*rparam,4,*rdata_len);
3918 /****************************************************************************
3919 get info about a user
3921 struct user_info_11 {
3922 char usri11_name[21]; 0-20
3924 char *usri11_comment; 22-25
3925 char *usri11_usr_comment; 26-29
3926 unsigned short usri11_priv; 30-31
3927 unsigned long usri11_auth_flags; 32-35
3928 long usri11_password_age; 36-39
3929 char *usri11_homedir; 40-43
3930 char *usri11_parms; 44-47
3931 long usri11_last_logon; 48-51
3932 long usri11_last_logoff; 52-55
3933 unsigned short usri11_bad_pw_count; 56-57
3934 unsigned short usri11_num_logons; 58-59
3935 char *usri11_logon_server; 60-63
3936 unsigned short usri11_country_code; 64-65
3937 char *usri11_workstations; 66-69
3938 unsigned long usri11_max_storage; 70-73
3939 unsigned short usri11_units_per_week; 74-75
3940 unsigned char *usri11_logon_hours; 76-79
3941 unsigned short usri11_code_page; 80-81
3946 usri11_name specifies the user name for which information is retrieved
3948 usri11_pad aligns the next data structure element to a word boundary
3950 usri11_comment is a null terminated ASCII comment
3952 usri11_user_comment is a null terminated ASCII comment about the user
3954 usri11_priv specifies the level of the privilege assigned to the user.
3955 The possible values are:
3957 Name Value Description
3958 USER_PRIV_GUEST 0 Guest privilege
3959 USER_PRIV_USER 1 User privilege
3960 USER_PRV_ADMIN 2 Administrator privilege
3962 usri11_auth_flags specifies the account operator privileges. The
3963 possible values are:
3965 Name Value Description
3966 AF_OP_PRINT 0 Print operator
3969 Leach, Naik [Page 28]
3973 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
3976 AF_OP_COMM 1 Communications operator
3977 AF_OP_SERVER 2 Server operator
3978 AF_OP_ACCOUNTS 3 Accounts operator
3981 usri11_password_age specifies how many seconds have elapsed since the
3982 password was last changed.
3984 usri11_home_dir points to a null terminated ASCII string that contains
3985 the path name of the user's home directory.
3987 usri11_parms points to a null terminated ASCII string that is set
3988 aside for use by applications.
3990 usri11_last_logon specifies the time when the user last logged on.
3991 This value is stored as the number of seconds elapsed since
3992 00:00:00, January 1, 1970.
3994 usri11_last_logoff specifies the time when the user last logged off.
3995 This value is stored as the number of seconds elapsed since
3996 00:00:00, January 1, 1970. A value of 0 means the last logoff
3999 usri11_bad_pw_count specifies the number of incorrect passwords
4000 entered since the last successful logon.
4002 usri11_log1_num_logons specifies the number of times this user has
4003 logged on. A value of -1 means the number of logons is unknown.
4005 usri11_logon_server points to a null terminated ASCII string that
4006 contains the name of the server to which logon requests are sent.
4007 A null string indicates logon requests should be sent to the
4010 usri11_country_code specifies the country code for the user's language
4013 usri11_workstations points to a null terminated ASCII string that
4014 contains the names of workstations the user may log on from.
4015 There may be up to 8 workstations, with the names separated by
4016 commas. A null strings indicates there are no restrictions.
4018 usri11_max_storage specifies the maximum amount of disk space the user
4019 can occupy. A value of 0xffffffff indicates there are no
4022 usri11_units_per_week specifies the equal number of time units into
4023 which a week is divided. This value must be equal to 168.
4025 usri11_logon_hours points to a 21 byte (168 bits) string that
4026 specifies the time during which the user can log on. Each bit
4027 represents one unique hour in a week. The first bit (bit 0, word
4028 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
4032 Leach, Naik [Page 29]
4036 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
4039 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
4040 are no restrictions.
4042 usri11_code_page specifies the code page for the user's language of
4045 All of the pointers in this data structure need to be treated
4046 specially. The pointer is a 32 bit pointer. The higher 16 bits need
4047 to be ignored. The converter word returned in the parameters section
4048 needs to be subtracted from the lower 16 bits to calculate an offset
4049 into the return buffer where this ASCII string resides.
4051 There is no auxiliary data in the response.
4053 ****************************************************************************/
4055 #define usri11_name 0
4056 #define usri11_pad 21
4057 #define usri11_comment 22
4058 #define usri11_usr_comment 26
4059 #define usri11_full_name 30
4060 #define usri11_priv 34
4061 #define usri11_auth_flags 36
4062 #define usri11_password_age 40
4063 #define usri11_homedir 44
4064 #define usri11_parms 48
4065 #define usri11_last_logon 52
4066 #define usri11_last_logoff 56
4067 #define usri11_bad_pw_count 60
4068 #define usri11_num_logons 62
4069 #define usri11_logon_server 64
4070 #define usri11_country_code 68
4071 #define usri11_workstations 70
4072 #define usri11_max_storage 74
4073 #define usri11_units_per_week 78
4074 #define usri11_logon_hours 80
4075 #define usri11_code_page 84
4076 #define usri11_end 86
4078 static bool api_RNetUserGetInfo(struct smbd_server_connection *sconn,
4079 connection_struct *conn, uint16 vuid,
4080 char *param, int tpscnt,
4081 char *data, int tdscnt,
4082 int mdrcnt,int mprcnt,
4083 char **rdata,char **rparam,
4084 int *rdata_len,int *rparam_len)
4086 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4087 char *str2 = skip_string(param,tpscnt,str1);
4088 char *UserName = skip_string(param,tpscnt,str2);
4089 char *p = skip_string(param,tpscnt,UserName);
4090 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4093 const char *level_string;
4095 TALLOC_CTX *mem_ctx = talloc_tos();
4097 struct rpc_pipe_client *cli = NULL;
4098 struct policy_handle connect_handle, domain_handle, user_handle;
4099 struct lsa_String domain_name;
4100 struct dom_sid2 *domain_sid;
4101 struct lsa_String names;
4102 struct samr_Ids rids;
4103 struct samr_Ids types;
4104 int errcode = W_ERROR_V(WERR_USER_NOT_FOUND);
4106 union samr_UserInfo *info;
4108 if (!str1 || !str2 || !UserName || !p) {
4113 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4118 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
4120 /* check it's a supported variant */
4121 if (strcmp(str1,"zWrLh") != 0) {
4125 case 0: level_string = "B21"; break;
4126 case 1: level_string = "B21BB16DWzzWz"; break;
4127 case 2: level_string = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
4128 case 10: level_string = "B21Bzzz"; break;
4129 case 11: level_string = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
4130 default: return False;
4133 if (strcmp(level_string,str2) != 0) {
4137 *rdata_len = mdrcnt + 1024;
4138 *rdata = smb_realloc_limit(*rdata,*rdata_len);
4144 endp = *rdata + *rdata_len;
4145 p2 = get_safe_ptr(*rdata,*rdata_len,p,usri11_end);
4150 ZERO_STRUCT(connect_handle);
4151 ZERO_STRUCT(domain_handle);
4152 ZERO_STRUCT(user_handle);
4154 status = rpc_pipe_open_internal(mem_ctx, &ndr_table_samr.syntax_id,
4156 &conn->sconn->client_id,
4157 conn->sconn->msg_ctx,
4159 if (!NT_STATUS_IS_OK(status)) {
4160 DEBUG(0,("api_RNetUserGetInfo: could not connect to samr: %s\n",
4161 nt_errstr(status)));
4162 errcode = W_ERROR_V(ntstatus_to_werror(status));
4166 status = rpccli_samr_Connect2(cli, mem_ctx,
4168 SAMR_ACCESS_CONNECT_TO_SERVER |
4169 SAMR_ACCESS_ENUM_DOMAINS |
4170 SAMR_ACCESS_LOOKUP_DOMAIN,
4172 if (!NT_STATUS_IS_OK(status)) {
4173 errcode = W_ERROR_V(ntstatus_to_werror(status));
4177 init_lsa_String(&domain_name, get_global_sam_name());
4179 status = rpccli_samr_LookupDomain(cli, mem_ctx,
4183 if (!NT_STATUS_IS_OK(status)) {
4184 errcode = W_ERROR_V(ntstatus_to_werror(status));
4188 status = rpccli_samr_OpenDomain(cli, mem_ctx,
4190 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
4193 if (!NT_STATUS_IS_OK(status)) {
4194 errcode = W_ERROR_V(ntstatus_to_werror(status));
4198 init_lsa_String(&names, UserName);
4200 status = rpccli_samr_LookupNames(cli, mem_ctx,
4206 if (!NT_STATUS_IS_OK(status)) {
4207 errcode = W_ERROR_V(ntstatus_to_werror(status));
4211 if (rids.count != 1) {
4212 errcode = W_ERROR_V(WERR_NO_SUCH_USER);
4215 if (rids.count != types.count) {
4216 errcode = W_ERROR_V(WERR_INVALID_PARAM);
4219 if (types.ids[0] != SID_NAME_USER) {
4220 errcode = W_ERROR_V(WERR_INVALID_PARAM);
4226 status = rpccli_samr_OpenUser(cli, mem_ctx,
4228 SAMR_USER_ACCESS_GET_LOCALE |
4229 SAMR_USER_ACCESS_GET_LOGONINFO |
4230 SAMR_USER_ACCESS_GET_ATTRIBUTES |
4231 SAMR_USER_ACCESS_GET_GROUPS |
4232 SAMR_USER_ACCESS_GET_GROUP_MEMBERSHIP |
4233 SEC_STD_READ_CONTROL,
4236 if (!NT_STATUS_IS_OK(status)) {
4237 errcode = W_ERROR_V(ntstatus_to_werror(status));
4241 status = rpccli_samr_QueryUserInfo2(cli, mem_ctx,
4245 if (!NT_STATUS_IS_OK(status)) {
4246 errcode = W_ERROR_V(ntstatus_to_werror(status));
4251 fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
4254 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
4259 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
4260 strlcpy(p2,"Comment",PTR_DIFF(endp,p2));
4261 p2 = skip_string(*rdata,*rdata_len,p2);
4266 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
4267 strlcpy(p2,"UserComment",PTR_DIFF(endp,p2));
4268 p2 = skip_string(*rdata,*rdata_len,p2);
4273 /* EEK! the cifsrap.txt doesn't have this in!!!! */
4274 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
4275 strlcpy(p2,info->info21.full_name.string,PTR_DIFF(endp,p2));
4276 p2 = skip_string(*rdata,*rdata_len,p2);
4283 const char *homedir = info->info21.home_directory.string;
4284 /* modelled after NTAS 3.51 reply */
4285 SSVAL(p,usri11_priv,
4286 (get_current_uid(conn) == sec_initial_uid())?
4287 USER_PRIV_ADMIN:USER_PRIV_USER);
4288 SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
4289 SIVALS(p,usri11_password_age,-1); /* password age */
4290 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
4291 strlcpy(p2, homedir, PTR_DIFF(endp,p2));
4292 p2 = skip_string(*rdata,*rdata_len,p2);
4296 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
4297 strlcpy(p2,"",PTR_DIFF(endp,p2));
4298 p2 = skip_string(*rdata,*rdata_len,p2);
4302 SIVAL(p,usri11_last_logon,0); /* last logon */
4303 SIVAL(p,usri11_last_logoff,0); /* last logoff */
4304 SSVALS(p,usri11_bad_pw_count,-1); /* bad pw counts */
4305 SSVALS(p,usri11_num_logons,-1); /* num logons */
4306 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
4307 strlcpy(p2,"\\\\*",PTR_DIFF(endp,p2));
4308 p2 = skip_string(*rdata,*rdata_len,p2);
4312 SSVAL(p,usri11_country_code,0); /* country code */
4314 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
4315 strlcpy(p2,"",PTR_DIFF(endp,p2));
4316 p2 = skip_string(*rdata,*rdata_len,p2);
4321 SIVALS(p,usri11_max_storage,-1); /* max storage */
4322 SSVAL(p,usri11_units_per_week,168); /* units per week */
4323 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
4325 /* a simple way to get logon hours at all times. */
4327 SCVAL(p2,21,0); /* fix zero termination */
4328 p2 = skip_string(*rdata,*rdata_len,p2);
4333 SSVAL(p,usri11_code_page,0); /* code page */
4336 if (uLevel == 1 || uLevel == 2) {
4337 memset(p+22,' ',16); /* password */
4338 SIVALS(p,38,-1); /* password age */
4340 (get_current_uid(conn) == sec_initial_uid())?
4341 USER_PRIV_ADMIN:USER_PRIV_USER);
4342 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
4343 strlcpy(p2, info->info21.home_directory.string,
4345 p2 = skip_string(*rdata,*rdata_len,p2);
4349 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
4351 SSVAL(p,52,0); /* flags */
4352 SIVAL(p,54,PTR_DIFF(p2,*rdata)); /* script_path */
4353 strlcpy(p2, info->info21.logon_script.string,
4355 p2 = skip_string(*rdata,*rdata_len,p2);
4360 SIVAL(p,58,0); /* auth_flags */
4361 SIVAL(p,62,PTR_DIFF(p2,*rdata)); /* full_name */
4362 strlcpy(p2,info->info21.full_name.string,PTR_DIFF(endp,p2));
4363 p2 = skip_string(*rdata,*rdata_len,p2);
4367 SIVAL(p,66,0); /* urs_comment */
4368 SIVAL(p,70,PTR_DIFF(p2,*rdata)); /* parms */
4369 strlcpy(p2,"",PTR_DIFF(endp,p2));
4370 p2 = skip_string(*rdata,*rdata_len,p2);
4374 SIVAL(p,74,0); /* workstations */
4375 SIVAL(p,78,0); /* last_logon */
4376 SIVAL(p,82,0); /* last_logoff */
4377 SIVALS(p,86,-1); /* acct_expires */
4378 SIVALS(p,90,-1); /* max_storage */
4379 SSVAL(p,94,168); /* units_per_week */
4380 SIVAL(p,96,PTR_DIFF(p2,*rdata)); /* logon_hours */
4383 SSVALS(p,100,-1); /* bad_pw_count */
4384 SSVALS(p,102,-1); /* num_logons */
4385 SIVAL(p,104,PTR_DIFF(p2,*rdata)); /* logon_server */
4387 TALLOC_CTX *ctx = talloc_tos();
4388 int space_rem = *rdata_len - (p2 - *rdata);
4391 if (space_rem <= 0) {
4394 tmp = talloc_strdup(ctx, "\\\\%L");
4398 tmp = talloc_sub_basic(ctx,
4411 p2 = skip_string(*rdata,*rdata_len,p2);
4415 SSVAL(p,108,49); /* country_code */
4416 SSVAL(p,110,860); /* code page */
4420 errcode = NERR_Success;
4423 *rdata_len = PTR_DIFF(p2,*rdata);
4425 if (cli && is_valid_policy_hnd(&user_handle)) {
4426 rpccli_samr_Close(cli, mem_ctx, &user_handle);
4428 if (cli && is_valid_policy_hnd(&domain_handle)) {
4429 rpccli_samr_Close(cli, mem_ctx, &domain_handle);
4431 if (cli && is_valid_policy_hnd(&connect_handle)) {
4432 rpccli_samr_Close(cli, mem_ctx, &connect_handle);
4435 SSVAL(*rparam,0,errcode);
4436 SSVAL(*rparam,2,0); /* converter word */
4437 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
4442 static bool api_WWkstaUserLogon(struct smbd_server_connection *sconn,
4443 connection_struct *conn,uint16 vuid,
4444 char *param, int tpscnt,
4445 char *data, int tdscnt,
4446 int mdrcnt,int mprcnt,
4447 char **rdata,char **rparam,
4448 int *rdata_len,int *rparam_len)
4450 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4451 char *str2 = skip_string(param,tpscnt,str1);
4452 char *p = skip_string(param,tpscnt,str2);
4454 struct pack_desc desc;
4456 /* With share level security vuid will always be zero.
4457 Don't depend on vuser being non-null !!. JRA */
4458 user_struct *vuser = get_valid_user_struct(sconn, vuid);
4460 if (!str1 || !str2 || !p) {
4465 DEBUG(3,(" Username of UID %d is %s\n",
4466 (int)vuser->server_info->utok.uid,
4467 vuser->server_info->unix_name));
4470 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4471 name = get_safe_str_ptr(param,tpscnt,p,2);
4476 memset((char *)&desc,'\0',sizeof(desc));
4478 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
4480 /* check it's a supported varient */
4481 if (strcmp(str1,"OOWb54WrLh") != 0) {
4484 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) {
4488 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4495 desc.buflen = mdrcnt;
4496 desc.subformat = NULL;
4499 if (init_package(&desc,1,0)) {
4500 PACKI(&desc,"W",0); /* code */
4501 PACKS(&desc,"B21",name); /* eff. name */
4502 PACKS(&desc,"B",""); /* pad */
4504 (get_current_uid(conn) == sec_initial_uid())?
4505 USER_PRIV_ADMIN:USER_PRIV_USER);
4506 PACKI(&desc,"D",0); /* auth flags XXX */
4507 PACKI(&desc,"W",0); /* num logons */
4508 PACKI(&desc,"W",0); /* bad pw count */
4509 PACKI(&desc,"D",0); /* last logon */
4510 PACKI(&desc,"D",-1); /* last logoff */
4511 PACKI(&desc,"D",-1); /* logoff time */
4512 PACKI(&desc,"D",-1); /* kickoff time */
4513 PACKI(&desc,"D",0); /* password age */
4514 PACKI(&desc,"D",0); /* password can change */
4515 PACKI(&desc,"D",-1); /* password must change */
4519 fstrcpy(mypath,"\\\\");
4520 fstrcat(mypath,get_local_machine_name());
4522 PACKS(&desc,"z",mypath); /* computer */
4525 PACKS(&desc,"z",lp_workgroup());/* domain */
4526 PACKS(&desc,"z", vuser ?
4527 vuser->server_info->info3->base.logon_script.string
4528 : ""); /* script path */
4529 PACKI(&desc,"D",0x00000000); /* reserved */
4532 *rdata_len = desc.usedlen;
4534 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4538 SSVALS(*rparam,0,desc.errcode);
4540 SSVAL(*rparam,4,desc.neededlen);
4542 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
4547 /****************************************************************************
4548 api_WAccessGetUserPerms
4549 ****************************************************************************/
4551 static bool api_WAccessGetUserPerms(struct smbd_server_connection *sconn,
4552 connection_struct *conn,uint16 vuid,
4553 char *param, int tpscnt,
4554 char *data, int tdscnt,
4555 int mdrcnt,int mprcnt,
4556 char **rdata,char **rparam,
4557 int *rdata_len,int *rparam_len)
4559 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4560 char *str2 = skip_string(param,tpscnt,str1);
4561 char *user = skip_string(param,tpscnt,str2);
4562 char *resource = skip_string(param,tpscnt,user);
4564 if (!str1 || !str2 || !user || !resource) {
4568 if (skip_string(param,tpscnt,resource) == NULL) {
4571 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
4573 /* check it's a supported varient */
4574 if (strcmp(str1,"zzh") != 0) {
4577 if (strcmp(str2,"") != 0) {
4582 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4586 SSVALS(*rparam,0,0); /* errorcode */
4587 SSVAL(*rparam,2,0); /* converter word */
4588 SSVAL(*rparam,4,0x7f); /* permission flags */
4593 /****************************************************************************
4594 api_WPrintJobEnumerate
4595 ****************************************************************************/
4597 static bool api_WPrintJobGetInfo(struct smbd_server_connection *sconn,
4598 connection_struct *conn, uint16 vuid,
4599 char *param, int tpscnt,
4600 char *data, int tdscnt,
4601 int mdrcnt,int mprcnt,
4602 char **rdata,char **rparam,
4603 int *rdata_len,int *rparam_len)
4605 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4606 char *str2 = skip_string(param,tpscnt,str1);
4607 char *p = skip_string(param,tpscnt,str2);
4611 struct pack_desc desc;
4614 TALLOC_CTX *mem_ctx = talloc_tos();
4617 struct rpc_pipe_client *cli = NULL;
4618 struct policy_handle handle;
4619 struct spoolss_DevmodeContainer devmode_ctr;
4620 union spoolss_JobInfo info;
4622 if (!str1 || !str2 || !p) {
4626 uLevel = get_safe_SVAL(param,tpscnt,p,2,-1);
4628 memset((char *)&desc,'\0',sizeof(desc));
4629 memset((char *)&status,'\0',sizeof(status));
4631 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
4633 /* check it's a supported varient */
4634 if (strcmp(str1,"WWrLh") != 0) {
4637 if (!check_printjob_info(&desc,uLevel,str2)) {
4641 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid)) {
4645 ZERO_STRUCT(handle);
4647 status = rpc_pipe_open_interface(conn,
4648 &ndr_table_spoolss.syntax_id,
4650 &conn->sconn->client_id,
4651 conn->sconn->msg_ctx,
4653 if (!NT_STATUS_IS_OK(status)) {
4654 DEBUG(0,("api_WPrintJobGetInfo: could not connect to spoolss: %s\n",
4655 nt_errstr(status)));
4656 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
4660 ZERO_STRUCT(devmode_ctr);
4662 status = rpccli_spoolss_OpenPrinter(cli, mem_ctx,
4669 if (!NT_STATUS_IS_OK(status)) {
4670 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
4673 if (!W_ERROR_IS_OK(werr)) {
4674 desc.errcode = W_ERROR_V(werr);
4678 werr = rpccli_spoolss_getjob(cli, mem_ctx,
4684 if (!W_ERROR_IS_OK(werr)) {
4685 desc.errcode = W_ERROR_V(werr);
4690 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4695 desc.buflen = mdrcnt;
4698 * Don't return data but need to get correct length
4699 * init_package will return wrong size if buflen=0
4701 desc.buflen = getlen(desc.format);
4702 desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen );
4705 if (init_package(&desc,1,0)) {
4706 fill_spoolss_printjob_info(uLevel, &desc, &info.info2, info.info2.position);
4707 *rdata_len = desc.usedlen;
4709 desc.errcode = NERR_JobNotFound;
4713 if (cli && is_valid_policy_hnd(&handle)) {
4714 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
4718 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4722 SSVALS(*rparam,0,desc.errcode);
4724 SSVAL(*rparam,4,desc.neededlen);
4728 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
4733 static bool api_WPrintJobEnumerate(struct smbd_server_connection *sconn,
4734 connection_struct *conn, uint16 vuid,
4735 char *param, int tpscnt,
4736 char *data, int tdscnt,
4737 int mdrcnt,int mprcnt,
4738 char **rdata,char **rparam,
4739 int *rdata_len,int *rparam_len)
4741 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4742 char *str2 = skip_string(param,tpscnt,str1);
4743 char *p = skip_string(param,tpscnt,str2);
4747 struct pack_desc desc;
4749 TALLOC_CTX *mem_ctx = talloc_tos();
4752 struct rpc_pipe_client *cli = NULL;
4753 struct policy_handle handle;
4754 struct spoolss_DevmodeContainer devmode_ctr;
4756 union spoolss_JobInfo *info;
4758 if (!str1 || !str2 || !p) {
4762 memset((char *)&desc,'\0',sizeof(desc));
4764 p = skip_string(param,tpscnt,p);
4768 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4770 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
4772 /* check it's a supported variant */
4773 if (strcmp(str1,"zWrLeh") != 0) {
4778 return False; /* defined only for uLevel 0,1,2 */
4781 if (!check_printjob_info(&desc,uLevel,str2)) {
4785 ZERO_STRUCT(handle);
4787 status = rpc_pipe_open_interface(conn,
4788 &ndr_table_spoolss.syntax_id,
4790 &conn->sconn->client_id,
4791 conn->sconn->msg_ctx,
4793 if (!NT_STATUS_IS_OK(status)) {
4794 DEBUG(0,("api_WPrintJobEnumerate: could not connect to spoolss: %s\n",
4795 nt_errstr(status)));
4796 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
4800 ZERO_STRUCT(devmode_ctr);
4802 status = rpccli_spoolss_OpenPrinter(cli, mem_ctx,
4806 SEC_FLAG_MAXIMUM_ALLOWED,
4809 if (!NT_STATUS_IS_OK(status)) {
4810 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
4813 if (!W_ERROR_IS_OK(werr)) {
4814 desc.errcode = W_ERROR_V(werr);
4818 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
4826 if (!W_ERROR_IS_OK(werr)) {
4827 desc.errcode = W_ERROR_V(werr);
4832 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4838 desc.buflen = mdrcnt;
4840 if (init_package(&desc,count,0)) {
4842 for (i = 0; i < count; i++) {
4843 fill_spoolss_printjob_info(uLevel, &desc, &info[i].info2, i);
4844 if (desc.errcode == NERR_Success) {
4850 if (cli && is_valid_policy_hnd(&handle)) {
4851 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
4854 *rdata_len = desc.usedlen;
4857 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4861 SSVALS(*rparam,0,desc.errcode);
4863 SSVAL(*rparam,4,succnt);
4864 SSVAL(*rparam,6,count);
4866 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
4871 static int check_printdest_info(struct pack_desc* desc,
4872 int uLevel, char* id)
4874 desc->subformat = NULL;
4877 desc->format = "B9";
4880 desc->format = "B9B21WWzW";
4886 desc->format = "zzzWWzzzWW";
4889 DEBUG(0,("check_printdest_info: invalid level %d\n",
4893 if (id == NULL || strcmp(desc->format,id) != 0) {
4894 DEBUG(0,("check_printdest_info: invalid string %s\n",
4895 id ? id : "<NULL>" ));
4901 static void fill_printdest_info(struct spoolss_PrinterInfo2 *info2, int uLevel,
4902 struct pack_desc* desc)
4906 strncpy(buf, info2->printername, sizeof(buf)-1);
4907 buf[sizeof(buf)-1] = 0;
4911 PACKS(desc,"B9",buf); /* szName */
4913 PACKS(desc,"B21",""); /* szUserName */
4914 PACKI(desc,"W",0); /* uJobId */
4915 PACKI(desc,"W",0); /* fsStatus */
4916 PACKS(desc,"z",""); /* pszStatus */
4917 PACKI(desc,"W",0); /* time */
4921 if (uLevel == 2 || uLevel == 3) {
4922 PACKS(desc,"z",buf); /* pszPrinterName */
4924 PACKS(desc,"z",""); /* pszUserName */
4925 PACKS(desc,"z",""); /* pszLogAddr */
4926 PACKI(desc,"W",0); /* uJobId */
4927 PACKI(desc,"W",0); /* fsStatus */
4928 PACKS(desc,"z",""); /* pszStatus */
4929 PACKS(desc,"z",""); /* pszComment */
4930 PACKS(desc,"z","NULL"); /* pszDrivers */
4931 PACKI(desc,"W",0); /* time */
4932 PACKI(desc,"W",0); /* pad1 */
4937 static bool api_WPrintDestGetInfo(struct smbd_server_connection *sconn,
4938 connection_struct *conn, uint16 vuid,
4939 char *param, int tpscnt,
4940 char *data, int tdscnt,
4941 int mdrcnt,int mprcnt,
4942 char **rdata,char **rparam,
4943 int *rdata_len,int *rparam_len)
4945 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4946 char *str2 = skip_string(param,tpscnt,str1);
4947 char *p = skip_string(param,tpscnt,str2);
4948 char* PrinterName = p;
4950 struct pack_desc desc;
4953 TALLOC_CTX *mem_ctx = talloc_tos();
4956 struct rpc_pipe_client *cli = NULL;
4957 struct policy_handle handle;
4958 struct spoolss_DevmodeContainer devmode_ctr;
4959 union spoolss_PrinterInfo info;
4961 if (!str1 || !str2 || !p) {
4965 memset((char *)&desc,'\0',sizeof(desc));
4967 p = skip_string(param,tpscnt,p);
4971 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4973 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
4975 /* check it's a supported varient */
4976 if (strcmp(str1,"zWrLh") != 0) {
4979 if (!check_printdest_info(&desc,uLevel,str2)) {
4983 ZERO_STRUCT(handle);
4985 status = rpc_pipe_open_interface(conn,
4986 &ndr_table_spoolss.syntax_id,
4988 &conn->sconn->client_id,
4989 conn->sconn->msg_ctx,
4991 if (!NT_STATUS_IS_OK(status)) {
4992 DEBUG(0,("api_WPrintDestGetInfo: could not connect to spoolss: %s\n",
4993 nt_errstr(status)));
4994 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
4998 ZERO_STRUCT(devmode_ctr);
5000 status = rpccli_spoolss_OpenPrinter(cli, mem_ctx,
5004 SEC_FLAG_MAXIMUM_ALLOWED,
5007 if (!NT_STATUS_IS_OK(status)) {
5009 desc.errcode = NERR_DestNotFound;
5013 if (!W_ERROR_IS_OK(werr)) {
5015 desc.errcode = NERR_DestNotFound;
5020 werr = rpccli_spoolss_getprinter(cli, mem_ctx,
5025 if (!W_ERROR_IS_OK(werr)) {
5027 desc.errcode = NERR_DestNotFound;
5033 *rdata = smb_realloc_limit(*rdata,mdrcnt);
5038 desc.buflen = mdrcnt;
5041 * Don't return data but need to get correct length
5042 * init_package will return wrong size if buflen=0
5044 desc.buflen = getlen(desc.format);
5045 desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen );
5047 if (init_package(&desc,1,0)) {
5048 fill_printdest_info(&info.info2, uLevel,&desc);
5052 if (cli && is_valid_policy_hnd(&handle)) {
5053 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
5056 *rdata_len = desc.usedlen;
5059 *rparam = smb_realloc_limit(*rparam,*rparam_len);
5063 SSVALS(*rparam,0,desc.errcode);
5065 SSVAL(*rparam,4,desc.neededlen);
5067 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
5073 static bool api_WPrintDestEnum(struct smbd_server_connection *sconn,
5074 connection_struct *conn, uint16 vuid,
5075 char *param, int tpscnt,
5076 char *data, int tdscnt,
5077 int mdrcnt,int mprcnt,
5078 char **rdata,char **rparam,
5079 int *rdata_len,int *rparam_len)
5081 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
5082 char *str2 = skip_string(param,tpscnt,str1);
5083 char *p = skip_string(param,tpscnt,str2);
5087 struct pack_desc desc;
5089 TALLOC_CTX *mem_ctx = talloc_tos();
5092 struct rpc_pipe_client *cli = NULL;
5093 union spoolss_PrinterInfo *info;
5096 if (!str1 || !str2 || !p) {
5100 memset((char *)&desc,'\0',sizeof(desc));
5102 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
5104 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
5106 /* check it's a supported varient */
5107 if (strcmp(str1,"WrLeh") != 0) {
5110 if (!check_printdest_info(&desc,uLevel,str2)) {
5116 status = rpc_pipe_open_interface(conn,
5117 &ndr_table_spoolss.syntax_id,
5119 &conn->sconn->client_id,
5120 conn->sconn->msg_ctx,
5122 if (!NT_STATUS_IS_OK(status)) {
5123 DEBUG(0,("api_WPrintDestEnum: could not connect to spoolss: %s\n",
5124 nt_errstr(status)));
5125 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
5129 werr = rpccli_spoolss_enumprinters(cli, mem_ctx,
5131 cli->srv_name_slash,
5136 if (!W_ERROR_IS_OK(werr)) {
5137 desc.errcode = W_ERROR_V(werr);
5139 desc.errcode = NERR_DestNotFound;
5147 *rdata = smb_realloc_limit(*rdata,mdrcnt);
5154 desc.buflen = mdrcnt;
5155 if (init_package(&desc,queuecnt,0)) {
5158 for (i = 0; i < count; i++) {
5159 fill_printdest_info(&info[i].info2, uLevel,&desc);
5161 if (desc.errcode == NERR_Success) {
5167 *rdata_len = desc.usedlen;
5170 *rparam = smb_realloc_limit(*rparam,*rparam_len);
5174 SSVALS(*rparam,0,desc.errcode);
5176 SSVAL(*rparam,4,succnt);
5177 SSVAL(*rparam,6,queuecnt);
5179 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
5184 static bool api_WPrintDriverEnum(struct smbd_server_connection *sconn,
5185 connection_struct *conn, uint16 vuid,
5186 char *param, int tpscnt,
5187 char *data, int tdscnt,
5188 int mdrcnt,int mprcnt,
5189 char **rdata,char **rparam,
5190 int *rdata_len,int *rparam_len)
5192 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
5193 char *str2 = skip_string(param,tpscnt,str1);
5194 char *p = skip_string(param,tpscnt,str2);
5197 struct pack_desc desc;
5199 if (!str1 || !str2 || !p) {
5203 memset((char *)&desc,'\0',sizeof(desc));
5205 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
5207 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
5209 /* check it's a supported varient */
5210 if (strcmp(str1,"WrLeh") != 0) {
5213 if (uLevel != 0 || strcmp(str2,"B41") != 0) {
5218 *rdata = smb_realloc_limit(*rdata,mdrcnt);
5224 desc.buflen = mdrcnt;
5225 if (init_package(&desc,1,0)) {
5226 PACKS(&desc,"B41","NULL");
5229 succnt = (desc.errcode == NERR_Success ? 1 : 0);
5231 *rdata_len = desc.usedlen;
5234 *rparam = smb_realloc_limit(*rparam,*rparam_len);
5238 SSVALS(*rparam,0,desc.errcode);
5240 SSVAL(*rparam,4,succnt);
5243 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
5248 static bool api_WPrintQProcEnum(struct smbd_server_connection *sconn,
5249 connection_struct *conn, uint16 vuid,
5250 char *param, int tpscnt,
5251 char *data, int tdscnt,
5252 int mdrcnt,int mprcnt,
5253 char **rdata,char **rparam,
5254 int *rdata_len,int *rparam_len)
5256 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
5257 char *str2 = skip_string(param,tpscnt,str1);
5258 char *p = skip_string(param,tpscnt,str2);
5261 struct pack_desc desc;
5263 if (!str1 || !str2 || !p) {
5266 memset((char *)&desc,'\0',sizeof(desc));
5268 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
5270 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
5272 /* check it's a supported varient */
5273 if (strcmp(str1,"WrLeh") != 0) {
5276 if (uLevel != 0 || strcmp(str2,"B13") != 0) {
5281 *rdata = smb_realloc_limit(*rdata,mdrcnt);
5287 desc.buflen = mdrcnt;
5289 if (init_package(&desc,1,0)) {
5290 PACKS(&desc,"B13","lpd");
5293 succnt = (desc.errcode == NERR_Success ? 1 : 0);
5295 *rdata_len = desc.usedlen;
5298 *rparam = smb_realloc_limit(*rparam,*rparam_len);
5302 SSVALS(*rparam,0,desc.errcode);
5304 SSVAL(*rparam,4,succnt);
5307 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
5312 static bool api_WPrintPortEnum(struct smbd_server_connection *sconn,
5313 connection_struct *conn, uint16 vuid,
5314 char *param, int tpscnt,
5315 char *data, int tdscnt,
5316 int mdrcnt,int mprcnt,
5317 char **rdata,char **rparam,
5318 int *rdata_len,int *rparam_len)
5320 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
5321 char *str2 = skip_string(param,tpscnt,str1);
5322 char *p = skip_string(param,tpscnt,str2);
5325 struct pack_desc desc;
5327 if (!str1 || !str2 || !p) {
5331 memset((char *)&desc,'\0',sizeof(desc));
5333 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
5335 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
5337 /* check it's a supported varient */
5338 if (strcmp(str1,"WrLeh") != 0) {
5341 if (uLevel != 0 || strcmp(str2,"B9") != 0) {
5346 *rdata = smb_realloc_limit(*rdata,mdrcnt);
5351 memset((char *)&desc,'\0',sizeof(desc));
5353 desc.buflen = mdrcnt;
5355 if (init_package(&desc,1,0)) {
5356 PACKS(&desc,"B13","lp0");
5359 succnt = (desc.errcode == NERR_Success ? 1 : 0);
5361 *rdata_len = desc.usedlen;
5364 *rparam = smb_realloc_limit(*rparam,*rparam_len);
5368 SSVALS(*rparam,0,desc.errcode);
5370 SSVAL(*rparam,4,succnt);
5373 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
5378 /****************************************************************************
5380 ****************************************************************************/
5382 static bool api_RNetSessionEnum(struct smbd_server_connection *sconn,
5383 connection_struct *conn, uint16 vuid,
5384 char *param, int tpscnt,
5385 char *data, int tdscnt,
5386 int mdrcnt,int mprcnt,
5387 char **rdata,char **rparam,
5388 int *rdata_len,int *rparam_len)
5391 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
5392 char *str2 = skip_string(param,tpscnt,str1);
5393 char *p = skip_string(param,tpscnt,str2);
5395 struct pack_desc desc;
5396 struct sessionid *session_list;
5397 int i, num_sessions;
5399 if (!str1 || !str2 || !p) {
5403 memset((char *)&desc,'\0',sizeof(desc));
5405 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
5407 DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel));
5408 DEBUG(7,("RNetSessionEnum req string=%s\n",str1));
5409 DEBUG(7,("RNetSessionEnum ret string=%s\n",str2));
5411 /* check it's a supported varient */
5412 if (strcmp(str1,RAP_NetSessionEnum_REQ) != 0) {
5415 if (uLevel != 2 || strcmp(str2,RAP_SESSION_INFO_L2) != 0) {
5419 num_sessions = list_sessions(talloc_tos(), &session_list);
5422 *rdata = smb_realloc_limit(*rdata,mdrcnt);
5427 memset((char *)&desc,'\0',sizeof(desc));
5429 desc.buflen = mdrcnt;
5431 if (!init_package(&desc,num_sessions,0)) {
5435 for(i=0; i<num_sessions; i++) {
5436 PACKS(&desc, "z", session_list[i].remote_machine);
5437 PACKS(&desc, "z", session_list[i].username);
5438 PACKI(&desc, "W", 1); /* num conns */
5439 PACKI(&desc, "W", 0); /* num opens */
5440 PACKI(&desc, "W", 1); /* num users */
5441 PACKI(&desc, "D", 0); /* session time */
5442 PACKI(&desc, "D", 0); /* idle time */
5443 PACKI(&desc, "D", 0); /* flags */
5444 PACKS(&desc, "z", "Unknown Client"); /* client type string */
5447 *rdata_len = desc.usedlen;
5450 *rparam = smb_realloc_limit(*rparam,*rparam_len);
5454 SSVALS(*rparam,0,desc.errcode);
5455 SSVAL(*rparam,2,0); /* converter */
5456 SSVAL(*rparam,4,num_sessions); /* count */
5458 DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc.errcode));
5464 /****************************************************************************
5465 The buffer was too small.
5466 ****************************************************************************/
5468 static bool api_TooSmall(struct smbd_server_connection *sconn,
5469 connection_struct *conn,uint16 vuid, char *param, char *data,
5470 int mdrcnt, int mprcnt,
5471 char **rdata, char **rparam,
5472 int *rdata_len, int *rparam_len)
5474 *rparam_len = MIN(*rparam_len,mprcnt);
5475 *rparam = smb_realloc_limit(*rparam,*rparam_len);
5482 SSVAL(*rparam,0,NERR_BufTooSmall);
5484 DEBUG(3,("Supplied buffer too small in API command\n"));
5489 /****************************************************************************
5490 The request is not supported.
5491 ****************************************************************************/
5493 static bool api_Unsupported(struct smbd_server_connection *sconn,
5494 connection_struct *conn, uint16 vuid,
5495 char *param, int tpscnt,
5496 char *data, int tdscnt,
5497 int mdrcnt, int mprcnt,
5498 char **rdata, char **rparam,
5499 int *rdata_len, int *rparam_len)
5502 *rparam = smb_realloc_limit(*rparam,*rparam_len);
5509 SSVAL(*rparam,0,NERR_notsupported);
5510 SSVAL(*rparam,2,0); /* converter word */
5512 DEBUG(3,("Unsupported API command\n"));
5517 static const struct {
5520 bool (*fn)(struct smbd_server_connection *sconn,
5521 connection_struct *, uint16,
5524 int,int,char **,char **,int *,int *);
5525 bool auth_user; /* Deny anonymous access? */
5526 } api_commands[] = {
5527 {"RNetShareEnum", RAP_WshareEnum, api_RNetShareEnum, True},
5528 {"RNetShareGetInfo", RAP_WshareGetInfo, api_RNetShareGetInfo},
5529 {"RNetShareAdd", RAP_WshareAdd, api_RNetShareAdd},
5530 {"RNetSessionEnum", RAP_WsessionEnum, api_RNetSessionEnum, True},
5531 {"RNetServerGetInfo", RAP_WserverGetInfo, api_RNetServerGetInfo},
5532 {"RNetGroupEnum", RAP_WGroupEnum, api_RNetGroupEnum, True},
5533 {"RNetGroupGetUsers", RAP_WGroupGetUsers, api_RNetGroupGetUsers, True},
5534 {"RNetUserEnum", RAP_WUserEnum, api_RNetUserEnum, True},
5535 {"RNetUserGetInfo", RAP_WUserGetInfo, api_RNetUserGetInfo},
5536 {"NetUserGetGroups", RAP_WUserGetGroups, api_NetUserGetGroups},
5537 {"NetWkstaGetInfo", RAP_WWkstaGetInfo, api_NetWkstaGetInfo},
5538 {"DosPrintQEnum", RAP_WPrintQEnum, api_DosPrintQEnum, True},
5539 {"DosPrintQGetInfo", RAP_WPrintQGetInfo, api_DosPrintQGetInfo},
5540 {"WPrintQueuePause", RAP_WPrintQPause, api_WPrintQueueCtrl},
5541 {"WPrintQueueResume", RAP_WPrintQContinue, api_WPrintQueueCtrl},
5542 {"WPrintJobEnumerate",RAP_WPrintJobEnum, api_WPrintJobEnumerate},
5543 {"WPrintJobGetInfo", RAP_WPrintJobGetInfo, api_WPrintJobGetInfo},
5544 {"RDosPrintJobDel", RAP_WPrintJobDel, api_RDosPrintJobDel},
5545 {"RDosPrintJobPause", RAP_WPrintJobPause, api_RDosPrintJobDel},
5546 {"RDosPrintJobResume",RAP_WPrintJobContinue, api_RDosPrintJobDel},
5547 {"WPrintDestEnum", RAP_WPrintDestEnum, api_WPrintDestEnum},
5548 {"WPrintDestGetInfo", RAP_WPrintDestGetInfo, api_WPrintDestGetInfo},
5549 {"NetRemoteTOD", RAP_NetRemoteTOD, api_NetRemoteTOD},
5550 {"WPrintQueuePurge", RAP_WPrintQPurge, api_WPrintQueueCtrl},
5551 {"NetServerEnum2", RAP_NetServerEnum2, api_RNetServerEnum2}, /* anon OK */
5552 {"NetServerEnum3", RAP_NetServerEnum3, api_RNetServerEnum3}, /* anon OK */
5553 {"WAccessGetUserPerms",RAP_WAccessGetUserPerms,api_WAccessGetUserPerms},
5554 {"SetUserPassword", RAP_WUserPasswordSet2, api_SetUserPassword},
5555 {"WWkstaUserLogon", RAP_WWkstaUserLogon, api_WWkstaUserLogon},
5556 {"PrintJobInfo", RAP_WPrintJobSetInfo, api_PrintJobInfo},
5557 {"WPrintDriverEnum", RAP_WPrintDriverEnum, api_WPrintDriverEnum},
5558 {"WPrintQProcEnum", RAP_WPrintQProcessorEnum,api_WPrintQProcEnum},
5559 {"WPrintPortEnum", RAP_WPrintPortEnum, api_WPrintPortEnum},
5560 {"SamOEMChangePassword",RAP_SamOEMChgPasswordUser2_P,api_SamOEMChangePassword}, /* anon OK */
5561 {NULL, -1, api_Unsupported}
5562 /* The following RAP calls are not implemented by Samba:
5564 RAP_WFileEnum2 - anon not OK
5569 /****************************************************************************
5570 Handle remote api calls.
5571 ****************************************************************************/
5573 void api_reply(connection_struct *conn, uint16 vuid,
5574 struct smb_request *req,
5575 char *data, char *params,
5576 int tdscnt, int tpscnt,
5577 int mdrcnt, int mprcnt)
5581 char *rparam = NULL;
5582 const char *name1 = NULL;
5583 const char *name2 = NULL;
5590 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
5591 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5596 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5599 api_command = SVAL(params,0);
5600 /* Is there a string at position params+2 ? */
5601 if (skip_string(params,tpscnt,params+2)) {
5606 name2 = skip_string(params,tpscnt,params+2);
5611 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
5615 tdscnt,tpscnt,mdrcnt,mprcnt));
5617 for (i=0;api_commands[i].name;i++) {
5618 if (api_commands[i].id == api_command && api_commands[i].fn) {
5619 DEBUG(3,("Doing %s\n",api_commands[i].name));
5624 /* Check whether this api call can be done anonymously */
5626 if (api_commands[i].auth_user && lp_restrict_anonymous()) {
5627 user_struct *user = get_valid_user_struct(req->sconn, vuid);
5629 if (!user || user->server_info->guest) {
5630 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5635 rdata = (char *)SMB_MALLOC(1024);
5637 memset(rdata,'\0',1024);
5640 rparam = (char *)SMB_MALLOC(1024);
5642 memset(rparam,'\0',1024);
5645 if(!rdata || !rparam) {
5646 DEBUG(0,("api_reply: malloc fail !\n"));
5649 reply_nterror(req, NT_STATUS_NO_MEMORY);
5653 reply = api_commands[i].fn(req->sconn, conn,
5655 params,tpscnt, /* params + length */
5656 data,tdscnt, /* data + length */
5658 &rdata,&rparam,&rdata_len,&rparam_len);
5661 if (rdata_len > mdrcnt || rparam_len > mprcnt) {
5662 reply = api_TooSmall(req->sconn,conn,vuid,params,data,
5664 &rdata,&rparam,&rdata_len,&rparam_len);
5667 /* if we get False back then it's actually unsupported */
5669 reply = api_Unsupported(req->sconn,conn,vuid,params,tpscnt,
5671 tdscnt,mdrcnt,mprcnt,
5672 &rdata,&rparam,&rdata_len,&rparam_len);
5675 /* If api_Unsupported returns false we can't return anything. */
5677 send_trans_reply(conn, req, rparam, rparam_len,
5678 rdata, rdata_len, False);