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/smbd.h"
30 #include "smbd/globals.h"
31 #include "rpc_client/rpc_client.h"
32 #include "../librpc/gen_ndr/ndr_samr_c.h"
33 #include "../librpc/gen_ndr/ndr_spoolss_c.h"
34 #include "rpc_client/cli_spoolss.h"
35 #include "rpc_client/init_spoolss.h"
36 #include "../librpc/gen_ndr/ndr_srvsvc_c.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 "../libcli/security/security.h"
43 #include "passdb/machine_sid.h"
45 #include "rpc_server/rpc_ncacn_np.h"
52 #define NERR_Success 0
53 #define NERR_badpass 86
54 #define NERR_notsupported 50
56 #define NERR_BASE (2100)
57 #define NERR_BufTooSmall (NERR_BASE+23)
58 #define NERR_JobNotFound (NERR_BASE+51)
59 #define NERR_DestNotFound (NERR_BASE+52)
61 #define ACCESS_READ 0x01
62 #define ACCESS_WRITE 0x02
63 #define ACCESS_CREATE 0x04
65 #define SHPWLEN 8 /* share password length */
67 /* Limit size of ipc replies */
69 static char *smb_realloc_limit(void *ptr, size_t size)
73 size = MAX((size),4*1024);
74 val = (char *)SMB_REALLOC(ptr,size);
76 memset(val,'\0',size);
81 static bool api_Unsupported(struct smbd_server_connection *sconn,
82 connection_struct *conn, uint64_t vuid,
83 char *param, int tpscnt,
84 char *data, int tdscnt,
85 int mdrcnt, int mprcnt,
86 char **rdata, char **rparam,
87 int *rdata_len, int *rparam_len);
89 static bool api_TooSmall(struct smbd_server_connection *sconn,
90 connection_struct *conn, uint64_t vuid, char *param, char *data,
91 int mdrcnt, int mprcnt,
92 char **rdata, char **rparam,
93 int *rdata_len, int *rparam_len);
96 static int CopyExpanded(connection_struct *conn,
97 int snum, char **dst, char *src, int *p_space_remaining)
99 TALLOC_CTX *ctx = talloc_tos();
103 if (!src || !dst || !p_space_remaining || !(*dst) ||
104 *p_space_remaining <= 0) {
108 buf = talloc_strdup(ctx, src);
110 *p_space_remaining = 0;
113 buf = talloc_string_sub(ctx, buf,"%S", lp_servicename(ctx, snum));
115 *p_space_remaining = 0;
118 buf = talloc_sub_advanced(ctx,
119 lp_servicename(ctx, SNUM(conn)),
120 conn->session_info->unix_info->unix_name,
122 conn->session_info->unix_token->gid,
123 conn->session_info->unix_info->sanitized_username,
124 conn->session_info->info->domain_name,
127 *p_space_remaining = 0;
130 l = push_ascii(*dst,buf,*p_space_remaining, STR_TERMINATE);
135 (*p_space_remaining) -= l;
139 static int CopyAndAdvance(char **dst, char *src, int *n)
142 if (!src || !dst || !n || !(*dst)) {
145 l = push_ascii(*dst,src,*n, STR_TERMINATE);
154 static int StrlenExpanded(connection_struct *conn, int snum, char *s)
156 TALLOC_CTX *ctx = talloc_tos();
161 buf = talloc_strdup(ctx,s);
165 buf = talloc_string_sub(ctx,buf,"%S",lp_servicename(ctx, snum));
169 buf = talloc_sub_advanced(ctx,
170 lp_servicename(ctx, SNUM(conn)),
171 conn->session_info->unix_info->unix_name,
173 conn->session_info->unix_token->gid,
174 conn->session_info->unix_info->sanitized_username,
175 conn->session_info->info->domain_name,
180 return strlen(buf) + 1;
183 /*******************************************************************
184 Check a API string for validity when we only need to check the prefix.
185 ******************************************************************/
187 static bool prefix_ok(const char *str, const char *prefix)
189 return(strncmp(str,prefix,strlen(prefix)) == 0);
193 const char *format; /* formatstring for structure */
194 const char *subformat; /* subformat for structure */
195 char *base; /* baseaddress of buffer */
196 int buflen; /* remaining size for fixed part; on init: length of base */
197 int subcount; /* count of substructures */
198 char *structbuf; /* pointer into buffer for remaining fixed part */
199 int stringlen; /* remaining size for variable part */
200 char *stringbuf; /* pointer into buffer for remaining variable part */
201 int neededlen; /* total needed size */
202 int usedlen; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
203 const char *curpos; /* current position; pointer into format or subformat */
207 static int get_counter(const char **p)
213 if (!isdigit((int)**p)) {
219 n = 10 * n + (i - '0');
227 static int getlen(const char *p)
236 case 'W': /* word (2 byte) */
239 case 'K': /* status word? (2 byte) */
242 case 'N': /* count of substructures (word) at end */
245 case 'D': /* double word (4 byte) */
246 case 'z': /* offset to zero terminated string (4 byte) */
247 case 'l': /* offset to user data (4 byte) */
250 case 'b': /* offset to data (with counter) (4 byte) */
254 case 'B': /* byte (with optional counter) */
255 n += get_counter(&p);
262 static bool init_package(struct pack_desc *p, int count, int subcount)
267 if (!p->format || !p->base) {
271 i = count * getlen(p->format);
273 i += subcount * getlen(p->subformat);
275 p->structbuf = p->base;
279 p->curpos = p->format;
285 * This is the old error code we used. Aparently
286 * WinNT/2k systems return ERRbuftoosmall (2123) and
287 * OS/2 needs this. I'm leaving this here so we can revert
290 p->errcode = ERRmoredata;
292 p->errcode = ERRbuftoosmall;
295 p->errcode = NERR_Success;
299 p->stringbuf = p->base + i;
301 return (p->errcode == NERR_Success);
304 static int package(struct pack_desc *p, ...)
307 int needed=0, stringneeded;
308 const char *str=NULL;
309 int is_string=0, stringused;
316 p->curpos = p->format;
318 p->curpos = p->subformat;
323 str = va_arg(args,char*);
324 SMB_ASSERT(strncmp(str,p->curpos,strlen(str)) == 0);
333 switch( *p->curpos++ ) {
334 case 'W': /* word (2 byte) */
336 temp = va_arg(args,int);
337 if (p->buflen >= needed) {
338 SSVAL(p->structbuf,0,temp);
341 case 'K': /* status word? (2 byte) */
343 temp = va_arg(args,int);
344 if (p->buflen >= needed) {
345 SSVAL(p->structbuf,0,temp);
348 case 'N': /* count of substructures (word) at end */
350 p->subcount = va_arg(args,int);
351 if (p->buflen >= needed) {
352 SSVAL(p->structbuf,0,p->subcount);
355 case 'D': /* double word (4 byte) */
357 temp = va_arg(args,int);
358 if (p->buflen >= needed) {
359 SIVAL(p->structbuf,0,temp);
362 case 'B': /* byte (with optional counter) */
363 needed = get_counter(&p->curpos);
365 char *s = va_arg(args,char*);
366 if (p->buflen >= needed) {
367 StrnCpy(p->structbuf,s?s:"",needed-1);
371 case 'z': /* offset to zero terminated string (4 byte) */
372 str = va_arg(args,char*);
373 stringneeded = (str ? strlen(str)+1 : 0);
376 case 'l': /* offset to user data (4 byte) */
377 str = va_arg(args,char*);
378 stringneeded = va_arg(args,int);
381 case 'b': /* offset to data (with counter) (4 byte) */
382 str = va_arg(args,char*);
383 stringneeded = get_counter(&p->curpos);
389 if (stringneeded >= 0) {
391 if (p->buflen >= needed) {
392 stringused = stringneeded;
393 if (stringused > p->stringlen) {
394 stringused = (is_string ? p->stringlen : 0);
395 if (p->errcode == NERR_Success) {
396 p->errcode = ERRmoredata;
400 SIVAL(p->structbuf,0,0);
402 SIVAL(p->structbuf,0,PTR_DIFF(p->stringbuf,p->base));
403 memcpy(p->stringbuf,str?str:"",stringused);
405 p->stringbuf[stringused-1] = '\0';
407 p->stringbuf += stringused;
408 p->stringlen -= stringused;
409 p->usedlen += stringused;
412 p->neededlen += stringneeded;
415 p->neededlen += needed;
416 if (p->buflen >= needed) {
417 p->structbuf += needed;
419 p->usedlen += needed;
421 if (p->errcode == NERR_Success) {
422 p->errcode = ERRmoredata;
429 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
430 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
432 #define PACK(desc,t,v) package(desc,v)
433 #define PACKl(desc,t,v,l) package(desc,v,l)
436 static void PACKI(struct pack_desc* desc, const char *t,int v)
441 static void PACKS(struct pack_desc* desc,const char *t,const char *v)
446 /****************************************************************************
448 ****************************************************************************/
450 static void PackDriverData(struct pack_desc* desc)
452 char drivdata[4+4+32];
453 SIVAL(drivdata,0,sizeof drivdata); /* cb */
454 SIVAL(drivdata,4,1000); /* lVersion */
455 memset(drivdata+8,0,32); /* szDeviceName */
456 push_ascii(drivdata+8,"NULL",32, STR_TERMINATE);
457 PACKl(desc,"l",drivdata,sizeof drivdata); /* pDriverData */
460 static int check_printq_info(struct pack_desc* desc,
461 unsigned int uLevel, char *id1, char *id2)
463 desc->subformat = NULL;
466 desc->format = "B13";
469 desc->format = "B13BWWWzzzzzWW";
472 desc->format = "B13BWWWzzzzzWN";
473 desc->subformat = "WB21BB16B10zWWzDDz";
476 desc->format = "zWWWWzzzzWWzzl";
479 desc->format = "zWWWWzzzzWNzzl";
480 desc->subformat = "WWzWWDDzz";
489 desc->format = "WzzzzzzzzN";
490 desc->subformat = "z";
493 DEBUG(0,("check_printq_info: invalid level %d\n",
497 if (id1 == NULL || strcmp(desc->format,id1) != 0) {
498 DEBUG(0,("check_printq_info: invalid format %s\n",
499 id1 ? id1 : "<NULL>" ));
502 if (desc->subformat && (id2 == NULL || strcmp(desc->subformat,id2) != 0)) {
503 DEBUG(0,("check_printq_info: invalid subformat %s\n",
504 id2 ? id2 : "<NULL>" ));
511 #define RAP_JOB_STATUS_QUEUED 0
512 #define RAP_JOB_STATUS_PAUSED 1
513 #define RAP_JOB_STATUS_SPOOLING 2
514 #define RAP_JOB_STATUS_PRINTING 3
515 #define RAP_JOB_STATUS_PRINTED 4
517 #define RAP_QUEUE_STATUS_PAUSED 1
518 #define RAP_QUEUE_STATUS_ERROR 2
520 /* turn a print job status into a on the wire status
522 static int printj_spoolss_status(int v)
524 if (v == JOB_STATUS_QUEUED)
525 return RAP_JOB_STATUS_QUEUED;
526 if (v & JOB_STATUS_PAUSED)
527 return RAP_JOB_STATUS_PAUSED;
528 if (v & JOB_STATUS_SPOOLING)
529 return RAP_JOB_STATUS_SPOOLING;
530 if (v & JOB_STATUS_PRINTING)
531 return RAP_JOB_STATUS_PRINTING;
535 /* turn a print queue status into a on the wire status
537 static int printq_spoolss_status(int v)
539 if (v == PRINTER_STATUS_OK)
541 if (v & PRINTER_STATUS_PAUSED)
542 return RAP_QUEUE_STATUS_PAUSED;
543 return RAP_QUEUE_STATUS_ERROR;
546 static void fill_spoolss_printjob_info(int uLevel,
547 struct pack_desc *desc,
548 struct spoolss_JobInfo2 *info2,
551 time_t t = spoolss_Time_to_time_t(&info2->submitted);
553 /* the client expects localtime */
554 t -= get_time_zone(t);
556 PACKI(desc,"W",pjobid_to_rap(info2->printer_name, info2->job_id)); /* uJobId */
558 PACKS(desc,"B21", info2->user_name); /* szUserName */
559 PACKS(desc,"B",""); /* pad */
560 PACKS(desc,"B16",""); /* szNotifyName */
561 PACKS(desc,"B10","PM_Q_RAW"); /* szDataType */
562 PACKS(desc,"z",""); /* pszParms */
563 PACKI(desc,"W",n+1); /* uPosition */
564 PACKI(desc,"W", printj_spoolss_status(info2->status)); /* fsStatus */
565 PACKS(desc,"z",""); /* pszStatus */
566 PACKI(desc,"D", t); /* ulSubmitted */
567 PACKI(desc,"D", info2->size); /* ulSize */
568 PACKS(desc,"z", info2->document_name); /* pszComment */
570 if (uLevel == 2 || uLevel == 3 || uLevel == 4) {
571 PACKI(desc,"W", info2->priority); /* uPriority */
572 PACKS(desc,"z", info2->user_name); /* pszUserName */
573 PACKI(desc,"W",n+1); /* uPosition */
574 PACKI(desc,"W", printj_spoolss_status(info2->status)); /* fsStatus */
575 PACKI(desc,"D",t); /* ulSubmitted */
576 PACKI(desc,"D", info2->size); /* ulSize */
577 PACKS(desc,"z","Samba"); /* pszComment */
578 PACKS(desc,"z", info2->document_name); /* pszDocument */
580 PACKS(desc,"z",""); /* pszNotifyName */
581 PACKS(desc,"z","PM_Q_RAW"); /* pszDataType */
582 PACKS(desc,"z",""); /* pszParms */
583 PACKS(desc,"z",""); /* pszStatus */
584 PACKS(desc,"z", info2->printer_name); /* pszQueue */
585 PACKS(desc,"z","lpd"); /* pszQProcName */
586 PACKS(desc,"z",""); /* pszQProcParms */
587 PACKS(desc,"z","NULL"); /* pszDriverName */
588 PackDriverData(desc); /* pDriverData */
589 PACKS(desc,"z",""); /* pszPrinterName */
590 } else if (uLevel == 4) { /* OS2 */
591 PACKS(desc,"z",""); /* pszSpoolFileName */
592 PACKS(desc,"z",""); /* pszPortName */
593 PACKS(desc,"z",""); /* pszStatus */
594 PACKI(desc,"D",0); /* ulPagesSpooled */
595 PACKI(desc,"D",0); /* ulPagesSent */
596 PACKI(desc,"D",0); /* ulPagesPrinted */
597 PACKI(desc,"D",0); /* ulTimePrinted */
598 PACKI(desc,"D",0); /* ulExtendJobStatus */
599 PACKI(desc,"D",0); /* ulStartPage */
600 PACKI(desc,"D",0); /* ulEndPage */
605 /********************************************************************
606 Respond to the DosPrintQInfo command with a level of 52
607 This is used to get printer driver information for Win9x clients
608 ********************************************************************/
609 static void fill_printq_info_52(struct spoolss_DriverInfo3 *driver,
610 struct pack_desc* desc, int count,
611 const char *printer_name)
615 trim_string(discard_const_p(char, driver->driver_path), "\\print$\\WIN40\\0\\", 0);
616 trim_string(discard_const_p(char, driver->data_file), "\\print$\\WIN40\\0\\", 0);
617 trim_string(discard_const_p(char, driver->help_file), "\\print$\\WIN40\\0\\", 0);
619 PACKI(desc, "W", 0x0400); /* don't know */
620 PACKS(desc, "z", driver->driver_name); /* long printer name */
621 PACKS(desc, "z", driver->driver_path); /* Driverfile Name */
622 PACKS(desc, "z", driver->data_file); /* Datafile name */
623 PACKS(desc, "z", driver->monitor_name); /* language monitor */
625 fstrcpy(location, "\\\\%L\\print$\\WIN40\\0");
626 standard_sub_basic( "", "", location, sizeof(location)-1 );
627 PACKS(desc,"z", location); /* share to retrieve files */
629 PACKS(desc,"z", driver->default_datatype); /* default data type */
630 PACKS(desc,"z", driver->help_file); /* helpfile name */
631 PACKS(desc,"z", driver->driver_path); /* driver name */
633 DEBUG(3,("Printer Driver Name: %s:\n",driver->driver_name));
634 DEBUG(3,("Driver: %s:\n",driver->driver_path));
635 DEBUG(3,("Data File: %s:\n",driver->data_file));
636 DEBUG(3,("Language Monitor: %s:\n",driver->monitor_name));
637 DEBUG(3,("Driver Location: %s:\n",location));
638 DEBUG(3,("Data Type: %s:\n",driver->default_datatype));
639 DEBUG(3,("Help File: %s:\n",driver->help_file));
640 PACKI(desc,"N",count); /* number of files to copy */
642 for ( i=0; i<count && driver->dependent_files && *driver->dependent_files[i]; i++)
644 trim_string(discard_const_p(char, driver->dependent_files[i]), "\\print$\\WIN40\\0\\", 0);
645 PACKS(desc,"z",driver->dependent_files[i]); /* driver files to copy */
646 DEBUG(3,("Dependent File: %s:\n", driver->dependent_files[i]));
651 DEBUG(3,("fill_printq_info_52: file count specified by client [%d] != number of dependent files [%i]\n",
654 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n", printer_name, i));
656 desc->errcode=NERR_Success;
660 static const char *strip_unc(const char *unc)
668 if ((p = strrchr(unc, '\\')) != NULL) {
675 static void fill_printq_info(int uLevel,
676 struct pack_desc* desc,
678 union spoolss_JobInfo *job_info,
679 struct spoolss_DriverInfo3 *driver_info,
680 struct spoolss_PrinterInfo2 *printer_info)
686 PACKS(desc,"B13", strip_unc(printer_info->printername));
691 PACKS(desc,"z", strip_unc(printer_info->printername));
694 PACKI(desc,"K", printq_spoolss_status(printer_info->status));
698 if (uLevel == 1 || uLevel == 2) {
699 PACKS(desc,"B",""); /* alignment */
700 PACKI(desc,"W",5); /* priority */
701 PACKI(desc,"W",0); /* start time */
702 PACKI(desc,"W",0); /* until time */
703 PACKS(desc,"z",""); /* pSepFile */
704 PACKS(desc,"z","lpd"); /* pPrProc */
705 PACKS(desc,"z", strip_unc(printer_info->printername)); /* pDestinations */
706 PACKS(desc,"z",""); /* pParms */
707 if (printer_info->printername == NULL) {
708 PACKS(desc,"z","UNKNOWN PRINTER");
709 PACKI(desc,"W",LPSTAT_ERROR);
711 PACKS(desc,"z", printer_info->comment);
712 PACKI(desc,"W", printq_spoolss_status(printer_info->status)); /* status */
714 PACKI(desc,(uLevel == 1 ? "W" : "N"),count);
717 if (uLevel == 3 || uLevel == 4) {
718 PACKI(desc,"W",5); /* uPriority */
719 PACKI(desc,"W",0); /* uStarttime */
720 PACKI(desc,"W",0); /* uUntiltime */
721 PACKI(desc,"W",5); /* pad1 */
722 PACKS(desc,"z",""); /* pszSepFile */
723 PACKS(desc,"z","WinPrint"); /* pszPrProc */
724 PACKS(desc,"z",NULL); /* pszParms */
725 PACKS(desc,"z",NULL); /* pszComment - don't ask.... JRA */
726 /* "don't ask" that it's done this way to fix corrupted
727 Win9X/ME printer comments. */
728 PACKI(desc,"W", printq_spoolss_status(printer_info->status)); /* fsStatus */
729 PACKI(desc,(uLevel == 3 ? "W" : "N"),count); /* cJobs */
730 PACKS(desc,"z", strip_unc(printer_info->printername)); /* pszPrinters */
731 PACKS(desc,"z", printer_info->drivername); /* pszDriverName */
732 PackDriverData(desc); /* pDriverData */
735 if (uLevel == 2 || uLevel == 4) {
737 for (i = 0; i < count; i++) {
738 fill_spoolss_printjob_info(uLevel == 2 ? 1 : 2, desc, &job_info[i].info2, i);
743 fill_printq_info_52(driver_info, desc, count, printer_info->printername);
746 /* This function returns the number of files for a given driver */
747 static int get_printerdrivernumber(const struct spoolss_DriverInfo3 *driver)
751 /* count the number of files */
752 while (driver->dependent_files && *driver->dependent_files[result])
758 static bool api_DosPrintQGetInfo(struct smbd_server_connection *sconn,
759 connection_struct *conn, uint64_t vuid,
760 char *param, int tpscnt,
761 char *data, int tdscnt,
762 int mdrcnt,int mprcnt,
763 char **rdata,char **rparam,
764 int *rdata_len,int *rparam_len)
766 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
767 char *str2 = skip_string(param,tpscnt,str1);
768 char *p = skip_string(param,tpscnt,str2);
773 struct pack_desc desc;
776 WERROR werr = WERR_OK;
777 TALLOC_CTX *mem_ctx = talloc_tos();
779 struct rpc_pipe_client *cli = NULL;
780 struct dcerpc_binding_handle *b = NULL;
781 struct policy_handle handle;
782 struct spoolss_DevmodeContainer devmode_ctr;
783 union spoolss_DriverInfo driver_info;
784 union spoolss_JobInfo *job_info = NULL;
785 union spoolss_PrinterInfo printer_info;
787 if (!str1 || !str2 || !p) {
790 memset((char *)&desc,'\0',sizeof(desc));
792 p = skip_string(param,tpscnt,p);
796 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
797 str3 = get_safe_str_ptr(param,tpscnt,p,4);
798 /* str3 may be null here and is checked in check_printq_info(). */
800 /* remove any trailing username */
801 if ((p = strchr_m(QueueName,'%')))
804 DEBUG(3,("api_DosPrintQGetInfo uLevel=%d name=%s\n",uLevel,QueueName));
806 /* check it's a supported varient */
807 if (!prefix_ok(str1,"zWrLh"))
809 if (!check_printq_info(&desc,uLevel,str2,str3)) {
811 * Patch from Scott Moomaw <scott@bridgewater.edu>
812 * to return the 'invalid info level' error if an
813 * unknown level was requested.
817 *rparam = smb_realloc_limit(*rparam,*rparam_len);
821 SSVALS(*rparam,0,ERRunknownlevel);
829 if (QueueName == NULL || (strlen(QueueName) < 1)) {
830 desc.errcode = W_ERROR_V(WERR_INVALID_PARAM);
834 status = rpc_pipe_open_interface(conn,
835 &ndr_table_spoolss.syntax_id,
837 conn->sconn->remote_address,
838 conn->sconn->msg_ctx,
840 if (!NT_STATUS_IS_OK(status)) {
841 DEBUG(0,("api_DosPrintQGetInfo: could not connect to spoolss: %s\n",
843 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
846 b = cli->binding_handle;
848 ZERO_STRUCT(devmode_ctr);
850 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
857 if (!NT_STATUS_IS_OK(status)) {
858 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
861 if (!W_ERROR_IS_OK(werr)) {
862 desc.errcode = W_ERROR_V(werr);
866 werr = rpccli_spoolss_getprinter(cli, mem_ctx,
871 if (!W_ERROR_IS_OK(werr)) {
872 desc.errcode = W_ERROR_V(werr);
877 uint32_t server_major_version;
878 uint32_t server_minor_version;
880 werr = rpccli_spoolss_getprinterdriver2(cli, mem_ctx,
888 &server_major_version,
889 &server_minor_version);
890 if (!W_ERROR_IS_OK(werr)) {
891 desc.errcode = W_ERROR_V(werr);
895 count = get_printerdrivernumber(&driver_info.info3);
896 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count));
899 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
907 if (!W_ERROR_IS_OK(werr)) {
908 desc.errcode = W_ERROR_V(werr);
916 *rdata = smb_realloc_limit(*rdata,mdrcnt);
921 desc.buflen = mdrcnt;
924 * Don't return data but need to get correct length
925 * init_package will return wrong size if buflen=0
927 desc.buflen = getlen(desc.format);
928 desc.base = tmpdata = (char *) SMB_MALLOC (desc.buflen);
931 if (init_package(&desc,1,count)) {
932 desc.subcount = count;
933 fill_printq_info(uLevel,&desc,count, job_info, &driver_info.info3, &printer_info.info2);
936 *rdata_len = desc.usedlen;
939 * We must set the return code to ERRbuftoosmall
940 * in order to support lanman style printing with Win NT/2k
943 if (!mdrcnt && lp_disable_spoolss())
944 desc.errcode = ERRbuftoosmall;
947 if (b && is_valid_policy_hnd(&handle)) {
948 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
951 *rdata_len = desc.usedlen;
953 *rparam = smb_realloc_limit(*rparam,*rparam_len);
958 SSVALS(*rparam,0,desc.errcode);
960 SSVAL(*rparam,4,desc.neededlen);
962 DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode));
969 /****************************************************************************
970 View list of all print jobs on all queues.
971 ****************************************************************************/
973 static bool api_DosPrintQEnum(struct smbd_server_connection *sconn,
974 connection_struct *conn, uint64_t vuid,
975 char *param, int tpscnt,
976 char *data, int tdscnt,
977 int mdrcnt, int mprcnt,
978 char **rdata, char** rparam,
979 int *rdata_len, int *rparam_len)
981 char *param_format = get_safe_str_ptr(param,tpscnt,param,2);
982 char *output_format1 = skip_string(param,tpscnt,param_format);
983 char *p = skip_string(param,tpscnt,output_format1);
984 unsigned int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
985 char *output_format2 = get_safe_str_ptr(param,tpscnt,p,4);
987 struct pack_desc desc;
988 int *subcntarr = NULL;
989 int queuecnt = 0, subcnt = 0, succnt = 0;
991 WERROR werr = WERR_OK;
992 TALLOC_CTX *mem_ctx = talloc_tos();
994 struct rpc_pipe_client *cli = NULL;
995 struct dcerpc_binding_handle *b = NULL;
996 struct spoolss_DevmodeContainer devmode_ctr;
997 uint32_t num_printers;
998 union spoolss_PrinterInfo *printer_info;
999 union spoolss_DriverInfo *driver_info;
1000 union spoolss_JobInfo **job_info;
1002 if (!param_format || !output_format1 || !p) {
1006 memset((char *)&desc,'\0',sizeof(desc));
1008 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
1010 if (!prefix_ok(param_format,"WrLeh")) {
1013 if (!check_printq_info(&desc,uLevel,output_format1,output_format2)) {
1015 * Patch from Scott Moomaw <scott@bridgewater.edu>
1016 * to return the 'invalid info level' error if an
1017 * unknown level was requested.
1021 *rparam = smb_realloc_limit(*rparam,*rparam_len);
1025 SSVALS(*rparam,0,ERRunknownlevel);
1031 status = rpc_pipe_open_interface(conn,
1032 &ndr_table_spoolss.syntax_id,
1034 conn->sconn->remote_address,
1035 conn->sconn->msg_ctx,
1037 if (!NT_STATUS_IS_OK(status)) {
1038 DEBUG(0,("api_DosPrintQEnum: could not connect to spoolss: %s\n",
1039 nt_errstr(status)));
1040 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
1043 b = cli->binding_handle;
1045 werr = rpccli_spoolss_enumprinters(cli, mem_ctx,
1047 cli->srv_name_slash,
1052 if (!W_ERROR_IS_OK(werr)) {
1053 desc.errcode = W_ERROR_V(werr);
1057 queuecnt = num_printers;
1059 job_info = talloc_array(mem_ctx, union spoolss_JobInfo *, num_printers);
1060 if (job_info == NULL) {
1064 driver_info = talloc_array(mem_ctx, union spoolss_DriverInfo, num_printers);
1065 if (driver_info == NULL) {
1069 if((subcntarr = SMB_MALLOC_ARRAY(int,queuecnt)) == NULL) {
1070 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
1075 *rdata = smb_realloc_limit(*rdata,mdrcnt);
1081 desc.buflen = mdrcnt;
1084 for (i = 0; i < num_printers; i++) {
1087 struct policy_handle handle;
1088 const char *printername;
1090 printername = talloc_strdup(mem_ctx, printer_info[i].info2.printername);
1091 if (printername == NULL) {
1095 ZERO_STRUCT(handle);
1096 ZERO_STRUCT(devmode_ctr);
1098 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
1105 if (!NT_STATUS_IS_OK(status)) {
1106 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
1109 if (!W_ERROR_IS_OK(werr)) {
1110 desc.errcode = W_ERROR_V(werr);
1114 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
1122 if (!W_ERROR_IS_OK(werr)) {
1123 desc.errcode = W_ERROR_V(werr);
1128 uint32_t server_major_version;
1129 uint32_t server_minor_version;
1131 werr = rpccli_spoolss_getprinterdriver2(cli, mem_ctx,
1139 &server_major_version,
1140 &server_minor_version);
1141 if (!W_ERROR_IS_OK(werr)) {
1142 desc.errcode = W_ERROR_V(werr);
1147 subcntarr[i] = num_jobs;
1148 subcnt += subcntarr[i];
1150 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
1153 if (init_package(&desc,queuecnt,subcnt)) {
1154 for (i = 0; i < num_printers; i++) {
1155 fill_printq_info(uLevel,&desc,subcntarr[i], job_info[i], &driver_info[i].info3, &printer_info[i].info2);
1156 if (desc.errcode == NERR_Success) {
1163 SAFE_FREE(subcntarr);
1164 *rdata_len = desc.usedlen;
1166 *rparam = smb_realloc_limit(*rparam,*rparam_len);
1170 SSVALS(*rparam,0,desc.errcode);
1172 SSVAL(*rparam,4,succnt);
1173 SSVAL(*rparam,6,queuecnt);
1179 SAFE_FREE(subcntarr);
1184 /****************************************************************************
1185 Get info level for a server list query.
1186 ****************************************************************************/
1188 static bool check_session_info(int uLevel, char* id)
1192 if (strcmp(id,"B16") != 0) {
1197 if (strcmp(id,"B16BBDz") != 0) {
1207 struct srv_info_struct {
1215 /*******************************************************************
1216 Get server info lists from the files saved by nmbd. Return the
1218 ******************************************************************/
1220 static int get_session_info(uint32 servertype,
1221 struct srv_info_struct **servers,
1227 bool local_list_only;
1230 lines = file_lines_load(cache_path(SERVER_LIST), NULL, 0, NULL);
1232 DEBUG(4,("Can't open %s - %s\n",cache_path(SERVER_LIST),strerror(errno)));
1236 /* request for everything is code for request all servers */
1237 if (servertype == SV_TYPE_ALL) {
1238 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1241 local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY);
1243 DEBUG(4,("Servertype search: %8x\n",servertype));
1245 for (i=0;lines[i];i++) {
1247 struct srv_info_struct *s;
1248 const char *ptr = lines[i];
1250 TALLOC_CTX *frame = NULL;
1257 if (count == alloced) {
1259 *servers = SMB_REALLOC_ARRAY(*servers,struct srv_info_struct, alloced);
1261 DEBUG(0,("get_session_info: failed to enlarge servers info struct!\n"));
1265 memset((char *)((*servers)+count),'\0',sizeof(**servers)*(alloced-count));
1267 s = &(*servers)[count];
1269 frame = talloc_stackframe();
1271 if (!next_token_talloc(frame,&ptr,&p, NULL)) {
1275 fstrcpy(s->name, p);
1278 if (!next_token_talloc(frame,&ptr, &p, NULL)) {
1284 s->comment[0] = '\0';
1285 if (!next_token_talloc(frame,&ptr, &p, NULL)) {
1289 fstrcpy(s->comment, p);
1290 string_truncate(s->comment, MAX_SERVER_STRING_LENGTH);
1292 s->domain[0] = '\0';
1293 if (!next_token_talloc(frame,&ptr,&p, NULL)) {
1294 /* this allows us to cope with an old nmbd */
1295 fstrcpy(s->domain,lp_workgroup());
1297 fstrcpy(s->domain, p);
1301 if (sscanf(stype,"%X",&s->type) != 1) {
1302 DEBUG(4,("r:host file "));
1306 /* Filter the servers/domains we return based on what was asked for. */
1308 /* Check to see if we are being asked for a local list only. */
1309 if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) {
1310 DEBUG(4,("r: local list only"));
1314 /* doesn't match up: don't want it */
1315 if (!(servertype & s->type)) {
1316 DEBUG(4,("r:serv type "));
1320 if ((servertype & SV_TYPE_DOMAIN_ENUM) !=
1321 (s->type & SV_TYPE_DOMAIN_ENUM)) {
1322 DEBUG(4,("s: dom mismatch "));
1326 if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM)) {
1330 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1331 s->type &= ~SV_TYPE_LOCAL_LIST_ONLY;
1334 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1335 s->name, s->type, s->comment, s->domain));
1336 s->server_added = True;
1339 DEBUG(4,("%20s %8x %25s %15s\n",
1340 s->name, s->type, s->comment, s->domain));
1348 /*******************************************************************
1349 Fill in a server info structure.
1350 ******************************************************************/
1352 static int fill_srv_info(struct srv_info_struct *service,
1353 int uLevel, char **buf, int *buflen,
1354 char **stringbuf, int *stringspace, char *baseaddr)
1377 len = strlen(service->comment)+1;
1381 *buflen = struct_len;
1383 return struct_len + len;
1388 if (*buflen < struct_len) {
1395 p2 = p + struct_len;
1396 l2 = *buflen - struct_len;
1404 push_ascii(p,service->name, MAX_NETBIOSNAME_LEN, STR_TERMINATE);
1408 push_ascii(p,service->name,MAX_NETBIOSNAME_LEN, STR_TERMINATE);
1409 SIVAL(p,18,service->type);
1410 SIVAL(p,22,PTR_DIFF(p2,baseaddr));
1411 len += CopyAndAdvance(&p2,service->comment,&l2);
1416 *buf = p + struct_len;
1417 *buflen -= struct_len;
1428 static int srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
1430 return strcasecmp_m(s1->name,s2->name);
1433 /****************************************************************************
1434 View list of servers available (or possibly domains). The info is
1435 extracted from lists saved by nmbd on the local host.
1436 ****************************************************************************/
1438 static bool api_RNetServerEnum2(struct smbd_server_connection *sconn,
1439 connection_struct *conn, uint64_t vuid,
1440 char *param, int tpscnt,
1441 char *data, int tdscnt,
1442 int mdrcnt, int mprcnt, char **rdata,
1443 char **rparam, int *rdata_len, int *rparam_len)
1445 char *str1 = get_safe_str_ptr(param, tpscnt, param, 2);
1446 char *str2 = skip_string(param,tpscnt,str1);
1447 char *p = skip_string(param,tpscnt,str2);
1448 int uLevel = get_safe_SVAL(param, tpscnt, p, 0, -1);
1449 int buf_len = get_safe_SVAL(param,tpscnt, p, 2, 0);
1450 uint32 servertype = get_safe_IVAL(param,tpscnt,p,4, 0);
1452 int data_len, fixed_len, string_len;
1453 int f_len = 0, s_len = 0;
1454 struct srv_info_struct *servers=NULL;
1455 int counted=0,total=0;
1458 bool domain_request;
1461 if (!str1 || !str2 || !p) {
1465 /* If someone sets all the bits they don't really mean to set
1466 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1469 if (servertype == SV_TYPE_ALL) {
1470 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1473 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1474 any other bit (they may just set this bit on its own) they
1475 want all the locally seen servers. However this bit can be
1476 set on its own so set the requested servers to be
1477 ALL - DOMAIN_ENUM. */
1479 if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM)) {
1480 servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
1483 domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
1484 local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
1488 if (!prefix_ok(str1,"WrLehD")) {
1491 if (!check_session_info(uLevel,str2)) {
1495 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1496 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1497 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1499 if (strcmp(str1, "WrLehDz") == 0) {
1500 if (skip_string(param,tpscnt,p) == NULL) {
1503 pull_ascii_fstring(domain, p);
1505 fstrcpy(domain, lp_workgroup());
1508 DEBUG(4, ("domain [%s]\n", domain));
1510 if (lp_browse_list()) {
1511 total = get_session_info(servertype,&servers,domain);
1514 data_len = fixed_len = string_len = 0;
1517 TYPESAFE_QSORT(servers, total, srv_comp);
1520 char *lastname=NULL;
1522 for (i=0;i<total;i++) {
1523 struct srv_info_struct *s = &servers[i];
1525 if (lastname && strequal(lastname,s->name)) {
1529 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1530 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1531 i, s->name, s->type, s->comment, s->domain));
1533 if (data_len < buf_len) {
1536 string_len += s_len;
1543 *rdata_len = fixed_len + string_len;
1544 *rdata = smb_realloc_limit(*rdata,*rdata_len);
1549 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1555 char *lastname=NULL;
1556 int count2 = counted;
1558 for (i = 0; i < total && count2;i++) {
1559 struct srv_info_struct *s = &servers[i];
1561 if (lastname && strequal(lastname,s->name)) {
1565 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1566 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1567 i, s->name, s->type, s->comment, s->domain));
1573 *rparam = smb_realloc_limit(*rparam,*rparam_len);
1577 SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata));
1579 SSVAL(*rparam,4,counted);
1580 SSVAL(*rparam,6,counted+missed);
1584 DEBUG(3,("NetServerEnum2 domain = %s uLevel=%d counted=%d total=%d\n",
1585 domain,uLevel,counted,counted+missed));
1590 static int srv_name_match(const char *n1, const char *n2)
1593 * [MS-RAP] footnote <88> for Section 3.2.5.15 says:
1595 * In Windows, FirstNameToReturn need not be an exact match:
1596 * the server will return a list of servers that exist on
1597 * the network greater than or equal to the FirstNameToReturn.
1599 int ret = strcasecmp_m(n1, n2);
1608 static bool api_RNetServerEnum3(struct smbd_server_connection *sconn,
1609 connection_struct *conn, uint64_t vuid,
1610 char *param, int tpscnt,
1611 char *data, int tdscnt,
1612 int mdrcnt, int mprcnt, char **rdata,
1613 char **rparam, int *rdata_len, int *rparam_len)
1615 char *str1 = get_safe_str_ptr(param, tpscnt, param, 2);
1616 char *str2 = skip_string(param,tpscnt,str1);
1617 char *p = skip_string(param,tpscnt,str2);
1618 int uLevel = get_safe_SVAL(param, tpscnt, p, 0, -1);
1619 int buf_len = get_safe_SVAL(param,tpscnt, p, 2, 0);
1620 uint32 servertype = get_safe_IVAL(param,tpscnt,p,4, 0);
1622 int data_len, fixed_len, string_len;
1623 int f_len = 0, s_len = 0;
1624 struct srv_info_struct *servers=NULL;
1625 int counted=0,first=0,total=0;
1629 bool domain_request;
1632 if (!str1 || !str2 || !p) {
1636 /* If someone sets all the bits they don't really mean to set
1637 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1640 if (servertype == SV_TYPE_ALL) {
1641 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1644 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1645 any other bit (they may just set this bit on its own) they
1646 want all the locally seen servers. However this bit can be
1647 set on its own so set the requested servers to be
1648 ALL - DOMAIN_ENUM. */
1650 if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM)) {
1651 servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
1654 domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
1655 local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
1659 if (strcmp(str1, "WrLehDzz") != 0) {
1662 if (!check_session_info(uLevel,str2)) {
1666 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1667 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1668 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1670 if (skip_string(param,tpscnt,p) == NULL) {
1673 pull_ascii_fstring(domain, p);
1674 if (domain[0] == '\0') {
1675 fstrcpy(domain, lp_workgroup());
1677 p = skip_string(param,tpscnt,p);
1678 if (skip_string(param,tpscnt,p) == NULL) {
1681 pull_ascii_fstring(first_name, p);
1683 DEBUG(4, ("domain: '%s' first_name: '%s'\n",
1684 domain, first_name));
1686 if (lp_browse_list()) {
1687 total = get_session_info(servertype,&servers,domain);
1690 data_len = fixed_len = string_len = 0;
1693 TYPESAFE_QSORT(servers, total, srv_comp);
1695 if (first_name[0] != '\0') {
1696 struct srv_info_struct *first_server = NULL;
1698 BINARY_ARRAY_SEARCH(servers, total, name, first_name,
1699 srv_name_match, first_server);
1701 first = PTR_DIFF(first_server, servers) / sizeof(*servers);
1703 * The binary search may not find the exact match
1704 * so we need to search backward to find the first match
1706 * This implements the strange matching windows
1707 * implements. (see the comment in srv_name_match().
1711 ret = strcasecmp_m(first_name,
1712 servers[first-1].name);
1719 /* we should return no entries */
1725 char *lastname=NULL;
1727 for (i=first;i<total;i++) {
1728 struct srv_info_struct *s = &servers[i];
1730 if (lastname && strequal(lastname,s->name)) {
1734 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1735 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1736 i, s->name, s->type, s->comment, s->domain));
1738 if (data_len < buf_len) {
1741 string_len += s_len;
1748 *rdata_len = fixed_len + string_len;
1749 *rdata = smb_realloc_limit(*rdata,*rdata_len);
1754 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1760 char *lastname=NULL;
1761 int count2 = counted;
1763 for (i = first; i < total && count2;i++) {
1764 struct srv_info_struct *s = &servers[i];
1766 if (lastname && strequal(lastname,s->name)) {
1770 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1771 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1772 i, s->name, s->type, s->comment, s->domain));
1778 *rparam = smb_realloc_limit(*rparam,*rparam_len);
1782 SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata));
1784 SSVAL(*rparam,4,counted);
1785 SSVAL(*rparam,6,counted+missed);
1787 DEBUG(3,("NetServerEnum3 domain = %s uLevel=%d first=%d[%s => %s] counted=%d total=%d\n",
1788 domain,uLevel,first,first_name,
1789 first < total ? servers[first].name : "",
1790 counted,counted+missed));
1797 /****************************************************************************
1798 command 0x34 - suspected of being a "Lookup Names" stub api
1799 ****************************************************************************/
1801 static bool api_RNetGroupGetUsers(struct smbd_server_connection *sconn,
1802 connection_struct *conn, uint64_t vuid,
1803 char *param, int tpscnt,
1804 char *data, int tdscnt,
1805 int mdrcnt, int mprcnt, char **rdata,
1806 char **rparam, int *rdata_len, int *rparam_len)
1808 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
1809 char *str2 = skip_string(param,tpscnt,str1);
1810 char *p = skip_string(param,tpscnt,str2);
1811 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
1812 int buf_len = get_safe_SVAL(param,tpscnt,p,2,0);
1816 if (!str1 || !str2 || !p) {
1820 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1821 str1, str2, p, uLevel, buf_len));
1823 if (!prefix_ok(str1,"zWrLeh")) {
1830 *rparam = smb_realloc_limit(*rparam,*rparam_len);
1835 SSVAL(*rparam,0,0x08AC); /* informational warning message */
1837 SSVAL(*rparam,4,counted);
1838 SSVAL(*rparam,6,counted+missed);
1843 /****************************************************************************
1844 get info about a share
1845 ****************************************************************************/
1847 static bool check_share_info(int uLevel, char* id)
1851 if (strcmp(id,"B13") != 0) {
1856 /* Level-2 descriptor is allowed (and ignored) */
1857 if (strcmp(id,"B13BWz") != 0 &&
1858 strcmp(id,"B13BWzWWWzB9B") != 0) {
1863 if (strcmp(id,"B13BWzWWWzB9B") != 0) {
1868 if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) {
1878 static int fill_share_info(connection_struct *conn, int snum, int uLevel,
1879 char** buf, int* buflen,
1880 char** stringbuf, int* stringspace, char* baseaddr)
1909 len += StrlenExpanded(conn,snum,lp_comment(talloc_tos(), snum));
1912 len += strlen(lp_pathname(talloc_tos(), snum)) + 1;
1915 *buflen = struct_len;
1920 return struct_len + len;
1925 if ((*buflen) < struct_len) {
1933 p2 = p + struct_len;
1934 l2 = (*buflen) - struct_len;
1941 push_ascii(p,lp_servicename(talloc_tos(), snum),13, STR_TERMINATE);
1947 type = STYPE_DISKTREE;
1948 if (lp_print_ok(snum)) {
1949 type = STYPE_PRINTQ;
1951 if (strequal("IPC",lp_fstype(talloc_tos(),snum))) {
1954 SSVAL(p,14,type); /* device type */
1955 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1956 len += CopyExpanded(conn,snum,&p2,lp_comment(talloc_tos(),snum),&l2);
1960 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1961 SSVALS(p,22,-1); /* max uses */
1962 SSVAL(p,24,1); /* current uses */
1963 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1964 len += CopyAndAdvance(&p2,lp_pathname(talloc_tos(),snum),&l2);
1965 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1969 memset(p+40,0,SHPWLEN+2);
1980 (*buf) = p + struct_len;
1981 (*buflen) -= struct_len;
1983 (*stringspace) = l2;
1992 static bool api_RNetShareGetInfo(struct smbd_server_connection *sconn,
1993 connection_struct *conn,uint64_t vuid,
1994 char *param, int tpscnt,
1995 char *data, int tdscnt,
1996 int mdrcnt,int mprcnt,
1997 char **rdata,char **rparam,
1998 int *rdata_len,int *rparam_len)
2000 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2001 char *str2 = skip_string(param,tpscnt,str1);
2002 char *netname_in = skip_string(param,tpscnt,str2);
2003 char *netname = NULL;
2004 char *p = skip_string(param,tpscnt,netname);
2005 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
2008 if (!str1 || !str2 || !netname_in || !p) {
2012 snum = find_service(talloc_tos(), netname_in, &netname);
2013 if (snum < 0 || !netname) {
2017 /* check it's a supported varient */
2018 if (!prefix_ok(str1,"zWrLh")) {
2021 if (!check_share_info(uLevel,str2)) {
2025 *rdata = smb_realloc_limit(*rdata,mdrcnt);
2030 *rdata_len = fill_share_info(conn,snum,uLevel,&p,&mdrcnt,0,0,0);
2031 if (*rdata_len < 0) {
2036 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2040 SSVAL(*rparam,0,NERR_Success);
2041 SSVAL(*rparam,2,0); /* converter word */
2042 SSVAL(*rparam,4,*rdata_len);
2047 /****************************************************************************
2048 View the list of available shares.
2050 This function is the server side of the NetShareEnum() RAP call.
2051 It fills the return buffer with share names and share comments.
2052 Note that the return buffer normally (in all known cases) allows only
2053 twelve byte strings for share names (plus one for a nul terminator).
2054 Share names longer than 12 bytes must be skipped.
2055 ****************************************************************************/
2057 static bool api_RNetShareEnum(struct smbd_server_connection *sconn,
2058 connection_struct *conn, uint64_t vuid,
2059 char *param, int tpscnt,
2060 char *data, int tdscnt,
2068 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2069 char *str2 = skip_string(param,tpscnt,str1);
2070 char *p = skip_string(param,tpscnt,str2);
2071 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
2072 int buf_len = get_safe_SVAL(param,tpscnt,p,2,0);
2075 int total=0,counted=0;
2076 bool missed = False;
2078 int data_len, fixed_len, string_len;
2079 int f_len = 0, s_len = 0;
2081 if (!str1 || !str2 || !p) {
2085 if (!prefix_ok(str1,"WrLeh")) {
2088 if (!check_share_info(uLevel,str2)) {
2092 /* Ensure all the usershares are loaded. */
2094 delete_and_reload_printers(sconn->ev_ctx, sconn->msg_ctx);
2095 load_registry_shares();
2096 count = load_usershare_shares(NULL, connections_snum_used);
2099 data_len = fixed_len = string_len = 0;
2100 for (i=0;i<count;i++) {
2101 fstring servicename_dos;
2102 if (!(lp_browseable(i) && lp_snum_ok(i))) {
2105 push_ascii_fstring(servicename_dos, lp_servicename(talloc_tos(), i));
2106 /* Maximum name length = 13. */
2107 if( lp_browseable( i ) && lp_snum_ok( i ) && (strlen(servicename_dos) < 13)) {
2109 data_len += fill_share_info(conn,i,uLevel,0,&f_len,0,&s_len,0);
2110 if (data_len < buf_len) {
2113 string_len += s_len;
2120 *rdata_len = fixed_len + string_len;
2121 *rdata = smb_realloc_limit(*rdata,*rdata_len);
2126 p2 = (*rdata) + fixed_len; /* auxiliary data (strings) will go here */
2131 for( i = 0; i < count; i++ ) {
2132 fstring servicename_dos;
2133 if (!(lp_browseable(i) && lp_snum_ok(i))) {
2137 push_ascii_fstring(servicename_dos,
2138 lp_servicename(talloc_tos(), i));
2139 if (lp_browseable(i) && lp_snum_ok(i) && (strlen(servicename_dos) < 13)) {
2140 if (fill_share_info( conn,i,uLevel,&p,&f_len,&p2,&s_len,*rdata ) < 0) {
2147 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2151 SSVAL(*rparam,0,missed ? ERRmoredata : NERR_Success);
2153 SSVAL(*rparam,4,counted);
2154 SSVAL(*rparam,6,total);
2156 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
2157 counted,total,uLevel,
2158 buf_len,*rdata_len,mdrcnt));
2163 /****************************************************************************
2165 ****************************************************************************/
2167 static bool api_RNetShareAdd(struct smbd_server_connection *sconn,
2168 connection_struct *conn,uint64_t vuid,
2169 char *param, int tpscnt,
2170 char *data, int tdscnt,
2171 int mdrcnt,int mprcnt,
2172 char **rdata,char **rparam,
2173 int *rdata_len,int *rparam_len)
2175 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2176 char *str2 = skip_string(param,tpscnt,str1);
2177 char *p = skip_string(param,tpscnt,str2);
2178 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
2181 char *pathname = NULL;
2182 unsigned int offset;
2184 size_t converted_size;
2186 WERROR werr = WERR_OK;
2187 TALLOC_CTX *mem_ctx = talloc_tos();
2189 struct rpc_pipe_client *cli = NULL;
2190 union srvsvc_NetShareInfo info;
2191 struct srvsvc_NetShareInfo2 info2;
2192 struct dcerpc_binding_handle *b;
2194 if (!str1 || !str2 || !p) {
2198 /* check it's a supported varient */
2199 if (!prefix_ok(str1,RAP_WShareAdd_REQ)) {
2202 if (!check_share_info(uLevel,str2)) {
2209 /* Do we have a string ? */
2210 if (skip_string(data,mdrcnt,data) == NULL) {
2213 pull_ascii_fstring(sharename,data);
2219 /* only support disk share adds */
2220 if (SVAL(data,14)!=STYPE_DISKTREE) {
2224 offset = IVAL(data, 16);
2225 if (offset >= mdrcnt) {
2226 res = ERRinvalidparam;
2230 /* Do we have a string ? */
2231 if (skip_string(data,mdrcnt,data+offset) == NULL) {
2234 pull_ascii_fstring(comment, offset? (data+offset) : "");
2236 offset = IVAL(data, 26);
2238 if (offset >= mdrcnt) {
2239 res = ERRinvalidparam;
2243 /* Do we have a string ? */
2244 if (skip_string(data,mdrcnt,data+offset) == NULL) {
2248 if (!pull_ascii_talloc(talloc_tos(), &pathname,
2249 offset ? (data+offset) : "", &converted_size))
2251 DEBUG(0,("api_RNetShareAdd: pull_ascii_talloc failed: %s",
2259 status = rpc_pipe_open_interface(mem_ctx, &ndr_table_srvsvc.syntax_id,
2261 conn->sconn->remote_address,
2262 conn->sconn->msg_ctx,
2264 if (!NT_STATUS_IS_OK(status)) {
2265 DEBUG(0,("api_RNetShareAdd: could not connect to srvsvc: %s\n",
2266 nt_errstr(status)));
2267 res = W_ERROR_V(ntstatus_to_werror(status));
2271 b = cli->binding_handle;
2273 info2.name = sharename;
2274 info2.type = STYPE_DISKTREE;
2275 info2.comment = comment;
2276 info2.permissions = 0;
2277 info2.max_users = 0;
2278 info2.current_users = 0;
2279 info2.path = pathname;
2280 info2.password = NULL;
2282 info.info2 = &info2;
2284 status = dcerpc_srvsvc_NetShareAdd(b, mem_ctx,
2285 cli->srv_name_slash,
2290 if (!NT_STATUS_IS_OK(status)) {
2291 res = W_ERROR_V(ntstatus_to_werror(status));
2294 if (!W_ERROR_IS_OK(werr)) {
2295 res = W_ERROR_V(werr);
2300 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2304 SSVAL(*rparam,0,NERR_Success);
2305 SSVAL(*rparam,2,0); /* converter word */
2306 SSVAL(*rparam,4,*rdata_len);
2314 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2319 SSVAL(*rparam,0,res);
2324 /****************************************************************************
2325 view list of groups available
2326 ****************************************************************************/
2328 static bool api_RNetGroupEnum(struct smbd_server_connection *sconn,
2329 connection_struct *conn,uint64_t vuid,
2330 char *param, int tpscnt,
2331 char *data, int tdscnt,
2332 int mdrcnt,int mprcnt,
2333 char **rdata,char **rparam,
2334 int *rdata_len,int *rparam_len)
2338 int resume_context, cli_buf_size;
2339 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2340 char *str2 = skip_string(param,tpscnt,str1);
2341 char *p = skip_string(param,tpscnt,str2);
2343 uint32_t num_groups;
2344 uint32_t resume_handle;
2345 struct rpc_pipe_client *samr_pipe;
2346 struct policy_handle samr_handle, domain_handle;
2347 NTSTATUS status, result;
2348 struct dcerpc_binding_handle *b;
2350 if (!str1 || !str2 || !p) {
2354 if (strcmp(str1,"WrLeh") != 0) {
2359 * W-> resume context (number of users to skip)
2360 * r -> return parameter pointer to receive buffer
2361 * L -> length of receive buffer
2362 * e -> return parameter number of entries
2363 * h -> return parameter total number of users
2366 if (strcmp("B21",str2) != 0) {
2370 status = rpc_pipe_open_interface(
2371 talloc_tos(), &ndr_table_samr.syntax_id,
2372 conn->session_info, conn->sconn->remote_address,
2373 conn->sconn->msg_ctx, &samr_pipe);
2374 if (!NT_STATUS_IS_OK(status)) {
2375 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2376 nt_errstr(status)));
2380 b = samr_pipe->binding_handle;
2382 status = dcerpc_samr_Connect2(b, talloc_tos(), lp_netbios_name(),
2383 SAMR_ACCESS_LOOKUP_DOMAIN, &samr_handle,
2385 if (!NT_STATUS_IS_OK(status)) {
2386 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2387 nt_errstr(status)));
2390 if (!NT_STATUS_IS_OK(result)) {
2391 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2392 nt_errstr(result)));
2396 status = dcerpc_samr_OpenDomain(b, talloc_tos(), &samr_handle,
2397 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS,
2398 get_global_sam_sid(), &domain_handle,
2400 if (!NT_STATUS_IS_OK(status)) {
2401 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2402 nt_errstr(status)));
2403 dcerpc_samr_Close(b, talloc_tos(), &samr_handle, &result);
2406 if (!NT_STATUS_IS_OK(result)) {
2407 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2408 nt_errstr(result)));
2409 dcerpc_samr_Close(b, talloc_tos(), &samr_handle, &result);
2413 resume_context = get_safe_SVAL(param,tpscnt,p,0,-1);
2414 cli_buf_size= get_safe_SVAL(param,tpscnt,p,2,0);
2415 DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: "
2416 "%d\n", resume_context, cli_buf_size));
2418 *rdata_len = cli_buf_size;
2419 *rdata = smb_realloc_limit(*rdata,*rdata_len);
2426 errflags = NERR_Success;
2431 struct samr_SamArray *sam_entries;
2432 uint32_t num_entries;
2434 status = dcerpc_samr_EnumDomainGroups(b, talloc_tos(),
2440 if (!NT_STATUS_IS_OK(status)) {
2441 DEBUG(10, ("dcerpc_samr_EnumDomainGroups returned "
2442 "%s\n", nt_errstr(status)));
2445 if (!NT_STATUS_IS_OK(result)) {
2447 DEBUG(10, ("dcerpc_samr_EnumDomainGroups returned "
2448 "%s\n", nt_errstr(result)));
2452 if (num_entries == 0) {
2453 DEBUG(10, ("dcerpc_samr_EnumDomainGroups returned "
2454 "no entries -- done\n"));
2458 for(i=0; i<num_entries; i++) {
2461 name = sam_entries->entries[i].name.string;
2463 if( ((PTR_DIFF(p,*rdata)+21) > *rdata_len) ) {
2464 /* set overflow error */
2465 DEBUG(3,("overflow on entry %d group %s\n", i,
2471 /* truncate the name at 21 chars. */
2473 strlcpy(p, name, 21);
2474 DEBUG(10,("adding entry %d group %s\n", i, p));
2476 p += 5; /* Both NT4 and W2k3SP1 do padding here. No
2481 if (errflags != NERR_Success) {
2485 TALLOC_FREE(sam_entries);
2488 dcerpc_samr_Close(b, talloc_tos(), &domain_handle, &result);
2489 dcerpc_samr_Close(b, talloc_tos(), &samr_handle, &result);
2491 *rdata_len = PTR_DIFF(p,*rdata);
2494 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2498 SSVAL(*rparam, 0, errflags);
2499 SSVAL(*rparam, 2, 0); /* converter word */
2500 SSVAL(*rparam, 4, num_groups); /* is this right?? */
2501 SSVAL(*rparam, 6, resume_context+num_groups); /* is this right?? */
2506 /*******************************************************************
2507 Get groups that a user is a member of.
2508 ******************************************************************/
2510 static bool api_NetUserGetGroups(struct smbd_server_connection *sconn,
2511 connection_struct *conn,uint64_t vuid,
2512 char *param, int tpscnt,
2513 char *data, int tdscnt,
2514 int mdrcnt,int mprcnt,
2515 char **rdata,char **rparam,
2516 int *rdata_len,int *rparam_len)
2518 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2519 char *str2 = skip_string(param,tpscnt,str1);
2520 char *UserName = skip_string(param,tpscnt,str2);
2521 char *p = skip_string(param,tpscnt,UserName);
2522 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
2523 const char *level_string;
2529 struct rpc_pipe_client *samr_pipe;
2530 struct policy_handle samr_handle, domain_handle, user_handle;
2531 struct lsa_String name;
2532 struct lsa_Strings names;
2533 struct samr_Ids type, rid;
2534 struct samr_RidWithAttributeArray *rids;
2535 NTSTATUS status, result;
2536 struct dcerpc_binding_handle *b;
2538 if (!str1 || !str2 || !UserName || !p) {
2543 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2548 /* check it's a supported varient */
2550 if ( strcmp(str1,"zWrLeh") != 0 )
2555 level_string = "B21";
2561 if (strcmp(level_string,str2) != 0)
2564 *rdata_len = mdrcnt + 1024;
2565 *rdata = smb_realloc_limit(*rdata,*rdata_len);
2570 SSVAL(*rparam,0,NERR_Success);
2571 SSVAL(*rparam,2,0); /* converter word */
2574 endp = *rdata + *rdata_len;
2576 status = rpc_pipe_open_interface(
2577 talloc_tos(), &ndr_table_samr.syntax_id,
2578 conn->session_info, conn->sconn->remote_address,
2579 conn->sconn->msg_ctx, &samr_pipe);
2580 if (!NT_STATUS_IS_OK(status)) {
2581 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2582 nt_errstr(status)));
2586 b = samr_pipe->binding_handle;
2588 status = dcerpc_samr_Connect2(b, talloc_tos(), lp_netbios_name(),
2589 SAMR_ACCESS_LOOKUP_DOMAIN, &samr_handle,
2591 if (!NT_STATUS_IS_OK(status)) {
2592 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2593 nt_errstr(status)));
2596 if (!NT_STATUS_IS_OK(result)) {
2597 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2598 nt_errstr(result)));
2602 status = dcerpc_samr_OpenDomain(b, talloc_tos(), &samr_handle,
2603 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
2604 get_global_sam_sid(), &domain_handle,
2606 if (!NT_STATUS_IS_OK(status)) {
2607 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2608 nt_errstr(status)));
2611 if (!NT_STATUS_IS_OK(result)) {
2612 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2613 nt_errstr(result)));
2617 name.string = UserName;
2619 status = dcerpc_samr_LookupNames(b, talloc_tos(),
2620 &domain_handle, 1, &name,
2623 if (!NT_STATUS_IS_OK(status)) {
2624 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2625 nt_errstr(status)));
2628 if (!NT_STATUS_IS_OK(result)) {
2629 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2630 nt_errstr(result)));
2633 if (rid.count != 1) {
2634 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
2637 if (type.count != 1) {
2638 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
2642 if (type.ids[0] != SID_NAME_USER) {
2643 DEBUG(10, ("%s is a %s, not a user\n", UserName,
2644 sid_type_lookup(type.ids[0])));
2648 status = dcerpc_samr_OpenUser(b, talloc_tos(),
2650 SAMR_USER_ACCESS_GET_GROUPS,
2651 rid.ids[0], &user_handle,
2653 if (!NT_STATUS_IS_OK(status)) {
2654 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2655 nt_errstr(status)));
2658 if (!NT_STATUS_IS_OK(result)) {
2659 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2660 nt_errstr(result)));
2664 status = dcerpc_samr_GetGroupsForUser(b, talloc_tos(),
2665 &user_handle, &rids,
2667 if (!NT_STATUS_IS_OK(status)) {
2668 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2669 nt_errstr(status)));
2672 if (!NT_STATUS_IS_OK(result)) {
2673 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2674 nt_errstr(result)));
2678 for (i=0; i<rids->count; i++) {
2680 status = dcerpc_samr_LookupRids(b, talloc_tos(),
2682 1, &rids->rids[i].rid,
2685 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result) && (names.count == 1)) {
2686 strlcpy(p, names.names[0].string, PTR_DIFF(endp,p));
2692 *rdata_len = PTR_DIFF(p,*rdata);
2694 SSVAL(*rparam,4,count); /* is this right?? */
2695 SSVAL(*rparam,6,count); /* is this right?? */
2700 dcerpc_samr_Close(b, talloc_tos(), &user_handle, &result);
2702 dcerpc_samr_Close(b, talloc_tos(), &domain_handle, &result);
2704 dcerpc_samr_Close(b, talloc_tos(), &samr_handle, &result);
2709 /*******************************************************************
2711 ******************************************************************/
2713 static bool api_RNetUserEnum(struct smbd_server_connection *sconn,
2714 connection_struct *conn, uint64_t vuid,
2715 char *param, int tpscnt,
2716 char *data, int tdscnt,
2717 int mdrcnt,int mprcnt,
2718 char **rdata,char **rparam,
2719 int *rdata_len,int *rparam_len)
2724 int i, resume_context, cli_buf_size;
2725 uint32_t resume_handle;
2727 struct rpc_pipe_client *samr_pipe;
2728 struct policy_handle samr_handle, domain_handle;
2729 NTSTATUS status, result;
2731 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2732 char *str2 = skip_string(param,tpscnt,str1);
2733 char *p = skip_string(param,tpscnt,str2);
2736 struct dcerpc_binding_handle *b;
2738 if (!str1 || !str2 || !p) {
2742 if (strcmp(str1,"WrLeh") != 0)
2745 * W-> resume context (number of users to skip)
2746 * r -> return parameter pointer to receive buffer
2747 * L -> length of receive buffer
2748 * e -> return parameter number of entries
2749 * h -> return parameter total number of users
2752 resume_context = get_safe_SVAL(param,tpscnt,p,0,-1);
2753 cli_buf_size= get_safe_SVAL(param,tpscnt,p,2,0);
2754 DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n",
2755 resume_context, cli_buf_size));
2758 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2763 /* check it's a supported varient */
2764 if (strcmp("B21",str2) != 0)
2767 *rdata_len = cli_buf_size;
2768 *rdata = smb_realloc_limit(*rdata,*rdata_len);
2774 endp = *rdata + *rdata_len;
2776 status = rpc_pipe_open_interface(
2777 talloc_tos(), &ndr_table_samr.syntax_id,
2778 conn->session_info, conn->sconn->remote_address,
2779 conn->sconn->msg_ctx, &samr_pipe);
2780 if (!NT_STATUS_IS_OK(status)) {
2781 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2782 nt_errstr(status)));
2786 b = samr_pipe->binding_handle;
2788 status = dcerpc_samr_Connect2(b, talloc_tos(), lp_netbios_name(),
2789 SAMR_ACCESS_LOOKUP_DOMAIN, &samr_handle,
2791 if (!NT_STATUS_IS_OK(status)) {
2792 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2793 nt_errstr(status)));
2796 if (!NT_STATUS_IS_OK(result)) {
2797 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2798 nt_errstr(result)));
2802 status = dcerpc_samr_OpenDomain(b, talloc_tos(), &samr_handle,
2803 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS,
2804 get_global_sam_sid(), &domain_handle,
2806 if (!NT_STATUS_IS_OK(status)) {
2807 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2808 nt_errstr(status)));
2809 dcerpc_samr_Close(b, talloc_tos(), &samr_handle, &result);
2812 if (!NT_STATUS_IS_OK(result)) {
2813 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2814 nt_errstr(result)));
2815 dcerpc_samr_Close(b, talloc_tos(), &samr_handle, &result);
2819 errflags=NERR_Success;
2824 struct samr_SamArray *sam_entries;
2825 uint32_t num_entries;
2827 status = dcerpc_samr_EnumDomainUsers(b, talloc_tos(),
2834 if (!NT_STATUS_IS_OK(status)) {
2835 DEBUG(10, ("dcerpc_samr_EnumDomainUsers returned "
2836 "%s\n", nt_errstr(status)));
2839 if (!NT_STATUS_IS_OK(result)) {
2840 DEBUG(10, ("dcerpc_samr_EnumDomainUsers returned "
2841 "%s\n", nt_errstr(result)));
2845 if (num_entries == 0) {
2846 DEBUG(10, ("dcerpc_samr_EnumDomainUsers returned "
2847 "no entries -- done\n"));
2851 for (i=0; i<num_entries; i++) {
2854 name = sam_entries->entries[i].name.string;
2856 if(((PTR_DIFF(p,*rdata)+21)<=*rdata_len)
2857 &&(strlen(name)<=21)) {
2858 strlcpy(p,name,PTR_DIFF(endp,p));
2859 DEBUG(10,("api_RNetUserEnum:adding entry %d "
2860 "username %s\n",count_sent,p));
2864 /* set overflow error */
2865 DEBUG(10,("api_RNetUserEnum:overflow on entry %d "
2866 "username %s\n",count_sent,name));
2872 if (errflags != NERR_Success) {
2876 TALLOC_FREE(sam_entries);
2879 dcerpc_samr_Close(b, talloc_tos(), &domain_handle, &result);
2880 dcerpc_samr_Close(b, talloc_tos(), &samr_handle, &result);
2882 *rdata_len = PTR_DIFF(p,*rdata);
2884 SSVAL(*rparam,0,errflags);
2885 SSVAL(*rparam,2,0); /* converter word */
2886 SSVAL(*rparam,4,count_sent); /* is this right?? */
2887 SSVAL(*rparam,6,num_users); /* is this right?? */
2892 /****************************************************************************
2893 Get the time of day info.
2894 ****************************************************************************/
2896 static bool api_NetRemoteTOD(struct smbd_server_connection *sconn,
2897 connection_struct *conn,uint64_t vuid,
2898 char *param, int tpscnt,
2899 char *data, int tdscnt,
2900 int mdrcnt,int mprcnt,
2901 char **rdata,char **rparam,
2902 int *rdata_len,int *rparam_len)
2905 time_t unixdate = time(NULL);
2909 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2915 *rdata = smb_realloc_limit(*rdata,*rdata_len);
2920 SSVAL(*rparam,0,NERR_Success);
2921 SSVAL(*rparam,2,0); /* converter word */
2925 srv_put_dos_date3(p,0,unixdate); /* this is the time that is looked at
2926 by NT in a "net time" operation,
2927 it seems to ignore the one below */
2929 /* the client expects to get localtime, not GMT, in this bit
2930 (I think, this needs testing) */
2931 t = localtime(&unixdate);
2936 SIVAL(p,4,0); /* msecs ? */
2937 SCVAL(p,8,t->tm_hour);
2938 SCVAL(p,9,t->tm_min);
2939 SCVAL(p,10,t->tm_sec);
2940 SCVAL(p,11,0); /* hundredths of seconds */
2941 SSVALS(p,12,get_time_zone(unixdate)/60); /* timezone in minutes from GMT */
2942 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
2943 SCVAL(p,16,t->tm_mday);
2944 SCVAL(p,17,t->tm_mon + 1);
2945 SSVAL(p,18,1900+t->tm_year);
2946 SCVAL(p,20,t->tm_wday);
2951 /****************************************************************************
2952 Set the user password (SamOEM version - gets plaintext).
2953 ****************************************************************************/
2955 static bool api_SamOEMChangePassword(struct smbd_server_connection *sconn,
2956 connection_struct *conn,uint64_t vuid,
2957 char *param, int tpscnt,
2958 char *data, int tdscnt,
2959 int mdrcnt,int mprcnt,
2960 char **rdata,char **rparam,
2961 int *rdata_len,int *rparam_len)
2964 char *p = get_safe_str_ptr(param,tpscnt,param,2);
2966 TALLOC_CTX *mem_ctx = talloc_tos();
2967 NTSTATUS status, result;
2968 struct rpc_pipe_client *cli = NULL;
2969 struct lsa_AsciiString server, account;
2970 struct samr_CryptPassword password;
2971 struct samr_Password hash;
2972 int errcode = NERR_badpass;
2974 struct dcerpc_binding_handle *b;
2977 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2987 SSVAL(*rparam,0,NERR_badpass);
2990 * Check the parameter definition is correct.
2993 /* Do we have a string ? */
2994 if (skip_string(param,tpscnt,p) == 0) {
2997 if(!strequal(p, "zsT")) {
2998 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", p));
3001 p = skip_string(param, tpscnt, p);
3006 /* Do we have a string ? */
3007 if (skip_string(param,tpscnt,p) == 0) {
3010 if(!strequal(p, "B516B16")) {
3011 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p));
3014 p = skip_string(param,tpscnt,p);
3018 /* Do we have a string ? */
3019 if (skip_string(param,tpscnt,p) == 0) {
3022 p += pull_ascii_fstring(user,p);
3024 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user));
3026 if (tdscnt != 532) {
3027 errcode = W_ERROR_V(WERR_INVALID_PARAM);
3031 bufsize = get_safe_SVAL(param,tpscnt,p,0,-1);
3032 if (bufsize != 532) {
3033 errcode = W_ERROR_V(WERR_INVALID_PARAM);
3037 memcpy(password.data, data, 516);
3038 memcpy(hash.hash, data+516, 16);
3040 status = rpc_pipe_open_interface(mem_ctx, &ndr_table_samr.syntax_id,
3042 conn->sconn->remote_address,
3043 conn->sconn->msg_ctx,
3045 if (!NT_STATUS_IS_OK(status)) {
3046 DEBUG(0,("api_SamOEMChangePassword: could not connect to samr: %s\n",
3047 nt_errstr(status)));
3048 errcode = W_ERROR_V(ntstatus_to_werror(status));
3052 b = cli->binding_handle;
3054 init_lsa_AsciiString(&server, lp_netbios_name());
3055 init_lsa_AsciiString(&account, user);
3057 status = dcerpc_samr_OemChangePasswordUser2(b, mem_ctx,
3063 if (!NT_STATUS_IS_OK(status)) {
3064 errcode = W_ERROR_V(ntstatus_to_werror(status));
3067 if (!NT_STATUS_IS_OK(result)) {
3068 errcode = W_ERROR_V(ntstatus_to_werror(result));
3072 errcode = NERR_Success;
3074 SSVAL(*rparam,0,errcode);
3075 SSVAL(*rparam,2,0); /* converter word */
3080 /****************************************************************************
3083 ****************************************************************************/
3085 static bool api_RDosPrintJobDel(struct smbd_server_connection *sconn,
3086 connection_struct *conn,uint64_t vuid,
3087 char *param, int tpscnt,
3088 char *data, int tdscnt,
3089 int mdrcnt,int mprcnt,
3090 char **rdata,char **rparam,
3091 int *rdata_len,int *rparam_len)
3093 int function = get_safe_SVAL(param,tpscnt,param,0,0);
3094 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3095 char *str2 = skip_string(param,tpscnt,str1);
3096 char *p = skip_string(param,tpscnt,str2);
3100 WERROR werr = WERR_OK;
3102 TALLOC_CTX *mem_ctx = talloc_tos();
3104 struct rpc_pipe_client *cli = NULL;
3105 struct dcerpc_binding_handle *b = NULL;
3106 struct policy_handle handle;
3107 struct spoolss_DevmodeContainer devmode_ctr;
3108 enum spoolss_JobControl command;
3110 if (!str1 || !str2 || !p) {
3114 * We use 1 here not 2 as we're checking
3115 * the last byte we want to access is safe.
3117 if (!is_offset_safe(param,tpscnt,p,1)) {
3120 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
3123 /* check it's a supported varient */
3124 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
3128 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3134 ZERO_STRUCT(handle);
3136 status = rpc_pipe_open_interface(conn,
3137 &ndr_table_spoolss.syntax_id,
3139 conn->sconn->remote_address,
3140 conn->sconn->msg_ctx,
3142 if (!NT_STATUS_IS_OK(status)) {
3143 DEBUG(0,("api_RDosPrintJobDel: could not connect to spoolss: %s\n",
3144 nt_errstr(status)));
3145 errcode = W_ERROR_V(ntstatus_to_werror(status));
3148 b = cli->binding_handle;
3150 ZERO_STRUCT(devmode_ctr);
3152 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
3156 JOB_ACCESS_ADMINISTER,
3159 if (!NT_STATUS_IS_OK(status)) {
3160 errcode = W_ERROR_V(ntstatus_to_werror(status));
3163 if (!W_ERROR_IS_OK(werr)) {
3164 errcode = W_ERROR_V(werr);
3168 /* FIXME: formerly NERR_JobNotFound was returned if job did not exist
3169 * and NERR_DestNotFound if share did not exist */
3171 errcode = NERR_Success;
3174 case 81: /* delete */
3175 command = SPOOLSS_JOB_CONTROL_DELETE;
3177 case 82: /* pause */
3178 command = SPOOLSS_JOB_CONTROL_PAUSE;
3180 case 83: /* resume */
3181 command = SPOOLSS_JOB_CONTROL_RESUME;
3184 errcode = NERR_notsupported;
3188 status = dcerpc_spoolss_SetJob(b, mem_ctx,
3191 NULL, /* unique ptr ctr */
3194 if (!NT_STATUS_IS_OK(status)) {
3195 errcode = W_ERROR_V(ntstatus_to_werror(status));
3198 if (!W_ERROR_IS_OK(werr)) {
3199 errcode = W_ERROR_V(werr);
3204 if (b && is_valid_policy_hnd(&handle)) {
3205 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
3208 SSVAL(*rparam,0,errcode);
3209 SSVAL(*rparam,2,0); /* converter word */
3214 /****************************************************************************
3215 Purge a print queue - or pause or resume it.
3216 ****************************************************************************/
3218 static bool api_WPrintQueueCtrl(struct smbd_server_connection *sconn,
3219 connection_struct *conn,uint64_t vuid,
3220 char *param, int tpscnt,
3221 char *data, int tdscnt,
3222 int mdrcnt,int mprcnt,
3223 char **rdata,char **rparam,
3224 int *rdata_len,int *rparam_len)
3226 int function = get_safe_SVAL(param,tpscnt,param,0,0);
3227 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3228 char *str2 = skip_string(param,tpscnt,str1);
3229 char *QueueName = skip_string(param,tpscnt,str2);
3230 int errcode = NERR_notsupported;
3231 WERROR werr = WERR_OK;
3234 TALLOC_CTX *mem_ctx = talloc_tos();
3235 struct rpc_pipe_client *cli = NULL;
3236 struct dcerpc_binding_handle *b = NULL;
3237 struct policy_handle handle;
3238 struct spoolss_SetPrinterInfoCtr info_ctr;
3239 struct spoolss_DevmodeContainer devmode_ctr;
3240 struct sec_desc_buf secdesc_ctr;
3241 enum spoolss_PrinterControl command;
3243 if (!str1 || !str2 || !QueueName) {
3247 /* check it's a supported varient */
3248 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
3252 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3258 if (skip_string(param,tpscnt,QueueName) == NULL) {
3262 ZERO_STRUCT(handle);
3264 status = rpc_pipe_open_interface(conn,
3265 &ndr_table_spoolss.syntax_id,
3267 conn->sconn->remote_address,
3268 conn->sconn->msg_ctx,
3270 if (!NT_STATUS_IS_OK(status)) {
3271 DEBUG(0,("api_WPrintQueueCtrl: could not connect to spoolss: %s\n",
3272 nt_errstr(status)));
3273 errcode = W_ERROR_V(ntstatus_to_werror(status));
3276 b = cli->binding_handle;
3278 ZERO_STRUCT(devmode_ctr);
3280 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
3284 PRINTER_ACCESS_ADMINISTER,
3287 if (!NT_STATUS_IS_OK(status)) {
3288 errcode = W_ERROR_V(ntstatus_to_werror(status));
3291 if (!W_ERROR_IS_OK(werr)) {
3292 errcode = W_ERROR_V(werr);
3297 case 74: /* Pause queue */
3298 command = SPOOLSS_PRINTER_CONTROL_PAUSE;
3300 case 75: /* Resume queue */
3301 command = SPOOLSS_PRINTER_CONTROL_RESUME;
3303 case 103: /* Purge */
3304 command = SPOOLSS_PRINTER_CONTROL_PURGE;
3307 werr = WERR_NOT_SUPPORTED;
3311 if (!W_ERROR_IS_OK(werr)) {
3312 errcode = W_ERROR_V(werr);
3316 ZERO_STRUCT(info_ctr);
3317 ZERO_STRUCT(secdesc_ctr);
3319 status = dcerpc_spoolss_SetPrinter(b, mem_ctx,
3326 if (!NT_STATUS_IS_OK(status)) {
3327 errcode = W_ERROR_V(ntstatus_to_werror(status));
3330 if (!W_ERROR_IS_OK(werr)) {
3331 errcode = W_ERROR_V(werr);
3335 errcode = W_ERROR_V(werr);
3339 if (b && is_valid_policy_hnd(&handle)) {
3340 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
3343 SSVAL(*rparam,0,errcode);
3344 SSVAL(*rparam,2,0); /* converter word */
3349 /****************************************************************************
3350 set the property of a print job (undocumented?)
3351 ? function = 0xb -> set name of print job
3352 ? function = 0x6 -> move print job up/down
3353 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
3354 or <WWsTP> <WB21BB16B10zWWzDDz>
3355 ****************************************************************************/
3357 static int check_printjob_info(struct pack_desc* desc,
3358 int uLevel, char* id)
3360 desc->subformat = NULL;
3362 case 0: desc->format = "W"; break;
3363 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
3364 case 2: desc->format = "WWzWWDDzz"; break;
3365 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
3366 case 4: desc->format = "WWzWWDDzzzzzDDDDDDD"; break;
3368 DEBUG(0,("check_printjob_info: invalid level %d\n",
3372 if (id == NULL || strcmp(desc->format,id) != 0) {
3373 DEBUG(0,("check_printjob_info: invalid format %s\n",
3374 id ? id : "<NULL>" ));
3380 static bool api_PrintJobInfo(struct smbd_server_connection *sconn,
3381 connection_struct *conn, uint64_t vuid,
3382 char *param, int tpscnt,
3383 char *data, int tdscnt,
3384 int mdrcnt,int mprcnt,
3385 char **rdata,char **rparam,
3386 int *rdata_len,int *rparam_len)
3388 struct pack_desc desc;
3389 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3390 char *str2 = skip_string(param,tpscnt,str1);
3391 char *p = skip_string(param,tpscnt,str2);
3394 int uLevel = get_safe_SVAL(param,tpscnt,p,2,-1);
3395 int function = get_safe_SVAL(param,tpscnt,p,4,-1);
3398 TALLOC_CTX *mem_ctx = talloc_tos();
3401 struct rpc_pipe_client *cli = NULL;
3402 struct dcerpc_binding_handle *b = NULL;
3403 struct policy_handle handle;
3404 struct spoolss_DevmodeContainer devmode_ctr;
3405 struct spoolss_JobInfoContainer ctr;
3406 union spoolss_JobInfo info;
3407 struct spoolss_SetJobInfo1 info1;
3409 if (!str1 || !str2 || !p) {
3413 * We use 1 here not 2 as we're checking
3414 * the last byte we want to access is safe.
3416 if (!is_offset_safe(param,tpscnt,p,1)) {
3419 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
3422 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3429 /* check it's a supported varient */
3430 if ((strcmp(str1,"WWsTP")) ||
3431 (!check_printjob_info(&desc,uLevel,str2)))
3434 errcode = NERR_notsupported;
3438 /* change print job name, data gives the name */
3444 ZERO_STRUCT(handle);
3446 status = rpc_pipe_open_interface(conn,
3447 &ndr_table_spoolss.syntax_id,
3449 conn->sconn->remote_address,
3450 conn->sconn->msg_ctx,
3452 if (!NT_STATUS_IS_OK(status)) {
3453 DEBUG(0,("api_PrintJobInfo: could not connect to spoolss: %s\n",
3454 nt_errstr(status)));
3455 errcode = W_ERROR_V(ntstatus_to_werror(status));
3458 b = cli->binding_handle;
3460 ZERO_STRUCT(devmode_ctr);
3462 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
3469 if (!NT_STATUS_IS_OK(status)) {
3470 errcode = W_ERROR_V(ntstatus_to_werror(status));
3473 if (!W_ERROR_IS_OK(werr)) {
3474 errcode = W_ERROR_V(werr);
3478 werr = rpccli_spoolss_getjob(cli, mem_ctx,
3484 if (!W_ERROR_IS_OK(werr)) {
3485 errcode = W_ERROR_V(werr);
3491 info1.job_id = info.info1.job_id;
3492 info1.printer_name = info.info1.printer_name;
3493 info1.user_name = info.info1.user_name;
3494 info1.document_name = data;
3495 info1.data_type = info.info1.data_type;
3496 info1.text_status = info.info1.text_status;
3497 info1.status = info.info1.status;
3498 info1.priority = info.info1.priority;
3499 info1.position = info.info1.position;
3500 info1.total_pages = info.info1.total_pages;
3501 info1.pages_printed = info.info1.pages_printed;
3502 info1.submitted = info.info1.submitted;
3505 ctr.info.info1 = &info1;
3507 status = dcerpc_spoolss_SetJob(b, mem_ctx,
3513 if (!NT_STATUS_IS_OK(status)) {
3514 errcode = W_ERROR_V(ntstatus_to_werror(status));
3517 if (!W_ERROR_IS_OK(werr)) {
3518 errcode = W_ERROR_V(werr);
3522 errcode = NERR_Success;
3525 if (b && is_valid_policy_hnd(&handle)) {
3526 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
3529 SSVALS(*rparam,0,errcode);
3530 SSVAL(*rparam,2,0); /* converter word */
3536 /****************************************************************************
3537 Get info about the server.
3538 ****************************************************************************/
3540 static bool api_RNetServerGetInfo(struct smbd_server_connection *sconn,
3541 connection_struct *conn,uint64_t vuid,
3542 char *param, int tpscnt,
3543 char *data, int tdscnt,
3544 int mdrcnt,int mprcnt,
3545 char **rdata,char **rparam,
3546 int *rdata_len,int *rparam_len)
3548 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3549 char *str2 = skip_string(param,tpscnt,str1);
3550 char *p = skip_string(param,tpscnt,str2);
3551 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
3557 TALLOC_CTX *mem_ctx = talloc_tos();
3558 struct rpc_pipe_client *cli = NULL;
3559 union srvsvc_NetSrvInfo info;
3561 struct dcerpc_binding_handle *b;
3563 if (!str1 || !str2 || !p) {
3567 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
3569 /* check it's a supported varient */
3570 if (!prefix_ok(str1,"WrLh")) {
3576 if (strcmp(str2,"B16") != 0) {
3582 if (strcmp(str2,"B16BBDz") != 0) {
3588 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")!= 0) {
3594 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz") != 0) {
3600 if (strcmp(str2,"DN") != 0) {
3606 if (strcmp(str2,"B16BBDzWWzzz") != 0) {
3615 *rdata_len = mdrcnt;
3616 *rdata = smb_realloc_limit(*rdata,*rdata_len);
3622 p2 = p + struct_len;
3624 status = rpc_pipe_open_interface(mem_ctx, &ndr_table_srvsvc.syntax_id,
3626 conn->sconn->remote_address,
3627 conn->sconn->msg_ctx,
3629 if (!NT_STATUS_IS_OK(status)) {
3630 DEBUG(0,("api_RNetServerGetInfo: could not connect to srvsvc: %s\n",
3631 nt_errstr(status)));
3632 errcode = W_ERROR_V(ntstatus_to_werror(status));
3636 b = cli->binding_handle;
3638 status = dcerpc_srvsvc_NetSrvGetInfo(b, mem_ctx,
3643 if (!NT_STATUS_IS_OK(status)) {
3644 errcode = W_ERROR_V(ntstatus_to_werror(status));
3647 if (!W_ERROR_IS_OK(werr)) {
3648 errcode = W_ERROR_V(werr);
3652 if (info.info101 == NULL) {
3653 errcode = W_ERROR_V(WERR_INVALID_PARAM);
3658 srvstr_push(NULL, 0, p, info.info101->server_name, 16,
3659 STR_ASCII|STR_UPPER|STR_TERMINATE);
3663 SCVAL(p,0,info.info101->version_major);
3664 SCVAL(p,1,info.info101->version_minor);
3665 SIVAL(p,2,info.info101->server_type);
3667 if (mdrcnt == struct_len) {
3670 SIVAL(p,6,PTR_DIFF(p2,*rdata));
3671 if (mdrcnt - struct_len <= 0) {
3675 info.info101->comment,
3676 MIN(mdrcnt - struct_len,
3677 MAX_SERVER_STRING_LENGTH),
3679 p2 = skip_string(*rdata,*rdata_len,p2);
3687 return False; /* not yet implemented */
3690 errcode = NERR_Success;
3694 *rdata_len = PTR_DIFF(p2,*rdata);
3697 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3701 SSVAL(*rparam,0,errcode);
3702 SSVAL(*rparam,2,0); /* converter word */
3703 SSVAL(*rparam,4,*rdata_len);
3708 /****************************************************************************
3709 Get info about the server.
3710 ****************************************************************************/
3712 static bool api_NetWkstaGetInfo(struct smbd_server_connection *sconn,
3713 connection_struct *conn,uint64_t vuid,
3714 char *param, int tpscnt,
3715 char *data, int tdscnt,
3716 int mdrcnt,int mprcnt,
3717 char **rdata,char **rparam,
3718 int *rdata_len,int *rparam_len)
3720 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3721 char *str2 = skip_string(param,tpscnt,str1);
3722 char *p = skip_string(param,tpscnt,str2);
3725 int level = get_safe_SVAL(param,tpscnt,p,0,-1);
3727 if (!str1 || !str2 || !p) {
3731 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
3734 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3739 /* check it's a supported varient */
3740 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz"))) {
3744 *rdata_len = mdrcnt + 1024;
3745 *rdata = smb_realloc_limit(*rdata,*rdata_len);
3750 SSVAL(*rparam,0,NERR_Success);
3751 SSVAL(*rparam,2,0); /* converter word */
3754 endp = *rdata + *rdata_len;
3756 p2 = get_safe_ptr(*rdata,*rdata_len,p,22);
3761 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
3762 strlcpy(p2,get_local_machine_name(),PTR_DIFF(endp,p2));
3763 if (!strupper_m(p2)) {
3766 p2 = skip_string(*rdata,*rdata_len,p2);
3772 SIVAL(p,0,PTR_DIFF(p2,*rdata));
3773 strlcpy(p2,conn->session_info->unix_info->sanitized_username,PTR_DIFF(endp,p2));
3774 p2 = skip_string(*rdata,*rdata_len,p2);
3780 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
3781 strlcpy(p2,lp_workgroup(),PTR_DIFF(endp,p2));
3782 if (!strupper_m(p2)) {
3785 p2 = skip_string(*rdata,*rdata_len,p2);
3791 SCVAL(p,0,SAMBA_MAJOR_NBT_ANNOUNCE_VERSION); /* system version - e.g 4 in 4.1 */
3792 SCVAL(p,1,SAMBA_MINOR_NBT_ANNOUNCE_VERSION); /* system version - e.g .1 in 4.1 */
3795 SIVAL(p,0,PTR_DIFF(p2,*rdata));
3796 strlcpy(p2,lp_workgroup(),PTR_DIFF(endp,p2)); /* don't know. login domain?? */
3797 p2 = skip_string(*rdata,*rdata_len,p2);
3803 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
3804 strlcpy(p2,"",PTR_DIFF(endp,p2));
3805 p2 = skip_string(*rdata,*rdata_len,p2);
3811 *rdata_len = PTR_DIFF(p2,*rdata);
3813 SSVAL(*rparam,4,*rdata_len);
3818 /****************************************************************************
3819 get info about a user
3821 struct user_info_11 {
3822 char usri11_name[21]; 0-20
3824 char *usri11_comment; 22-25
3825 char *usri11_usr_comment; 26-29
3826 unsigned short usri11_priv; 30-31
3827 unsigned long usri11_auth_flags; 32-35
3828 long usri11_password_age; 36-39
3829 char *usri11_homedir; 40-43
3830 char *usri11_parms; 44-47
3831 long usri11_last_logon; 48-51
3832 long usri11_last_logoff; 52-55
3833 unsigned short usri11_bad_pw_count; 56-57
3834 unsigned short usri11_num_logons; 58-59
3835 char *usri11_logon_server; 60-63
3836 unsigned short usri11_country_code; 64-65
3837 char *usri11_workstations; 66-69
3838 unsigned long usri11_max_storage; 70-73
3839 unsigned short usri11_units_per_week; 74-75
3840 unsigned char *usri11_logon_hours; 76-79
3841 unsigned short usri11_code_page; 80-81
3846 usri11_name specifies the user name for which information is retrieved
3848 usri11_pad aligns the next data structure element to a word boundary
3850 usri11_comment is a null terminated ASCII comment
3852 usri11_user_comment is a null terminated ASCII comment about the user
3854 usri11_priv specifies the level of the privilege assigned to the user.
3855 The possible values are:
3857 Name Value Description
3858 USER_PRIV_GUEST 0 Guest privilege
3859 USER_PRIV_USER 1 User privilege
3860 USER_PRV_ADMIN 2 Administrator privilege
3862 usri11_auth_flags specifies the account operator privileges. The
3863 possible values are:
3865 Name Value Description
3866 AF_OP_PRINT 0 Print operator
3869 Leach, Naik [Page 28]
3873 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
3876 AF_OP_COMM 1 Communications operator
3877 AF_OP_SERVER 2 Server operator
3878 AF_OP_ACCOUNTS 3 Accounts operator
3881 usri11_password_age specifies how many seconds have elapsed since the
3882 password was last changed.
3884 usri11_home_dir points to a null terminated ASCII string that contains
3885 the path name of the user's home directory.
3887 usri11_parms points to a null terminated ASCII string that is set
3888 aside for use by applications.
3890 usri11_last_logon specifies the time when the user last logged on.
3891 This value is stored as the number of seconds elapsed since
3892 00:00:00, January 1, 1970.
3894 usri11_last_logoff specifies the time when the user last logged off.
3895 This value is stored as the number of seconds elapsed since
3896 00:00:00, January 1, 1970. A value of 0 means the last logoff
3899 usri11_bad_pw_count specifies the number of incorrect passwords
3900 entered since the last successful logon.
3902 usri11_log1_num_logons specifies the number of times this user has
3903 logged on. A value of -1 means the number of logons is unknown.
3905 usri11_logon_server points to a null terminated ASCII string that
3906 contains the name of the server to which logon requests are sent.
3907 A null string indicates logon requests should be sent to the
3910 usri11_country_code specifies the country code for the user's language
3913 usri11_workstations points to a null terminated ASCII string that
3914 contains the names of workstations the user may log on from.
3915 There may be up to 8 workstations, with the names separated by
3916 commas. A null strings indicates there are no restrictions.
3918 usri11_max_storage specifies the maximum amount of disk space the user
3919 can occupy. A value of 0xffffffff indicates there are no
3922 usri11_units_per_week specifies the equal number of time units into
3923 which a week is divided. This value must be equal to 168.
3925 usri11_logon_hours points to a 21 byte (168 bits) string that
3926 specifies the time during which the user can log on. Each bit
3927 represents one unique hour in a week. The first bit (bit 0, word
3928 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
3932 Leach, Naik [Page 29]
3936 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
3939 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
3940 are no restrictions.
3942 usri11_code_page specifies the code page for the user's language of
3945 All of the pointers in this data structure need to be treated
3946 specially. The pointer is a 32 bit pointer. The higher 16 bits need
3947 to be ignored. The converter word returned in the parameters section
3948 needs to be subtracted from the lower 16 bits to calculate an offset
3949 into the return buffer where this ASCII string resides.
3951 There is no auxiliary data in the response.
3953 ****************************************************************************/
3955 #define usri11_name 0
3956 #define usri11_pad 21
3957 #define usri11_comment 22
3958 #define usri11_usr_comment 26
3959 #define usri11_full_name 30
3960 #define usri11_priv 34
3961 #define usri11_auth_flags 36
3962 #define usri11_password_age 40
3963 #define usri11_homedir 44
3964 #define usri11_parms 48
3965 #define usri11_last_logon 52
3966 #define usri11_last_logoff 56
3967 #define usri11_bad_pw_count 60
3968 #define usri11_num_logons 62
3969 #define usri11_logon_server 64
3970 #define usri11_country_code 68
3971 #define usri11_workstations 70
3972 #define usri11_max_storage 74
3973 #define usri11_units_per_week 78
3974 #define usri11_logon_hours 80
3975 #define usri11_code_page 84
3976 #define usri11_end 86
3978 static bool api_RNetUserGetInfo(struct smbd_server_connection *sconn,
3979 connection_struct *conn, uint64_t vuid,
3980 char *param, int tpscnt,
3981 char *data, int tdscnt,
3982 int mdrcnt,int mprcnt,
3983 char **rdata,char **rparam,
3984 int *rdata_len,int *rparam_len)
3986 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3987 char *str2 = skip_string(param,tpscnt,str1);
3988 char *UserName = skip_string(param,tpscnt,str2);
3989 char *p = skip_string(param,tpscnt,UserName);
3990 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
3993 const char *level_string;
3995 TALLOC_CTX *mem_ctx = talloc_tos();
3996 NTSTATUS status, result;
3997 struct rpc_pipe_client *cli = NULL;
3998 struct policy_handle connect_handle, domain_handle, user_handle;
3999 struct lsa_String domain_name;
4000 struct dom_sid2 *domain_sid;
4001 struct lsa_String names;
4002 struct samr_Ids rids;
4003 struct samr_Ids types;
4004 int errcode = W_ERROR_V(WERR_USER_NOT_FOUND);
4006 union samr_UserInfo *info;
4007 struct dcerpc_binding_handle *b = NULL;
4009 if (!str1 || !str2 || !UserName || !p) {
4014 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4019 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
4021 /* check it's a supported variant */
4022 if (strcmp(str1,"zWrLh") != 0) {
4026 case 0: level_string = "B21"; break;
4027 case 1: level_string = "B21BB16DWzzWz"; break;
4028 case 2: level_string = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
4029 case 10: level_string = "B21Bzzz"; break;
4030 case 11: level_string = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
4031 default: return False;
4034 if (strcmp(level_string,str2) != 0) {
4038 *rdata_len = mdrcnt + 1024;
4039 *rdata = smb_realloc_limit(*rdata,*rdata_len);
4045 endp = *rdata + *rdata_len;
4046 p2 = get_safe_ptr(*rdata,*rdata_len,p,usri11_end);
4051 ZERO_STRUCT(connect_handle);
4052 ZERO_STRUCT(domain_handle);
4053 ZERO_STRUCT(user_handle);
4055 status = rpc_pipe_open_interface(mem_ctx, &ndr_table_samr.syntax_id,
4057 conn->sconn->remote_address,
4058 conn->sconn->msg_ctx,
4060 if (!NT_STATUS_IS_OK(status)) {
4061 DEBUG(0,("api_RNetUserGetInfo: could not connect to samr: %s\n",
4062 nt_errstr(status)));
4063 errcode = W_ERROR_V(ntstatus_to_werror(status));
4067 b = cli->binding_handle;
4069 status = dcerpc_samr_Connect2(b, mem_ctx,
4071 SAMR_ACCESS_CONNECT_TO_SERVER |
4072 SAMR_ACCESS_ENUM_DOMAINS |
4073 SAMR_ACCESS_LOOKUP_DOMAIN,
4076 if (!NT_STATUS_IS_OK(status)) {
4077 errcode = W_ERROR_V(ntstatus_to_werror(status));
4080 if (!NT_STATUS_IS_OK(result)) {
4081 errcode = W_ERROR_V(ntstatus_to_werror(result));
4085 init_lsa_String(&domain_name, get_global_sam_name());
4087 status = dcerpc_samr_LookupDomain(b, mem_ctx,
4092 if (!NT_STATUS_IS_OK(status)) {
4093 errcode = W_ERROR_V(ntstatus_to_werror(status));
4096 if (!NT_STATUS_IS_OK(result)) {
4097 errcode = W_ERROR_V(ntstatus_to_werror(result));
4101 status = dcerpc_samr_OpenDomain(b, mem_ctx,
4103 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
4107 if (!NT_STATUS_IS_OK(status)) {
4108 errcode = W_ERROR_V(ntstatus_to_werror(status));
4111 if (!NT_STATUS_IS_OK(result)) {
4112 errcode = W_ERROR_V(ntstatus_to_werror(result));
4116 init_lsa_String(&names, UserName);
4118 status = dcerpc_samr_LookupNames(b, mem_ctx,
4125 if (!NT_STATUS_IS_OK(status)) {
4126 errcode = W_ERROR_V(ntstatus_to_werror(status));
4129 if (!NT_STATUS_IS_OK(result)) {
4130 errcode = W_ERROR_V(ntstatus_to_werror(result));
4134 if (rids.count != 1) {
4135 errcode = W_ERROR_V(WERR_NO_SUCH_USER);
4138 if (rids.count != types.count) {
4139 errcode = W_ERROR_V(WERR_INVALID_PARAM);
4142 if (types.ids[0] != SID_NAME_USER) {
4143 errcode = W_ERROR_V(WERR_INVALID_PARAM);
4149 status = dcerpc_samr_OpenUser(b, mem_ctx,
4151 SAMR_USER_ACCESS_GET_LOCALE |
4152 SAMR_USER_ACCESS_GET_LOGONINFO |
4153 SAMR_USER_ACCESS_GET_ATTRIBUTES |
4154 SAMR_USER_ACCESS_GET_GROUPS |
4155 SAMR_USER_ACCESS_GET_GROUP_MEMBERSHIP |
4156 SEC_STD_READ_CONTROL,
4160 if (!NT_STATUS_IS_OK(status)) {
4161 errcode = W_ERROR_V(ntstatus_to_werror(status));
4164 if (!NT_STATUS_IS_OK(result)) {
4165 errcode = W_ERROR_V(ntstatus_to_werror(result));
4169 status = dcerpc_samr_QueryUserInfo2(b, mem_ctx,
4174 if (!NT_STATUS_IS_OK(status)) {
4175 errcode = W_ERROR_V(ntstatus_to_werror(status));
4178 if (!NT_STATUS_IS_OK(result)) {
4179 errcode = W_ERROR_V(ntstatus_to_werror(result));
4184 fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
4187 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
4192 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
4193 strlcpy(p2,"Comment",PTR_DIFF(endp,p2));
4194 p2 = skip_string(*rdata,*rdata_len,p2);
4199 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
4200 strlcpy(p2,"UserComment",PTR_DIFF(endp,p2));
4201 p2 = skip_string(*rdata,*rdata_len,p2);
4206 /* EEK! the cifsrap.txt doesn't have this in!!!! */
4207 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
4208 strlcpy(p2,info->info21.full_name.string,PTR_DIFF(endp,p2));
4209 p2 = skip_string(*rdata,*rdata_len,p2);
4216 const char *homedir = info->info21.home_directory.string;
4217 /* modelled after NTAS 3.51 reply */
4218 SSVAL(p,usri11_priv,
4219 (get_current_uid(conn) == sec_initial_uid())?
4220 USER_PRIV_ADMIN:USER_PRIV_USER);
4221 SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
4222 SIVALS(p,usri11_password_age,-1); /* password age */
4223 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
4224 strlcpy(p2, homedir, PTR_DIFF(endp,p2));
4225 p2 = skip_string(*rdata,*rdata_len,p2);
4229 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
4230 strlcpy(p2,"",PTR_DIFF(endp,p2));
4231 p2 = skip_string(*rdata,*rdata_len,p2);
4235 SIVAL(p,usri11_last_logon,0); /* last logon */
4236 SIVAL(p,usri11_last_logoff,0); /* last logoff */
4237 SSVALS(p,usri11_bad_pw_count,-1); /* bad pw counts */
4238 SSVALS(p,usri11_num_logons,-1); /* num logons */
4239 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
4240 strlcpy(p2,"\\\\*",PTR_DIFF(endp,p2));
4241 p2 = skip_string(*rdata,*rdata_len,p2);
4245 SSVAL(p,usri11_country_code,0); /* country code */
4247 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
4248 strlcpy(p2,"",PTR_DIFF(endp,p2));
4249 p2 = skip_string(*rdata,*rdata_len,p2);
4254 SIVALS(p,usri11_max_storage,-1); /* max storage */
4255 SSVAL(p,usri11_units_per_week,168); /* units per week */
4256 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
4258 /* a simple way to get logon hours at all times. */
4260 SCVAL(p2,21,0); /* fix zero termination */
4261 p2 = skip_string(*rdata,*rdata_len,p2);
4266 SSVAL(p,usri11_code_page,0); /* code page */
4269 if (uLevel == 1 || uLevel == 2) {
4270 memset(p+22,' ',16); /* password */
4271 SIVALS(p,38,-1); /* password age */
4273 (get_current_uid(conn) == sec_initial_uid())?
4274 USER_PRIV_ADMIN:USER_PRIV_USER);
4275 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
4276 strlcpy(p2, info->info21.home_directory.string,
4278 p2 = skip_string(*rdata,*rdata_len,p2);
4282 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
4284 SSVAL(p,52,0); /* flags */
4285 SIVAL(p,54,PTR_DIFF(p2,*rdata)); /* script_path */
4286 strlcpy(p2, info->info21.logon_script.string,
4288 p2 = skip_string(*rdata,*rdata_len,p2);
4293 SIVAL(p,58,0); /* auth_flags */
4294 SIVAL(p,62,PTR_DIFF(p2,*rdata)); /* full_name */
4295 strlcpy(p2,info->info21.full_name.string,PTR_DIFF(endp,p2));
4296 p2 = skip_string(*rdata,*rdata_len,p2);
4300 SIVAL(p,66,0); /* urs_comment */
4301 SIVAL(p,70,PTR_DIFF(p2,*rdata)); /* parms */
4302 strlcpy(p2,"",PTR_DIFF(endp,p2));
4303 p2 = skip_string(*rdata,*rdata_len,p2);
4307 SIVAL(p,74,0); /* workstations */
4308 SIVAL(p,78,0); /* last_logon */
4309 SIVAL(p,82,0); /* last_logoff */
4310 SIVALS(p,86,-1); /* acct_expires */
4311 SIVALS(p,90,-1); /* max_storage */
4312 SSVAL(p,94,168); /* units_per_week */
4313 SIVAL(p,96,PTR_DIFF(p2,*rdata)); /* logon_hours */
4316 SSVALS(p,100,-1); /* bad_pw_count */
4317 SSVALS(p,102,-1); /* num_logons */
4318 SIVAL(p,104,PTR_DIFF(p2,*rdata)); /* logon_server */
4320 TALLOC_CTX *ctx = talloc_tos();
4321 int space_rem = *rdata_len - (p2 - *rdata);
4324 if (space_rem <= 0) {
4327 tmp = talloc_strdup(ctx, "\\\\%L");
4331 tmp = talloc_sub_basic(ctx,
4344 p2 = skip_string(*rdata,*rdata_len,p2);
4348 SSVAL(p,108,49); /* country_code */
4349 SSVAL(p,110,860); /* code page */
4353 errcode = NERR_Success;
4356 *rdata_len = PTR_DIFF(p2,*rdata);
4358 if (b && is_valid_policy_hnd(&user_handle)) {
4359 dcerpc_samr_Close(b, mem_ctx, &user_handle, &result);
4361 if (b && is_valid_policy_hnd(&domain_handle)) {
4362 dcerpc_samr_Close(b, mem_ctx, &domain_handle, &result);
4364 if (b && is_valid_policy_hnd(&connect_handle)) {
4365 dcerpc_samr_Close(b, mem_ctx, &connect_handle, &result);
4368 SSVAL(*rparam,0,errcode);
4369 SSVAL(*rparam,2,0); /* converter word */
4370 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
4375 static bool api_WWkstaUserLogon(struct smbd_server_connection *sconn,
4376 connection_struct *conn,uint64_t vuid,
4377 char *param, int tpscnt,
4378 char *data, int tdscnt,
4379 int mdrcnt,int mprcnt,
4380 char **rdata,char **rparam,
4381 int *rdata_len,int *rparam_len)
4383 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4384 char *str2 = skip_string(param,tpscnt,str1);
4385 char *p = skip_string(param,tpscnt,str2);
4387 struct pack_desc desc;
4389 /* With share level security vuid will always be zero.
4390 Don't depend on vuser being non-null !!. JRA */
4391 struct user_struct *vuser = get_valid_user_struct(sconn, vuid);
4393 if (!str1 || !str2 || !p) {
4398 DEBUG(3,(" Username of UID %d is %s\n",
4399 (int)vuser->session_info->unix_token->uid,
4400 vuser->session_info->unix_info->unix_name));
4403 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4404 name = get_safe_str_ptr(param,tpscnt,p,2);
4409 memset((char *)&desc,'\0',sizeof(desc));
4411 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
4413 /* check it's a supported varient */
4414 if (strcmp(str1,"OOWb54WrLh") != 0) {
4417 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) {
4421 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4428 desc.buflen = mdrcnt;
4429 desc.subformat = NULL;
4432 if (init_package(&desc,1,0)) {
4433 PACKI(&desc,"W",0); /* code */
4434 PACKS(&desc,"B21",name); /* eff. name */
4435 PACKS(&desc,"B",""); /* pad */
4437 (get_current_uid(conn) == sec_initial_uid())?
4438 USER_PRIV_ADMIN:USER_PRIV_USER);
4439 PACKI(&desc,"D",0); /* auth flags XXX */
4440 PACKI(&desc,"W",0); /* num logons */
4441 PACKI(&desc,"W",0); /* bad pw count */
4442 PACKI(&desc,"D",0); /* last logon */
4443 PACKI(&desc,"D",-1); /* last logoff */
4444 PACKI(&desc,"D",-1); /* logoff time */
4445 PACKI(&desc,"D",-1); /* kickoff time */
4446 PACKI(&desc,"D",0); /* password age */
4447 PACKI(&desc,"D",0); /* password can change */
4448 PACKI(&desc,"D",-1); /* password must change */
4452 fstrcpy(mypath,"\\\\");
4453 fstrcat(mypath,get_local_machine_name());
4454 if (!strupper_m(mypath)) {
4457 PACKS(&desc,"z",mypath); /* computer */
4460 PACKS(&desc,"z",lp_workgroup());/* domain */
4461 PACKS(&desc,"z", vuser ?
4462 vuser->session_info->info->logon_script
4463 : ""); /* script path */
4464 PACKI(&desc,"D",0x00000000); /* reserved */
4467 *rdata_len = desc.usedlen;
4469 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4473 SSVALS(*rparam,0,desc.errcode);
4475 SSVAL(*rparam,4,desc.neededlen);
4477 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
4482 /****************************************************************************
4483 api_WAccessGetUserPerms
4484 ****************************************************************************/
4486 static bool api_WAccessGetUserPerms(struct smbd_server_connection *sconn,
4487 connection_struct *conn,uint64_t vuid,
4488 char *param, int tpscnt,
4489 char *data, int tdscnt,
4490 int mdrcnt,int mprcnt,
4491 char **rdata,char **rparam,
4492 int *rdata_len,int *rparam_len)
4494 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4495 char *str2 = skip_string(param,tpscnt,str1);
4496 char *user = skip_string(param,tpscnt,str2);
4497 char *resource = skip_string(param,tpscnt,user);
4499 if (!str1 || !str2 || !user || !resource) {
4503 if (skip_string(param,tpscnt,resource) == NULL) {
4506 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
4508 /* check it's a supported varient */
4509 if (strcmp(str1,"zzh") != 0) {
4512 if (strcmp(str2,"") != 0) {
4517 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4521 SSVALS(*rparam,0,0); /* errorcode */
4522 SSVAL(*rparam,2,0); /* converter word */
4523 SSVAL(*rparam,4,0x7f); /* permission flags */
4528 /****************************************************************************
4529 api_WPrintJobEnumerate
4530 ****************************************************************************/
4532 static bool api_WPrintJobGetInfo(struct smbd_server_connection *sconn,
4533 connection_struct *conn, uint64_t vuid,
4534 char *param, int tpscnt,
4535 char *data, int tdscnt,
4536 int mdrcnt,int mprcnt,
4537 char **rdata,char **rparam,
4538 int *rdata_len,int *rparam_len)
4540 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4541 char *str2 = skip_string(param,tpscnt,str1);
4542 char *p = skip_string(param,tpscnt,str2);
4546 struct pack_desc desc;
4549 TALLOC_CTX *mem_ctx = talloc_tos();
4552 struct rpc_pipe_client *cli = NULL;
4553 struct dcerpc_binding_handle *b = NULL;
4554 struct policy_handle handle;
4555 struct spoolss_DevmodeContainer devmode_ctr;
4556 union spoolss_JobInfo info;
4558 if (!str1 || !str2 || !p) {
4562 uLevel = get_safe_SVAL(param,tpscnt,p,2,-1);
4564 memset((char *)&desc,'\0',sizeof(desc));
4565 memset((char *)&status,'\0',sizeof(status));
4567 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
4569 /* check it's a supported varient */
4570 if (strcmp(str1,"WWrLh") != 0) {
4573 if (!check_printjob_info(&desc,uLevel,str2)) {
4577 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid)) {
4581 ZERO_STRUCT(handle);
4583 status = rpc_pipe_open_interface(conn,
4584 &ndr_table_spoolss.syntax_id,
4586 conn->sconn->remote_address,
4587 conn->sconn->msg_ctx,
4589 if (!NT_STATUS_IS_OK(status)) {
4590 DEBUG(0,("api_WPrintJobGetInfo: could not connect to spoolss: %s\n",
4591 nt_errstr(status)));
4592 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
4595 b = cli->binding_handle;
4597 ZERO_STRUCT(devmode_ctr);
4599 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
4606 if (!NT_STATUS_IS_OK(status)) {
4607 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
4610 if (!W_ERROR_IS_OK(werr)) {
4611 desc.errcode = W_ERROR_V(werr);
4615 werr = rpccli_spoolss_getjob(cli, mem_ctx,
4621 if (!W_ERROR_IS_OK(werr)) {
4622 desc.errcode = W_ERROR_V(werr);
4627 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4632 desc.buflen = mdrcnt;
4635 * Don't return data but need to get correct length
4636 * init_package will return wrong size if buflen=0
4638 desc.buflen = getlen(desc.format);
4639 desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen );
4642 if (init_package(&desc,1,0)) {
4643 fill_spoolss_printjob_info(uLevel, &desc, &info.info2, info.info2.position);
4644 *rdata_len = desc.usedlen;
4646 desc.errcode = NERR_JobNotFound;
4650 if (b && is_valid_policy_hnd(&handle)) {
4651 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
4655 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4659 SSVALS(*rparam,0,desc.errcode);
4661 SSVAL(*rparam,4,desc.neededlen);
4665 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
4670 static bool api_WPrintJobEnumerate(struct smbd_server_connection *sconn,
4671 connection_struct *conn, uint64_t vuid,
4672 char *param, int tpscnt,
4673 char *data, int tdscnt,
4674 int mdrcnt,int mprcnt,
4675 char **rdata,char **rparam,
4676 int *rdata_len,int *rparam_len)
4678 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4679 char *str2 = skip_string(param,tpscnt,str1);
4680 char *p = skip_string(param,tpscnt,str2);
4684 struct pack_desc desc;
4686 TALLOC_CTX *mem_ctx = talloc_tos();
4689 struct rpc_pipe_client *cli = NULL;
4690 struct dcerpc_binding_handle *b = NULL;
4691 struct policy_handle handle;
4692 struct spoolss_DevmodeContainer devmode_ctr;
4694 union spoolss_JobInfo *info;
4696 if (!str1 || !str2 || !p) {
4700 memset((char *)&desc,'\0',sizeof(desc));
4702 p = skip_string(param,tpscnt,p);
4706 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4708 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
4710 /* check it's a supported variant */
4711 if (strcmp(str1,"zWrLeh") != 0) {
4716 return False; /* defined only for uLevel 0,1,2 */
4719 if (!check_printjob_info(&desc,uLevel,str2)) {
4723 ZERO_STRUCT(handle);
4725 status = rpc_pipe_open_interface(conn,
4726 &ndr_table_spoolss.syntax_id,
4728 conn->sconn->remote_address,
4729 conn->sconn->msg_ctx,
4731 if (!NT_STATUS_IS_OK(status)) {
4732 DEBUG(0,("api_WPrintJobEnumerate: could not connect to spoolss: %s\n",
4733 nt_errstr(status)));
4734 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
4737 b = cli->binding_handle;
4739 ZERO_STRUCT(devmode_ctr);
4741 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
4748 if (!NT_STATUS_IS_OK(status)) {
4749 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
4752 if (!W_ERROR_IS_OK(werr)) {
4753 desc.errcode = W_ERROR_V(werr);
4757 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
4765 if (!W_ERROR_IS_OK(werr)) {
4766 desc.errcode = W_ERROR_V(werr);
4771 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4777 desc.buflen = mdrcnt;
4779 if (init_package(&desc,count,0)) {
4781 for (i = 0; i < count; i++) {
4782 fill_spoolss_printjob_info(uLevel, &desc, &info[i].info2, i);
4783 if (desc.errcode == NERR_Success) {
4789 if (b && is_valid_policy_hnd(&handle)) {
4790 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
4793 *rdata_len = desc.usedlen;
4796 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4800 SSVALS(*rparam,0,desc.errcode);
4802 SSVAL(*rparam,4,succnt);
4803 SSVAL(*rparam,6,count);
4805 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
4810 static int check_printdest_info(struct pack_desc* desc,
4811 int uLevel, char* id)
4813 desc->subformat = NULL;
4816 desc->format = "B9";
4819 desc->format = "B9B21WWzW";
4825 desc->format = "zzzWWzzzWW";
4828 DEBUG(0,("check_printdest_info: invalid level %d\n",
4832 if (id == NULL || strcmp(desc->format,id) != 0) {
4833 DEBUG(0,("check_printdest_info: invalid string %s\n",
4834 id ? id : "<NULL>" ));
4840 static void fill_printdest_info(struct spoolss_PrinterInfo2 *info2, int uLevel,
4841 struct pack_desc* desc)
4845 strncpy(buf, info2->printername, sizeof(buf)-1);
4846 buf[sizeof(buf)-1] = 0;
4847 (void)strupper_m(buf);
4850 PACKS(desc,"B9",buf); /* szName */
4852 PACKS(desc,"B21",""); /* szUserName */
4853 PACKI(desc,"W",0); /* uJobId */
4854 PACKI(desc,"W",0); /* fsStatus */
4855 PACKS(desc,"z",""); /* pszStatus */
4856 PACKI(desc,"W",0); /* time */
4860 if (uLevel == 2 || uLevel == 3) {
4861 PACKS(desc,"z",buf); /* pszPrinterName */
4863 PACKS(desc,"z",""); /* pszUserName */
4864 PACKS(desc,"z",""); /* pszLogAddr */
4865 PACKI(desc,"W",0); /* uJobId */
4866 PACKI(desc,"W",0); /* fsStatus */
4867 PACKS(desc,"z",""); /* pszStatus */
4868 PACKS(desc,"z",""); /* pszComment */
4869 PACKS(desc,"z","NULL"); /* pszDrivers */
4870 PACKI(desc,"W",0); /* time */
4871 PACKI(desc,"W",0); /* pad1 */
4876 static bool api_WPrintDestGetInfo(struct smbd_server_connection *sconn,
4877 connection_struct *conn, uint64_t vuid,
4878 char *param, int tpscnt,
4879 char *data, int tdscnt,
4880 int mdrcnt,int mprcnt,
4881 char **rdata,char **rparam,
4882 int *rdata_len,int *rparam_len)
4884 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4885 char *str2 = skip_string(param,tpscnt,str1);
4886 char *p = skip_string(param,tpscnt,str2);
4887 char* PrinterName = p;
4889 struct pack_desc desc;
4892 TALLOC_CTX *mem_ctx = talloc_tos();
4895 struct rpc_pipe_client *cli = NULL;
4896 struct dcerpc_binding_handle *b = NULL;
4897 struct policy_handle handle;
4898 struct spoolss_DevmodeContainer devmode_ctr;
4899 union spoolss_PrinterInfo info;
4901 if (!str1 || !str2 || !p) {
4905 memset((char *)&desc,'\0',sizeof(desc));
4907 p = skip_string(param,tpscnt,p);
4911 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4913 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
4915 /* check it's a supported varient */
4916 if (strcmp(str1,"zWrLh") != 0) {
4919 if (!check_printdest_info(&desc,uLevel,str2)) {
4923 ZERO_STRUCT(handle);
4925 status = rpc_pipe_open_interface(conn,
4926 &ndr_table_spoolss.syntax_id,
4928 conn->sconn->remote_address,
4929 conn->sconn->msg_ctx,
4931 if (!NT_STATUS_IS_OK(status)) {
4932 DEBUG(0,("api_WPrintDestGetInfo: could not connect to spoolss: %s\n",
4933 nt_errstr(status)));
4934 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
4937 b = cli->binding_handle;
4939 ZERO_STRUCT(devmode_ctr);
4941 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
4948 if (!NT_STATUS_IS_OK(status)) {
4950 desc.errcode = NERR_DestNotFound;
4954 if (!W_ERROR_IS_OK(werr)) {
4956 desc.errcode = NERR_DestNotFound;
4961 werr = rpccli_spoolss_getprinter(cli, mem_ctx,
4966 if (!W_ERROR_IS_OK(werr)) {
4968 desc.errcode = NERR_DestNotFound;
4974 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4979 desc.buflen = mdrcnt;
4982 * Don't return data but need to get correct length
4983 * init_package will return wrong size if buflen=0
4985 desc.buflen = getlen(desc.format);
4986 desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen );
4988 if (init_package(&desc,1,0)) {
4989 fill_printdest_info(&info.info2, uLevel,&desc);
4993 if (b && is_valid_policy_hnd(&handle)) {
4994 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
4997 *rdata_len = desc.usedlen;
5000 *rparam = smb_realloc_limit(*rparam,*rparam_len);
5004 SSVALS(*rparam,0,desc.errcode);
5006 SSVAL(*rparam,4,desc.neededlen);
5008 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
5014 static bool api_WPrintDestEnum(struct smbd_server_connection *sconn,
5015 connection_struct *conn, uint64_t vuid,
5016 char *param, int tpscnt,
5017 char *data, int tdscnt,
5018 int mdrcnt,int mprcnt,
5019 char **rdata,char **rparam,
5020 int *rdata_len,int *rparam_len)
5022 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
5023 char *str2 = skip_string(param,tpscnt,str1);
5024 char *p = skip_string(param,tpscnt,str2);
5028 struct pack_desc desc;
5030 TALLOC_CTX *mem_ctx = talloc_tos();
5033 struct rpc_pipe_client *cli = NULL;
5034 union spoolss_PrinterInfo *info;
5037 if (!str1 || !str2 || !p) {
5041 memset((char *)&desc,'\0',sizeof(desc));
5043 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
5045 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
5047 /* check it's a supported varient */
5048 if (strcmp(str1,"WrLeh") != 0) {
5051 if (!check_printdest_info(&desc,uLevel,str2)) {
5057 status = rpc_pipe_open_interface(conn,
5058 &ndr_table_spoolss.syntax_id,
5060 conn->sconn->remote_address,
5061 conn->sconn->msg_ctx,
5063 if (!NT_STATUS_IS_OK(status)) {
5064 DEBUG(0,("api_WPrintDestEnum: could not connect to spoolss: %s\n",
5065 nt_errstr(status)));
5066 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
5070 werr = rpccli_spoolss_enumprinters(cli, mem_ctx,
5072 cli->srv_name_slash,
5077 if (!W_ERROR_IS_OK(werr)) {
5078 desc.errcode = W_ERROR_V(werr);
5080 desc.errcode = NERR_DestNotFound;
5088 *rdata = smb_realloc_limit(*rdata,mdrcnt);
5095 desc.buflen = mdrcnt;
5096 if (init_package(&desc,queuecnt,0)) {
5099 for (i = 0; i < count; i++) {
5100 fill_printdest_info(&info[i].info2, uLevel,&desc);
5102 if (desc.errcode == NERR_Success) {
5108 *rdata_len = desc.usedlen;
5111 *rparam = smb_realloc_limit(*rparam,*rparam_len);
5115 SSVALS(*rparam,0,desc.errcode);
5117 SSVAL(*rparam,4,succnt);
5118 SSVAL(*rparam,6,queuecnt);
5120 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
5125 static bool api_WPrintDriverEnum(struct smbd_server_connection *sconn,
5126 connection_struct *conn, uint64_t vuid,
5127 char *param, int tpscnt,
5128 char *data, int tdscnt,
5129 int mdrcnt,int mprcnt,
5130 char **rdata,char **rparam,
5131 int *rdata_len,int *rparam_len)
5133 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
5134 char *str2 = skip_string(param,tpscnt,str1);
5135 char *p = skip_string(param,tpscnt,str2);
5138 struct pack_desc desc;
5140 if (!str1 || !str2 || !p) {
5144 memset((char *)&desc,'\0',sizeof(desc));
5146 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
5148 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
5150 /* check it's a supported varient */
5151 if (strcmp(str1,"WrLeh") != 0) {
5154 if (uLevel != 0 || strcmp(str2,"B41") != 0) {
5159 *rdata = smb_realloc_limit(*rdata,mdrcnt);
5165 desc.buflen = mdrcnt;
5166 if (init_package(&desc,1,0)) {
5167 PACKS(&desc,"B41","NULL");
5170 succnt = (desc.errcode == NERR_Success ? 1 : 0);
5172 *rdata_len = desc.usedlen;
5175 *rparam = smb_realloc_limit(*rparam,*rparam_len);
5179 SSVALS(*rparam,0,desc.errcode);
5181 SSVAL(*rparam,4,succnt);
5184 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
5189 static bool api_WPrintQProcEnum(struct smbd_server_connection *sconn,
5190 connection_struct *conn, uint64_t vuid,
5191 char *param, int tpscnt,
5192 char *data, int tdscnt,
5193 int mdrcnt,int mprcnt,
5194 char **rdata,char **rparam,
5195 int *rdata_len,int *rparam_len)
5197 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
5198 char *str2 = skip_string(param,tpscnt,str1);
5199 char *p = skip_string(param,tpscnt,str2);
5202 struct pack_desc desc;
5204 if (!str1 || !str2 || !p) {
5207 memset((char *)&desc,'\0',sizeof(desc));
5209 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
5211 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
5213 /* check it's a supported varient */
5214 if (strcmp(str1,"WrLeh") != 0) {
5217 if (uLevel != 0 || strcmp(str2,"B13") != 0) {
5222 *rdata = smb_realloc_limit(*rdata,mdrcnt);
5228 desc.buflen = mdrcnt;
5230 if (init_package(&desc,1,0)) {
5231 PACKS(&desc,"B13","lpd");
5234 succnt = (desc.errcode == NERR_Success ? 1 : 0);
5236 *rdata_len = desc.usedlen;
5239 *rparam = smb_realloc_limit(*rparam,*rparam_len);
5243 SSVALS(*rparam,0,desc.errcode);
5245 SSVAL(*rparam,4,succnt);
5248 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
5253 static bool api_WPrintPortEnum(struct smbd_server_connection *sconn,
5254 connection_struct *conn, uint64_t vuid,
5255 char *param, int tpscnt,
5256 char *data, int tdscnt,
5257 int mdrcnt,int mprcnt,
5258 char **rdata,char **rparam,
5259 int *rdata_len,int *rparam_len)
5261 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
5262 char *str2 = skip_string(param,tpscnt,str1);
5263 char *p = skip_string(param,tpscnt,str2);
5266 struct pack_desc desc;
5268 if (!str1 || !str2 || !p) {
5272 memset((char *)&desc,'\0',sizeof(desc));
5274 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
5276 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
5278 /* check it's a supported varient */
5279 if (strcmp(str1,"WrLeh") != 0) {
5282 if (uLevel != 0 || strcmp(str2,"B9") != 0) {
5287 *rdata = smb_realloc_limit(*rdata,mdrcnt);
5292 memset((char *)&desc,'\0',sizeof(desc));
5294 desc.buflen = mdrcnt;
5296 if (init_package(&desc,1,0)) {
5297 PACKS(&desc,"B13","lp0");
5300 succnt = (desc.errcode == NERR_Success ? 1 : 0);
5302 *rdata_len = desc.usedlen;
5305 *rparam = smb_realloc_limit(*rparam,*rparam_len);
5309 SSVALS(*rparam,0,desc.errcode);
5311 SSVAL(*rparam,4,succnt);
5314 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
5319 /****************************************************************************
5321 ****************************************************************************/
5323 static bool api_RNetSessionEnum(struct smbd_server_connection *sconn,
5324 connection_struct *conn, uint64_t vuid,
5325 char *param, int tpscnt,
5326 char *data, int tdscnt,
5327 int mdrcnt,int mprcnt,
5328 char **rdata,char **rparam,
5329 int *rdata_len,int *rparam_len)
5332 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
5333 char *str2 = skip_string(param,tpscnt,str1);
5334 char *p = skip_string(param,tpscnt,str2);
5336 struct pack_desc desc;
5339 TALLOC_CTX *mem_ctx = talloc_tos();
5342 struct rpc_pipe_client *cli = NULL;
5343 struct dcerpc_binding_handle *b = NULL;
5344 struct srvsvc_NetSessInfoCtr info_ctr;
5345 uint32_t totalentries, resume_handle = 0;
5348 if (!str1 || !str2 || !p) {
5354 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
5356 DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel));
5357 DEBUG(7,("RNetSessionEnum req string=%s\n",str1));
5358 DEBUG(7,("RNetSessionEnum ret string=%s\n",str2));
5360 /* check it's a supported varient */
5361 if (strcmp(str1,RAP_NetSessionEnum_REQ) != 0) {
5364 if (uLevel != 2 || strcmp(str2,RAP_SESSION_INFO_L2) != 0) {
5368 status = rpc_pipe_open_interface(conn,
5369 &ndr_table_srvsvc.syntax_id,
5371 conn->sconn->remote_address,
5372 conn->sconn->msg_ctx,
5374 if (!NT_STATUS_IS_OK(status)) {
5375 DEBUG(0,("RNetSessionEnum: could not connect to srvsvc: %s\n",
5376 nt_errstr(status)));
5377 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
5380 b = cli->binding_handle;
5383 info_ctr.ctr.ctr1 = talloc_zero(talloc_tos(), struct srvsvc_NetSessCtr1);
5384 if (info_ctr.ctr.ctr1 == NULL) {
5385 desc.errcode = W_ERROR_V(WERR_NOMEM);
5389 status = dcerpc_srvsvc_NetSessEnum(b, mem_ctx,
5390 cli->srv_name_slash,
5394 (uint32_t)-1, /* max_buffer */
5398 if (!NT_STATUS_IS_OK(status)) {
5399 DEBUG(0,("RNetSessionEnum: dcerpc_srvsvc_NetSessEnum failed: %s\n",
5400 nt_errstr(status)));
5401 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
5405 if (!W_ERROR_IS_OK(werr)) {
5406 DEBUG(0,("RNetSessionEnum: dcerpc_srvsvc_NetSessEnum failed: %s\n",
5408 desc.errcode = W_ERROR_V(werr);
5412 count = info_ctr.ctr.ctr1->count;
5416 *rdata = smb_realloc_limit(*rdata,mdrcnt);
5423 desc.buflen = mdrcnt;
5425 if (!init_package(&desc, count,0)) {
5429 for(i=0; i < count; i++) {
5430 PACKS(&desc, "z", info_ctr.ctr.ctr1->array[i].client);
5431 PACKS(&desc, "z", info_ctr.ctr.ctr1->array[i].user);
5432 PACKI(&desc, "W", 1); /* num conns */
5433 PACKI(&desc, "W", info_ctr.ctr.ctr1->array[i].num_open);
5434 PACKI(&desc, "W", 1); /* num users */
5435 PACKI(&desc, "D", 0); /* session time */
5436 PACKI(&desc, "D", 0); /* idle time */
5437 PACKI(&desc, "D", 0); /* flags */
5438 PACKS(&desc, "z", "Unknown Client"); /* client type string */
5441 *rdata_len = desc.usedlen;
5444 *rparam = smb_realloc_limit(*rparam,*rparam_len);
5448 SSVALS(*rparam,0,desc.errcode);
5449 SSVAL(*rparam,2,0); /* converter */
5450 SSVAL(*rparam,4, count); /* count */
5452 DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc.errcode));
5458 /****************************************************************************
5459 The buffer was too small.
5460 ****************************************************************************/
5462 static bool api_TooSmall(struct smbd_server_connection *sconn,
5463 connection_struct *conn,uint64_t vuid, char *param, char *data,
5464 int mdrcnt, int mprcnt,
5465 char **rdata, char **rparam,
5466 int *rdata_len, int *rparam_len)
5468 *rparam_len = MIN(*rparam_len,mprcnt);
5469 *rparam = smb_realloc_limit(*rparam,*rparam_len);
5476 SSVAL(*rparam,0,NERR_BufTooSmall);
5478 DEBUG(3,("Supplied buffer too small in API command\n"));
5483 /****************************************************************************
5484 The request is not supported.
5485 ****************************************************************************/
5487 static bool api_Unsupported(struct smbd_server_connection *sconn,
5488 connection_struct *conn, uint64_t vuid,
5489 char *param, int tpscnt,
5490 char *data, int tdscnt,
5491 int mdrcnt, int mprcnt,
5492 char **rdata, char **rparam,
5493 int *rdata_len, int *rparam_len)
5496 *rparam = smb_realloc_limit(*rparam,*rparam_len);
5503 SSVAL(*rparam,0,NERR_notsupported);
5504 SSVAL(*rparam,2,0); /* converter word */
5506 DEBUG(3,("Unsupported API command\n"));
5511 static const struct {
5514 bool (*fn)(struct smbd_server_connection *sconn,
5515 connection_struct *, uint64_t,
5518 int,int,char **,char **,int *,int *);
5519 bool auth_user; /* Deny anonymous access? */
5520 } api_commands[] = {
5521 {"RNetShareEnum", RAP_WshareEnum, api_RNetShareEnum, True},
5522 {"RNetShareGetInfo", RAP_WshareGetInfo, api_RNetShareGetInfo},
5523 {"RNetShareAdd", RAP_WshareAdd, api_RNetShareAdd},
5524 {"RNetSessionEnum", RAP_WsessionEnum, api_RNetSessionEnum, True},
5525 {"RNetServerGetInfo", RAP_WserverGetInfo, api_RNetServerGetInfo},
5526 {"RNetGroupEnum", RAP_WGroupEnum, api_RNetGroupEnum, True},
5527 {"RNetGroupGetUsers", RAP_WGroupGetUsers, api_RNetGroupGetUsers, True},
5528 {"RNetUserEnum", RAP_WUserEnum, api_RNetUserEnum, True},
5529 {"RNetUserGetInfo", RAP_WUserGetInfo, api_RNetUserGetInfo},
5530 {"NetUserGetGroups", RAP_WUserGetGroups, api_NetUserGetGroups},
5531 {"NetWkstaGetInfo", RAP_WWkstaGetInfo, api_NetWkstaGetInfo},
5532 {"DosPrintQEnum", RAP_WPrintQEnum, api_DosPrintQEnum, True},
5533 {"DosPrintQGetInfo", RAP_WPrintQGetInfo, api_DosPrintQGetInfo},
5534 {"WPrintQueuePause", RAP_WPrintQPause, api_WPrintQueueCtrl},
5535 {"WPrintQueueResume", RAP_WPrintQContinue, api_WPrintQueueCtrl},
5536 {"WPrintJobEnumerate",RAP_WPrintJobEnum, api_WPrintJobEnumerate},
5537 {"WPrintJobGetInfo", RAP_WPrintJobGetInfo, api_WPrintJobGetInfo},
5538 {"RDosPrintJobDel", RAP_WPrintJobDel, api_RDosPrintJobDel},
5539 {"RDosPrintJobPause", RAP_WPrintJobPause, api_RDosPrintJobDel},
5540 {"RDosPrintJobResume",RAP_WPrintJobContinue, api_RDosPrintJobDel},
5541 {"WPrintDestEnum", RAP_WPrintDestEnum, api_WPrintDestEnum},
5542 {"WPrintDestGetInfo", RAP_WPrintDestGetInfo, api_WPrintDestGetInfo},
5543 {"NetRemoteTOD", RAP_NetRemoteTOD, api_NetRemoteTOD},
5544 {"WPrintQueuePurge", RAP_WPrintQPurge, api_WPrintQueueCtrl},
5545 {"NetServerEnum2", RAP_NetServerEnum2, api_RNetServerEnum2}, /* anon OK */
5546 {"NetServerEnum3", RAP_NetServerEnum3, api_RNetServerEnum3}, /* anon OK */
5547 {"WAccessGetUserPerms",RAP_WAccessGetUserPerms,api_WAccessGetUserPerms},
5548 {"WWkstaUserLogon", RAP_WWkstaUserLogon, api_WWkstaUserLogon},
5549 {"PrintJobInfo", RAP_WPrintJobSetInfo, api_PrintJobInfo},
5550 {"WPrintDriverEnum", RAP_WPrintDriverEnum, api_WPrintDriverEnum},
5551 {"WPrintQProcEnum", RAP_WPrintQProcessorEnum,api_WPrintQProcEnum},
5552 {"WPrintPortEnum", RAP_WPrintPortEnum, api_WPrintPortEnum},
5553 {"SamOEMChangePassword",RAP_SamOEMChgPasswordUser2_P,api_SamOEMChangePassword}, /* anon OK */
5554 {NULL, -1, api_Unsupported}
5555 /* The following RAP calls are not implemented by Samba:
5557 RAP_WFileEnum2 - anon not OK
5562 /****************************************************************************
5563 Handle remote api calls.
5564 ****************************************************************************/
5566 void api_reply(connection_struct *conn, uint64_t vuid,
5567 struct smb_request *req,
5568 char *data, char *params,
5569 int tdscnt, int tpscnt,
5570 int mdrcnt, int mprcnt)
5574 char *rparam = NULL;
5575 const char *name1 = NULL;
5576 const char *name2 = NULL;
5583 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
5584 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5589 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5592 api_command = SVAL(params,0);
5593 /* Is there a string at position params+2 ? */
5594 if (skip_string(params,tpscnt,params+2)) {
5599 name2 = skip_string(params,tpscnt,params+2);
5604 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
5608 tdscnt,tpscnt,mdrcnt,mprcnt));
5610 for (i=0;api_commands[i].name;i++) {
5611 if (api_commands[i].id == api_command && api_commands[i].fn) {
5612 DEBUG(3,("Doing %s\n",api_commands[i].name));
5617 /* Check whether this api call can be done anonymously */
5619 if (api_commands[i].auth_user && lp_restrict_anonymous()) {
5620 struct user_struct *user = get_valid_user_struct(req->sconn, vuid);
5622 if (!user || security_session_user_level(user->session_info, NULL) < SECURITY_USER) {
5623 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5628 rdata = (char *)SMB_MALLOC(1024);
5630 memset(rdata,'\0',1024);
5633 rparam = (char *)SMB_MALLOC(1024);
5635 memset(rparam,'\0',1024);
5638 if(!rdata || !rparam) {
5639 DEBUG(0,("api_reply: malloc fail !\n"));
5642 reply_nterror(req, NT_STATUS_NO_MEMORY);
5646 reply = api_commands[i].fn(req->sconn, conn,
5648 params,tpscnt, /* params + length */
5649 data,tdscnt, /* data + length */
5651 &rdata,&rparam,&rdata_len,&rparam_len);
5654 if (rdata_len > mdrcnt || rparam_len > mprcnt) {
5655 reply = api_TooSmall(req->sconn,conn,vuid,params,data,
5657 &rdata,&rparam,&rdata_len,&rparam_len);
5660 /* if we get False back then it's actually unsupported */
5662 reply = api_Unsupported(req->sconn,conn,vuid,params,tpscnt,
5664 tdscnt,mdrcnt,mprcnt,
5665 &rdata,&rparam,&rdata_len,&rparam_len);
5668 /* If api_Unsupported returns false we can't return anything. */
5670 send_trans_reply(conn, req, rparam, rparam_len,
5671 rdata, rdata_len, False);