2 Unix SMB/CIFS implementation.
3 Inter-process communication and named pipe handling
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Jeremy Allison 2007.
8 Copyright (C) John H Terpstra 1995-1998
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 This file handles the named pipe and mailslot calls
25 in the SMBtrans protocol
29 #include "smbd/globals.h"
30 #include "../librpc/gen_ndr/cli_samr.h"
31 #include "../librpc/gen_ndr/cli_spoolss.h"
32 #include "../librpc/gen_ndr/srv_samr.h"
33 #include "../librpc/gen_ndr/srv_spoolss.h"
34 #include "../librpc/gen_ndr/rap.h"
35 #include "../lib/util/binsearch.h"
42 #define NERR_Success 0
43 #define NERR_badpass 86
44 #define NERR_notsupported 50
46 #define NERR_BASE (2100)
47 #define NERR_BufTooSmall (NERR_BASE+23)
48 #define NERR_JobNotFound (NERR_BASE+51)
49 #define NERR_DestNotFound (NERR_BASE+52)
51 #define ACCESS_READ 0x01
52 #define ACCESS_WRITE 0x02
53 #define ACCESS_CREATE 0x04
55 #define SHPWLEN 8 /* share password length */
57 /* Limit size of ipc replies */
59 static char *smb_realloc_limit(void *ptr, size_t size)
63 size = MAX((size),4*1024);
64 val = (char *)SMB_REALLOC(ptr,size);
66 memset(val,'\0',size);
71 static bool api_Unsupported(connection_struct *conn, uint16 vuid,
72 char *param, int tpscnt,
73 char *data, int tdscnt,
74 int mdrcnt, int mprcnt,
75 char **rdata, char **rparam,
76 int *rdata_len, int *rparam_len);
78 static bool api_TooSmall(connection_struct *conn, uint16 vuid, char *param, char *data,
79 int mdrcnt, int mprcnt,
80 char **rdata, char **rparam,
81 int *rdata_len, int *rparam_len);
84 static int CopyExpanded(connection_struct *conn,
85 int snum, char **dst, char *src, int *p_space_remaining)
87 TALLOC_CTX *ctx = talloc_tos();
91 if (!src || !dst || !p_space_remaining || !(*dst) ||
92 *p_space_remaining <= 0) {
96 buf = talloc_strdup(ctx, src);
98 *p_space_remaining = 0;
101 buf = talloc_string_sub(ctx, buf,"%S",lp_servicename(snum));
103 *p_space_remaining = 0;
106 buf = talloc_sub_advanced(ctx,
107 lp_servicename(SNUM(conn)),
108 conn->server_info->unix_name,
110 conn->server_info->utok.gid,
111 conn->server_info->sanitized_username,
112 pdb_get_domain(conn->server_info->sam_account),
115 *p_space_remaining = 0;
118 l = push_ascii(*dst,buf,*p_space_remaining, STR_TERMINATE);
123 (*p_space_remaining) -= l;
127 static int CopyAndAdvance(char **dst, char *src, int *n)
130 if (!src || !dst || !n || !(*dst)) {
133 l = push_ascii(*dst,src,*n, STR_TERMINATE);
142 static int StrlenExpanded(connection_struct *conn, int snum, char *s)
144 TALLOC_CTX *ctx = talloc_tos();
149 buf = talloc_strdup(ctx,s);
153 buf = talloc_string_sub(ctx,buf,"%S",lp_servicename(snum));
157 buf = talloc_sub_advanced(ctx,
158 lp_servicename(SNUM(conn)),
159 conn->server_info->unix_name,
161 conn->server_info->utok.gid,
162 conn->server_info->sanitized_username,
163 pdb_get_domain(conn->server_info->sam_account),
168 return strlen(buf) + 1;
171 static char *Expand(connection_struct *conn, int snum, char *s)
173 TALLOC_CTX *ctx = talloc_tos();
179 buf = talloc_strdup(ctx,s);
183 buf = talloc_string_sub(ctx,buf,"%S",lp_servicename(snum));
187 return talloc_sub_advanced(ctx,
188 lp_servicename(SNUM(conn)),
189 conn->server_info->unix_name,
191 conn->server_info->utok.gid,
192 conn->server_info->sanitized_username,
193 pdb_get_domain(conn->server_info->sam_account),
197 /*******************************************************************
198 Check a API string for validity when we only need to check the prefix.
199 ******************************************************************/
201 static bool prefix_ok(const char *str, const char *prefix)
203 return(strncmp(str,prefix,strlen(prefix)) == 0);
207 const char *format; /* formatstring for structure */
208 const char *subformat; /* subformat for structure */
209 char *base; /* baseaddress of buffer */
210 int buflen; /* remaining size for fixed part; on init: length of base */
211 int subcount; /* count of substructures */
212 char *structbuf; /* pointer into buffer for remaining fixed part */
213 int stringlen; /* remaining size for variable part */
214 char *stringbuf; /* pointer into buffer for remaining variable part */
215 int neededlen; /* total needed size */
216 int usedlen; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
217 const char *curpos; /* current position; pointer into format or subformat */
221 static int get_counter(const char **p)
227 if (!isdigit((int)**p)) {
233 n = 10 * n + (i - '0');
241 static int getlen(const char *p)
250 case 'W': /* word (2 byte) */
253 case 'K': /* status word? (2 byte) */
256 case 'N': /* count of substructures (word) at end */
259 case 'D': /* double word (4 byte) */
260 case 'z': /* offset to zero terminated string (4 byte) */
261 case 'l': /* offset to user data (4 byte) */
264 case 'b': /* offset to data (with counter) (4 byte) */
268 case 'B': /* byte (with optional counter) */
269 n += get_counter(&p);
276 static bool init_package(struct pack_desc *p, int count, int subcount)
281 if (!p->format || !p->base) {
285 i = count * getlen(p->format);
287 i += subcount * getlen(p->subformat);
289 p->structbuf = p->base;
293 p->curpos = p->format;
299 * This is the old error code we used. Aparently
300 * WinNT/2k systems return ERRbuftoosmall (2123) and
301 * OS/2 needs this. I'm leaving this here so we can revert
304 p->errcode = ERRmoredata;
306 p->errcode = ERRbuftoosmall;
309 p->errcode = NERR_Success;
313 p->stringbuf = p->base + i;
315 return (p->errcode == NERR_Success);
318 static int package(struct pack_desc *p, ...)
321 int needed=0, stringneeded;
322 const char *str=NULL;
323 int is_string=0, stringused;
330 p->curpos = p->format;
332 p->curpos = p->subformat;
337 str = va_arg(args,char*);
338 SMB_ASSERT(strncmp(str,p->curpos,strlen(str)) == 0);
347 switch( *p->curpos++ ) {
348 case 'W': /* word (2 byte) */
350 temp = va_arg(args,int);
351 if (p->buflen >= needed) {
352 SSVAL(p->structbuf,0,temp);
355 case 'K': /* status word? (2 byte) */
357 temp = va_arg(args,int);
358 if (p->buflen >= needed) {
359 SSVAL(p->structbuf,0,temp);
362 case 'N': /* count of substructures (word) at end */
364 p->subcount = va_arg(args,int);
365 if (p->buflen >= needed) {
366 SSVAL(p->structbuf,0,p->subcount);
369 case 'D': /* double word (4 byte) */
371 temp = va_arg(args,int);
372 if (p->buflen >= needed) {
373 SIVAL(p->structbuf,0,temp);
376 case 'B': /* byte (with optional counter) */
377 needed = get_counter(&p->curpos);
379 char *s = va_arg(args,char*);
380 if (p->buflen >= needed) {
381 StrnCpy(p->structbuf,s?s:"",needed-1);
385 case 'z': /* offset to zero terminated string (4 byte) */
386 str = va_arg(args,char*);
387 stringneeded = (str ? strlen(str)+1 : 0);
390 case 'l': /* offset to user data (4 byte) */
391 str = va_arg(args,char*);
392 stringneeded = va_arg(args,int);
395 case 'b': /* offset to data (with counter) (4 byte) */
396 str = va_arg(args,char*);
397 stringneeded = get_counter(&p->curpos);
403 if (stringneeded >= 0) {
405 if (p->buflen >= needed) {
406 stringused = stringneeded;
407 if (stringused > p->stringlen) {
408 stringused = (is_string ? p->stringlen : 0);
409 if (p->errcode == NERR_Success) {
410 p->errcode = ERRmoredata;
414 SIVAL(p->structbuf,0,0);
416 SIVAL(p->structbuf,0,PTR_DIFF(p->stringbuf,p->base));
417 memcpy(p->stringbuf,str?str:"",stringused);
419 p->stringbuf[stringused-1] = '\0';
421 p->stringbuf += stringused;
422 p->stringlen -= stringused;
423 p->usedlen += stringused;
426 p->neededlen += stringneeded;
429 p->neededlen += needed;
430 if (p->buflen >= needed) {
431 p->structbuf += needed;
433 p->usedlen += needed;
435 if (p->errcode == NERR_Success) {
436 p->errcode = ERRmoredata;
443 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
444 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
446 #define PACK(desc,t,v) package(desc,v)
447 #define PACKl(desc,t,v,l) package(desc,v,l)
450 static void PACKI(struct pack_desc* desc, const char *t,int v)
455 static void PACKS(struct pack_desc* desc,const char *t,const char *v)
460 /****************************************************************************
462 ****************************************************************************/
464 static void PackDriverData(struct pack_desc* desc)
466 char drivdata[4+4+32];
467 SIVAL(drivdata,0,sizeof drivdata); /* cb */
468 SIVAL(drivdata,4,1000); /* lVersion */
469 memset(drivdata+8,0,32); /* szDeviceName */
470 push_ascii(drivdata+8,"NULL",32, STR_TERMINATE);
471 PACKl(desc,"l",drivdata,sizeof drivdata); /* pDriverData */
474 static int check_printq_info(struct pack_desc* desc,
475 unsigned int uLevel, char *id1, char *id2)
477 desc->subformat = NULL;
480 desc->format = "B13";
483 desc->format = "B13BWWWzzzzzWW";
486 desc->format = "B13BWWWzzzzzWN";
487 desc->subformat = "WB21BB16B10zWWzDDz";
490 desc->format = "zWWWWzzzzWWzzl";
493 desc->format = "zWWWWzzzzWNzzl";
494 desc->subformat = "WWzWWDDzz";
503 desc->format = "WzzzzzzzzN";
504 desc->subformat = "z";
507 DEBUG(0,("check_printq_info: invalid level %d\n",
511 if (id1 == NULL || strcmp(desc->format,id1) != 0) {
512 DEBUG(0,("check_printq_info: invalid format %s\n",
513 id1 ? id1 : "<NULL>" ));
516 if (desc->subformat && (id2 == NULL || strcmp(desc->subformat,id2) != 0)) {
517 DEBUG(0,("check_printq_info: invalid subformat %s\n",
518 id2 ? id2 : "<NULL>" ));
525 #define RAP_JOB_STATUS_QUEUED 0
526 #define RAP_JOB_STATUS_PAUSED 1
527 #define RAP_JOB_STATUS_SPOOLING 2
528 #define RAP_JOB_STATUS_PRINTING 3
529 #define RAP_JOB_STATUS_PRINTED 4
531 #define RAP_QUEUE_STATUS_PAUSED 1
532 #define RAP_QUEUE_STATUS_ERROR 2
534 /* turn a print job status into a on the wire status
536 static int printj_status(int v)
540 return RAP_JOB_STATUS_QUEUED;
542 return RAP_JOB_STATUS_PAUSED;
544 return RAP_JOB_STATUS_SPOOLING;
546 return RAP_JOB_STATUS_PRINTING;
551 static int printj_spoolss_status(int v)
553 if (v == JOB_STATUS_QUEUED)
554 return RAP_JOB_STATUS_QUEUED;
555 if (v & JOB_STATUS_PAUSED)
556 return RAP_JOB_STATUS_PAUSED;
557 if (v & JOB_STATUS_SPOOLING)
558 return RAP_JOB_STATUS_SPOOLING;
559 if (v & JOB_STATUS_PRINTING)
560 return RAP_JOB_STATUS_PRINTING;
564 /* turn a print queue status into a on the wire status
566 static int printq_status(int v)
572 return RAP_QUEUE_STATUS_PAUSED;
574 return RAP_QUEUE_STATUS_ERROR;
577 static void fill_printjob_info(connection_struct *conn, int snum, int uLevel,
578 struct pack_desc *desc,
579 print_queue_struct *queue, int n)
581 time_t t = queue->time;
583 /* the client expects localtime */
584 t -= get_time_zone(t);
586 PACKI(desc,"W",pjobid_to_rap(lp_const_servicename(snum),queue->job)); /* uJobId */
588 PACKS(desc,"B21",queue->fs_user); /* szUserName */
589 PACKS(desc,"B",""); /* pad */
590 PACKS(desc,"B16",""); /* szNotifyName */
591 PACKS(desc,"B10","PM_Q_RAW"); /* szDataType */
592 PACKS(desc,"z",""); /* pszParms */
593 PACKI(desc,"W",n+1); /* uPosition */
594 PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */
595 PACKS(desc,"z",""); /* pszStatus */
596 PACKI(desc,"D",t); /* ulSubmitted */
597 PACKI(desc,"D",queue->size); /* ulSize */
598 PACKS(desc,"z",queue->fs_file); /* pszComment */
600 if (uLevel == 2 || uLevel == 3 || uLevel == 4) {
601 PACKI(desc,"W",queue->priority); /* uPriority */
602 PACKS(desc,"z",queue->fs_user); /* pszUserName */
603 PACKI(desc,"W",n+1); /* uPosition */
604 PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */
605 PACKI(desc,"D",t); /* ulSubmitted */
606 PACKI(desc,"D",queue->size); /* ulSize */
607 PACKS(desc,"z","Samba"); /* pszComment */
608 PACKS(desc,"z",queue->fs_file); /* pszDocument */
610 PACKS(desc,"z",""); /* pszNotifyName */
611 PACKS(desc,"z","PM_Q_RAW"); /* pszDataType */
612 PACKS(desc,"z",""); /* pszParms */
613 PACKS(desc,"z",""); /* pszStatus */
614 PACKS(desc,"z",SERVICE(snum)); /* pszQueue */
615 PACKS(desc,"z","lpd"); /* pszQProcName */
616 PACKS(desc,"z",""); /* pszQProcParms */
617 PACKS(desc,"z","NULL"); /* pszDriverName */
618 PackDriverData(desc); /* pDriverData */
619 PACKS(desc,"z",""); /* pszPrinterName */
620 } else if (uLevel == 4) { /* OS2 */
621 PACKS(desc,"z",""); /* pszSpoolFileName */
622 PACKS(desc,"z",""); /* pszPortName */
623 PACKS(desc,"z",""); /* pszStatus */
624 PACKI(desc,"D",0); /* ulPagesSpooled */
625 PACKI(desc,"D",0); /* ulPagesSent */
626 PACKI(desc,"D",0); /* ulPagesPrinted */
627 PACKI(desc,"D",0); /* ulTimePrinted */
628 PACKI(desc,"D",0); /* ulExtendJobStatus */
629 PACKI(desc,"D",0); /* ulStartPage */
630 PACKI(desc,"D",0); /* ulEndPage */
635 static time_t spoolss_Time_to_time_t(const struct spoolss_Time *r)
639 unixtime.tm_year = r->year - 1900;
640 unixtime.tm_mon = r->month - 1;
641 unixtime.tm_wday = r->day_of_week;
642 unixtime.tm_mday = r->day;
643 unixtime.tm_hour = r->hour;
644 unixtime.tm_min = r->minute;
645 unixtime.tm_sec = r->second;
647 return mktime(&unixtime);
650 static void fill_spoolss_printjob_info(int uLevel,
651 struct pack_desc *desc,
652 struct spoolss_JobInfo2 *info2,
655 time_t t = spoolss_Time_to_time_t(&info2->submitted);
657 /* the client expects localtime */
658 t -= get_time_zone(t);
660 PACKI(desc,"W",pjobid_to_rap(info2->printer_name, info2->job_id)); /* uJobId */
662 PACKS(desc,"B21", info2->user_name); /* szUserName */
663 PACKS(desc,"B",""); /* pad */
664 PACKS(desc,"B16",""); /* szNotifyName */
665 PACKS(desc,"B10","PM_Q_RAW"); /* szDataType */
666 PACKS(desc,"z",""); /* pszParms */
667 PACKI(desc,"W",n+1); /* uPosition */
668 PACKI(desc,"W", printj_spoolss_status(info2->status)); /* fsStatus */
669 PACKS(desc,"z",""); /* pszStatus */
670 PACKI(desc,"D", t); /* ulSubmitted */
671 PACKI(desc,"D", info2->size); /* ulSize */
672 PACKS(desc,"z", info2->document_name); /* pszComment */
674 if (uLevel == 2 || uLevel == 3 || uLevel == 4) {
675 PACKI(desc,"W", info2->priority); /* uPriority */
676 PACKS(desc,"z", info2->user_name); /* pszUserName */
677 PACKI(desc,"W",n+1); /* uPosition */
678 PACKI(desc,"W", printj_spoolss_status(info2->status)); /* fsStatus */
679 PACKI(desc,"D",t); /* ulSubmitted */
680 PACKI(desc,"D", info2->size); /* ulSize */
681 PACKS(desc,"z","Samba"); /* pszComment */
682 PACKS(desc,"z", info2->document_name); /* pszDocument */
684 PACKS(desc,"z",""); /* pszNotifyName */
685 PACKS(desc,"z","PM_Q_RAW"); /* pszDataType */
686 PACKS(desc,"z",""); /* pszParms */
687 PACKS(desc,"z",""); /* pszStatus */
688 PACKS(desc,"z", info2->printer_name); /* pszQueue */
689 PACKS(desc,"z","lpd"); /* pszQProcName */
690 PACKS(desc,"z",""); /* pszQProcParms */
691 PACKS(desc,"z","NULL"); /* pszDriverName */
692 PackDriverData(desc); /* pDriverData */
693 PACKS(desc,"z",""); /* pszPrinterName */
694 } else if (uLevel == 4) { /* OS2 */
695 PACKS(desc,"z",""); /* pszSpoolFileName */
696 PACKS(desc,"z",""); /* pszPortName */
697 PACKS(desc,"z",""); /* pszStatus */
698 PACKI(desc,"D",0); /* ulPagesSpooled */
699 PACKI(desc,"D",0); /* ulPagesSent */
700 PACKI(desc,"D",0); /* ulPagesPrinted */
701 PACKI(desc,"D",0); /* ulTimePrinted */
702 PACKI(desc,"D",0); /* ulExtendJobStatus */
703 PACKI(desc,"D",0); /* ulStartPage */
704 PACKI(desc,"D",0); /* ulEndPage */
709 /********************************************************************
710 Return a driver name given an snum.
711 Returns True if from tdb, False otherwise.
712 ********************************************************************/
714 static bool get_driver_name(int snum, char **pp_drivername)
716 NT_PRINTER_INFO_LEVEL *info = NULL;
719 get_a_printer (NULL, &info, 2, lp_servicename(snum));
721 *pp_drivername = talloc_strdup(talloc_tos(),
722 info->info_2->drivername);
724 free_a_printer(&info, 2);
725 if (!*pp_drivername) {
733 /********************************************************************
734 Respond to the DosPrintQInfo command with a level of 52
735 This is used to get printer driver information for Win9x clients
736 ********************************************************************/
737 static void fill_printq_info_52(connection_struct *conn, int snum,
738 struct pack_desc* desc, int count )
742 struct spoolss_DriverInfo8 *driver = NULL;
743 NT_PRINTER_INFO_LEVEL *printer = NULL;
745 if ( !W_ERROR_IS_OK(get_a_printer( NULL, &printer, 2, lp_servicename(snum))) ) {
746 DEBUG(3,("fill_printq_info_52: Failed to lookup printer [%s]\n",
747 lp_servicename(snum)));
751 if (!W_ERROR_IS_OK(get_a_printer_driver(talloc_tos(), &driver, printer->info_2->drivername,
754 DEBUG(3,("fill_printq_info_52: Failed to lookup driver [%s]\n",
755 printer->info_2->drivername));
759 trim_string((char *)driver->driver_path, "\\print$\\WIN40\\0\\", 0);
760 trim_string((char *)driver->data_file, "\\print$\\WIN40\\0\\", 0);
761 trim_string((char *)driver->help_file, "\\print$\\WIN40\\0\\", 0);
763 PACKI(desc, "W", 0x0400); /* don't know */
764 PACKS(desc, "z", driver->driver_name); /* long printer name */
765 PACKS(desc, "z", driver->driver_path); /* Driverfile Name */
766 PACKS(desc, "z", driver->data_file); /* Datafile name */
767 PACKS(desc, "z", driver->monitor_name); /* language monitor */
769 fstrcpy(location, "\\\\%L\\print$\\WIN40\\0");
770 standard_sub_basic( "", "", location, sizeof(location)-1 );
771 PACKS(desc,"z", location); /* share to retrieve files */
773 PACKS(desc,"z", driver->default_datatype); /* default data type */
774 PACKS(desc,"z", driver->help_file); /* helpfile name */
775 PACKS(desc,"z", driver->driver_path); /* driver name */
777 DEBUG(3,("Printer Driver Name: %s:\n",driver->driver_name));
778 DEBUG(3,("Driver: %s:\n",driver->driver_path));
779 DEBUG(3,("Data File: %s:\n",driver->data_file));
780 DEBUG(3,("Language Monitor: %s:\n",driver->monitor_name));
781 DEBUG(3,("Driver Location: %s:\n",location));
782 DEBUG(3,("Data Type: %s:\n",driver->default_datatype));
783 DEBUG(3,("Help File: %s:\n",driver->help_file));
784 PACKI(desc,"N",count); /* number of files to copy */
786 for ( i=0; i<count && driver->dependent_files && *driver->dependent_files[i]; i++)
788 trim_string((char *)driver->dependent_files[i], "\\print$\\WIN40\\0\\", 0);
789 PACKS(desc,"z",driver->dependent_files[i]); /* driver files to copy */
790 DEBUG(3,("Dependent File: %s:\n", driver->dependent_files[i]));
795 DEBUG(3,("fill_printq_info_52: file count specified by client [%d] != number of dependent files [%i]\n",
798 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n", SERVICE(snum),i));
800 desc->errcode=NERR_Success;
804 DEBUG(3,("fill_printq_info: Can't supply driver files\n"));
805 desc->errcode=NERR_notsupported;
809 free_a_printer( &printer, 2 );
811 free_a_printer_driver(driver);
815 static void fill_printq_info(connection_struct *conn, int snum, int uLevel,
816 struct pack_desc* desc,
817 int count, print_queue_struct* queue,
818 print_status_struct* status)
823 PACKS(desc,"B13",SERVICE(snum));
828 PACKS(desc,"z",Expand(conn,snum,SERVICE(snum)));
831 PACKI(desc,"K",printq_status(status->status));
835 if (uLevel == 1 || uLevel == 2) {
836 PACKS(desc,"B",""); /* alignment */
837 PACKI(desc,"W",5); /* priority */
838 PACKI(desc,"W",0); /* start time */
839 PACKI(desc,"W",0); /* until time */
840 PACKS(desc,"z",""); /* pSepFile */
841 PACKS(desc,"z","lpd"); /* pPrProc */
842 PACKS(desc,"z",SERVICE(snum)); /* pDestinations */
843 PACKS(desc,"z",""); /* pParms */
845 PACKS(desc,"z","UNKNOWN PRINTER");
846 PACKI(desc,"W",LPSTAT_ERROR);
848 else if (!status || !status->message[0]) {
849 PACKS(desc,"z",Expand(conn,snum,lp_comment(snum)));
850 PACKI(desc,"W",LPSTAT_OK); /* status */
852 PACKS(desc,"z",status->message);
853 PACKI(desc,"W",printq_status(status->status)); /* status */
855 PACKI(desc,(uLevel == 1 ? "W" : "N"),count);
858 if (uLevel == 3 || uLevel == 4) {
859 char *drivername = NULL;
861 PACKI(desc,"W",5); /* uPriority */
862 PACKI(desc,"W",0); /* uStarttime */
863 PACKI(desc,"W",0); /* uUntiltime */
864 PACKI(desc,"W",5); /* pad1 */
865 PACKS(desc,"z",""); /* pszSepFile */
866 PACKS(desc,"z","WinPrint"); /* pszPrProc */
867 PACKS(desc,"z",NULL); /* pszParms */
868 PACKS(desc,"z",NULL); /* pszComment - don't ask.... JRA */
869 /* "don't ask" that it's done this way to fix corrupted
870 Win9X/ME printer comments. */
872 PACKI(desc,"W",LPSTAT_OK); /* fsStatus */
874 PACKI(desc,"W",printq_status(status->status)); /* fsStatus */
876 PACKI(desc,(uLevel == 3 ? "W" : "N"),count); /* cJobs */
877 PACKS(desc,"z",SERVICE(snum)); /* pszPrinters */
878 get_driver_name(snum,&drivername);
882 PACKS(desc,"z",drivername); /* pszDriverName */
883 PackDriverData(desc); /* pDriverData */
886 if (uLevel == 2 || uLevel == 4) {
888 for (i=0;i<count;i++)
889 fill_printjob_info(conn,snum,uLevel == 2 ? 1 : 2,desc,&queue[i],i);
893 fill_printq_info_52( conn, snum, desc, count );
896 /* This function returns the number of files for a given driver */
897 static int get_printerdrivernumber(int snum)
900 struct spoolss_DriverInfo8 *driver;
901 NT_PRINTER_INFO_LEVEL *printer = NULL;
905 if ( !W_ERROR_IS_OK(get_a_printer( NULL, &printer, 2, lp_servicename(snum))) ) {
906 DEBUG(3,("get_printerdrivernumber: Failed to lookup printer [%s]\n",
907 lp_servicename(snum)));
911 if (!W_ERROR_IS_OK(get_a_printer_driver(talloc_tos(), &driver, printer->info_2->drivername,
914 DEBUG(3,("get_printerdrivernumber: Failed to lookup driver [%s]\n",
915 printer->info_2->drivername));
919 /* count the number of files */
920 while (driver->dependent_files && *driver->dependent_files[result])
924 free_a_printer( &printer, 2 );
926 free_a_printer_driver(driver);
931 static bool api_DosPrintQGetInfo(connection_struct *conn, uint16 vuid,
932 char *param, int tpscnt,
933 char *data, int tdscnt,
934 int mdrcnt,int mprcnt,
935 char **rdata,char **rparam,
936 int *rdata_len,int *rparam_len)
938 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
939 char *str2 = skip_string(param,tpscnt,str1);
940 char *p = skip_string(param,tpscnt,str2);
946 struct pack_desc desc;
947 print_queue_struct *queue=NULL;
948 print_status_struct status;
951 if (!str1 || !str2 || !p) {
954 memset((char *)&status,'\0',sizeof(status));
955 memset((char *)&desc,'\0',sizeof(desc));
957 p = skip_string(param,tpscnt,p);
961 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
962 str3 = get_safe_str_ptr(param,tpscnt,p,4);
963 /* str3 may be null here and is checked in check_printq_info(). */
965 /* remove any trailing username */
966 if ((p = strchr_m(QueueName,'%')))
969 DEBUG(3,("api_DosPrintQGetInfo uLevel=%d name=%s\n",uLevel,QueueName));
971 /* check it's a supported varient */
972 if (!prefix_ok(str1,"zWrLh"))
974 if (!check_printq_info(&desc,uLevel,str2,str3)) {
976 * Patch from Scott Moomaw <scott@bridgewater.edu>
977 * to return the 'invalid info level' error if an
978 * unknown level was requested.
982 *rparam = smb_realloc_limit(*rparam,*rparam_len);
986 SSVALS(*rparam,0,ERRunknownlevel);
992 snum = find_service(QueueName);
993 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
997 count = get_printerdrivernumber(snum);
998 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count));
1000 count = print_queue_status(snum, &queue,&status);
1004 *rdata = smb_realloc_limit(*rdata,mdrcnt);
1010 desc.buflen = mdrcnt;
1013 * Don't return data but need to get correct length
1014 * init_package will return wrong size if buflen=0
1016 desc.buflen = getlen(desc.format);
1017 desc.base = tmpdata = (char *) SMB_MALLOC (desc.buflen);
1020 if (init_package(&desc,1,count)) {
1021 desc.subcount = count;
1022 fill_printq_info(conn,snum,uLevel,&desc,count,queue,&status);
1025 *rdata_len = desc.usedlen;
1028 * We must set the return code to ERRbuftoosmall
1029 * in order to support lanman style printing with Win NT/2k
1032 if (!mdrcnt && lp_disable_spoolss())
1033 desc.errcode = ERRbuftoosmall;
1035 *rdata_len = desc.usedlen;
1037 *rparam = smb_realloc_limit(*rparam,*rparam_len);
1043 SSVALS(*rparam,0,desc.errcode);
1045 SSVAL(*rparam,4,desc.neededlen);
1047 DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode));
1055 /****************************************************************************
1056 View list of all print jobs on all queues.
1057 ****************************************************************************/
1059 static bool api_DosPrintQEnum(connection_struct *conn, uint16 vuid,
1060 char *param, int tpscnt,
1061 char *data, int tdscnt,
1062 int mdrcnt, int mprcnt,
1063 char **rdata, char** rparam,
1064 int *rdata_len, int *rparam_len)
1066 char *param_format = get_safe_str_ptr(param,tpscnt,param,2);
1067 char *output_format1 = skip_string(param,tpscnt,param_format);
1068 char *p = skip_string(param,tpscnt,output_format1);
1069 unsigned int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
1070 char *output_format2 = get_safe_str_ptr(param,tpscnt,p,4);
1071 int services = lp_numservices();
1073 struct pack_desc desc;
1074 print_queue_struct **queue = NULL;
1075 print_status_struct *status = NULL;
1076 int *subcntarr = NULL;
1077 int queuecnt = 0, subcnt = 0, succnt = 0;
1079 if (!param_format || !output_format1 || !p) {
1083 memset((char *)&desc,'\0',sizeof(desc));
1085 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
1087 if (!prefix_ok(param_format,"WrLeh")) {
1090 if (!check_printq_info(&desc,uLevel,output_format1,output_format2)) {
1092 * Patch from Scott Moomaw <scott@bridgewater.edu>
1093 * to return the 'invalid info level' error if an
1094 * unknown level was requested.
1098 *rparam = smb_realloc_limit(*rparam,*rparam_len);
1102 SSVALS(*rparam,0,ERRunknownlevel);
1108 for (i = 0; i < services; i++) {
1109 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
1114 if((queue = SMB_MALLOC_ARRAY(print_queue_struct*, queuecnt)) == NULL) {
1115 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
1118 memset(queue,0,queuecnt*sizeof(print_queue_struct*));
1119 if((status = SMB_MALLOC_ARRAY(print_status_struct,queuecnt)) == NULL) {
1120 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
1123 memset(status,0,queuecnt*sizeof(print_status_struct));
1124 if((subcntarr = SMB_MALLOC_ARRAY(int,queuecnt)) == NULL) {
1125 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
1131 for (i = 0; i < services; i++) {
1132 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
1133 subcntarr[n] = print_queue_status(i, &queue[n],&status[n]);
1134 subcnt += subcntarr[n];
1140 *rdata = smb_realloc_limit(*rdata,mdrcnt);
1146 desc.buflen = mdrcnt;
1148 if (init_package(&desc,queuecnt,subcnt)) {
1151 for (i = 0; i < services; i++) {
1152 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
1153 fill_printq_info(conn,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]);
1155 if (desc.errcode == NERR_Success) {
1162 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);
1175 for (i = 0; i < queuecnt; i++) {
1177 SAFE_FREE(queue[i]);
1188 SAFE_FREE(subcntarr);
1189 for (i = 0; i < queuecnt; i++) {
1191 SAFE_FREE(queue[i]);
1200 /****************************************************************************
1201 Get info level for a server list query.
1202 ****************************************************************************/
1204 static bool check_server_info(int uLevel, char* id)
1208 if (strcmp(id,"B16") != 0) {
1213 if (strcmp(id,"B16BBDz") != 0) {
1223 struct srv_info_struct {
1231 /*******************************************************************
1232 Get server info lists from the files saved by nmbd. Return the
1234 ******************************************************************/
1236 static int get_server_info(uint32 servertype,
1237 struct srv_info_struct **servers,
1243 bool local_list_only;
1246 lines = file_lines_load(cache_path(SERVER_LIST), NULL, 0, NULL);
1248 DEBUG(4,("Can't open %s - %s\n",cache_path(SERVER_LIST),strerror(errno)));
1252 /* request for everything is code for request all servers */
1253 if (servertype == SV_TYPE_ALL) {
1254 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1257 local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY);
1259 DEBUG(4,("Servertype search: %8x\n",servertype));
1261 for (i=0;lines[i];i++) {
1263 struct srv_info_struct *s;
1264 const char *ptr = lines[i];
1266 TALLOC_CTX *frame = NULL;
1273 if (count == alloced) {
1275 *servers = SMB_REALLOC_ARRAY(*servers,struct srv_info_struct, alloced);
1277 DEBUG(0,("get_server_info: failed to enlarge servers info struct!\n"));
1281 memset((char *)((*servers)+count),'\0',sizeof(**servers)*(alloced-count));
1283 s = &(*servers)[count];
1285 frame = talloc_stackframe();
1287 if (!next_token_talloc(frame,&ptr,&p, NULL)) {
1291 fstrcpy(s->name, p);
1294 if (!next_token_talloc(frame,&ptr, &p, NULL)) {
1300 s->comment[0] = '\0';
1301 if (!next_token_talloc(frame,&ptr, &p, NULL)) {
1305 fstrcpy(s->comment, p);
1306 string_truncate(s->comment, MAX_SERVER_STRING_LENGTH);
1308 s->domain[0] = '\0';
1309 if (!next_token_talloc(frame,&ptr,&p, NULL)) {
1310 /* this allows us to cope with an old nmbd */
1311 fstrcpy(s->domain,lp_workgroup());
1313 fstrcpy(s->domain, p);
1317 if (sscanf(stype,"%X",&s->type) != 1) {
1318 DEBUG(4,("r:host file "));
1322 /* Filter the servers/domains we return based on what was asked for. */
1324 /* Check to see if we are being asked for a local list only. */
1325 if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) {
1326 DEBUG(4,("r: local list only"));
1330 /* doesn't match up: don't want it */
1331 if (!(servertype & s->type)) {
1332 DEBUG(4,("r:serv type "));
1336 if ((servertype & SV_TYPE_DOMAIN_ENUM) !=
1337 (s->type & SV_TYPE_DOMAIN_ENUM)) {
1338 DEBUG(4,("s: dom mismatch "));
1342 if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM)) {
1346 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1347 s->type &= ~SV_TYPE_LOCAL_LIST_ONLY;
1350 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1351 s->name, s->type, s->comment, s->domain));
1352 s->server_added = True;
1355 DEBUG(4,("%20s %8x %25s %15s\n",
1356 s->name, s->type, s->comment, s->domain));
1364 /*******************************************************************
1365 Fill in a server info structure.
1366 ******************************************************************/
1368 static int fill_srv_info(struct srv_info_struct *service,
1369 int uLevel, char **buf, int *buflen,
1370 char **stringbuf, int *stringspace, char *baseaddr)
1393 len = strlen(service->comment)+1;
1397 *buflen = struct_len;
1399 return struct_len + len;
1404 if (*buflen < struct_len) {
1411 p2 = p + struct_len;
1412 l2 = *buflen - struct_len;
1420 push_ascii(p,service->name, MAX_NETBIOSNAME_LEN, STR_TERMINATE);
1424 push_ascii(p,service->name,MAX_NETBIOSNAME_LEN, STR_TERMINATE);
1425 SIVAL(p,18,service->type);
1426 SIVAL(p,22,PTR_DIFF(p2,baseaddr));
1427 len += CopyAndAdvance(&p2,service->comment,&l2);
1432 *buf = p + struct_len;
1433 *buflen -= struct_len;
1444 static int srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
1446 return StrCaseCmp(s1->name,s2->name);
1449 /****************************************************************************
1450 View list of servers available (or possibly domains). The info is
1451 extracted from lists saved by nmbd on the local host.
1452 ****************************************************************************/
1454 static bool api_RNetServerEnum2(connection_struct *conn, uint16 vuid,
1455 char *param, int tpscnt,
1456 char *data, int tdscnt,
1457 int mdrcnt, int mprcnt, char **rdata,
1458 char **rparam, int *rdata_len, int *rparam_len)
1460 char *str1 = get_safe_str_ptr(param, tpscnt, param, 2);
1461 char *str2 = skip_string(param,tpscnt,str1);
1462 char *p = skip_string(param,tpscnt,str2);
1463 int uLevel = get_safe_SVAL(param, tpscnt, p, 0, -1);
1464 int buf_len = get_safe_SVAL(param,tpscnt, p, 2, 0);
1465 uint32 servertype = get_safe_IVAL(param,tpscnt,p,4, 0);
1467 int data_len, fixed_len, string_len;
1468 int f_len = 0, s_len = 0;
1469 struct srv_info_struct *servers=NULL;
1470 int counted=0,total=0;
1473 bool domain_request;
1476 if (!str1 || !str2 || !p) {
1480 /* If someone sets all the bits they don't really mean to set
1481 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1484 if (servertype == SV_TYPE_ALL) {
1485 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1488 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1489 any other bit (they may just set this bit on its own) they
1490 want all the locally seen servers. However this bit can be
1491 set on its own so set the requested servers to be
1492 ALL - DOMAIN_ENUM. */
1494 if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM)) {
1495 servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
1498 domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
1499 local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
1503 if (!prefix_ok(str1,"WrLehD")) {
1506 if (!check_server_info(uLevel,str2)) {
1510 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1511 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1512 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1514 if (strcmp(str1, "WrLehDz") == 0) {
1515 if (skip_string(param,tpscnt,p) == NULL) {
1518 pull_ascii_fstring(domain, p);
1520 fstrcpy(domain, lp_workgroup());
1523 DEBUG(4, ("domain [%s]\n", domain));
1525 if (lp_browse_list()) {
1526 total = get_server_info(servertype,&servers,domain);
1529 data_len = fixed_len = string_len = 0;
1532 TYPESAFE_QSORT(servers, total, srv_comp);
1535 char *lastname=NULL;
1537 for (i=0;i<total;i++) {
1538 struct srv_info_struct *s = &servers[i];
1540 if (lastname && strequal(lastname,s->name)) {
1544 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1545 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1546 i, s->name, s->type, s->comment, s->domain));
1548 if (data_len < buf_len) {
1551 string_len += s_len;
1558 *rdata_len = fixed_len + string_len;
1559 *rdata = smb_realloc_limit(*rdata,*rdata_len);
1564 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1570 char *lastname=NULL;
1571 int count2 = counted;
1573 for (i = 0; i < total && count2;i++) {
1574 struct srv_info_struct *s = &servers[i];
1576 if (lastname && strequal(lastname,s->name)) {
1580 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1581 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1582 i, s->name, s->type, s->comment, s->domain));
1588 *rparam = smb_realloc_limit(*rparam,*rparam_len);
1592 SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata));
1594 SSVAL(*rparam,4,counted);
1595 SSVAL(*rparam,6,counted+missed);
1599 DEBUG(3,("NetServerEnum2 domain = %s uLevel=%d counted=%d total=%d\n",
1600 domain,uLevel,counted,counted+missed));
1605 static int srv_name_match(const char *n1, const char *n2)
1608 * [MS-RAP] footnote <88> for Section 3.2.5.15 says:
1610 * In Windows, FirstNameToReturn need not be an exact match:
1611 * the server will return a list of servers that exist on
1612 * the network greater than or equal to the FirstNameToReturn.
1614 int ret = StrCaseCmp(n1, n2);
1623 static bool api_RNetServerEnum3(connection_struct *conn, uint16 vuid,
1624 char *param, int tpscnt,
1625 char *data, int tdscnt,
1626 int mdrcnt, int mprcnt, char **rdata,
1627 char **rparam, int *rdata_len, int *rparam_len)
1629 char *str1 = get_safe_str_ptr(param, tpscnt, param, 2);
1630 char *str2 = skip_string(param,tpscnt,str1);
1631 char *p = skip_string(param,tpscnt,str2);
1632 int uLevel = get_safe_SVAL(param, tpscnt, p, 0, -1);
1633 int buf_len = get_safe_SVAL(param,tpscnt, p, 2, 0);
1634 uint32 servertype = get_safe_IVAL(param,tpscnt,p,4, 0);
1636 int data_len, fixed_len, string_len;
1637 int f_len = 0, s_len = 0;
1638 struct srv_info_struct *servers=NULL;
1639 int counted=0,first=0,total=0;
1643 bool domain_request;
1646 if (!str1 || !str2 || !p) {
1650 /* If someone sets all the bits they don't really mean to set
1651 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1654 if (servertype == SV_TYPE_ALL) {
1655 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1658 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1659 any other bit (they may just set this bit on its own) they
1660 want all the locally seen servers. However this bit can be
1661 set on its own so set the requested servers to be
1662 ALL - DOMAIN_ENUM. */
1664 if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM)) {
1665 servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
1668 domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
1669 local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
1673 if (strcmp(str1, "WrLehDzz") != 0) {
1676 if (!check_server_info(uLevel,str2)) {
1680 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1681 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1682 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1684 if (skip_string(param,tpscnt,p) == NULL) {
1687 pull_ascii_fstring(domain, p);
1688 if (domain[0] == '\0') {
1689 fstrcpy(domain, lp_workgroup());
1691 p = skip_string(param,tpscnt,p);
1692 if (skip_string(param,tpscnt,p) == NULL) {
1695 pull_ascii_fstring(first_name, p);
1697 DEBUG(4, ("domain: '%s' first_name: '%s'\n",
1698 domain, first_name));
1700 if (lp_browse_list()) {
1701 total = get_server_info(servertype,&servers,domain);
1704 data_len = fixed_len = string_len = 0;
1707 TYPESAFE_QSORT(servers, total, srv_comp);
1709 if (first_name[0] != '\0') {
1710 struct srv_info_struct *first_server = NULL;
1712 BINARY_ARRAY_SEARCH(servers, total, name, first_name,
1713 srv_name_match, first_server);
1715 first = PTR_DIFF(first_server, servers) / sizeof(*servers);
1717 * The binary search may not find the exact match
1718 * so we need to search backward to find the first match
1720 * This implements the strange matching windows
1721 * implements. (see the comment in srv_name_match().
1725 ret = StrCaseCmp(first_name,
1726 servers[first-1].name);
1733 /* we should return no entries */
1739 char *lastname=NULL;
1741 for (i=first;i<total;i++) {
1742 struct srv_info_struct *s = &servers[i];
1744 if (lastname && strequal(lastname,s->name)) {
1748 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1749 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1750 i, s->name, s->type, s->comment, s->domain));
1752 if (data_len < buf_len) {
1755 string_len += s_len;
1762 *rdata_len = fixed_len + string_len;
1763 *rdata = smb_realloc_limit(*rdata,*rdata_len);
1768 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1774 char *lastname=NULL;
1775 int count2 = counted;
1777 for (i = first; i < total && count2;i++) {
1778 struct srv_info_struct *s = &servers[i];
1780 if (lastname && strequal(lastname,s->name)) {
1784 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1785 DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1786 i, s->name, s->type, s->comment, s->domain));
1792 *rparam = smb_realloc_limit(*rparam,*rparam_len);
1796 SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata));
1798 SSVAL(*rparam,4,counted);
1799 SSVAL(*rparam,6,counted+missed);
1801 DEBUG(3,("NetServerEnum3 domain = %s uLevel=%d first=%d[%s => %s] counted=%d total=%d\n",
1802 domain,uLevel,first,first_name,
1803 first < total ? servers[first].name : "",
1804 counted,counted+missed));
1811 /****************************************************************************
1812 command 0x34 - suspected of being a "Lookup Names" stub api
1813 ****************************************************************************/
1815 static bool api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid,
1816 char *param, int tpscnt,
1817 char *data, int tdscnt,
1818 int mdrcnt, int mprcnt, char **rdata,
1819 char **rparam, int *rdata_len, int *rparam_len)
1821 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
1822 char *str2 = skip_string(param,tpscnt,str1);
1823 char *p = skip_string(param,tpscnt,str2);
1824 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
1825 int buf_len = get_safe_SVAL(param,tpscnt,p,2,0);
1829 if (!str1 || !str2 || !p) {
1833 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1834 str1, str2, p, uLevel, buf_len));
1836 if (!prefix_ok(str1,"zWrLeh")) {
1843 *rparam = smb_realloc_limit(*rparam,*rparam_len);
1848 SSVAL(*rparam,0,0x08AC); /* informational warning message */
1850 SSVAL(*rparam,4,counted);
1851 SSVAL(*rparam,6,counted+missed);
1856 /****************************************************************************
1857 get info about a share
1858 ****************************************************************************/
1860 static bool check_share_info(int uLevel, char* id)
1864 if (strcmp(id,"B13") != 0) {
1869 /* Level-2 descriptor is allowed (and ignored) */
1870 if (strcmp(id,"B13BWz") != 0 &&
1871 strcmp(id,"B13BWzWWWzB9B") != 0) {
1876 if (strcmp(id,"B13BWzWWWzB9B") != 0) {
1881 if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) {
1891 static int fill_share_info(connection_struct *conn, int snum, int uLevel,
1892 char** buf, int* buflen,
1893 char** stringbuf, int* stringspace, char* baseaddr)
1922 len += StrlenExpanded(conn,snum,lp_comment(snum));
1925 len += strlen(lp_pathname(snum)) + 1;
1928 *buflen = struct_len;
1933 return struct_len + len;
1938 if ((*buflen) < struct_len) {
1946 p2 = p + struct_len;
1947 l2 = (*buflen) - struct_len;
1954 push_ascii(p,lp_servicename(snum),13, STR_TERMINATE);
1960 type = STYPE_DISKTREE;
1961 if (lp_print_ok(snum)) {
1962 type = STYPE_PRINTQ;
1964 if (strequal("IPC",lp_fstype(snum))) {
1967 SSVAL(p,14,type); /* device type */
1968 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1969 len += CopyExpanded(conn,snum,&p2,lp_comment(snum),&l2);
1973 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1974 SSVALS(p,22,-1); /* max uses */
1975 SSVAL(p,24,1); /* current uses */
1976 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1977 len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1978 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1982 memset(p+40,0,SHPWLEN+2);
1993 (*buf) = p + struct_len;
1994 (*buflen) -= struct_len;
1996 (*stringspace) = l2;
2005 static bool api_RNetShareGetInfo(connection_struct *conn,uint16 vuid,
2006 char *param, int tpscnt,
2007 char *data, int tdscnt,
2008 int mdrcnt,int mprcnt,
2009 char **rdata,char **rparam,
2010 int *rdata_len,int *rparam_len)
2012 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2013 char *str2 = skip_string(param,tpscnt,str1);
2014 char *netname = skip_string(param,tpscnt,str2);
2015 char *p = skip_string(param,tpscnt,netname);
2016 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
2019 if (!str1 || !str2 || !netname || !p) {
2023 snum = find_service(netname);
2028 /* check it's a supported varient */
2029 if (!prefix_ok(str1,"zWrLh")) {
2032 if (!check_share_info(uLevel,str2)) {
2036 *rdata = smb_realloc_limit(*rdata,mdrcnt);
2041 *rdata_len = fill_share_info(conn,snum,uLevel,&p,&mdrcnt,0,0,0);
2042 if (*rdata_len < 0) {
2047 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2051 SSVAL(*rparam,0,NERR_Success);
2052 SSVAL(*rparam,2,0); /* converter word */
2053 SSVAL(*rparam,4,*rdata_len);
2058 /****************************************************************************
2059 View the list of available shares.
2061 This function is the server side of the NetShareEnum() RAP call.
2062 It fills the return buffer with share names and share comments.
2063 Note that the return buffer normally (in all known cases) allows only
2064 twelve byte strings for share names (plus one for a nul terminator).
2065 Share names longer than 12 bytes must be skipped.
2066 ****************************************************************************/
2068 static bool api_RNetShareEnum( connection_struct *conn, uint16 vuid,
2069 char *param, int tpscnt,
2070 char *data, int tdscnt,
2078 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2079 char *str2 = skip_string(param,tpscnt,str1);
2080 char *p = skip_string(param,tpscnt,str2);
2081 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
2082 int buf_len = get_safe_SVAL(param,tpscnt,p,2,0);
2085 int total=0,counted=0;
2086 bool missed = False;
2088 int data_len, fixed_len, string_len;
2089 int f_len = 0, s_len = 0;
2091 if (!str1 || !str2 || !p) {
2095 if (!prefix_ok(str1,"WrLeh")) {
2098 if (!check_share_info(uLevel,str2)) {
2102 /* Ensure all the usershares are loaded. */
2104 load_registry_shares();
2105 count = load_usershare_shares();
2108 data_len = fixed_len = string_len = 0;
2109 for (i=0;i<count;i++) {
2110 fstring servicename_dos;
2111 if (!(lp_browseable(i) && lp_snum_ok(i))) {
2114 push_ascii_fstring(servicename_dos, lp_servicename(i));
2115 /* Maximum name length = 13. */
2116 if( lp_browseable( i ) && lp_snum_ok( i ) && (strlen(servicename_dos) < 13)) {
2118 data_len += fill_share_info(conn,i,uLevel,0,&f_len,0,&s_len,0);
2119 if (data_len < buf_len) {
2122 string_len += s_len;
2129 *rdata_len = fixed_len + string_len;
2130 *rdata = smb_realloc_limit(*rdata,*rdata_len);
2135 p2 = (*rdata) + fixed_len; /* auxiliary data (strings) will go here */
2140 for( i = 0; i < count; i++ ) {
2141 fstring servicename_dos;
2142 if (!(lp_browseable(i) && lp_snum_ok(i))) {
2146 push_ascii_fstring(servicename_dos, lp_servicename(i));
2147 if (lp_browseable(i) && lp_snum_ok(i) && (strlen(servicename_dos) < 13)) {
2148 if (fill_share_info( conn,i,uLevel,&p,&f_len,&p2,&s_len,*rdata ) < 0) {
2155 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2159 SSVAL(*rparam,0,missed ? ERRmoredata : NERR_Success);
2161 SSVAL(*rparam,4,counted);
2162 SSVAL(*rparam,6,total);
2164 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
2165 counted,total,uLevel,
2166 buf_len,*rdata_len,mdrcnt));
2171 /****************************************************************************
2173 ****************************************************************************/
2175 static bool api_RNetShareAdd(connection_struct *conn,uint16 vuid,
2176 char *param, int tpscnt,
2177 char *data, int tdscnt,
2178 int mdrcnt,int mprcnt,
2179 char **rdata,char **rparam,
2180 int *rdata_len,int *rparam_len)
2182 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2183 char *str2 = skip_string(param,tpscnt,str1);
2184 char *p = skip_string(param,tpscnt,str2);
2185 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
2188 char *pathname = NULL;
2189 char *command, *cmdname;
2190 unsigned int offset;
2193 size_t converted_size;
2195 if (!str1 || !str2 || !p) {
2199 /* check it's a supported varient */
2200 if (!prefix_ok(str1,RAP_WShareAdd_REQ)) {
2203 if (!check_share_info(uLevel,str2)) {
2210 /* Do we have a string ? */
2211 if (skip_string(data,mdrcnt,data) == NULL) {
2214 pull_ascii_fstring(sharename,data);
2215 snum = find_service(sharename);
2216 if (snum >= 0) { /* already exists */
2225 /* only support disk share adds */
2226 if (SVAL(data,14)!=STYPE_DISKTREE) {
2230 offset = IVAL(data, 16);
2231 if (offset >= mdrcnt) {
2232 res = ERRinvalidparam;
2236 /* Do we have a string ? */
2237 if (skip_string(data,mdrcnt,data+offset) == NULL) {
2240 pull_ascii_fstring(comment, offset? (data+offset) : "");
2242 offset = IVAL(data, 26);
2244 if (offset >= mdrcnt) {
2245 res = ERRinvalidparam;
2249 /* Do we have a string ? */
2250 if (skip_string(data,mdrcnt,data+offset) == NULL) {
2254 if (!pull_ascii_talloc(talloc_tos(), &pathname,
2255 offset ? (data+offset) : "", &converted_size))
2257 DEBUG(0,("api_RNetShareAdd: pull_ascii_talloc failed: %s",
2265 string_replace(sharename, '"', ' ');
2266 string_replace(pathname, '"', ' ');
2267 string_replace(comment, '"', ' ');
2269 cmdname = lp_add_share_cmd();
2271 if (!cmdname || *cmdname == '\0') {
2275 if (asprintf(&command, "%s \"%s\" \"%s\" \"%s\" \"%s\"",
2276 lp_add_share_cmd(), get_dyn_CONFIGFILE(), sharename,
2277 pathname, comment) == -1) {
2281 DEBUG(10,("api_RNetShareAdd: Running [%s]\n", command ));
2283 if ((res = smbrun(command, NULL)) != 0) {
2284 DEBUG(1,("api_RNetShareAdd: Running [%s] returned (%d)\n",
2291 message_send_all(smbd_messaging_context(),
2292 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
2296 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2300 SSVAL(*rparam,0,NERR_Success);
2301 SSVAL(*rparam,2,0); /* converter word */
2302 SSVAL(*rparam,4,*rdata_len);
2310 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2315 SSVAL(*rparam,0,res);
2320 /****************************************************************************
2321 view list of groups available
2322 ****************************************************************************/
2324 static bool api_RNetGroupEnum(connection_struct *conn,uint16 vuid,
2325 char *param, int tpscnt,
2326 char *data, int tdscnt,
2327 int mdrcnt,int mprcnt,
2328 char **rdata,char **rparam,
2329 int *rdata_len,int *rparam_len)
2333 int resume_context, cli_buf_size;
2334 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2335 char *str2 = skip_string(param,tpscnt,str1);
2336 char *p = skip_string(param,tpscnt,str2);
2338 uint32_t num_groups;
2339 uint32_t resume_handle;
2340 struct rpc_pipe_client *samr_pipe;
2341 struct policy_handle samr_handle, domain_handle;
2344 if (!str1 || !str2 || !p) {
2348 if (strcmp(str1,"WrLeh") != 0) {
2353 * W-> resume context (number of users to skip)
2354 * r -> return parameter pointer to receive buffer
2355 * L -> length of receive buffer
2356 * e -> return parameter number of entries
2357 * h -> return parameter total number of users
2360 if (strcmp("B21",str2) != 0) {
2364 status = rpc_pipe_open_internal(
2365 talloc_tos(), &ndr_table_samr.syntax_id, rpc_samr_dispatch,
2366 conn->server_info, &samr_pipe);
2367 if (!NT_STATUS_IS_OK(status)) {
2368 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2369 nt_errstr(status)));
2373 status = rpccli_samr_Connect2(samr_pipe, talloc_tos(), global_myname(),
2374 SAMR_ACCESS_LOOKUP_DOMAIN, &samr_handle);
2375 if (!NT_STATUS_IS_OK(status)) {
2376 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2377 nt_errstr(status)));
2381 status = rpccli_samr_OpenDomain(samr_pipe, talloc_tos(), &samr_handle,
2382 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS,
2383 get_global_sam_sid(), &domain_handle);
2384 if (!NT_STATUS_IS_OK(status)) {
2385 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2386 nt_errstr(status)));
2387 rpccli_samr_Close(samr_pipe, talloc_tos(), &samr_handle);
2391 resume_context = get_safe_SVAL(param,tpscnt,p,0,-1);
2392 cli_buf_size= get_safe_SVAL(param,tpscnt,p,2,0);
2393 DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: "
2394 "%d\n", resume_context, cli_buf_size));
2396 *rdata_len = cli_buf_size;
2397 *rdata = smb_realloc_limit(*rdata,*rdata_len);
2404 errflags = NERR_Success;
2409 struct samr_SamArray *sam_entries;
2410 uint32_t num_entries;
2412 status = rpccli_samr_EnumDomainGroups(samr_pipe, talloc_tos(),
2417 if (!NT_STATUS_IS_OK(status)) {
2418 DEBUG(10, ("rpccli_samr_EnumDomainGroups returned "
2419 "%s\n", nt_errstr(status)));
2423 if (num_entries == 0) {
2424 DEBUG(10, ("rpccli_samr_EnumDomainGroups returned "
2425 "no entries -- done\n"));
2429 for(i=0; i<num_entries; i++) {
2432 name = sam_entries->entries[i].name.string;
2434 if( ((PTR_DIFF(p,*rdata)+21) > *rdata_len) ) {
2435 /* set overflow error */
2436 DEBUG(3,("overflow on entry %d group %s\n", i,
2442 /* truncate the name at 21 chars. */
2444 strlcpy(p, name, 21);
2445 DEBUG(10,("adding entry %d group %s\n", i, p));
2447 p += 5; /* Both NT4 and W2k3SP1 do padding here. No
2452 if (errflags != NERR_Success) {
2456 TALLOC_FREE(sam_entries);
2459 rpccli_samr_Close(samr_pipe, talloc_tos(), &domain_handle);
2460 rpccli_samr_Close(samr_pipe, talloc_tos(), &samr_handle);
2462 *rdata_len = PTR_DIFF(p,*rdata);
2465 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2469 SSVAL(*rparam, 0, errflags);
2470 SSVAL(*rparam, 2, 0); /* converter word */
2471 SSVAL(*rparam, 4, num_groups); /* is this right?? */
2472 SSVAL(*rparam, 6, resume_context+num_groups); /* is this right?? */
2477 /*******************************************************************
2478 Get groups that a user is a member of.
2479 ******************************************************************/
2481 static bool api_NetUserGetGroups(connection_struct *conn,uint16 vuid,
2482 char *param, int tpscnt,
2483 char *data, int tdscnt,
2484 int mdrcnt,int mprcnt,
2485 char **rdata,char **rparam,
2486 int *rdata_len,int *rparam_len)
2488 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2489 char *str2 = skip_string(param,tpscnt,str1);
2490 char *UserName = skip_string(param,tpscnt,str2);
2491 char *p = skip_string(param,tpscnt,UserName);
2492 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
2493 const char *level_string;
2499 struct rpc_pipe_client *samr_pipe;
2500 struct policy_handle samr_handle, domain_handle, user_handle;
2501 struct lsa_String name;
2502 struct lsa_Strings names;
2503 struct samr_Ids type, rid;
2504 struct samr_RidWithAttributeArray *rids;
2507 if (!str1 || !str2 || !UserName || !p) {
2512 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2517 /* check it's a supported varient */
2519 if ( strcmp(str1,"zWrLeh") != 0 )
2524 level_string = "B21";
2530 if (strcmp(level_string,str2) != 0)
2533 *rdata_len = mdrcnt + 1024;
2534 *rdata = smb_realloc_limit(*rdata,*rdata_len);
2539 SSVAL(*rparam,0,NERR_Success);
2540 SSVAL(*rparam,2,0); /* converter word */
2543 endp = *rdata + *rdata_len;
2545 status = rpc_pipe_open_internal(
2546 talloc_tos(), &ndr_table_samr.syntax_id, rpc_samr_dispatch,
2547 conn->server_info, &samr_pipe);
2548 if (!NT_STATUS_IS_OK(status)) {
2549 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2550 nt_errstr(status)));
2554 status = rpccli_samr_Connect2(samr_pipe, talloc_tos(), global_myname(),
2555 SAMR_ACCESS_LOOKUP_DOMAIN, &samr_handle);
2556 if (!NT_STATUS_IS_OK(status)) {
2557 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2558 nt_errstr(status)));
2562 status = rpccli_samr_OpenDomain(samr_pipe, talloc_tos(), &samr_handle,
2563 SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
2564 get_global_sam_sid(), &domain_handle);
2565 if (!NT_STATUS_IS_OK(status)) {
2566 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2567 nt_errstr(status)));
2571 name.string = UserName;
2573 status = rpccli_samr_LookupNames(samr_pipe, talloc_tos(),
2574 &domain_handle, 1, &name,
2576 if (!NT_STATUS_IS_OK(status)) {
2577 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2578 nt_errstr(status)));
2582 if (type.ids[0] != SID_NAME_USER) {
2583 DEBUG(10, ("%s is a %s, not a user\n", UserName,
2584 sid_type_lookup(type.ids[0])));
2588 status = rpccli_samr_OpenUser(samr_pipe, talloc_tos(),
2590 SAMR_USER_ACCESS_GET_GROUPS,
2591 rid.ids[0], &user_handle);
2592 if (!NT_STATUS_IS_OK(status)) {
2593 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2594 nt_errstr(status)));
2598 status = rpccli_samr_GetGroupsForUser(samr_pipe, talloc_tos(),
2599 &user_handle, &rids);
2600 if (!NT_STATUS_IS_OK(status)) {
2601 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2602 nt_errstr(status)));
2606 for (i=0; i<rids->count; i++) {
2608 status = rpccli_samr_LookupRids(samr_pipe, talloc_tos(),
2610 1, &rids->rids[i].rid,
2612 if (NT_STATUS_IS_OK(status) && (names.count == 1)) {
2613 strlcpy(p, names.names[0].string, PTR_DIFF(endp,p));
2619 *rdata_len = PTR_DIFF(p,*rdata);
2621 SSVAL(*rparam,4,count); /* is this right?? */
2622 SSVAL(*rparam,6,count); /* is this right?? */
2627 rpccli_samr_Close(samr_pipe, talloc_tos(), &user_handle);
2629 rpccli_samr_Close(samr_pipe, talloc_tos(), &domain_handle);
2631 rpccli_samr_Close(samr_pipe, talloc_tos(), &samr_handle);
2636 /*******************************************************************
2638 ******************************************************************/
2640 static bool api_RNetUserEnum(connection_struct *conn, uint16 vuid,
2641 char *param, int tpscnt,
2642 char *data, int tdscnt,
2643 int mdrcnt,int mprcnt,
2644 char **rdata,char **rparam,
2645 int *rdata_len,int *rparam_len)
2650 int i, resume_context, cli_buf_size;
2651 uint32_t resume_handle;
2653 struct rpc_pipe_client *samr_pipe;
2654 struct policy_handle samr_handle, domain_handle;
2657 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2658 char *str2 = skip_string(param,tpscnt,str1);
2659 char *p = skip_string(param,tpscnt,str2);
2662 if (!str1 || !str2 || !p) {
2666 if (strcmp(str1,"WrLeh") != 0)
2669 * W-> resume context (number of users to skip)
2670 * r -> return parameter pointer to receive buffer
2671 * L -> length of receive buffer
2672 * e -> return parameter number of entries
2673 * h -> return parameter total number of users
2676 resume_context = get_safe_SVAL(param,tpscnt,p,0,-1);
2677 cli_buf_size= get_safe_SVAL(param,tpscnt,p,2,0);
2678 DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n",
2679 resume_context, cli_buf_size));
2682 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2687 /* check it's a supported varient */
2688 if (strcmp("B21",str2) != 0)
2691 *rdata_len = cli_buf_size;
2692 *rdata = smb_realloc_limit(*rdata,*rdata_len);
2698 endp = *rdata + *rdata_len;
2700 status = rpc_pipe_open_internal(
2701 talloc_tos(), &ndr_table_samr.syntax_id, rpc_samr_dispatch,
2702 conn->server_info, &samr_pipe);
2703 if (!NT_STATUS_IS_OK(status)) {
2704 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2705 nt_errstr(status)));
2709 status = rpccli_samr_Connect2(samr_pipe, talloc_tos(), global_myname(),
2710 SAMR_ACCESS_LOOKUP_DOMAIN, &samr_handle);
2711 if (!NT_STATUS_IS_OK(status)) {
2712 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2713 nt_errstr(status)));
2717 status = rpccli_samr_OpenDomain(samr_pipe, talloc_tos(), &samr_handle,
2718 SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS,
2719 get_global_sam_sid(), &domain_handle);
2720 if (!NT_STATUS_IS_OK(status)) {
2721 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2722 nt_errstr(status)));
2723 rpccli_samr_Close(samr_pipe, talloc_tos(), &samr_handle);
2727 errflags=NERR_Success;
2732 struct samr_SamArray *sam_entries;
2733 uint32_t num_entries;
2735 status = rpccli_samr_EnumDomainUsers(samr_pipe, talloc_tos(),
2741 if (!NT_STATUS_IS_OK(status)) {
2742 DEBUG(10, ("rpccli_samr_EnumDomainUsers returned "
2743 "%s\n", nt_errstr(status)));
2747 if (num_entries == 0) {
2748 DEBUG(10, ("rpccli_samr_EnumDomainUsers returned "
2749 "no entries -- done\n"));
2753 for (i=0; i<num_entries; i++) {
2756 name = sam_entries->entries[i].name.string;
2758 if(((PTR_DIFF(p,*rdata)+21)<=*rdata_len)
2759 &&(strlen(name)<=21)) {
2760 strlcpy(p,name,PTR_DIFF(endp,p));
2761 DEBUG(10,("api_RNetUserEnum:adding entry %d "
2762 "username %s\n",count_sent,p));
2766 /* set overflow error */
2767 DEBUG(10,("api_RNetUserEnum:overflow on entry %d "
2768 "username %s\n",count_sent,name));
2774 if (errflags != NERR_Success) {
2778 TALLOC_FREE(sam_entries);
2781 rpccli_samr_Close(samr_pipe, talloc_tos(), &domain_handle);
2782 rpccli_samr_Close(samr_pipe, talloc_tos(), &samr_handle);
2784 *rdata_len = PTR_DIFF(p,*rdata);
2786 SSVAL(*rparam,0,errflags);
2787 SSVAL(*rparam,2,0); /* converter word */
2788 SSVAL(*rparam,4,count_sent); /* is this right?? */
2789 SSVAL(*rparam,6,num_users); /* is this right?? */
2794 /****************************************************************************
2795 Get the time of day info.
2796 ****************************************************************************/
2798 static bool api_NetRemoteTOD(connection_struct *conn,uint16 vuid,
2799 char *param, int tpscnt,
2800 char *data, int tdscnt,
2801 int mdrcnt,int mprcnt,
2802 char **rdata,char **rparam,
2803 int *rdata_len,int *rparam_len)
2806 time_t unixdate = time(NULL);
2810 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2816 *rdata = smb_realloc_limit(*rdata,*rdata_len);
2821 SSVAL(*rparam,0,NERR_Success);
2822 SSVAL(*rparam,2,0); /* converter word */
2826 srv_put_dos_date3(p,0,unixdate); /* this is the time that is looked at
2827 by NT in a "net time" operation,
2828 it seems to ignore the one below */
2830 /* the client expects to get localtime, not GMT, in this bit
2831 (I think, this needs testing) */
2832 t = localtime(&unixdate);
2837 SIVAL(p,4,0); /* msecs ? */
2838 SCVAL(p,8,t->tm_hour);
2839 SCVAL(p,9,t->tm_min);
2840 SCVAL(p,10,t->tm_sec);
2841 SCVAL(p,11,0); /* hundredths of seconds */
2842 SSVALS(p,12,get_time_zone(unixdate)/60); /* timezone in minutes from GMT */
2843 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
2844 SCVAL(p,16,t->tm_mday);
2845 SCVAL(p,17,t->tm_mon + 1);
2846 SSVAL(p,18,1900+t->tm_year);
2847 SCVAL(p,20,t->tm_wday);
2852 /****************************************************************************
2853 Set the user password.
2854 *****************************************************************************/
2856 static bool api_SetUserPassword(connection_struct *conn,uint16 vuid,
2857 char *param, int tpscnt,
2858 char *data, int tdscnt,
2859 int mdrcnt,int mprcnt,
2860 char **rdata,char **rparam,
2861 int *rdata_len,int *rparam_len)
2863 char *np = get_safe_str_ptr(param,tpscnt,param,2);
2866 fstring pass1,pass2;
2868 /* Skip 2 strings. */
2869 p = skip_string(param,tpscnt,np);
2870 p = skip_string(param,tpscnt,p);
2876 /* Do we have a string ? */
2877 if (skip_string(param,tpscnt,p) == NULL) {
2880 pull_ascii_fstring(user,p);
2882 p = skip_string(param,tpscnt,p);
2887 memset(pass1,'\0',sizeof(pass1));
2888 memset(pass2,'\0',sizeof(pass2));
2890 * We use 31 here not 32 as we're checking
2891 * the last byte we want to access is safe.
2893 if (!is_offset_safe(param,tpscnt,p,31)) {
2897 memcpy(pass2,p+16,16);
2900 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2907 SSVAL(*rparam,0,NERR_badpass);
2908 SSVAL(*rparam,2,0); /* converter word */
2910 DEBUG(3,("Set password for <%s>\n",user));
2913 * Attempt to verify the old password against smbpasswd entries
2914 * Win98 clients send old and new password in plaintext for this call.
2918 struct auth_serversupplied_info *server_info = NULL;
2919 DATA_BLOB password = data_blob(pass1, strlen(pass1)+1);
2921 if (NT_STATUS_IS_OK(check_plaintext_password(user,password,&server_info))) {
2924 if (NT_STATUS_IS_OK(change_oem_password(server_info->sam_account, pass1, pass2, False, NULL))) {
2925 SSVAL(*rparam,0,NERR_Success);
2929 TALLOC_FREE(server_info);
2931 data_blob_clear_free(&password);
2935 * If the plaintext change failed, attempt
2936 * the old encrypted method. NT will generate this
2937 * after trying the samr method. Note that this
2938 * method is done as a last resort as this
2939 * password change method loses the NT password hash
2940 * and cannot change the UNIX password as no plaintext
2944 if(SVAL(*rparam,0) != NERR_Success) {
2945 struct samu *hnd = NULL;
2947 if (check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &hnd)) {
2949 if (change_lanman_password(hnd,(uchar *)pass2)) {
2950 SSVAL(*rparam,0,NERR_Success);
2957 memset((char *)pass1,'\0',sizeof(fstring));
2958 memset((char *)pass2,'\0',sizeof(fstring));
2963 /****************************************************************************
2964 Set the user password (SamOEM version - gets plaintext).
2965 ****************************************************************************/
2967 static bool api_SamOEMChangePassword(connection_struct *conn,uint16 vuid,
2968 char *param, int tpscnt,
2969 char *data, int tdscnt,
2970 int mdrcnt,int mprcnt,
2971 char **rdata,char **rparam,
2972 int *rdata_len,int *rparam_len)
2974 struct smbd_server_connection *sconn = smbd_server_conn;
2976 char *p = get_safe_str_ptr(param,tpscnt,param,2);
2978 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2988 SSVAL(*rparam,0,NERR_badpass);
2991 * Check the parameter definition is correct.
2994 /* Do we have a string ? */
2995 if (skip_string(param,tpscnt,p) == 0) {
2998 if(!strequal(p, "zsT")) {
2999 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", p));
3002 p = skip_string(param, tpscnt, p);
3007 /* Do we have a string ? */
3008 if (skip_string(param,tpscnt,p) == 0) {
3011 if(!strequal(p, "B516B16")) {
3012 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p));
3015 p = skip_string(param,tpscnt,p);
3019 /* Do we have a string ? */
3020 if (skip_string(param,tpscnt,p) == 0) {
3023 p += pull_ascii_fstring(user,p);
3025 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user));
3028 * Pass the user through the NT -> unix user mapping
3032 (void)map_username(sconn, user);
3034 if (NT_STATUS_IS_OK(pass_oem_change(user, (uchar*) data, (uchar *)&data[516], NULL, NULL, NULL))) {
3035 SSVAL(*rparam,0,NERR_Success);
3041 /****************************************************************************
3044 ****************************************************************************/
3046 static bool api_RDosPrintJobDel(connection_struct *conn,uint16 vuid,
3047 char *param, int tpscnt,
3048 char *data, int tdscnt,
3049 int mdrcnt,int mprcnt,
3050 char **rdata,char **rparam,
3051 int *rdata_len,int *rparam_len)
3053 int function = get_safe_SVAL(param,tpscnt,param,0,0);
3054 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3055 char *str2 = skip_string(param,tpscnt,str1);
3056 char *p = skip_string(param,tpscnt,str2);
3060 WERROR werr = WERR_OK;
3062 TALLOC_CTX *mem_ctx = talloc_tos();
3064 struct rpc_pipe_client *cli = NULL;
3065 struct policy_handle handle;
3066 struct spoolss_DevmodeContainer devmode_ctr;
3067 enum spoolss_JobControl command;
3069 if (!str1 || !str2 || !p) {
3073 * We use 1 here not 2 as we're checking
3074 * the last byte we want to access is safe.
3076 if (!is_offset_safe(param,tpscnt,p,1)) {
3079 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
3082 /* check it's a supported varient */
3083 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
3087 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3093 ZERO_STRUCT(handle);
3095 status = rpc_pipe_open_internal(mem_ctx, &ndr_table_spoolss.syntax_id,
3096 rpc_spoolss_dispatch, conn->server_info,
3098 if (!NT_STATUS_IS_OK(status)) {
3099 DEBUG(0,("api_RDosPrintJobDel: could not connect to spoolss: %s\n",
3100 nt_errstr(status)));
3101 errcode = W_ERROR_V(ntstatus_to_werror(status));
3105 ZERO_STRUCT(devmode_ctr);
3107 status = rpccli_spoolss_OpenPrinter(cli, mem_ctx,
3111 SEC_FLAG_MAXIMUM_ALLOWED,
3114 if (!NT_STATUS_IS_OK(status)) {
3115 errcode = W_ERROR_V(ntstatus_to_werror(status));
3118 if (!W_ERROR_IS_OK(werr)) {
3119 errcode = W_ERROR_V(werr);
3123 /* FIXME: formerly NERR_JobNotFound was returned if job did not exist
3124 * and NERR_DestNotFound if share did not exist */
3126 errcode = NERR_Success;
3129 case 81: /* delete */
3130 command = SPOOLSS_JOB_CONTROL_DELETE;
3132 case 82: /* pause */
3133 command = SPOOLSS_JOB_CONTROL_PAUSE;
3135 case 83: /* resume */
3136 command = SPOOLSS_JOB_CONTROL_RESUME;
3139 errcode = NERR_notsupported;
3143 status = rpccli_spoolss_SetJob(cli, mem_ctx,
3146 NULL, /* unique ptr ctr */
3149 if (!NT_STATUS_IS_OK(status)) {
3150 errcode = W_ERROR_V(ntstatus_to_werror(status));
3153 if (!W_ERROR_IS_OK(werr)) {
3154 errcode = W_ERROR_V(werr);
3159 if (is_valid_policy_hnd(&handle)) {
3160 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
3163 SSVAL(*rparam,0,errcode);
3164 SSVAL(*rparam,2,0); /* converter word */
3169 /****************************************************************************
3170 Purge a print queue - or pause or resume it.
3171 ****************************************************************************/
3173 static bool api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid,
3174 char *param, int tpscnt,
3175 char *data, int tdscnt,
3176 int mdrcnt,int mprcnt,
3177 char **rdata,char **rparam,
3178 int *rdata_len,int *rparam_len)
3180 int function = get_safe_SVAL(param,tpscnt,param,0,0);
3181 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3182 char *str2 = skip_string(param,tpscnt,str1);
3183 char *QueueName = skip_string(param,tpscnt,str2);
3184 int errcode = NERR_notsupported;
3185 WERROR werr = WERR_OK;
3188 TALLOC_CTX *mem_ctx = talloc_tos();
3189 struct rpc_pipe_client *cli = NULL;
3190 struct policy_handle handle;
3191 struct spoolss_SetPrinterInfoCtr info_ctr;
3192 struct spoolss_DevmodeContainer devmode_ctr;
3193 struct sec_desc_buf secdesc_ctr;
3194 enum spoolss_PrinterControl command;
3196 if (!str1 || !str2 || !QueueName) {
3200 /* check it's a supported varient */
3201 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
3205 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3211 if (skip_string(param,tpscnt,QueueName) == NULL) {
3215 ZERO_STRUCT(handle);
3217 status = rpc_pipe_open_internal(mem_ctx, &ndr_table_spoolss.syntax_id,
3218 rpc_spoolss_dispatch, conn->server_info,
3220 if (!NT_STATUS_IS_OK(status)) {
3221 DEBUG(0,("api_WPrintQueueCtrl: could not connect to spoolss: %s\n",
3222 nt_errstr(status)));
3223 errcode = W_ERROR_V(ntstatus_to_werror(status));
3227 ZERO_STRUCT(devmode_ctr);
3229 status = rpccli_spoolss_OpenPrinter(cli, mem_ctx,
3233 SEC_FLAG_MAXIMUM_ALLOWED,
3236 if (!NT_STATUS_IS_OK(status)) {
3237 errcode = W_ERROR_V(ntstatus_to_werror(status));
3240 if (!W_ERROR_IS_OK(werr)) {
3241 errcode = W_ERROR_V(werr);
3246 case 74: /* Pause queue */
3247 command = SPOOLSS_PRINTER_CONTROL_PAUSE;
3249 case 75: /* Resume queue */
3250 command = SPOOLSS_PRINTER_CONTROL_RESUME;
3252 case 103: /* Purge */
3253 command = SPOOLSS_PRINTER_CONTROL_PURGE;
3256 werr = WERR_NOT_SUPPORTED;
3260 if (!W_ERROR_IS_OK(werr)) {
3261 errcode = W_ERROR_V(werr);
3265 ZERO_STRUCT(info_ctr);
3266 ZERO_STRUCT(secdesc_ctr);
3268 status = rpccli_spoolss_SetPrinter(cli, mem_ctx,
3275 if (!NT_STATUS_IS_OK(status)) {
3276 errcode = W_ERROR_V(ntstatus_to_werror(status));
3279 if (!W_ERROR_IS_OK(werr)) {
3280 errcode = W_ERROR_V(werr);
3284 errcode = W_ERROR_V(werr);
3288 if (is_valid_policy_hnd(&handle)) {
3289 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
3292 SSVAL(*rparam,0,errcode);
3293 SSVAL(*rparam,2,0); /* converter word */
3298 /****************************************************************************
3299 set the property of a print job (undocumented?)
3300 ? function = 0xb -> set name of print job
3301 ? function = 0x6 -> move print job up/down
3302 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
3303 or <WWsTP> <WB21BB16B10zWWzDDz>
3304 ****************************************************************************/
3306 static int check_printjob_info(struct pack_desc* desc,
3307 int uLevel, char* id)
3309 desc->subformat = NULL;
3311 case 0: desc->format = "W"; break;
3312 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
3313 case 2: desc->format = "WWzWWDDzz"; break;
3314 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
3315 case 4: desc->format = "WWzWWDDzzzzzDDDDDDD"; break;
3317 DEBUG(0,("check_printjob_info: invalid level %d\n",
3321 if (id == NULL || strcmp(desc->format,id) != 0) {
3322 DEBUG(0,("check_printjob_info: invalid format %s\n",
3323 id ? id : "<NULL>" ));
3329 static bool api_PrintJobInfo(connection_struct *conn, uint16 vuid,
3330 char *param, int tpscnt,
3331 char *data, int tdscnt,
3332 int mdrcnt,int mprcnt,
3333 char **rdata,char **rparam,
3334 int *rdata_len,int *rparam_len)
3336 struct pack_desc desc;
3337 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3338 char *str2 = skip_string(param,tpscnt,str1);
3339 char *p = skip_string(param,tpscnt,str2);
3342 int uLevel = get_safe_SVAL(param,tpscnt,p,2,-1);
3343 int function = get_safe_SVAL(param,tpscnt,p,4,-1);
3346 if (!str1 || !str2 || !p) {
3350 * We use 1 here not 2 as we're checking
3351 * the last byte we want to access is safe.
3353 if (!is_offset_safe(param,tpscnt,p,1)) {
3356 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
3359 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3364 if (!share_defined(sharename)) {
3365 DEBUG(0,("api_PrintJobInfo: sharen [%s] not defined\n",
3372 /* check it's a supported varient */
3373 if ((strcmp(str1,"WWsTP")) ||
3374 (!check_printjob_info(&desc,uLevel,str2)))
3377 if (!print_job_exists(sharename, jobid)) {
3378 errcode=NERR_JobNotFound;
3382 errcode = NERR_notsupported;
3386 /* change job place in the queue,
3387 data gives the new place */
3388 place = SVAL(data,0);
3389 if (print_job_set_place(sharename, jobid, place)) {
3390 errcode=NERR_Success;
3395 /* change print job name, data gives the name */
3396 if (print_job_set_name(sharename, jobid, data)) {
3397 errcode=NERR_Success;
3406 SSVALS(*rparam,0,errcode);
3407 SSVAL(*rparam,2,0); /* converter word */
3413 /****************************************************************************
3414 Get info about the server.
3415 ****************************************************************************/
3417 static bool api_RNetServerGetInfo(connection_struct *conn,uint16 vuid,
3418 char *param, int tpscnt,
3419 char *data, int tdscnt,
3420 int mdrcnt,int mprcnt,
3421 char **rdata,char **rparam,
3422 int *rdata_len,int *rparam_len)
3424 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3425 char *str2 = skip_string(param,tpscnt,str1);
3426 char *p = skip_string(param,tpscnt,str2);
3427 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
3431 if (!str1 || !str2 || !p) {
3435 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
3437 /* check it's a supported varient */
3438 if (!prefix_ok(str1,"WrLh")) {
3444 if (strcmp(str2,"B16") != 0) {
3450 if (strcmp(str2,"B16BBDz") != 0) {
3456 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")!= 0) {
3462 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz") != 0) {
3468 if (strcmp(str2,"DN") != 0) {
3474 if (strcmp(str2,"B16BBDzWWzzz") != 0) {
3483 *rdata_len = mdrcnt;
3484 *rdata = smb_realloc_limit(*rdata,*rdata_len);
3490 p2 = p + struct_len;
3492 srvstr_push(NULL, 0, p,global_myname(),16,
3493 STR_ASCII|STR_UPPER|STR_TERMINATE);
3497 struct srv_info_struct *servers=NULL;
3499 char *comment = NULL;
3500 TALLOC_CTX *ctx = talloc_tos();
3501 uint32 servertype= lp_default_server_announce();
3503 comment = talloc_strdup(ctx,lp_serverstring());
3508 if ((count=get_server_info(SV_TYPE_ALL,&servers,lp_workgroup()))>0) {
3509 for (i=0;i<count;i++) {
3510 if (strequal(servers[i].name,global_myname())) {
3511 servertype = servers[i].type;
3512 TALLOC_FREE(comment);
3513 comment = talloc_strdup(ctx,
3514 servers[i].comment);
3524 SCVAL(p,0,lp_major_announce_version());
3525 SCVAL(p,1,lp_minor_announce_version());
3526 SIVAL(p,2,servertype);
3528 if (mdrcnt == struct_len) {
3531 SIVAL(p,6,PTR_DIFF(p2,*rdata));
3532 comment = talloc_sub_advanced(
3534 lp_servicename(SNUM(conn)),
3535 conn->server_info->unix_name,
3537 conn->server_info->utok.gid,
3538 conn->server_info->sanitized_username,
3539 pdb_get_domain(conn->server_info->sam_account),
3544 if (mdrcnt - struct_len <= 0) {
3549 MIN(mdrcnt - struct_len,
3550 MAX_SERVER_STRING_LENGTH),
3552 p2 = skip_string(*rdata,*rdata_len,p2);
3560 return False; /* not yet implemented */
3563 *rdata_len = PTR_DIFF(p2,*rdata);
3566 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3570 SSVAL(*rparam,0,NERR_Success);
3571 SSVAL(*rparam,2,0); /* converter word */
3572 SSVAL(*rparam,4,*rdata_len);
3577 /****************************************************************************
3578 Get info about the server.
3579 ****************************************************************************/
3581 static bool api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid,
3582 char *param, int tpscnt,
3583 char *data, int tdscnt,
3584 int mdrcnt,int mprcnt,
3585 char **rdata,char **rparam,
3586 int *rdata_len,int *rparam_len)
3588 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3589 char *str2 = skip_string(param,tpscnt,str1);
3590 char *p = skip_string(param,tpscnt,str2);
3593 int level = get_safe_SVAL(param,tpscnt,p,0,-1);
3595 if (!str1 || !str2 || !p) {
3599 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
3602 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3607 /* check it's a supported varient */
3608 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz"))) {
3612 *rdata_len = mdrcnt + 1024;
3613 *rdata = smb_realloc_limit(*rdata,*rdata_len);
3618 SSVAL(*rparam,0,NERR_Success);
3619 SSVAL(*rparam,2,0); /* converter word */
3622 endp = *rdata + *rdata_len;
3624 p2 = get_safe_ptr(*rdata,*rdata_len,p,22);
3629 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
3630 strlcpy(p2,get_local_machine_name(),PTR_DIFF(endp,p2));
3632 p2 = skip_string(*rdata,*rdata_len,p2);
3638 SIVAL(p,0,PTR_DIFF(p2,*rdata));
3639 strlcpy(p2,conn->server_info->sanitized_username,PTR_DIFF(endp,p2));
3640 p2 = skip_string(*rdata,*rdata_len,p2);
3646 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
3647 strlcpy(p2,lp_workgroup(),PTR_DIFF(endp,p2));
3649 p2 = skip_string(*rdata,*rdata_len,p2);
3655 SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
3656 SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
3659 SIVAL(p,0,PTR_DIFF(p2,*rdata));
3660 strlcpy(p2,lp_workgroup(),PTR_DIFF(endp,p2)); /* don't know. login domain?? */
3661 p2 = skip_string(*rdata,*rdata_len,p2);
3667 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
3668 strlcpy(p2,"",PTR_DIFF(endp,p2));
3669 p2 = skip_string(*rdata,*rdata_len,p2);
3675 *rdata_len = PTR_DIFF(p2,*rdata);
3677 SSVAL(*rparam,4,*rdata_len);
3682 /****************************************************************************
3683 get info about a user
3685 struct user_info_11 {
3686 char usri11_name[21]; 0-20
3688 char *usri11_comment; 22-25
3689 char *usri11_usr_comment; 26-29
3690 unsigned short usri11_priv; 30-31
3691 unsigned long usri11_auth_flags; 32-35
3692 long usri11_password_age; 36-39
3693 char *usri11_homedir; 40-43
3694 char *usri11_parms; 44-47
3695 long usri11_last_logon; 48-51
3696 long usri11_last_logoff; 52-55
3697 unsigned short usri11_bad_pw_count; 56-57
3698 unsigned short usri11_num_logons; 58-59
3699 char *usri11_logon_server; 60-63
3700 unsigned short usri11_country_code; 64-65
3701 char *usri11_workstations; 66-69
3702 unsigned long usri11_max_storage; 70-73
3703 unsigned short usri11_units_per_week; 74-75
3704 unsigned char *usri11_logon_hours; 76-79
3705 unsigned short usri11_code_page; 80-81
3710 usri11_name specifies the user name for which information is retrieved
3712 usri11_pad aligns the next data structure element to a word boundary
3714 usri11_comment is a null terminated ASCII comment
3716 usri11_user_comment is a null terminated ASCII comment about the user
3718 usri11_priv specifies the level of the privilege assigned to the user.
3719 The possible values are:
3721 Name Value Description
3722 USER_PRIV_GUEST 0 Guest privilege
3723 USER_PRIV_USER 1 User privilege
3724 USER_PRV_ADMIN 2 Administrator privilege
3726 usri11_auth_flags specifies the account operator privileges. The
3727 possible values are:
3729 Name Value Description
3730 AF_OP_PRINT 0 Print operator
3733 Leach, Naik [Page 28]
3737 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
3740 AF_OP_COMM 1 Communications operator
3741 AF_OP_SERVER 2 Server operator
3742 AF_OP_ACCOUNTS 3 Accounts operator
3745 usri11_password_age specifies how many seconds have elapsed since the
3746 password was last changed.
3748 usri11_home_dir points to a null terminated ASCII string that contains
3749 the path name of the user's home directory.
3751 usri11_parms points to a null terminated ASCII string that is set
3752 aside for use by applications.
3754 usri11_last_logon specifies the time when the user last logged on.
3755 This value is stored as the number of seconds elapsed since
3756 00:00:00, January 1, 1970.
3758 usri11_last_logoff specifies the time when the user last logged off.
3759 This value is stored as the number of seconds elapsed since
3760 00:00:00, January 1, 1970. A value of 0 means the last logoff
3763 usri11_bad_pw_count specifies the number of incorrect passwords
3764 entered since the last successful logon.
3766 usri11_log1_num_logons specifies the number of times this user has
3767 logged on. A value of -1 means the number of logons is unknown.
3769 usri11_logon_server points to a null terminated ASCII string that
3770 contains the name of the server to which logon requests are sent.
3771 A null string indicates logon requests should be sent to the
3774 usri11_country_code specifies the country code for the user's language
3777 usri11_workstations points to a null terminated ASCII string that
3778 contains the names of workstations the user may log on from.
3779 There may be up to 8 workstations, with the names separated by
3780 commas. A null strings indicates there are no restrictions.
3782 usri11_max_storage specifies the maximum amount of disk space the user
3783 can occupy. A value of 0xffffffff indicates there are no
3786 usri11_units_per_week specifies the equal number of time units into
3787 which a week is divided. This value must be equal to 168.
3789 usri11_logon_hours points to a 21 byte (168 bits) string that
3790 specifies the time during which the user can log on. Each bit
3791 represents one unique hour in a week. The first bit (bit 0, word
3792 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
3796 Leach, Naik [Page 29]
3800 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
3803 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
3804 are no restrictions.
3806 usri11_code_page specifies the code page for the user's language of
3809 All of the pointers in this data structure need to be treated
3810 specially. The pointer is a 32 bit pointer. The higher 16 bits need
3811 to be ignored. The converter word returned in the parameters section
3812 needs to be subtracted from the lower 16 bits to calculate an offset
3813 into the return buffer where this ASCII string resides.
3815 There is no auxiliary data in the response.
3817 ****************************************************************************/
3819 #define usri11_name 0
3820 #define usri11_pad 21
3821 #define usri11_comment 22
3822 #define usri11_usr_comment 26
3823 #define usri11_full_name 30
3824 #define usri11_priv 34
3825 #define usri11_auth_flags 36
3826 #define usri11_password_age 40
3827 #define usri11_homedir 44
3828 #define usri11_parms 48
3829 #define usri11_last_logon 52
3830 #define usri11_last_logoff 56
3831 #define usri11_bad_pw_count 60
3832 #define usri11_num_logons 62
3833 #define usri11_logon_server 64
3834 #define usri11_country_code 68
3835 #define usri11_workstations 70
3836 #define usri11_max_storage 74
3837 #define usri11_units_per_week 78
3838 #define usri11_logon_hours 80
3839 #define usri11_code_page 84
3840 #define usri11_end 86
3842 #define USER_PRIV_GUEST 0
3843 #define USER_PRIV_USER 1
3844 #define USER_PRIV_ADMIN 2
3846 #define AF_OP_PRINT 0
3847 #define AF_OP_COMM 1
3848 #define AF_OP_SERVER 2
3849 #define AF_OP_ACCOUNTS 3
3852 static bool api_RNetUserGetInfo(connection_struct *conn, uint16 vuid,
3853 char *param, int tpscnt,
3854 char *data, int tdscnt,
3855 int mdrcnt,int mprcnt,
3856 char **rdata,char **rparam,
3857 int *rdata_len,int *rparam_len)
3859 struct smbd_server_connection *sconn = smbd_server_conn;
3860 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3861 char *str2 = skip_string(param,tpscnt,str1);
3862 char *UserName = skip_string(param,tpscnt,str2);
3863 char *p = skip_string(param,tpscnt,UserName);
3864 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
3867 const char *level_string;
3869 /* get NIS home of a previously validated user - simeon */
3870 /* With share level security vuid will always be zero.
3871 Don't depend on vuser being non-null !!. JRA */
3872 user_struct *vuser = get_valid_user_struct(sconn, vuid);
3874 DEBUG(3,(" Username of UID %d is %s\n",
3875 (int)vuser->server_info->utok.uid,
3876 vuser->server_info->unix_name));
3879 if (!str1 || !str2 || !UserName || !p) {
3884 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3889 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
3891 /* check it's a supported variant */
3892 if (strcmp(str1,"zWrLh") != 0) {
3896 case 0: level_string = "B21"; break;
3897 case 1: level_string = "B21BB16DWzzWz"; break;
3898 case 2: level_string = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
3899 case 10: level_string = "B21Bzzz"; break;
3900 case 11: level_string = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
3901 default: return False;
3904 if (strcmp(level_string,str2) != 0) {
3908 *rdata_len = mdrcnt + 1024;
3909 *rdata = smb_realloc_limit(*rdata,*rdata_len);
3914 SSVAL(*rparam,0,NERR_Success);
3915 SSVAL(*rparam,2,0); /* converter word */
3918 endp = *rdata + *rdata_len;
3919 p2 = get_safe_ptr(*rdata,*rdata_len,p,usri11_end);
3925 fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
3928 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
3933 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
3934 strlcpy(p2,"Comment",PTR_DIFF(endp,p2));
3935 p2 = skip_string(*rdata,*rdata_len,p2);
3940 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
3941 strlcpy(p2,"UserComment",PTR_DIFF(endp,p2));
3942 p2 = skip_string(*rdata,*rdata_len,p2);
3947 /* EEK! the cifsrap.txt doesn't have this in!!!! */
3948 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
3949 strlcpy(p2,((vuser != NULL)
3950 ? pdb_get_fullname(vuser->server_info->sam_account)
3951 : UserName),PTR_DIFF(endp,p2));
3952 p2 = skip_string(*rdata,*rdata_len,p2);
3959 const char *homedir = "";
3960 if (vuser != NULL) {
3961 homedir = pdb_get_homedir(
3962 vuser->server_info->sam_account);
3964 /* modelled after NTAS 3.51 reply */
3965 SSVAL(p,usri11_priv,
3966 (get_current_uid(conn) == sec_initial_uid())?
3967 USER_PRIV_ADMIN:USER_PRIV_USER);
3968 SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
3969 SIVALS(p,usri11_password_age,-1); /* password age */
3970 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
3971 strlcpy(p2, homedir, PTR_DIFF(endp,p2));
3972 p2 = skip_string(*rdata,*rdata_len,p2);
3976 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
3977 strlcpy(p2,"",PTR_DIFF(endp,p2));
3978 p2 = skip_string(*rdata,*rdata_len,p2);
3982 SIVAL(p,usri11_last_logon,0); /* last logon */
3983 SIVAL(p,usri11_last_logoff,0); /* last logoff */
3984 SSVALS(p,usri11_bad_pw_count,-1); /* bad pw counts */
3985 SSVALS(p,usri11_num_logons,-1); /* num logons */
3986 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
3987 strlcpy(p2,"\\\\*",PTR_DIFF(endp,p2));
3988 p2 = skip_string(*rdata,*rdata_len,p2);
3992 SSVAL(p,usri11_country_code,0); /* country code */
3994 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
3995 strlcpy(p2,"",PTR_DIFF(endp,p2));
3996 p2 = skip_string(*rdata,*rdata_len,p2);
4001 SIVALS(p,usri11_max_storage,-1); /* max storage */
4002 SSVAL(p,usri11_units_per_week,168); /* units per week */
4003 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
4005 /* a simple way to get logon hours at all times. */
4007 SCVAL(p2,21,0); /* fix zero termination */
4008 p2 = skip_string(*rdata,*rdata_len,p2);
4013 SSVAL(p,usri11_code_page,0); /* code page */
4016 if (uLevel == 1 || uLevel == 2) {
4017 memset(p+22,' ',16); /* password */
4018 SIVALS(p,38,-1); /* password age */
4020 (get_current_uid(conn) == sec_initial_uid())?
4021 USER_PRIV_ADMIN:USER_PRIV_USER);
4022 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
4023 strlcpy(p2, vuser ? pdb_get_homedir(
4024 vuser->server_info->sam_account) : "",
4026 p2 = skip_string(*rdata,*rdata_len,p2);
4030 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
4032 SSVAL(p,52,0); /* flags */
4033 SIVAL(p,54,PTR_DIFF(p2,*rdata)); /* script_path */
4034 strlcpy(p2, vuser ? pdb_get_logon_script(
4035 vuser->server_info->sam_account) : "",
4037 p2 = skip_string(*rdata,*rdata_len,p2);
4042 SIVAL(p,60,0); /* auth_flags */
4043 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
4044 strlcpy(p2,((vuser != NULL)
4045 ? pdb_get_fullname(vuser->server_info->sam_account)
4046 : UserName),PTR_DIFF(endp,p2));
4047 p2 = skip_string(*rdata,*rdata_len,p2);
4051 SIVAL(p,68,0); /* urs_comment */
4052 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
4053 strlcpy(p2,"",PTR_DIFF(endp,p2));
4054 p2 = skip_string(*rdata,*rdata_len,p2);
4058 SIVAL(p,76,0); /* workstations */
4059 SIVAL(p,80,0); /* last_logon */
4060 SIVAL(p,84,0); /* last_logoff */
4061 SIVALS(p,88,-1); /* acct_expires */
4062 SIVALS(p,92,-1); /* max_storage */
4063 SSVAL(p,96,168); /* units_per_week */
4064 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
4067 SSVALS(p,102,-1); /* bad_pw_count */
4068 SSVALS(p,104,-1); /* num_logons */
4069 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
4071 TALLOC_CTX *ctx = talloc_tos();
4072 int space_rem = *rdata_len - (p2 - *rdata);
4075 if (space_rem <= 0) {
4078 tmp = talloc_strdup(ctx, "\\\\%L");
4082 tmp = talloc_sub_basic(ctx,
4095 p2 = skip_string(*rdata,*rdata_len,p2);
4099 SSVAL(p,110,49); /* country_code */
4100 SSVAL(p,112,860); /* code page */
4104 *rdata_len = PTR_DIFF(p2,*rdata);
4106 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
4111 static bool api_WWkstaUserLogon(connection_struct *conn,uint16 vuid,
4112 char *param, int tpscnt,
4113 char *data, int tdscnt,
4114 int mdrcnt,int mprcnt,
4115 char **rdata,char **rparam,
4116 int *rdata_len,int *rparam_len)
4118 struct smbd_server_connection *sconn = smbd_server_conn;
4119 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4120 char *str2 = skip_string(param,tpscnt,str1);
4121 char *p = skip_string(param,tpscnt,str2);
4123 struct pack_desc desc;
4125 /* With share level security vuid will always be zero.
4126 Don't depend on vuser being non-null !!. JRA */
4127 user_struct *vuser = get_valid_user_struct(sconn, vuid);
4129 if (!str1 || !str2 || !p) {
4134 DEBUG(3,(" Username of UID %d is %s\n",
4135 (int)vuser->server_info->utok.uid,
4136 vuser->server_info->unix_name));
4139 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4140 name = get_safe_str_ptr(param,tpscnt,p,2);
4145 memset((char *)&desc,'\0',sizeof(desc));
4147 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
4149 /* check it's a supported varient */
4150 if (strcmp(str1,"OOWb54WrLh") != 0) {
4153 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) {
4157 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4164 desc.buflen = mdrcnt;
4165 desc.subformat = NULL;
4168 if (init_package(&desc,1,0)) {
4169 PACKI(&desc,"W",0); /* code */
4170 PACKS(&desc,"B21",name); /* eff. name */
4171 PACKS(&desc,"B",""); /* pad */
4173 (get_current_uid(conn) == sec_initial_uid())?
4174 USER_PRIV_ADMIN:USER_PRIV_USER);
4175 PACKI(&desc,"D",0); /* auth flags XXX */
4176 PACKI(&desc,"W",0); /* num logons */
4177 PACKI(&desc,"W",0); /* bad pw count */
4178 PACKI(&desc,"D",0); /* last logon */
4179 PACKI(&desc,"D",-1); /* last logoff */
4180 PACKI(&desc,"D",-1); /* logoff time */
4181 PACKI(&desc,"D",-1); /* kickoff time */
4182 PACKI(&desc,"D",0); /* password age */
4183 PACKI(&desc,"D",0); /* password can change */
4184 PACKI(&desc,"D",-1); /* password must change */
4188 fstrcpy(mypath,"\\\\");
4189 fstrcat(mypath,get_local_machine_name());
4191 PACKS(&desc,"z",mypath); /* computer */
4194 PACKS(&desc,"z",lp_workgroup());/* domain */
4195 PACKS(&desc,"z", vuser ? pdb_get_logon_script(
4196 vuser->server_info->sam_account) : ""); /* script path */
4197 PACKI(&desc,"D",0x00000000); /* reserved */
4200 *rdata_len = desc.usedlen;
4202 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4206 SSVALS(*rparam,0,desc.errcode);
4208 SSVAL(*rparam,4,desc.neededlen);
4210 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
4215 /****************************************************************************
4216 api_WAccessGetUserPerms
4217 ****************************************************************************/
4219 static bool api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid,
4220 char *param, int tpscnt,
4221 char *data, int tdscnt,
4222 int mdrcnt,int mprcnt,
4223 char **rdata,char **rparam,
4224 int *rdata_len,int *rparam_len)
4226 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4227 char *str2 = skip_string(param,tpscnt,str1);
4228 char *user = skip_string(param,tpscnt,str2);
4229 char *resource = skip_string(param,tpscnt,user);
4231 if (!str1 || !str2 || !user || !resource) {
4235 if (skip_string(param,tpscnt,resource) == NULL) {
4238 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
4240 /* check it's a supported varient */
4241 if (strcmp(str1,"zzh") != 0) {
4244 if (strcmp(str2,"") != 0) {
4249 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4253 SSVALS(*rparam,0,0); /* errorcode */
4254 SSVAL(*rparam,2,0); /* converter word */
4255 SSVAL(*rparam,4,0x7f); /* permission flags */
4260 /****************************************************************************
4261 api_WPrintJobEnumerate
4262 ****************************************************************************/
4264 static bool api_WPrintJobGetInfo(connection_struct *conn, uint16 vuid,
4265 char *param, int tpscnt,
4266 char *data, int tdscnt,
4267 int mdrcnt,int mprcnt,
4268 char **rdata,char **rparam,
4269 int *rdata_len,int *rparam_len)
4271 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4272 char *str2 = skip_string(param,tpscnt,str1);
4273 char *p = skip_string(param,tpscnt,str2);
4277 struct pack_desc desc;
4280 TALLOC_CTX *mem_ctx = talloc_tos();
4283 struct rpc_pipe_client *cli = NULL;
4284 struct policy_handle handle;
4285 struct spoolss_DevmodeContainer devmode_ctr;
4286 union spoolss_JobInfo info;
4288 if (!str1 || !str2 || !p) {
4292 uLevel = get_safe_SVAL(param,tpscnt,p,2,-1);
4294 memset((char *)&desc,'\0',sizeof(desc));
4295 memset((char *)&status,'\0',sizeof(status));
4297 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
4299 /* check it's a supported varient */
4300 if (strcmp(str1,"WWrLh") != 0) {
4303 if (!check_printjob_info(&desc,uLevel,str2)) {
4307 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid)) {
4311 ZERO_STRUCT(handle);
4313 status = rpc_pipe_open_internal(mem_ctx, &ndr_table_spoolss.syntax_id,
4314 rpc_spoolss_dispatch, conn->server_info,
4316 if (!NT_STATUS_IS_OK(status)) {
4317 DEBUG(0,("api_WPrintJobGetInfo: could not connect to spoolss: %s\n",
4318 nt_errstr(status)));
4319 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
4323 ZERO_STRUCT(devmode_ctr);
4325 status = rpccli_spoolss_OpenPrinter(cli, mem_ctx,
4329 SEC_FLAG_MAXIMUM_ALLOWED,
4332 if (!NT_STATUS_IS_OK(status)) {
4333 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
4336 if (!W_ERROR_IS_OK(werr)) {
4337 desc.errcode = W_ERROR_V(werr);
4341 werr = rpccli_spoolss_getjob(cli, mem_ctx,
4347 if (!W_ERROR_IS_OK(werr)) {
4348 desc.errcode = W_ERROR_V(werr);
4353 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4358 desc.buflen = mdrcnt;
4361 * Don't return data but need to get correct length
4362 * init_package will return wrong size if buflen=0
4364 desc.buflen = getlen(desc.format);
4365 desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen );
4368 if (init_package(&desc,1,0)) {
4369 fill_spoolss_printjob_info(uLevel, &desc, &info.info2, info.info2.position);
4370 *rdata_len = desc.usedlen;
4372 desc.errcode = NERR_JobNotFound;
4376 if (is_valid_policy_hnd(&handle)) {
4377 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
4381 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4385 SSVALS(*rparam,0,desc.errcode);
4387 SSVAL(*rparam,4,desc.neededlen);
4391 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
4396 static bool api_WPrintJobEnumerate(connection_struct *conn, uint16 vuid,
4397 char *param, int tpscnt,
4398 char *data, int tdscnt,
4399 int mdrcnt,int mprcnt,
4400 char **rdata,char **rparam,
4401 int *rdata_len,int *rparam_len)
4403 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4404 char *str2 = skip_string(param,tpscnt,str1);
4405 char *p = skip_string(param,tpscnt,str2);
4409 struct pack_desc desc;
4411 TALLOC_CTX *mem_ctx = talloc_tos();
4414 struct rpc_pipe_client *cli = NULL;
4415 struct policy_handle handle;
4416 struct spoolss_DevmodeContainer devmode_ctr;
4418 union spoolss_JobInfo *info;
4420 if (!str1 || !str2 || !p) {
4424 memset((char *)&desc,'\0',sizeof(desc));
4425 memset((char *)&status,'\0',sizeof(status));
4427 p = skip_string(param,tpscnt,p);
4431 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4433 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
4435 /* check it's a supported variant */
4436 if (strcmp(str1,"zWrLeh") != 0) {
4441 return False; /* defined only for uLevel 0,1,2 */
4444 if (!check_printjob_info(&desc,uLevel,str2)) {
4448 ZERO_STRUCT(handle);
4450 status = rpc_pipe_open_internal(mem_ctx, &ndr_table_spoolss.syntax_id,
4451 rpc_spoolss_dispatch, conn->server_info,
4453 if (!NT_STATUS_IS_OK(status)) {
4454 DEBUG(0,("api_RDosPrintJobDel: could not connect to spoolss: %s\n",
4455 nt_errstr(status)));
4456 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
4460 ZERO_STRUCT(devmode_ctr);
4462 status = rpccli_spoolss_OpenPrinter(cli, mem_ctx,
4466 SEC_FLAG_MAXIMUM_ALLOWED,
4469 if (!NT_STATUS_IS_OK(status)) {
4470 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
4473 if (!W_ERROR_IS_OK(werr)) {
4474 desc.errcode = W_ERROR_V(werr);
4478 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
4486 if (!W_ERROR_IS_OK(werr)) {
4487 desc.errcode = W_ERROR_V(werr);
4492 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4498 desc.buflen = mdrcnt;
4500 if (init_package(&desc,count,0)) {
4502 for (i = 0; i < count; i++) {
4503 fill_spoolss_printjob_info(uLevel, &desc, &info[i].info2, i);
4504 if (desc.errcode == NERR_Success) {
4510 if (is_valid_policy_hnd(&handle)) {
4511 rpccli_spoolss_ClosePrinter(cli, mem_ctx, &handle, NULL);
4514 *rdata_len = desc.usedlen;
4517 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4521 SSVALS(*rparam,0,desc.errcode);
4523 SSVAL(*rparam,4,succnt);
4524 SSVAL(*rparam,6,count);
4526 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
4531 static int check_printdest_info(struct pack_desc* desc,
4532 int uLevel, char* id)
4534 desc->subformat = NULL;
4537 desc->format = "B9";
4540 desc->format = "B9B21WWzW";
4546 desc->format = "zzzWWzzzWW";
4549 DEBUG(0,("check_printdest_info: invalid level %d\n",
4553 if (id == NULL || strcmp(desc->format,id) != 0) {
4554 DEBUG(0,("check_printdest_info: invalid string %s\n",
4555 id ? id : "<NULL>" ));
4561 static void fill_printdest_info(connection_struct *conn, int snum, int uLevel,
4562 struct pack_desc* desc)
4566 strncpy(buf,SERVICE(snum),sizeof(buf)-1);
4567 buf[sizeof(buf)-1] = 0;
4571 PACKS(desc,"B9",buf); /* szName */
4573 PACKS(desc,"B21",""); /* szUserName */
4574 PACKI(desc,"W",0); /* uJobId */
4575 PACKI(desc,"W",0); /* fsStatus */
4576 PACKS(desc,"z",""); /* pszStatus */
4577 PACKI(desc,"W",0); /* time */
4581 if (uLevel == 2 || uLevel == 3) {
4582 PACKS(desc,"z",buf); /* pszPrinterName */
4584 PACKS(desc,"z",""); /* pszUserName */
4585 PACKS(desc,"z",""); /* pszLogAddr */
4586 PACKI(desc,"W",0); /* uJobId */
4587 PACKI(desc,"W",0); /* fsStatus */
4588 PACKS(desc,"z",""); /* pszStatus */
4589 PACKS(desc,"z",""); /* pszComment */
4590 PACKS(desc,"z","NULL"); /* pszDrivers */
4591 PACKI(desc,"W",0); /* time */
4592 PACKI(desc,"W",0); /* pad1 */
4597 static bool api_WPrintDestGetInfo(connection_struct *conn, uint16 vuid,
4598 char *param, int tpscnt,
4599 char *data, int tdscnt,
4600 int mdrcnt,int mprcnt,
4601 char **rdata,char **rparam,
4602 int *rdata_len,int *rparam_len)
4604 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4605 char *str2 = skip_string(param,tpscnt,str1);
4606 char *p = skip_string(param,tpscnt,str2);
4607 char* PrinterName = p;
4609 struct pack_desc desc;
4613 if (!str1 || !str2 || !p) {
4617 memset((char *)&desc,'\0',sizeof(desc));
4619 p = skip_string(param,tpscnt,p);
4623 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4625 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
4627 /* check it's a supported varient */
4628 if (strcmp(str1,"zWrLh") != 0) {
4631 if (!check_printdest_info(&desc,uLevel,str2)) {
4635 snum = find_service(PrinterName);
4636 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) ) {
4638 desc.errcode = NERR_DestNotFound;
4642 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4647 desc.buflen = mdrcnt;
4650 * Don't return data but need to get correct length
4651 * init_package will return wrong size if buflen=0
4653 desc.buflen = getlen(desc.format);
4654 desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen );
4656 if (init_package(&desc,1,0)) {
4657 fill_printdest_info(conn,snum,uLevel,&desc);
4659 *rdata_len = desc.usedlen;
4663 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4667 SSVALS(*rparam,0,desc.errcode);
4669 SSVAL(*rparam,4,desc.neededlen);
4671 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
4677 static bool api_WPrintDestEnum(connection_struct *conn, uint16 vuid,
4678 char *param, int tpscnt,
4679 char *data, int tdscnt,
4680 int mdrcnt,int mprcnt,
4681 char **rdata,char **rparam,
4682 int *rdata_len,int *rparam_len)
4684 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4685 char *str2 = skip_string(param,tpscnt,str1);
4686 char *p = skip_string(param,tpscnt,str2);
4690 struct pack_desc desc;
4691 int services = lp_numservices();
4693 if (!str1 || !str2 || !p) {
4697 memset((char *)&desc,'\0',sizeof(desc));
4699 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4701 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
4703 /* check it's a supported varient */
4704 if (strcmp(str1,"WrLeh") != 0) {
4707 if (!check_printdest_info(&desc,uLevel,str2)) {
4712 for (i = 0; i < services; i++) {
4713 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
4719 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4726 desc.buflen = mdrcnt;
4727 if (init_package(&desc,queuecnt,0)) {
4730 for (i = 0; i < services; i++) {
4731 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
4732 fill_printdest_info(conn,i,uLevel,&desc);
4734 if (desc.errcode == NERR_Success) {
4741 *rdata_len = desc.usedlen;
4744 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4748 SSVALS(*rparam,0,desc.errcode);
4750 SSVAL(*rparam,4,succnt);
4751 SSVAL(*rparam,6,queuecnt);
4753 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
4758 static bool api_WPrintDriverEnum(connection_struct *conn, uint16 vuid,
4759 char *param, int tpscnt,
4760 char *data, int tdscnt,
4761 int mdrcnt,int mprcnt,
4762 char **rdata,char **rparam,
4763 int *rdata_len,int *rparam_len)
4765 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4766 char *str2 = skip_string(param,tpscnt,str1);
4767 char *p = skip_string(param,tpscnt,str2);
4770 struct pack_desc desc;
4772 if (!str1 || !str2 || !p) {
4776 memset((char *)&desc,'\0',sizeof(desc));
4778 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4780 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
4782 /* check it's a supported varient */
4783 if (strcmp(str1,"WrLeh") != 0) {
4786 if (uLevel != 0 || strcmp(str2,"B41") != 0) {
4791 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4797 desc.buflen = mdrcnt;
4798 if (init_package(&desc,1,0)) {
4799 PACKS(&desc,"B41","NULL");
4802 succnt = (desc.errcode == NERR_Success ? 1 : 0);
4804 *rdata_len = desc.usedlen;
4807 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4811 SSVALS(*rparam,0,desc.errcode);
4813 SSVAL(*rparam,4,succnt);
4816 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
4821 static bool api_WPrintQProcEnum(connection_struct *conn, uint16 vuid,
4822 char *param, int tpscnt,
4823 char *data, int tdscnt,
4824 int mdrcnt,int mprcnt,
4825 char **rdata,char **rparam,
4826 int *rdata_len,int *rparam_len)
4828 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4829 char *str2 = skip_string(param,tpscnt,str1);
4830 char *p = skip_string(param,tpscnt,str2);
4833 struct pack_desc desc;
4835 if (!str1 || !str2 || !p) {
4838 memset((char *)&desc,'\0',sizeof(desc));
4840 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4842 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
4844 /* check it's a supported varient */
4845 if (strcmp(str1,"WrLeh") != 0) {
4848 if (uLevel != 0 || strcmp(str2,"B13") != 0) {
4853 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4859 desc.buflen = mdrcnt;
4861 if (init_package(&desc,1,0)) {
4862 PACKS(&desc,"B13","lpd");
4865 succnt = (desc.errcode == NERR_Success ? 1 : 0);
4867 *rdata_len = desc.usedlen;
4870 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4874 SSVALS(*rparam,0,desc.errcode);
4876 SSVAL(*rparam,4,succnt);
4879 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
4884 static bool api_WPrintPortEnum(connection_struct *conn, uint16 vuid,
4885 char *param, int tpscnt,
4886 char *data, int tdscnt,
4887 int mdrcnt,int mprcnt,
4888 char **rdata,char **rparam,
4889 int *rdata_len,int *rparam_len)
4891 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4892 char *str2 = skip_string(param,tpscnt,str1);
4893 char *p = skip_string(param,tpscnt,str2);
4896 struct pack_desc desc;
4898 if (!str1 || !str2 || !p) {
4902 memset((char *)&desc,'\0',sizeof(desc));
4904 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4906 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
4908 /* check it's a supported varient */
4909 if (strcmp(str1,"WrLeh") != 0) {
4912 if (uLevel != 0 || strcmp(str2,"B9") != 0) {
4917 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4922 memset((char *)&desc,'\0',sizeof(desc));
4924 desc.buflen = mdrcnt;
4926 if (init_package(&desc,1,0)) {
4927 PACKS(&desc,"B13","lp0");
4930 succnt = (desc.errcode == NERR_Success ? 1 : 0);
4932 *rdata_len = desc.usedlen;
4935 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4939 SSVALS(*rparam,0,desc.errcode);
4941 SSVAL(*rparam,4,succnt);
4944 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
4949 /****************************************************************************
4951 ****************************************************************************/
4953 static bool api_RNetSessionEnum(connection_struct *conn, uint16 vuid,
4954 char *param, int tpscnt,
4955 char *data, int tdscnt,
4956 int mdrcnt,int mprcnt,
4957 char **rdata,char **rparam,
4958 int *rdata_len,int *rparam_len)
4961 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4962 char *str2 = skip_string(param,tpscnt,str1);
4963 char *p = skip_string(param,tpscnt,str2);
4965 struct pack_desc desc;
4966 struct sessionid *session_list;
4967 int i, num_sessions;
4969 if (!str1 || !str2 || !p) {
4973 memset((char *)&desc,'\0',sizeof(desc));
4975 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4977 DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel));
4978 DEBUG(7,("RNetSessionEnum req string=%s\n",str1));
4979 DEBUG(7,("RNetSessionEnum ret string=%s\n",str2));
4981 /* check it's a supported varient */
4982 if (strcmp(str1,RAP_NetSessionEnum_REQ) != 0) {
4985 if (uLevel != 2 || strcmp(str2,RAP_SESSION_INFO_L2) != 0) {
4989 num_sessions = list_sessions(talloc_tos(), &session_list);
4992 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4997 memset((char *)&desc,'\0',sizeof(desc));
4999 desc.buflen = mdrcnt;
5001 if (!init_package(&desc,num_sessions,0)) {
5005 for(i=0; i<num_sessions; i++) {
5006 PACKS(&desc, "z", session_list[i].remote_machine);
5007 PACKS(&desc, "z", session_list[i].username);
5008 PACKI(&desc, "W", 1); /* num conns */
5009 PACKI(&desc, "W", 0); /* num opens */
5010 PACKI(&desc, "W", 1); /* num users */
5011 PACKI(&desc, "D", 0); /* session time */
5012 PACKI(&desc, "D", 0); /* idle time */
5013 PACKI(&desc, "D", 0); /* flags */
5014 PACKS(&desc, "z", "Unknown Client"); /* client type string */
5017 *rdata_len = desc.usedlen;
5020 *rparam = smb_realloc_limit(*rparam,*rparam_len);
5024 SSVALS(*rparam,0,desc.errcode);
5025 SSVAL(*rparam,2,0); /* converter */
5026 SSVAL(*rparam,4,num_sessions); /* count */
5028 DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc.errcode));
5034 /****************************************************************************
5035 The buffer was too small.
5036 ****************************************************************************/
5038 static bool api_TooSmall(connection_struct *conn,uint16 vuid, char *param, char *data,
5039 int mdrcnt, int mprcnt,
5040 char **rdata, char **rparam,
5041 int *rdata_len, int *rparam_len)
5043 *rparam_len = MIN(*rparam_len,mprcnt);
5044 *rparam = smb_realloc_limit(*rparam,*rparam_len);
5051 SSVAL(*rparam,0,NERR_BufTooSmall);
5053 DEBUG(3,("Supplied buffer too small in API command\n"));
5058 /****************************************************************************
5059 The request is not supported.
5060 ****************************************************************************/
5062 static bool api_Unsupported(connection_struct *conn, uint16 vuid,
5063 char *param, int tpscnt,
5064 char *data, int tdscnt,
5065 int mdrcnt, int mprcnt,
5066 char **rdata, char **rparam,
5067 int *rdata_len, int *rparam_len)
5070 *rparam = smb_realloc_limit(*rparam,*rparam_len);
5077 SSVAL(*rparam,0,NERR_notsupported);
5078 SSVAL(*rparam,2,0); /* converter word */
5080 DEBUG(3,("Unsupported API command\n"));
5085 static const struct {
5088 bool (*fn)(connection_struct *, uint16,
5091 int,int,char **,char **,int *,int *);
5092 bool auth_user; /* Deny anonymous access? */
5093 } api_commands[] = {
5094 {"RNetShareEnum", RAP_WshareEnum, api_RNetShareEnum, True},
5095 {"RNetShareGetInfo", RAP_WshareGetInfo, api_RNetShareGetInfo},
5096 {"RNetShareAdd", RAP_WshareAdd, api_RNetShareAdd},
5097 {"RNetSessionEnum", RAP_WsessionEnum, api_RNetSessionEnum, True},
5098 {"RNetServerGetInfo", RAP_WserverGetInfo, api_RNetServerGetInfo},
5099 {"RNetGroupEnum", RAP_WGroupEnum, api_RNetGroupEnum, True},
5100 {"RNetGroupGetUsers", RAP_WGroupGetUsers, api_RNetGroupGetUsers, True},
5101 {"RNetUserEnum", RAP_WUserEnum, api_RNetUserEnum, True},
5102 {"RNetUserGetInfo", RAP_WUserGetInfo, api_RNetUserGetInfo},
5103 {"NetUserGetGroups", RAP_WUserGetGroups, api_NetUserGetGroups},
5104 {"NetWkstaGetInfo", RAP_WWkstaGetInfo, api_NetWkstaGetInfo},
5105 {"DosPrintQEnum", RAP_WPrintQEnum, api_DosPrintQEnum, True},
5106 {"DosPrintQGetInfo", RAP_WPrintQGetInfo, api_DosPrintQGetInfo},
5107 {"WPrintQueuePause", RAP_WPrintQPause, api_WPrintQueueCtrl},
5108 {"WPrintQueueResume", RAP_WPrintQContinue, api_WPrintQueueCtrl},
5109 {"WPrintJobEnumerate",RAP_WPrintJobEnum, api_WPrintJobEnumerate},
5110 {"WPrintJobGetInfo", RAP_WPrintJobGetInfo, api_WPrintJobGetInfo},
5111 {"RDosPrintJobDel", RAP_WPrintJobDel, api_RDosPrintJobDel},
5112 {"RDosPrintJobPause", RAP_WPrintJobPause, api_RDosPrintJobDel},
5113 {"RDosPrintJobResume",RAP_WPrintJobContinue, api_RDosPrintJobDel},
5114 {"WPrintDestEnum", RAP_WPrintDestEnum, api_WPrintDestEnum},
5115 {"WPrintDestGetInfo", RAP_WPrintDestGetInfo, api_WPrintDestGetInfo},
5116 {"NetRemoteTOD", RAP_NetRemoteTOD, api_NetRemoteTOD},
5117 {"WPrintQueuePurge", RAP_WPrintQPurge, api_WPrintQueueCtrl},
5118 {"NetServerEnum2", RAP_NetServerEnum2, api_RNetServerEnum2}, /* anon OK */
5119 {"NetServerEnum3", RAP_NetServerEnum3, api_RNetServerEnum3}, /* anon OK */
5120 {"WAccessGetUserPerms",RAP_WAccessGetUserPerms,api_WAccessGetUserPerms},
5121 {"SetUserPassword", RAP_WUserPasswordSet2, api_SetUserPassword},
5122 {"WWkstaUserLogon", RAP_WWkstaUserLogon, api_WWkstaUserLogon},
5123 {"PrintJobInfo", RAP_WPrintJobSetInfo, api_PrintJobInfo},
5124 {"WPrintDriverEnum", RAP_WPrintDriverEnum, api_WPrintDriverEnum},
5125 {"WPrintQProcEnum", RAP_WPrintQProcessorEnum,api_WPrintQProcEnum},
5126 {"WPrintPortEnum", RAP_WPrintPortEnum, api_WPrintPortEnum},
5127 {"SamOEMChangePassword",RAP_SamOEMChgPasswordUser2_P,api_SamOEMChangePassword}, /* anon OK */
5128 {NULL, -1, api_Unsupported}
5129 /* The following RAP calls are not implemented by Samba:
5131 RAP_WFileEnum2 - anon not OK
5136 /****************************************************************************
5137 Handle remote api calls.
5138 ****************************************************************************/
5140 void api_reply(connection_struct *conn, uint16 vuid,
5141 struct smb_request *req,
5142 char *data, char *params,
5143 int tdscnt, int tpscnt,
5144 int mdrcnt, int mprcnt)
5146 struct smbd_server_connection *sconn = smbd_server_conn;
5149 char *rparam = NULL;
5150 const char *name1 = NULL;
5151 const char *name2 = NULL;
5158 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
5159 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5164 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
5167 api_command = SVAL(params,0);
5168 /* Is there a string at position params+2 ? */
5169 if (skip_string(params,tpscnt,params+2)) {
5174 name2 = skip_string(params,tpscnt,params+2);
5179 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
5183 tdscnt,tpscnt,mdrcnt,mprcnt));
5185 for (i=0;api_commands[i].name;i++) {
5186 if (api_commands[i].id == api_command && api_commands[i].fn) {
5187 DEBUG(3,("Doing %s\n",api_commands[i].name));
5192 /* Check whether this api call can be done anonymously */
5194 if (api_commands[i].auth_user && lp_restrict_anonymous()) {
5195 user_struct *user = get_valid_user_struct(sconn, vuid);
5197 if (!user || user->server_info->guest) {
5198 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
5203 rdata = (char *)SMB_MALLOC(1024);
5205 memset(rdata,'\0',1024);
5208 rparam = (char *)SMB_MALLOC(1024);
5210 memset(rparam,'\0',1024);
5213 if(!rdata || !rparam) {
5214 DEBUG(0,("api_reply: malloc fail !\n"));
5217 reply_nterror(req, NT_STATUS_NO_MEMORY);
5221 reply = api_commands[i].fn(conn,
5223 params,tpscnt, /* params + length */
5224 data,tdscnt, /* data + length */
5226 &rdata,&rparam,&rdata_len,&rparam_len);
5229 if (rdata_len > mdrcnt || rparam_len > mprcnt) {
5230 reply = api_TooSmall(conn,vuid,params,data,mdrcnt,mprcnt,
5231 &rdata,&rparam,&rdata_len,&rparam_len);
5234 /* if we get False back then it's actually unsupported */
5236 reply = api_Unsupported(conn,vuid,params,tpscnt,data,tdscnt,mdrcnt,mprcnt,
5237 &rdata,&rparam,&rdata_len,&rparam_len);
5240 /* If api_Unsupported returns false we can't return anything. */
5242 send_trans_reply(conn, req, rparam, rparam_len,
5243 rdata, rdata_len, False);