LCOV - code coverage report
Current view: top level - source3/smbd - smb1_lanman.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 215 2933 7.3 %
Date: 2024-06-13 04:01:37 Functions: 8 62 12.9 %

          Line data    Source code
       1             : /*
       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.
       6             : 
       7             :    SMB Version handling
       8             :    Copyright (C) John H Terpstra 1995-1998
       9             : 
      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.
      14             : 
      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.
      19             : 
      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/>.
      22             :    */
      23             : /*
      24             :    This file handles the named pipe and mailslot calls
      25             :    in the SMBtrans protocol
      26             :    */
      27             : 
      28             : #include "includes.h"
      29             : #include "smbd/smbd.h"
      30             : #include "smbd/globals.h"
      31             : #include "rpc_client/rpc_client.h"
      32             : #include "../librpc/gen_ndr/ndr_samr_c.h"
      33             : #include "../librpc/gen_ndr/ndr_spoolss_c.h"
      34             : #include "rpc_client/cli_spoolss.h"
      35             : #include "rpc_client/init_spoolss.h"
      36             : #include "../librpc/gen_ndr/ndr_srvsvc_c.h"
      37             : #include "../librpc/gen_ndr/rap.h"
      38             : #include "../lib/util/binsearch.h"
      39             : #include "../libcli/auth/libcli_auth.h"
      40             : #include "rpc_client/init_lsa.h"
      41             : #include "../libcli/security/security.h"
      42             : #include "printing.h"
      43             : #include "passdb/machine_sid.h"
      44             : #include "auth.h"
      45             : #include "rpc_server/rpc_ncacn_np.h"
      46             : #include "lib/util/string_wrappers.h"
      47             : #include "source3/printing/rap_jobid.h"
      48             : #include "source3/lib/substitute.h"
      49             : 
      50             : #ifdef CHECK_TYPES
      51             : #undef CHECK_TYPES
      52             : #endif
      53             : #define CHECK_TYPES 0
      54             : 
      55             : #define NERR_Success 0
      56             : #define NERR_badpass 86
      57             : #define NERR_notsupported 50
      58             : 
      59             : #define NERR_BASE (2100)
      60             : #define NERR_BufTooSmall (NERR_BASE+23)
      61             : #define NERR_JobNotFound (NERR_BASE+51)
      62             : #define NERR_DestNotFound (NERR_BASE+52)
      63             : 
      64             : #define ACCESS_READ 0x01
      65             : #define ACCESS_WRITE 0x02
      66             : #define ACCESS_CREATE 0x04
      67             : 
      68             : #define SHPWLEN 8               /* share password length */
      69             : 
      70             : /* Limit size of ipc replies */
      71             : 
      72           8 : static char *smb_realloc_limit(void *ptr, size_t size)
      73             : {
      74             :         char *val;
      75             : 
      76           8 :         size = MAX((size),4*1024);
      77           8 :         val = (char *)SMB_REALLOC(ptr,size);
      78           8 :         if (val) {
      79           8 :                 memset(val,'\0',size);
      80             :         }
      81           8 :         return val;
      82             : }
      83             : 
      84             : static bool api_Unsupported(struct smbd_server_connection *sconn,
      85             :                             connection_struct *conn, uint64_t vuid,
      86             :                                 char *param, int tpscnt,
      87             :                                 char *data, int tdscnt,
      88             :                                 int mdrcnt, int mprcnt,
      89             :                                 char **rdata, char **rparam,
      90             :                                 int *rdata_len, int *rparam_len);
      91             : 
      92             : static bool api_TooSmall(struct smbd_server_connection *sconn,
      93             :                          connection_struct *conn, uint64_t vuid, char *param, char *data,
      94             :                          int mdrcnt, int mprcnt,
      95             :                          char **rdata, char **rparam,
      96             :                          int *rdata_len, int *rparam_len);
      97             : 
      98             : 
      99           0 : static int CopyExpanded(connection_struct *conn,
     100             :                         int snum, char **dst, char *src, int *p_space_remaining)
     101             : {
     102           0 :         TALLOC_CTX *ctx = talloc_tos();
     103           0 :         const struct loadparm_substitution *lp_sub =
     104           0 :                 loadparm_s3_global_substitution();
     105           0 :         char *buf = NULL;
     106             :         int l;
     107             : 
     108           0 :         if (!src || !dst || !p_space_remaining || !(*dst) ||
     109           0 :                         *p_space_remaining <= 0) {
     110           0 :                 return 0;
     111             :         }
     112             : 
     113           0 :         buf = talloc_strdup(ctx, src);
     114           0 :         if (!buf) {
     115           0 :                 *p_space_remaining = 0;
     116           0 :                 return 0;
     117             :         }
     118           0 :         buf = talloc_string_sub(ctx, buf,"%S", lp_servicename(ctx, lp_sub, snum));
     119           0 :         if (!buf) {
     120           0 :                 *p_space_remaining = 0;
     121           0 :                 return 0;
     122             :         }
     123           0 :         buf = talloc_sub_full(ctx,
     124           0 :                                   lp_servicename(ctx, lp_sub, SNUM(conn)),
     125           0 :                                 conn->session_info->unix_info->unix_name,
     126           0 :                                 conn->connectpath,
     127           0 :                                 conn->session_info->unix_token->gid,
     128           0 :                                 conn->session_info->unix_info->sanitized_username,
     129           0 :                                 conn->session_info->info->domain_name,
     130             :                                 buf);
     131           0 :         if (!buf) {
     132           0 :                 *p_space_remaining = 0;
     133           0 :                 return 0;
     134             :         }
     135           0 :         l = push_ascii(*dst,buf,*p_space_remaining, STR_TERMINATE);
     136           0 :         if (l == 0) {
     137           0 :                 return 0;
     138             :         }
     139           0 :         (*dst) += l;
     140           0 :         (*p_space_remaining) -= l;
     141           0 :         return l;
     142             : }
     143             : 
     144           4 : static int CopyAndAdvance(char **dst, char *src, int *n)
     145             : {
     146             :         int l;
     147           4 :         if (!src || !dst || !n || !(*dst)) {
     148           0 :                 return 0;
     149             :         }
     150           4 :         l = push_ascii(*dst,src,*n, STR_TERMINATE);
     151           4 :         if (l == 0) {
     152           0 :                 return 0;
     153             :         }
     154           4 :         (*dst) += l;
     155           4 :         (*n) -= l;
     156           4 :         return l;
     157             : }
     158             : 
     159           0 : static int StrlenExpanded(connection_struct *conn, int snum, char *s)
     160             : {
     161           0 :         TALLOC_CTX *ctx = talloc_tos();
     162           0 :         const struct loadparm_substitution *lp_sub =
     163           0 :                 loadparm_s3_global_substitution();
     164           0 :         char *buf = NULL;
     165           0 :         if (!s) {
     166           0 :                 return 0;
     167             :         }
     168           0 :         buf = talloc_strdup(ctx,s);
     169           0 :         if (!buf) {
     170           0 :                 return 0;
     171             :         }
     172           0 :         buf = talloc_string_sub(ctx,buf,"%S",lp_servicename(ctx, lp_sub, snum));
     173           0 :         if (!buf) {
     174           0 :                 return 0;
     175             :         }
     176           0 :         buf = talloc_sub_full(ctx,
     177           0 :                                   lp_servicename(ctx, lp_sub, SNUM(conn)),
     178           0 :                                 conn->session_info->unix_info->unix_name,
     179           0 :                                 conn->connectpath,
     180           0 :                                 conn->session_info->unix_token->gid,
     181           0 :                                 conn->session_info->unix_info->sanitized_username,
     182           0 :                                 conn->session_info->info->domain_name,
     183             :                                 buf);
     184           0 :         if (!buf) {
     185           0 :                 return 0;
     186             :         }
     187           0 :         return strlen(buf) + 1;
     188             : }
     189             : 
     190             : /*******************************************************************
     191             :  Check a API string for validity when we only need to check the prefix.
     192             : ******************************************************************/
     193             : 
     194           4 : static bool prefix_ok(const char *str, const char *prefix)
     195             : {
     196           4 :         return(strncmp(str,prefix,strlen(prefix)) == 0);
     197             : }
     198             : 
     199             : struct pack_desc {
     200             :         const char *format;         /* formatstring for structure */
     201             :         const char *subformat;  /* subformat for structure */
     202             :         char *base;         /* baseaddress of buffer */
     203             :         int buflen;        /* remaining size for fixed part; on init: length of base */
     204             :         int subcount;       /* count of substructures */
     205             :         char *structbuf;  /* pointer into buffer for remaining fixed part */
     206             :         int stringlen;    /* remaining size for variable part */
     207             :         char *stringbuf;  /* pointer into buffer for remaining variable part */
     208             :         int neededlen;    /* total needed size */
     209             :         int usedlen;        /* total used size (usedlen <= neededlen and usedlen <= buflen) */
     210             :         const char *curpos;         /* current position; pointer into format or subformat */
     211             :         int errcode;
     212             : };
     213             : 
     214           0 : static int get_counter(const char **p)
     215             : {
     216             :         int i, n;
     217           0 :         if (!p || !(*p)) {
     218           0 :                 return 1;
     219             :         }
     220           0 :         if (!isdigit((int)**p)) {
     221           0 :                 return 1;
     222             :         }
     223           0 :         for (n = 0;;) {
     224           0 :                 i = **p;
     225           0 :                 if (isdigit(i)) {
     226           0 :                         n = 10 * n + (i - '0');
     227             :                 } else {
     228           0 :                         return n;
     229             :                 }
     230           0 :                 (*p)++;
     231             :         }
     232             : }
     233             : 
     234           0 : static int getlen(const char *p)
     235             : {
     236           0 :         int n = 0;
     237           0 :         if (!p) {
     238           0 :                 return 0;
     239             :         }
     240             : 
     241           0 :         while (*p) {
     242           0 :                 switch( *p++ ) {
     243           0 :                 case 'W':                       /* word (2 byte) */
     244           0 :                         n += 2;
     245           0 :                         break;
     246           0 :                 case 'K':                       /* status word? (2 byte) */
     247           0 :                         n += 2;
     248           0 :                         break;
     249           0 :                 case 'N':                       /* count of substructures (word) at end */
     250           0 :                         n += 2;
     251           0 :                         break;
     252           0 :                 case 'D':                       /* double word (4 byte) */
     253             :                 case 'z':                       /* offset to zero terminated string (4 byte) */
     254             :                 case 'l':                       /* offset to user data (4 byte) */
     255           0 :                         n += 4;
     256           0 :                         break;
     257           0 :                 case 'b':                       /* offset to data (with counter) (4 byte) */
     258           0 :                         n += 4;
     259           0 :                         get_counter(&p);
     260           0 :                         break;
     261           0 :                 case 'B':                       /* byte (with optional counter) */
     262           0 :                         n += get_counter(&p);
     263           0 :                         break;
     264             :                 }
     265             :         }
     266           0 :         return n;
     267             : }
     268             : 
     269           0 : static bool init_package(struct pack_desc *p, int count, int subcount)
     270             : {
     271           0 :         int n = p->buflen;
     272             :         int i;
     273             : 
     274           0 :         if (!p->format || !p->base) {
     275           0 :                 return False;
     276             :         }
     277             : 
     278           0 :         i = count * getlen(p->format);
     279           0 :         if (p->subformat) {
     280           0 :                 i += subcount * getlen(p->subformat);
     281             :         }
     282           0 :         p->structbuf = p->base;
     283           0 :         p->neededlen = 0;
     284           0 :         p->usedlen = 0;
     285           0 :         p->subcount = 0;
     286           0 :         p->curpos = p->format;
     287           0 :         if (i > n) {
     288           0 :                 p->neededlen = i;
     289           0 :                 i = n = 0;
     290             : #if 0
     291             :                 /*
     292             :                  * This is the old error code we used. Aparently
     293             :                  * WinNT/2k systems return ERRbuftoosmall (2123) and
     294             :                  * OS/2 needs this. I'm leaving this here so we can revert
     295             :                  * if needed. JRA.
     296             :                  */
     297             :                 p->errcode = ERRmoredata;
     298             : #else
     299           0 :                 p->errcode = ERRbuftoosmall;
     300             : #endif
     301             :         } else {
     302           0 :                 p->errcode = NERR_Success;
     303             :         }
     304           0 :         p->buflen = i;
     305           0 :         n -= i;
     306           0 :         p->stringbuf = p->base + i;
     307           0 :         p->stringlen = n;
     308           0 :         return (p->errcode == NERR_Success);
     309             : }
     310             : 
     311           0 : static int package(struct pack_desc *p, ...)
     312             : {
     313             :         va_list args;
     314           0 :         int needed=0, stringneeded;
     315           0 :         const char *str=NULL;
     316           0 :         int is_string=0, stringused;
     317             :         int32_t temp;
     318             : 
     319           0 :         va_start(args,p);
     320             : 
     321           0 :         if (!*p->curpos) {
     322           0 :                 if (!p->subcount) {
     323           0 :                         p->curpos = p->format;
     324             :                 } else {
     325           0 :                         p->curpos = p->subformat;
     326           0 :                         p->subcount--;
     327             :                 }
     328             :         }
     329             : #if CHECK_TYPES
     330             :         str = va_arg(args,char*);
     331             :         SMB_ASSERT(strncmp(str,p->curpos,strlen(str)) == 0);
     332             : #endif
     333           0 :         stringneeded = -1;
     334             : 
     335           0 :         if (!p->curpos) {
     336           0 :                 va_end(args);
     337           0 :                 return 0;
     338             :         }
     339             : 
     340           0 :         switch( *p->curpos++ ) {
     341           0 :                 case 'W':                       /* word (2 byte) */
     342           0 :                         needed = 2;
     343           0 :                         temp = va_arg(args,int);
     344           0 :                         if (p->buflen >= needed) {
     345           0 :                                 SSVAL(p->structbuf,0,temp);
     346             :                         }
     347           0 :                         break;
     348           0 :                 case 'K':                       /* status word? (2 byte) */
     349           0 :                         needed = 2;
     350           0 :                         temp = va_arg(args,int);
     351           0 :                         if (p->buflen >= needed) {
     352           0 :                                 SSVAL(p->structbuf,0,temp);
     353             :                         }
     354           0 :                         break;
     355           0 :                 case 'N':                       /* count of substructures (word) at end */
     356           0 :                         needed = 2;
     357           0 :                         p->subcount = va_arg(args,int);
     358           0 :                         if (p->buflen >= needed) {
     359           0 :                                 SSVAL(p->structbuf,0,p->subcount);
     360             :                         }
     361           0 :                         break;
     362           0 :                 case 'D':                       /* double word (4 byte) */
     363           0 :                         needed = 4;
     364           0 :                         temp = va_arg(args,int);
     365           0 :                         if (p->buflen >= needed) {
     366           0 :                                 SIVAL(p->structbuf,0,temp);
     367             :                         }
     368           0 :                         break;
     369           0 :                 case 'B':                       /* byte (with optional counter) */
     370           0 :                         needed = get_counter(&p->curpos);
     371           0 :                         {
     372           0 :                                 char *s = va_arg(args,char*);
     373           0 :                                 if (p->buflen >= needed) {
     374           0 :                                         strlcpy(p->structbuf,s?s:"",needed);
     375             :                                 }
     376             :                         }
     377           0 :                         break;
     378           0 :                 case 'z':                       /* offset to zero terminated string (4 byte) */
     379           0 :                         str = va_arg(args,char*);
     380           0 :                         stringneeded = (str ? strlen(str)+1 : 0);
     381           0 :                         is_string = 1;
     382           0 :                         break;
     383           0 :                 case 'l':                       /* offset to user data (4 byte) */
     384           0 :                         str = va_arg(args,char*);
     385           0 :                         stringneeded = va_arg(args,int);
     386           0 :                         is_string = 0;
     387           0 :                         break;
     388           0 :                 case 'b':                       /* offset to data (with counter) (4 byte) */
     389           0 :                         str = va_arg(args,char*);
     390           0 :                         stringneeded = get_counter(&p->curpos);
     391           0 :                         is_string = 0;
     392           0 :                         break;
     393             :         }
     394             : 
     395           0 :         va_end(args);
     396           0 :         if (stringneeded >= 0) {
     397           0 :                 needed = 4;
     398           0 :                 if (p->buflen >= needed) {
     399           0 :                         stringused = stringneeded;
     400           0 :                         if (stringused > p->stringlen) {
     401           0 :                                 stringused = (is_string ? p->stringlen : 0);
     402           0 :                                 if (p->errcode == NERR_Success) {
     403           0 :                                         p->errcode = ERRmoredata;
     404             :                                 }
     405             :                         }
     406           0 :                         if (!stringused) {
     407           0 :                                 SIVAL(p->structbuf,0,0);
     408             :                         } else {
     409           0 :                                 SIVAL(p->structbuf,0,PTR_DIFF(p->stringbuf,p->base));
     410           0 :                                 memcpy(p->stringbuf,str?str:"",stringused);
     411           0 :                                 if (is_string) {
     412           0 :                                         p->stringbuf[stringused-1] = '\0';
     413             :                                 }
     414           0 :                                 p->stringbuf += stringused;
     415           0 :                                 p->stringlen -= stringused;
     416           0 :                                 p->usedlen += stringused;
     417             :                         }
     418             :                 }
     419           0 :                 p->neededlen += stringneeded;
     420             :         }
     421             : 
     422           0 :         p->neededlen += needed;
     423           0 :         if (p->buflen >= needed) {
     424           0 :                 p->structbuf += needed;
     425           0 :                 p->buflen -= needed;
     426           0 :                 p->usedlen += needed;
     427             :         } else {
     428           0 :                 if (p->errcode == NERR_Success) {
     429           0 :                         p->errcode = ERRmoredata;
     430             :                 }
     431             :         }
     432           0 :         return 1;
     433             : }
     434             : 
     435             : #if CHECK_TYPES
     436             : #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
     437             : #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
     438             : #else
     439             : #define PACK(desc,t,v) package(desc,v)
     440             : #define PACKl(desc,t,v,l) package(desc,v,l)
     441             : #endif
     442             : 
     443           0 : static void PACKI(struct pack_desc* desc, const char *t,int v)
     444             : {
     445           0 :         PACK(desc,t,v);
     446           0 : }
     447             : 
     448           0 : static void PACKS(struct pack_desc* desc,const char *t,const char *v)
     449             : {
     450           0 :         PACK(desc,t,v);
     451           0 : }
     452             : 
     453             : /****************************************************************************
     454             :  Get a print queue.
     455             : ****************************************************************************/
     456             : 
     457           0 : static void PackDriverData(struct pack_desc* desc)
     458             : {
     459             :         char drivdata[4+4+32];
     460           0 :         SIVAL(drivdata,0,sizeof drivdata); /* cb */
     461           0 :         SIVAL(drivdata,4,1000); /* lVersion */
     462           0 :         memset(drivdata+8,0,32);        /* szDeviceName */
     463           0 :         push_ascii(drivdata+8,"NULL",32, STR_TERMINATE);
     464           0 :         PACKl(desc,"l",drivdata,sizeof drivdata); /* pDriverData */
     465           0 : }
     466             : 
     467           0 : static int check_printq_info(struct pack_desc* desc,
     468             :                                 unsigned int uLevel, char *id1, char *id2)
     469             : {
     470           0 :         desc->subformat = NULL;
     471           0 :         switch( uLevel ) {
     472           0 :                 case 0:
     473           0 :                         desc->format = "B13";
     474           0 :                         break;
     475           0 :                 case 1:
     476           0 :                         desc->format = "B13BWWWzzzzzWW";
     477           0 :                         break;
     478           0 :                 case 2:
     479           0 :                         desc->format = "B13BWWWzzzzzWN";
     480           0 :                         desc->subformat = "WB21BB16B10zWWzDDz";
     481           0 :                         break;
     482           0 :                 case 3:
     483           0 :                         desc->format = "zWWWWzzzzWWzzl";
     484           0 :                         break;
     485           0 :                 case 4:
     486           0 :                         desc->format = "zWWWWzzzzWNzzl";
     487           0 :                         desc->subformat = "WWzWWDDzz";
     488           0 :                         break;
     489           0 :                 case 5:
     490           0 :                         desc->format = "z";
     491           0 :                         break;
     492           0 :                 case 51:
     493           0 :                         desc->format = "K";
     494           0 :                         break;
     495           0 :                 case 52:
     496           0 :                         desc->format = "WzzzzzzzzN";
     497           0 :                         desc->subformat = "z";
     498           0 :                         break;
     499           0 :                 default:
     500           0 :                         DEBUG(0,("check_printq_info: invalid level %d\n",
     501             :                                 uLevel ));
     502           0 :                         return False;
     503             :         }
     504           0 :         if (id1 == NULL || strcmp(desc->format,id1) != 0) {
     505           0 :                 DEBUG(0,("check_printq_info: invalid format %s\n",
     506             :                         id1 ? id1 : "<NULL>" ));
     507           0 :                 return False;
     508             :         }
     509           0 :         if (desc->subformat && (id2 == NULL || strcmp(desc->subformat,id2) != 0)) {
     510           0 :                 DEBUG(0,("check_printq_info: invalid subformat %s\n",
     511             :                         id2 ? id2 : "<NULL>" ));
     512           0 :                 return False;
     513             :         }
     514           0 :         return True;
     515             : }
     516             : 
     517             : 
     518             : #define RAP_JOB_STATUS_QUEUED 0
     519             : #define RAP_JOB_STATUS_PAUSED 1
     520             : #define RAP_JOB_STATUS_SPOOLING 2
     521             : #define RAP_JOB_STATUS_PRINTING 3
     522             : #define RAP_JOB_STATUS_PRINTED 4
     523             : 
     524             : #define RAP_QUEUE_STATUS_PAUSED 1
     525             : #define RAP_QUEUE_STATUS_ERROR 2
     526             : 
     527             : /* turn a print job status into a on the wire status
     528             : */
     529           0 : static int printj_spoolss_status(int v)
     530             : {
     531           0 :         if (v == JOB_STATUS_QUEUED)
     532           0 :                 return RAP_JOB_STATUS_QUEUED;
     533           0 :         if (v & JOB_STATUS_PAUSED)
     534           0 :                 return RAP_JOB_STATUS_PAUSED;
     535           0 :         if (v & JOB_STATUS_SPOOLING)
     536           0 :                 return RAP_JOB_STATUS_SPOOLING;
     537           0 :         if (v & JOB_STATUS_PRINTING)
     538           0 :                 return RAP_JOB_STATUS_PRINTING;
     539           0 :         return 0;
     540             : }
     541             : 
     542             : /* turn a print queue status into a on the wire status
     543             : */
     544           0 : static int printq_spoolss_status(int v)
     545             : {
     546           0 :         if (v == PRINTER_STATUS_OK)
     547           0 :                 return 0;
     548           0 :         if (v & PRINTER_STATUS_PAUSED)
     549           0 :                 return RAP_QUEUE_STATUS_PAUSED;
     550           0 :         return RAP_QUEUE_STATUS_ERROR;
     551             : }
     552             : 
     553           0 : static void fill_spoolss_printjob_info(int uLevel,
     554             :                                        struct pack_desc *desc,
     555             :                                        struct spoolss_JobInfo2 *info2,
     556             :                                        int n)
     557             : {
     558           0 :         time_t t = spoolss_Time_to_time_t(&info2->submitted);
     559             : 
     560             :         /* the client expects localtime */
     561           0 :         t -= get_time_zone(t);
     562             : 
     563           0 :         PACKI(desc,"W",pjobid_to_rap(info2->printer_name, info2->job_id)); /* uJobId */
     564           0 :         if (uLevel == 1) {
     565           0 :                 PACKS(desc,"B21", info2->user_name); /* szUserName */
     566           0 :                 PACKS(desc,"B","");         /* pad */
     567           0 :                 PACKS(desc,"B16","");       /* szNotifyName */
     568           0 :                 PACKS(desc,"B10","PM_Q_RAW"); /* szDataType */
     569           0 :                 PACKS(desc,"z","");         /* pszParms */
     570           0 :                 PACKI(desc,"W",n+1);          /* uPosition */
     571           0 :                 PACKI(desc,"W", printj_spoolss_status(info2->status)); /* fsStatus */
     572           0 :                 PACKS(desc,"z","");         /* pszStatus */
     573           0 :                 PACKI(desc,"D", t); /* ulSubmitted */
     574           0 :                 PACKI(desc,"D", info2->size); /* ulSize */
     575           0 :                 PACKS(desc,"z", info2->document_name); /* pszComment */
     576             :         }
     577           0 :         if (uLevel == 2 || uLevel == 3 || uLevel == 4) {
     578           0 :                 PACKI(desc,"W", info2->priority);          /* uPriority */
     579           0 :                 PACKS(desc,"z", info2->user_name); /* pszUserName */
     580           0 :                 PACKI(desc,"W",n+1);          /* uPosition */
     581           0 :                 PACKI(desc,"W", printj_spoolss_status(info2->status)); /* fsStatus */
     582           0 :                 PACKI(desc,"D",t); /* ulSubmitted */
     583           0 :                 PACKI(desc,"D", info2->size); /* ulSize */
     584           0 :                 PACKS(desc,"z","Samba");    /* pszComment */
     585           0 :                 PACKS(desc,"z", info2->document_name); /* pszDocument */
     586           0 :                 if (uLevel == 3) {
     587           0 :                         PACKS(desc,"z",""); /* pszNotifyName */
     588           0 :                         PACKS(desc,"z","PM_Q_RAW"); /* pszDataType */
     589           0 :                         PACKS(desc,"z",""); /* pszParms */
     590           0 :                         PACKS(desc,"z",""); /* pszStatus */
     591           0 :                         PACKS(desc,"z", info2->printer_name); /* pszQueue */
     592           0 :                         PACKS(desc,"z","lpd");      /* pszQProcName */
     593           0 :                         PACKS(desc,"z",""); /* pszQProcParms */
     594           0 :                         PACKS(desc,"z","NULL"); /* pszDriverName */
     595           0 :                         PackDriverData(desc);   /* pDriverData */
     596           0 :                         PACKS(desc,"z",""); /* pszPrinterName */
     597           0 :                 } else if (uLevel == 4) {   /* OS2 */
     598           0 :                         PACKS(desc,"z","");       /* pszSpoolFileName  */
     599           0 :                         PACKS(desc,"z","");       /* pszPortName       */
     600           0 :                         PACKS(desc,"z","");       /* pszStatus         */
     601           0 :                         PACKI(desc,"D",0);        /* ulPagesSpooled    */
     602           0 :                         PACKI(desc,"D",0);        /* ulPagesSent       */
     603           0 :                         PACKI(desc,"D",0);        /* ulPagesPrinted    */
     604           0 :                         PACKI(desc,"D",0);        /* ulTimePrinted     */
     605           0 :                         PACKI(desc,"D",0);        /* ulExtendJobStatus */
     606           0 :                         PACKI(desc,"D",0);        /* ulStartPage       */
     607           0 :                         PACKI(desc,"D",0);        /* ulEndPage         */
     608             :                 }
     609             :         }
     610           0 : }
     611             : 
     612             : /********************************************************************
     613             :  Respond to the DosPrintQInfo command with a level of 52
     614             :  This is used to get printer driver information for Win9x clients
     615             :  ********************************************************************/
     616           0 : static void fill_printq_info_52(struct spoolss_DriverInfo3 *driver,
     617             :                                 struct pack_desc* desc, int count,
     618             :                                 const char *printer_name)
     619             : {
     620             :         int                             i;
     621             :         fstring                         location;
     622           0 :         trim_string(discard_const_p(char, driver->driver_path), "\\print$\\WIN40\\0\\", 0);
     623           0 :         trim_string(discard_const_p(char, driver->data_file), "\\print$\\WIN40\\0\\", 0);
     624           0 :         trim_string(discard_const_p(char, driver->help_file), "\\print$\\WIN40\\0\\", 0);
     625             : 
     626           0 :         PACKI(desc, "W", 0x0400);                     /* don't know */
     627           0 :         PACKS(desc, "z", driver->driver_name);        /* long printer name */
     628           0 :         PACKS(desc, "z", driver->driver_path);  /* Driverfile Name */
     629           0 :         PACKS(desc, "z", driver->data_file);    /* Datafile name */
     630           0 :         PACKS(desc, "z", driver->monitor_name); /* language monitor */
     631             : 
     632           0 :         fstrcpy(location, "\\\\%L\\print$\\WIN40\\0");
     633           0 :         standard_sub_basic( "", "", location, sizeof(location)-1 );
     634           0 :         PACKS(desc,"z", location);                          /* share to retrieve files */
     635             : 
     636           0 :         PACKS(desc,"z", driver->default_datatype);    /* default data type */
     637           0 :         PACKS(desc,"z", driver->help_file);           /* helpfile name */
     638           0 :         PACKS(desc,"z", driver->driver_path);               /* driver name */
     639             : 
     640           0 :         DEBUG(3,("Printer Driver Name: %s:\n",driver->driver_name));
     641           0 :         DEBUG(3,("Driver: %s:\n",driver->driver_path));
     642           0 :         DEBUG(3,("Data File: %s:\n",driver->data_file));
     643           0 :         DEBUG(3,("Language Monitor: %s:\n",driver->monitor_name));
     644           0 :         DEBUG(3,("Driver Location: %s:\n",location));
     645           0 :         DEBUG(3,("Data Type: %s:\n",driver->default_datatype));
     646           0 :         DEBUG(3,("Help File: %s:\n",driver->help_file));
     647           0 :         PACKI(desc,"N",count);                     /* number of files to copy */
     648             : 
     649           0 :         for ( i=0; i<count && driver->dependent_files && *driver->dependent_files[i]; i++)
     650             :         {
     651           0 :                 trim_string(discard_const_p(char, driver->dependent_files[i]), "\\print$\\WIN40\\0\\", 0);
     652           0 :                 PACKS(desc,"z",driver->dependent_files[i]);         /* driver files to copy */
     653           0 :                 DEBUG(3,("Dependent File: %s:\n", driver->dependent_files[i]));
     654             :         }
     655             : 
     656             :         /* sanity check */
     657           0 :         if ( i != count )
     658           0 :                 DEBUG(3,("fill_printq_info_52: file count specified by client [%d] != number of dependent files [%i]\n",
     659             :                         count, i));
     660             : 
     661           0 :         DEBUG(3,("fill_printq_info on <%s> gave %d entries\n", printer_name, i));
     662             : 
     663           0 :         desc->errcode=NERR_Success;
     664             : 
     665           0 : }
     666             : 
     667           0 : static const char *strip_unc(const char *unc)
     668             : {
     669             :         char *p;
     670             : 
     671           0 :         if (unc == NULL) {
     672           0 :                 return NULL;
     673             :         }
     674             : 
     675           0 :         if ((p = strrchr(unc, '\\')) != NULL) {
     676           0 :                 return p+1;
     677             :         }
     678             : 
     679           0 :         return unc;
     680             : }
     681             : 
     682           0 : static void fill_printq_info(int uLevel,
     683             :                              struct pack_desc* desc,
     684             :                              int count,
     685             :                              union spoolss_JobInfo *job_info,
     686             :                              struct spoolss_DriverInfo3 *driver_info,
     687             :                              struct spoolss_PrinterInfo2 *printer_info)
     688             : {
     689           0 :         switch (uLevel) {
     690           0 :         case 0:
     691             :         case 1:
     692             :         case 2:
     693           0 :                 PACKS(desc,"B13", strip_unc(printer_info->printername));
     694           0 :                 break;
     695           0 :         case 3:
     696             :         case 4:
     697             :         case 5:
     698           0 :                 PACKS(desc,"z", strip_unc(printer_info->printername));
     699           0 :                 break;
     700           0 :         case 51:
     701           0 :                 PACKI(desc,"K", printq_spoolss_status(printer_info->status));
     702           0 :                 break;
     703             :         }
     704             : 
     705           0 :         if (uLevel == 1 || uLevel == 2) {
     706           0 :                 PACKS(desc,"B","");         /* alignment */
     707           0 :                 PACKI(desc,"W",5);            /* priority */
     708           0 :                 PACKI(desc,"W",0);            /* start time */
     709           0 :                 PACKI(desc,"W",0);            /* until time */
     710           0 :                 PACKS(desc,"z","");         /* pSepFile */
     711           0 :                 PACKS(desc,"z","lpd");      /* pPrProc */
     712           0 :                 PACKS(desc,"z", strip_unc(printer_info->printername)); /* pDestinations */
     713           0 :                 PACKS(desc,"z","");         /* pParms */
     714           0 :                 if (printer_info->printername == NULL) {
     715           0 :                         PACKS(desc,"z","UNKNOWN PRINTER");
     716           0 :                         PACKI(desc,"W",LPSTAT_ERROR);
     717             :                 } else {
     718           0 :                         PACKS(desc,"z", printer_info->comment);
     719           0 :                         PACKI(desc,"W", printq_spoolss_status(printer_info->status)); /* status */
     720             :                 }
     721           0 :                 PACKI(desc,(uLevel == 1 ? "W" : "N"),count);
     722             :         }
     723             : 
     724           0 :         if (uLevel == 3 || uLevel == 4) {
     725           0 :                 PACKI(desc,"W",5);            /* uPriority */
     726           0 :                 PACKI(desc,"W",0);            /* uStarttime */
     727           0 :                 PACKI(desc,"W",0);            /* uUntiltime */
     728           0 :                 PACKI(desc,"W",5);            /* pad1 */
     729           0 :                 PACKS(desc,"z","");         /* pszSepFile */
     730           0 :                 PACKS(desc,"z","WinPrint"); /* pszPrProc */
     731           0 :                 PACKS(desc,"z",NULL);         /* pszParms */
     732           0 :                 PACKS(desc,"z",NULL);         /* pszComment - don't ask.... JRA */
     733             :                 /* "don't ask" that it's done this way to fix corrupted
     734             :                    Win9X/ME printer comments. */
     735           0 :                 PACKI(desc,"W", printq_spoolss_status(printer_info->status)); /* fsStatus */
     736           0 :                 PACKI(desc,(uLevel == 3 ? "W" : "N"),count);        /* cJobs */
     737           0 :                 PACKS(desc,"z", strip_unc(printer_info->printername)); /* pszPrinters */
     738           0 :                 PACKS(desc,"z", printer_info->drivername);         /* pszDriverName */
     739           0 :                 PackDriverData(desc);   /* pDriverData */
     740             :         }
     741             : 
     742           0 :         if (uLevel == 2 || uLevel == 4) {
     743             :                 int i;
     744           0 :                 for (i = 0; i < count; i++) {
     745           0 :                         fill_spoolss_printjob_info(uLevel == 2 ? 1 : 2, desc, &job_info[i].info2, i);
     746             :                 }
     747             :         }
     748             : 
     749           0 :         if (uLevel==52)
     750           0 :                 fill_printq_info_52(driver_info, desc, count, printer_info->printername);
     751           0 : }
     752             : 
     753             : /* This function returns the number of files for a given driver */
     754           0 : static int get_printerdrivernumber(const struct spoolss_DriverInfo3 *driver)
     755             : {
     756           0 :         int                             result = 0;
     757             : 
     758             :         /* count the number of files */
     759           0 :         while (driver->dependent_files && *driver->dependent_files[result])
     760           0 :                 result++;
     761             : 
     762           0 :         return result;
     763             : }
     764             : 
     765           0 : static bool api_DosPrintQGetInfo(struct smbd_server_connection *sconn,
     766             :                                  connection_struct *conn, uint64_t vuid,
     767             :                                 char *param, int tpscnt,
     768             :                                 char *data, int tdscnt,
     769             :                                 int mdrcnt,int mprcnt,
     770             :                                 char **rdata,char **rparam,
     771             :                                 int *rdata_len,int *rparam_len)
     772             : {
     773           0 :         char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
     774           0 :         char *str2 = skip_string(param,tpscnt,str1);
     775           0 :         char *p = skip_string(param,tpscnt,str2);
     776           0 :         char *QueueName = p;
     777             :         unsigned int uLevel;
     778           0 :         uint32_t count = 0;
     779             :         char *str3;
     780             :         struct pack_desc desc;
     781           0 :         char* tmpdata=NULL;
     782             : 
     783           0 :         WERROR werr = WERR_OK;
     784           0 :         TALLOC_CTX *mem_ctx = talloc_tos();
     785             :         NTSTATUS status;
     786           0 :         struct rpc_pipe_client *cli = NULL;
     787           0 :         struct dcerpc_binding_handle *b = NULL;
     788             :         struct policy_handle handle;
     789             :         struct spoolss_DevmodeContainer devmode_ctr;
     790             :         union spoolss_DriverInfo driver_info;
     791           0 :         union spoolss_JobInfo *job_info = NULL;
     792             :         union spoolss_PrinterInfo printer_info;
     793             : 
     794           0 :         if (!str1 || !str2 || !p) {
     795           0 :                 return False;
     796             :         }
     797           0 :         memset((char *)&desc,'\0',sizeof(desc));
     798             : 
     799           0 :         p = skip_string(param,tpscnt,p);
     800           0 :         if (!p) {
     801           0 :                 return False;
     802             :         }
     803           0 :         uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
     804           0 :         str3 = get_safe_str_ptr(param,tpscnt,p,4);
     805             :         /* str3 may be null here and is checked in check_printq_info(). */
     806             : 
     807             :         /* remove any trailing username */
     808           0 :         if ((p = strchr_m(QueueName,'%')))
     809           0 :                 *p = 0;
     810             : 
     811           0 :         DEBUG(3,("api_DosPrintQGetInfo uLevel=%d name=%s\n",uLevel,QueueName));
     812             : 
     813             :         /* check it's a supported varient */
     814           0 :         if (!prefix_ok(str1,"zWrLh"))
     815           0 :                 return False;
     816           0 :         if (!check_printq_info(&desc,uLevel,str2,str3)) {
     817             :                 /*
     818             :                  * Patch from Scott Moomaw <scott@bridgewater.edu>
     819             :                  * to return the 'invalid info level' error if an
     820             :                  * unknown level was requested.
     821             :                  */
     822           0 :                 *rdata_len = 0;
     823           0 :                 *rparam_len = 6;
     824           0 :                 *rparam = smb_realloc_limit(*rparam,*rparam_len);
     825           0 :                 if (!*rparam) {
     826           0 :                         return False;
     827             :                 }
     828           0 :                 SSVALS(*rparam,0,ERRunknownlevel);
     829           0 :                 SSVAL(*rparam,2,0);
     830           0 :                 SSVAL(*rparam,4,0);
     831           0 :                 return(True);
     832             :         }
     833             : 
     834           0 :         ZERO_STRUCT(handle);
     835             : 
     836           0 :         if (QueueName == NULL || (strlen(QueueName) < 1)) {
     837           0 :                 desc.errcode = W_ERROR_V(WERR_INVALID_PARAMETER);
     838           0 :                 goto out;
     839             :         }
     840             : 
     841           0 :         status = rpc_pipe_open_interface(mem_ctx,
     842             :                                          &ndr_table_spoolss,
     843           0 :                                          conn->session_info,
     844           0 :                                          conn->sconn->remote_address,
     845           0 :                                          conn->sconn->local_address,
     846           0 :                                          conn->sconn->msg_ctx,
     847             :                                          &cli);
     848           0 :         if (!NT_STATUS_IS_OK(status)) {
     849           0 :                 DEBUG(0,("api_DosPrintQGetInfo: could not connect to spoolss: %s\n",
     850             :                           nt_errstr(status)));
     851           0 :                 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
     852           0 :                 goto out;
     853             :         }
     854           0 :         b = cli->binding_handle;
     855             : 
     856           0 :         ZERO_STRUCT(devmode_ctr);
     857             : 
     858           0 :         status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
     859             :                                             QueueName,
     860             :                                             "RAW",
     861             :                                             devmode_ctr,
     862             :                                             PRINTER_ACCESS_USE,
     863             :                                             &handle,
     864             :                                             &werr);
     865           0 :         if (!NT_STATUS_IS_OK(status)) {
     866           0 :                 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
     867           0 :                 goto out;
     868             :         }
     869           0 :         if (!W_ERROR_IS_OK(werr)) {
     870           0 :                 desc.errcode = W_ERROR_V(werr);
     871           0 :                 goto out;
     872             :         }
     873             : 
     874           0 :         werr = rpccli_spoolss_getprinter(cli, mem_ctx,
     875             :                                          &handle,
     876             :                                          2,
     877             :                                          0,
     878             :                                          &printer_info);
     879           0 :         if (!W_ERROR_IS_OK(werr)) {
     880           0 :                 desc.errcode = W_ERROR_V(werr);
     881           0 :                 goto out;
     882             :         }
     883             : 
     884           0 :         if (uLevel==52) {
     885             :                 uint32_t server_major_version;
     886             :                 uint32_t server_minor_version;
     887             : 
     888           0 :                 werr = rpccli_spoolss_getprinterdriver2(cli, mem_ctx,
     889             :                                                         &handle,
     890             :                                                         "Windows 4.0",
     891             :                                                         3, /* level */
     892             :                                                         0,
     893             :                                                         0, /* version */
     894             :                                                         0,
     895             :                                                         &driver_info,
     896             :                                                         &server_major_version,
     897             :                                                         &server_minor_version);
     898           0 :                 if (!W_ERROR_IS_OK(werr)) {
     899           0 :                         desc.errcode = W_ERROR_V(werr);
     900           0 :                         goto out;
     901             :                 }
     902             : 
     903           0 :                 count = get_printerdrivernumber(&driver_info.info3);
     904           0 :                 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count));
     905             :         } else {
     906             :                 uint32_t num_jobs;
     907           0 :                 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
     908             :                                                &handle,
     909             :                                                0, /* firstjob */
     910             :                                                0xff, /* numjobs */
     911             :                                                2, /* level */
     912             :                                                0, /* offered */
     913             :                                                &num_jobs,
     914             :                                                &job_info);
     915           0 :                 if (!W_ERROR_IS_OK(werr)) {
     916           0 :                         desc.errcode = W_ERROR_V(werr);
     917           0 :                         goto out;
     918             :                 }
     919             : 
     920           0 :                 count = num_jobs;
     921             :         }
     922             : 
     923           0 :         if (mdrcnt > 0) {
     924           0 :                 *rdata = smb_realloc_limit(*rdata,mdrcnt);
     925           0 :                 if (!*rdata) {
     926           0 :                         return False;
     927             :                 }
     928           0 :                 desc.base = *rdata;
     929           0 :                 desc.buflen = mdrcnt;
     930             :         } else {
     931             :                 /*
     932             :                  * Don't return data but need to get correct length
     933             :                  * init_package will return wrong size if buflen=0
     934             :                  */
     935           0 :                 desc.buflen = getlen(desc.format);
     936           0 :                 desc.base = tmpdata = (char *) SMB_MALLOC (desc.buflen);
     937             :         }
     938             : 
     939           0 :         if (init_package(&desc,1,count)) {
     940           0 :                 desc.subcount = count;
     941           0 :                 fill_printq_info(uLevel,&desc,count, job_info, &driver_info.info3, &printer_info.info2);
     942             :         }
     943             : 
     944           0 :         *rdata_len = desc.usedlen;
     945             : 
     946             :         /*
     947             :          * We must set the return code to ERRbuftoosmall
     948             :          * in order to support lanman style printing with Win NT/2k
     949             :          * clients       --jerry
     950             :          */
     951           0 :         if (!mdrcnt && lp_disable_spoolss())
     952           0 :                 desc.errcode = ERRbuftoosmall;
     953             : 
     954           0 :  out:
     955           0 :         if (b && is_valid_policy_hnd(&handle)) {
     956           0 :                 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
     957             :         }
     958             : 
     959           0 :         *rdata_len = desc.usedlen;
     960           0 :         *rparam_len = 6;
     961           0 :         *rparam = smb_realloc_limit(*rparam,*rparam_len);
     962           0 :         if (!*rparam) {
     963           0 :                 SAFE_FREE(tmpdata);
     964           0 :                 return False;
     965             :         }
     966           0 :         SSVALS(*rparam,0,desc.errcode);
     967           0 :         SSVAL(*rparam,2,0);
     968           0 :         SSVAL(*rparam,4,desc.neededlen);
     969             : 
     970           0 :         DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode));
     971             : 
     972           0 :         SAFE_FREE(tmpdata);
     973             : 
     974           0 :         return(True);
     975             : }
     976             : 
     977             : /****************************************************************************
     978             :  View list of all print jobs on all queues.
     979             : ****************************************************************************/
     980             : 
     981           0 : static bool api_DosPrintQEnum(struct smbd_server_connection *sconn,
     982             :                               connection_struct *conn, uint64_t vuid,
     983             :                                 char *param, int tpscnt,
     984             :                                 char *data, int tdscnt,
     985             :                                 int mdrcnt, int mprcnt,
     986             :                                 char **rdata, char** rparam,
     987             :                                 int *rdata_len, int *rparam_len)
     988             : {
     989           0 :         char *param_format = get_safe_str_ptr(param,tpscnt,param,2);
     990           0 :         char *output_format1 = skip_string(param,tpscnt,param_format);
     991           0 :         char *p = skip_string(param,tpscnt,output_format1);
     992           0 :         unsigned int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
     993           0 :         char *output_format2 = get_safe_str_ptr(param,tpscnt,p,4);
     994             :         int i;
     995             :         struct pack_desc desc;
     996           0 :         int *subcntarr = NULL;
     997           0 :         int queuecnt = 0, subcnt = 0, succnt = 0;
     998             : 
     999           0 :         WERROR werr = WERR_OK;
    1000           0 :         TALLOC_CTX *mem_ctx = talloc_tos();
    1001             :         NTSTATUS status;
    1002           0 :         struct rpc_pipe_client *cli = NULL;
    1003           0 :         struct dcerpc_binding_handle *b = NULL;
    1004             :         struct spoolss_DevmodeContainer devmode_ctr;
    1005             :         uint32_t num_printers;
    1006             :         union spoolss_PrinterInfo *printer_info;
    1007             :         union spoolss_DriverInfo *driver_info;
    1008             :         union spoolss_JobInfo **job_info;
    1009             : 
    1010           0 :         if (!param_format || !output_format1 || !p) {
    1011           0 :                 return False;
    1012             :         }
    1013             : 
    1014           0 :         memset((char *)&desc,'\0',sizeof(desc));
    1015             : 
    1016           0 :         DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
    1017             : 
    1018           0 :         if (!prefix_ok(param_format,"WrLeh")) {
    1019           0 :                 return False;
    1020             :         }
    1021           0 :         if (!check_printq_info(&desc,uLevel,output_format1,output_format2)) {
    1022             :                 /*
    1023             :                  * Patch from Scott Moomaw <scott@bridgewater.edu>
    1024             :                  * to return the 'invalid info level' error if an
    1025             :                  * unknown level was requested.
    1026             :                  */
    1027           0 :                 *rdata_len = 0;
    1028           0 :                 *rparam_len = 6;
    1029           0 :                 *rparam = smb_realloc_limit(*rparam,*rparam_len);
    1030           0 :                 if (!*rparam) {
    1031           0 :                         return False;
    1032             :                 }
    1033           0 :                 SSVALS(*rparam,0,ERRunknownlevel);
    1034           0 :                 SSVAL(*rparam,2,0);
    1035           0 :                 SSVAL(*rparam,4,0);
    1036           0 :                 return(True);
    1037             :         }
    1038             : 
    1039           0 :         status = rpc_pipe_open_interface(mem_ctx,
    1040             :                                          &ndr_table_spoolss,
    1041           0 :                                          conn->session_info,
    1042           0 :                                          conn->sconn->remote_address,
    1043           0 :                                          conn->sconn->local_address,
    1044           0 :                                          conn->sconn->msg_ctx,
    1045             :                                          &cli);
    1046           0 :         if (!NT_STATUS_IS_OK(status)) {
    1047           0 :                 DEBUG(0,("api_DosPrintQEnum: could not connect to spoolss: %s\n",
    1048             :                           nt_errstr(status)));
    1049           0 :                 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
    1050           0 :                 goto out;
    1051             :         }
    1052           0 :         b = cli->binding_handle;
    1053             : 
    1054           0 :         werr = rpccli_spoolss_enumprinters(cli, mem_ctx,
    1055             :                                            PRINTER_ENUM_LOCAL,
    1056           0 :                                            cli->srv_name_slash,
    1057             :                                            2,
    1058             :                                            0,
    1059             :                                            &num_printers,
    1060             :                                            &printer_info);
    1061           0 :         if (!W_ERROR_IS_OK(werr)) {
    1062           0 :                 desc.errcode = W_ERROR_V(werr);
    1063           0 :                 goto out;
    1064             :         }
    1065             : 
    1066           0 :         queuecnt = num_printers;
    1067             : 
    1068           0 :         job_info = talloc_array(mem_ctx, union spoolss_JobInfo *, num_printers);
    1069           0 :         if (job_info == NULL) {
    1070           0 :                 goto err;
    1071             :         }
    1072             : 
    1073           0 :         driver_info = talloc_array(mem_ctx, union spoolss_DriverInfo, num_printers);
    1074           0 :         if (driver_info == NULL) {
    1075           0 :                 goto err;
    1076             :         }
    1077             : 
    1078           0 :         if((subcntarr = SMB_MALLOC_ARRAY(int,queuecnt)) == NULL) {
    1079           0 :                 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
    1080           0 :                 goto err;
    1081             :         }
    1082             : 
    1083           0 :         if (mdrcnt > 0) {
    1084           0 :                 *rdata = smb_realloc_limit(*rdata,mdrcnt);
    1085           0 :                 if (!*rdata) {
    1086           0 :                         goto err;
    1087             :                 }
    1088             :         }
    1089           0 :         desc.base = *rdata;
    1090           0 :         desc.buflen = mdrcnt;
    1091             : 
    1092           0 :         subcnt = 0;
    1093           0 :         for (i = 0; i < num_printers; i++) {
    1094             : 
    1095             :                 uint32_t num_jobs;
    1096             :                 struct policy_handle handle;
    1097             :                 const char *printername;
    1098             : 
    1099           0 :                 printername = talloc_strdup(mem_ctx, printer_info[i].info2.printername);
    1100           0 :                 if (printername == NULL) {
    1101           0 :                         goto err;
    1102             :                 }
    1103             : 
    1104           0 :                 ZERO_STRUCT(handle);
    1105           0 :                 ZERO_STRUCT(devmode_ctr);
    1106             : 
    1107           0 :                 status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
    1108             :                                                     printername,
    1109             :                                                     "RAW",
    1110             :                                                     devmode_ctr,
    1111             :                                                     PRINTER_ACCESS_USE,
    1112             :                                                     &handle,
    1113             :                                                     &werr);
    1114           0 :                 if (!NT_STATUS_IS_OK(status)) {
    1115           0 :                         desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
    1116           0 :                         goto out;
    1117             :                 }
    1118           0 :                 if (!W_ERROR_IS_OK(werr)) {
    1119           0 :                         desc.errcode = W_ERROR_V(werr);
    1120           0 :                         goto out;
    1121             :                 }
    1122             : 
    1123           0 :                 werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
    1124             :                                                &handle,
    1125             :                                                0, /* firstjob */
    1126             :                                                0xff, /* numjobs */
    1127             :                                                2, /* level */
    1128             :                                                0, /* offered */
    1129             :                                                &num_jobs,
    1130           0 :                                                &job_info[i]);
    1131           0 :                 if (!W_ERROR_IS_OK(werr)) {
    1132           0 :                         desc.errcode = W_ERROR_V(werr);
    1133           0 :                         goto out;
    1134             :                 }
    1135             : 
    1136           0 :                 if (uLevel==52) {
    1137             :                         uint32_t server_major_version;
    1138             :                         uint32_t server_minor_version;
    1139             : 
    1140           0 :                         werr = rpccli_spoolss_getprinterdriver2(cli, mem_ctx,
    1141             :                                                                 &handle,
    1142             :                                                                 "Windows 4.0",
    1143             :                                                                 3, /* level */
    1144             :                                                                 0,
    1145             :                                                                 0, /* version */
    1146             :                                                                 0,
    1147           0 :                                                                 &driver_info[i],
    1148             :                                                                 &server_major_version,
    1149             :                                                                 &server_minor_version);
    1150           0 :                         if (!W_ERROR_IS_OK(werr)) {
    1151           0 :                                 desc.errcode = W_ERROR_V(werr);
    1152           0 :                                 goto out;
    1153             :                         }
    1154             :                 }
    1155             : 
    1156           0 :                 subcntarr[i] = num_jobs;
    1157           0 :                 subcnt += subcntarr[i];
    1158             : 
    1159           0 :                 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
    1160             :         }
    1161             : 
    1162           0 :         if (init_package(&desc,queuecnt,subcnt)) {
    1163           0 :                 for (i = 0; i < num_printers; i++) {
    1164           0 :                         fill_printq_info(uLevel,&desc,subcntarr[i], job_info[i], &driver_info[i].info3, &printer_info[i].info2);
    1165           0 :                         if (desc.errcode == NERR_Success) {
    1166           0 :                                 succnt = i;
    1167             :                         }
    1168             :                 }
    1169             :         }
    1170             : 
    1171           0 :  out:
    1172           0 :         SAFE_FREE(subcntarr);
    1173           0 :         *rdata_len = desc.usedlen;
    1174           0 :         *rparam_len = 8;
    1175           0 :         *rparam = smb_realloc_limit(*rparam,*rparam_len);
    1176           0 :         if (!*rparam) {
    1177           0 :                 goto err;
    1178             :         }
    1179           0 :         SSVALS(*rparam,0,desc.errcode);
    1180           0 :         SSVAL(*rparam,2,0);
    1181           0 :         SSVAL(*rparam,4,succnt);
    1182           0 :         SSVAL(*rparam,6,queuecnt);
    1183             : 
    1184           0 :         return True;
    1185             : 
    1186           0 :   err:
    1187             : 
    1188           0 :         SAFE_FREE(subcntarr);
    1189             : 
    1190           0 :         return False;
    1191             : }
    1192             : 
    1193             : /****************************************************************************
    1194             :  Get info level for a server list query.
    1195             : ****************************************************************************/
    1196             : 
    1197           4 : static bool check_session_info(int uLevel, char* id)
    1198             : {
    1199           4 :         switch( uLevel ) {
    1200           0 :                 case 0:
    1201           0 :                         if (strcmp(id,"B16") != 0) {
    1202           0 :                                 return False;
    1203             :                         }
    1204           0 :                         break;
    1205           4 :                 case 1:
    1206           4 :                         if (strcmp(id,"B16BBDz") != 0) {
    1207           0 :                                 return False;
    1208             :                         }
    1209           4 :                         break;
    1210           0 :                 default:
    1211           0 :                         return False;
    1212             :         }
    1213           4 :         return True;
    1214             : }
    1215             : 
    1216             : struct srv_info_struct {
    1217             :         fstring name;
    1218             :         uint32_t type;
    1219             :         fstring comment;
    1220             :         fstring domain;
    1221             :         bool server_added;
    1222             : };
    1223             : 
    1224             : /*******************************************************************
    1225             :  Get server info lists from the files saved by nmbd. Return the
    1226             :  number of entries.
    1227             : ******************************************************************/
    1228             : 
    1229           4 : static int get_session_info(uint32_t servertype,
    1230             :                            struct srv_info_struct **servers,
    1231             :                            const char *domain)
    1232             : {
    1233           4 :         int count=0;
    1234           4 :         int alloced=0;
    1235             :         char **lines;
    1236             :         bool local_list_only;
    1237             :         int i;
    1238           4 :         char *slist_cache_path = cache_path(talloc_tos(), SERVER_LIST);
    1239           4 :         if (slist_cache_path == NULL) {
    1240           0 :                 return 0;
    1241             :         }
    1242             : 
    1243           4 :         lines = file_lines_load(slist_cache_path, NULL, 0, NULL);
    1244           4 :         if (!lines) {
    1245           0 :                 DEBUG(4, ("Can't open %s - %s\n",
    1246             :                           slist_cache_path, strerror(errno)));
    1247           0 :                 TALLOC_FREE(slist_cache_path);
    1248           0 :                 return 0;
    1249             :         }
    1250           4 :         TALLOC_FREE(slist_cache_path);
    1251             : 
    1252             :         /* request for everything is code for request all servers */
    1253           4 :         if (servertype == SV_TYPE_ALL) {
    1254           0 :                 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
    1255             :         }
    1256             : 
    1257           4 :         local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY);
    1258             : 
    1259           4 :         DEBUG(4,("Servertype search: %8x\n",servertype));
    1260             : 
    1261          16 :         for (i=0;lines[i];i++) {
    1262             :                 fstring stype;
    1263             :                 struct srv_info_struct *s;
    1264          12 :                 const char *ptr = lines[i];
    1265          12 :                 bool ok = True;
    1266          12 :                 TALLOC_CTX *frame = NULL;
    1267             :                 char *p;
    1268             : 
    1269          12 :                 if (!*ptr) {
    1270           6 :                         continue;
    1271             :                 }
    1272             : 
    1273           8 :                 if (count == alloced) {
    1274           4 :                         alloced += 10;
    1275           4 :                         *servers = SMB_REALLOC_ARRAY(*servers,struct srv_info_struct, alloced);
    1276           4 :                         if (!*servers) {
    1277           0 :                                 DEBUG(0,("get_session_info: failed to enlarge servers info struct!\n"));
    1278           0 :                                 TALLOC_FREE(lines);
    1279           0 :                                 return 0;
    1280             :                         }
    1281           4 :                         memset((char *)((*servers)+count),'\0',sizeof(**servers)*(alloced-count));
    1282             :                 }
    1283           8 :                 s = &(*servers)[count];
    1284             : 
    1285           8 :                 frame = talloc_stackframe();
    1286           8 :                 s->name[0] = '\0';
    1287           8 :                 if (!next_token_talloc(frame,&ptr,&p, NULL)) {
    1288           0 :                         TALLOC_FREE(frame);
    1289           0 :                         continue;
    1290             :                 }
    1291           8 :                 fstrcpy(s->name, p);
    1292             : 
    1293           8 :                 stype[0] = '\0';
    1294           8 :                 if (!next_token_talloc(frame,&ptr, &p, NULL)) {
    1295           0 :                         TALLOC_FREE(frame);
    1296           0 :                         continue;
    1297             :                 }
    1298           8 :                 fstrcpy(stype, p);
    1299             : 
    1300           8 :                 s->comment[0] = '\0';
    1301           8 :                 if (!next_token_talloc(frame,&ptr, &p, NULL)) {
    1302           0 :                         TALLOC_FREE(frame);
    1303           0 :                         continue;
    1304             :                 }
    1305           8 :                 fstrcpy(s->comment, p);
    1306           8 :                 string_truncate(s->comment, MAX_SERVER_STRING_LENGTH);
    1307             : 
    1308           8 :                 s->domain[0] = '\0';
    1309           8 :                 if (!next_token_talloc(frame,&ptr,&p, NULL)) {
    1310             :                         /* this allows us to cope with an old nmbd */
    1311           0 :                         fstrcpy(s->domain,lp_workgroup());
    1312             :                 } else {
    1313           8 :                         fstrcpy(s->domain, p);
    1314             :                 }
    1315           8 :                 TALLOC_FREE(frame);
    1316             : 
    1317           8 :                 if (sscanf(stype,"%X",&s->type) != 1) {
    1318           0 :                         DEBUG(4,("r:host file "));
    1319           0 :                         ok = False;
    1320             :                 }
    1321             : 
    1322             :                 /* Filter the servers/domains we return based on what was asked for. */
    1323             : 
    1324             :                 /* Check to see if we are being asked for a local list only. */
    1325           8 :                 if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) {
    1326           0 :                         DEBUG(4,("r: local list only"));
    1327           0 :                         ok = False;
    1328             :                 }
    1329             : 
    1330             :                 /* doesn't match up: don't want it */
    1331           8 :                 if (!(servertype & s->type)) {
    1332           2 :                         DEBUG(4,("r:serv type "));
    1333           2 :                         ok = False;
    1334             :                 }
    1335             : 
    1336           8 :                 if ((servertype & SV_TYPE_DOMAIN_ENUM) !=
    1337           8 :                                 (s->type & SV_TYPE_DOMAIN_ENUM)) {
    1338           4 :                         DEBUG(4,("s: dom mismatch "));
    1339           4 :                         ok = False;
    1340             :                 }
    1341             : 
    1342           8 :                 if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM)) {
    1343           0 :                         ok = False;
    1344             :                 }
    1345             : 
    1346             :                 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
    1347           8 :                 s->type &= ~SV_TYPE_LOCAL_LIST_ONLY;
    1348             : 
    1349           8 :                 if (ok) {
    1350           4 :                         DEBUG(4,("**SV** %20s %8x %25s %15s\n",
    1351             :                                 s->name, s->type, s->comment, s->domain));
    1352           4 :                         s->server_added = True;
    1353           4 :                         count++;
    1354             :                 } else {
    1355           4 :                         DEBUG(4,("%20s %8x %25s %15s\n",
    1356             :                                 s->name, s->type, s->comment, s->domain));
    1357             :                 }
    1358             :         }
    1359             : 
    1360           4 :         TALLOC_FREE(lines);
    1361           4 :         return count;
    1362             : }
    1363             : 
    1364             : /*******************************************************************
    1365             :  Fill in a server info structure.
    1366             : ******************************************************************/
    1367             : 
    1368           8 : static int fill_srv_info(struct srv_info_struct *service,
    1369             :                          int uLevel, char **buf, int *buflen,
    1370             :                          char **stringbuf, int *stringspace, char *baseaddr)
    1371             : {
    1372             :         int struct_len;
    1373             :         char* p;
    1374             :         char* p2;
    1375             :         int l2;
    1376             :         int len;
    1377             : 
    1378           8 :         switch (uLevel) {
    1379           0 :                 case 0:
    1380           0 :                         struct_len = 16;
    1381           0 :                         break;
    1382           8 :                 case 1:
    1383           8 :                         struct_len = 26;
    1384           8 :                         break;
    1385           0 :                 default:
    1386           0 :                         return -1;
    1387             :         }
    1388             : 
    1389           8 :         if (!buf) {
    1390           4 :                 len = 0;
    1391           4 :                 switch (uLevel) {
    1392           4 :                         case 1:
    1393           4 :                                 len = strlen(service->comment)+1;
    1394           4 :                                 break;
    1395             :                 }
    1396             : 
    1397           4 :                 *buflen = struct_len;
    1398           4 :                 *stringspace = len;
    1399           4 :                 return struct_len + len;
    1400             :         }
    1401             : 
    1402           4 :         len = struct_len;
    1403           4 :         p = *buf;
    1404           4 :         if (*buflen < struct_len) {
    1405           0 :                 return -1;
    1406             :         }
    1407           4 :         if (stringbuf) {
    1408           4 :                 p2 = *stringbuf;
    1409           4 :                 l2 = *stringspace;
    1410             :         } else {
    1411           0 :                 p2 = p + struct_len;
    1412           0 :                 l2 = *buflen - struct_len;
    1413             :         }
    1414           4 :         if (!baseaddr) {
    1415           0 :                 baseaddr = p;
    1416             :         }
    1417             : 
    1418           4 :         switch (uLevel) {
    1419           0 :                 case 0:
    1420           0 :                         push_ascii(p,service->name, MAX_NETBIOSNAME_LEN, STR_TERMINATE);
    1421           0 :                         break;
    1422             : 
    1423           4 :                 case 1:
    1424           4 :                         push_ascii(p,service->name,MAX_NETBIOSNAME_LEN, STR_TERMINATE);
    1425           4 :                         SIVAL(p,18,service->type);
    1426           4 :                         SIVAL(p,22,PTR_DIFF(p2,baseaddr));
    1427           4 :                         len += CopyAndAdvance(&p2,service->comment,&l2);
    1428           4 :                         break;
    1429             :         }
    1430             : 
    1431           4 :         if (stringbuf) {
    1432           4 :                 *buf = p + struct_len;
    1433           4 :                 *buflen -= struct_len;
    1434           4 :                 *stringbuf = p2;
    1435           4 :                 *stringspace = l2;
    1436             :         } else {
    1437           0 :                 *buf = p2;
    1438           0 :                 *buflen -= len;
    1439             :         }
    1440           4 :         return len;
    1441             : }
    1442             : 
    1443             : 
    1444           0 : static int srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
    1445             : {
    1446           0 :         return strcasecmp_m(s1->name,s2->name);
    1447             : }
    1448             : 
    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             : ****************************************************************************/
    1453             : 
    1454           4 : static bool api_RNetServerEnum2(struct smbd_server_connection *sconn,
    1455             :                                 connection_struct *conn, uint64_t vuid,
    1456             :                                 char *param, int tpscnt,
    1457             :                                 char *data, int tdscnt,
    1458             :                                 int mdrcnt, int mprcnt, char **rdata,
    1459             :                                 char **rparam, int *rdata_len, int *rparam_len)
    1460             : {
    1461           4 :         char *str1 = get_safe_str_ptr(param, tpscnt, param, 2);
    1462           4 :         char *str2 = skip_string(param,tpscnt,str1);
    1463           4 :         char *p = skip_string(param,tpscnt,str2);
    1464           4 :         int uLevel = get_safe_SVAL(param, tpscnt, p, 0, -1);
    1465           4 :         int buf_len = get_safe_SVAL(param,tpscnt, p, 2, 0);
    1466           4 :         uint32_t servertype = get_safe_IVAL(param,tpscnt,p,4, 0);
    1467             :         char *p2;
    1468             :         int data_len, fixed_len, string_len;
    1469           4 :         int f_len = 0, s_len = 0;
    1470           4 :         struct srv_info_struct *servers=NULL;
    1471           4 :         int counted=0,total=0;
    1472             :         int i,missed;
    1473             :         fstring domain;
    1474             :         bool domain_request;
    1475             :         bool local_request;
    1476             : 
    1477           4 :         if (!str1 || !str2 || !p) {
    1478           0 :                 return False;
    1479             :         }
    1480             : 
    1481             :         /* If someone sets all the bits they don't really mean to set
    1482             :            DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
    1483             :            known servers. */
    1484             : 
    1485           4 :         if (servertype == SV_TYPE_ALL) {
    1486           2 :                 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
    1487             :         }
    1488             : 
    1489             :         /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
    1490             :            any other bit (they may just set this bit on its own) they
    1491             :            want all the locally seen servers. However this bit can be
    1492             :            set on its own so set the requested servers to be
    1493             :            ALL - DOMAIN_ENUM. */
    1494             : 
    1495           4 :         if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM)) {
    1496           0 :                 servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
    1497             :         }
    1498             : 
    1499           4 :         domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
    1500           4 :         local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
    1501             : 
    1502           4 :         p += 8;
    1503             : 
    1504           4 :         if (!prefix_ok(str1,"WrLehD")) {
    1505           0 :                 return False;
    1506             :         }
    1507           4 :         if (!check_session_info(uLevel,str2)) {
    1508           0 :                 return False;
    1509             :         }
    1510             : 
    1511           4 :         DEBUG(4, ("server request level: %s %8x ", str2, servertype));
    1512           4 :         DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
    1513           4 :         DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
    1514             : 
    1515           4 :         if (strcmp(str1, "WrLehDz") == 0) {
    1516           4 :                 if (skip_string(param,tpscnt,p) == NULL) {
    1517           0 :                         return False;
    1518             :                 }
    1519           4 :                 pull_ascii_fstring(domain, p);
    1520             :         } else {
    1521           0 :                 fstrcpy(domain, lp_workgroup());
    1522             :         }
    1523             : 
    1524           4 :         DEBUG(4, ("domain [%s]\n", domain));
    1525             : 
    1526           4 :         if (lp_browse_list()) {
    1527           4 :                 total = get_session_info(servertype,&servers,domain);
    1528             :         }
    1529             : 
    1530           4 :         data_len = fixed_len = string_len = 0;
    1531           4 :         missed = 0;
    1532             : 
    1533           4 :         TYPESAFE_QSORT(servers, total, srv_comp);
    1534             : 
    1535             :         {
    1536           4 :                 char *lastname=NULL;
    1537             : 
    1538           8 :                 for (i=0;i<total;i++) {
    1539           4 :                         struct srv_info_struct *s = &servers[i];
    1540             : 
    1541           4 :                         if (lastname && strequal(lastname,s->name)) {
    1542           0 :                                 continue;
    1543             :                         }
    1544           4 :                         lastname = s->name;
    1545           4 :                         data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
    1546           4 :                         DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
    1547             :                                 i, s->name, s->type, s->comment, s->domain));
    1548             : 
    1549           4 :                         if (data_len < buf_len) {
    1550           4 :                                 counted++;
    1551           4 :                                 fixed_len += f_len;
    1552           4 :                                 string_len += s_len;
    1553             :                         } else {
    1554           0 :                                 missed++;
    1555             :                         }
    1556             :                 }
    1557             :         }
    1558             : 
    1559           4 :         *rdata_len = fixed_len + string_len;
    1560           4 :         *rdata = smb_realloc_limit(*rdata,*rdata_len);
    1561           4 :         if (!*rdata) {
    1562           0 :                 return False;
    1563             :         }
    1564             : 
    1565           4 :         p2 = (*rdata) + fixed_len;      /* auxilliary data (strings) will go here */
    1566           4 :         p = *rdata;
    1567           4 :         f_len = fixed_len;
    1568           4 :         s_len = string_len;
    1569             : 
    1570             :         {
    1571           4 :                 char *lastname=NULL;
    1572           4 :                 int count2 = counted;
    1573             : 
    1574           8 :                 for (i = 0; i < total && count2;i++) {
    1575           4 :                         struct srv_info_struct *s = &servers[i];
    1576             : 
    1577           4 :                         if (lastname && strequal(lastname,s->name)) {
    1578           0 :                                 continue;
    1579             :                         }
    1580           4 :                         lastname = s->name;
    1581           4 :                         fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
    1582           4 :                         DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
    1583             :                                 i, s->name, s->type, s->comment, s->domain));
    1584           4 :                         count2--;
    1585             :                 }
    1586             :         }
    1587             : 
    1588           4 :         *rparam_len = 8;
    1589           4 :         *rparam = smb_realloc_limit(*rparam,*rparam_len);
    1590           4 :         if (!*rparam) {
    1591           0 :                 return False;
    1592             :         }
    1593           4 :         SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata));
    1594           4 :         SSVAL(*rparam,2,0);
    1595           4 :         SSVAL(*rparam,4,counted);
    1596           4 :         SSVAL(*rparam,6,counted+missed);
    1597             : 
    1598           4 :         SAFE_FREE(servers);
    1599             : 
    1600           4 :         DEBUG(3,("NetServerEnum2 domain = %s uLevel=%d counted=%d total=%d\n",
    1601             :                 domain,uLevel,counted,counted+missed));
    1602             : 
    1603           4 :         return True;
    1604             : }
    1605             : 
    1606           0 : static int srv_name_match(const char *n1, const char *n2)
    1607             : {
    1608             :         /*
    1609             :          * [MS-RAP] footnote <88> for Section 3.2.5.15 says:
    1610             :          *
    1611             :          *  In Windows, FirstNameToReturn need not be an exact match:
    1612             :          *  the server will return a list of servers that exist on
    1613             :          *  the network greater than or equal to the FirstNameToReturn.
    1614             :          */
    1615           0 :         int ret = strcasecmp_m(n1, n2);
    1616             : 
    1617           0 :         if (ret <= 0) {
    1618           0 :                 return 0;
    1619             :         }
    1620             : 
    1621           0 :         return ret;
    1622             : }
    1623             : 
    1624           0 : static bool api_RNetServerEnum3(struct smbd_server_connection *sconn,
    1625             :                                 connection_struct *conn, uint64_t vuid,
    1626             :                                 char *param, int tpscnt,
    1627             :                                 char *data, int tdscnt,
    1628             :                                 int mdrcnt, int mprcnt, char **rdata,
    1629             :                                 char **rparam, int *rdata_len, int *rparam_len)
    1630             : {
    1631           0 :         char *str1 = get_safe_str_ptr(param, tpscnt, param, 2);
    1632           0 :         char *str2 = skip_string(param,tpscnt,str1);
    1633           0 :         char *p = skip_string(param,tpscnt,str2);
    1634           0 :         int uLevel = get_safe_SVAL(param, tpscnt, p, 0, -1);
    1635           0 :         int buf_len = get_safe_SVAL(param,tpscnt, p, 2, 0);
    1636           0 :         uint32_t servertype = get_safe_IVAL(param,tpscnt,p,4, 0);
    1637             :         char *p2;
    1638             :         int data_len, fixed_len, string_len;
    1639           0 :         int f_len = 0, s_len = 0;
    1640           0 :         struct srv_info_struct *servers=NULL;
    1641           0 :         int counted=0,first=0,total=0;
    1642             :         int i,missed;
    1643             :         fstring domain;
    1644             :         fstring first_name;
    1645             :         bool domain_request;
    1646             :         bool local_request;
    1647             : 
    1648           0 :         if (!str1 || !str2 || !p) {
    1649           0 :                 return False;
    1650             :         }
    1651             : 
    1652             :         /* If someone sets all the bits they don't really mean to set
    1653             :            DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
    1654             :            known servers. */
    1655             : 
    1656           0 :         if (servertype == SV_TYPE_ALL) {
    1657           0 :                 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
    1658             :         }
    1659             : 
    1660             :         /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
    1661             :            any other bit (they may just set this bit on its own) they
    1662             :            want all the locally seen servers. However this bit can be
    1663             :            set on its own so set the requested servers to be
    1664             :            ALL - DOMAIN_ENUM. */
    1665             : 
    1666           0 :         if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM)) {
    1667           0 :                 servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
    1668             :         }
    1669             : 
    1670           0 :         domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
    1671           0 :         local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
    1672             : 
    1673           0 :         p += 8;
    1674             : 
    1675           0 :         if (strcmp(str1, "WrLehDzz") != 0) {
    1676           0 :                 return false;
    1677             :         }
    1678           0 :         if (!check_session_info(uLevel,str2)) {
    1679           0 :                 return False;
    1680             :         }
    1681             : 
    1682           0 :         DEBUG(4, ("server request level: %s %8x ", str2, servertype));
    1683           0 :         DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
    1684           0 :         DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
    1685             : 
    1686           0 :         if (skip_string(param,tpscnt,p) == NULL) {
    1687           0 :                 return False;
    1688             :         }
    1689           0 :         pull_ascii_fstring(domain, p);
    1690           0 :         if (domain[0] == '\0') {
    1691           0 :                 fstrcpy(domain, lp_workgroup());
    1692             :         }
    1693           0 :         p = skip_string(param,tpscnt,p);
    1694           0 :         if (skip_string(param,tpscnt,p) == NULL) {
    1695           0 :                 return False;
    1696             :         }
    1697           0 :         pull_ascii_fstring(first_name, p);
    1698             : 
    1699           0 :         DEBUG(4, ("domain: '%s' first_name: '%s'\n",
    1700             :                   domain, first_name));
    1701             : 
    1702           0 :         if (lp_browse_list()) {
    1703           0 :                 total = get_session_info(servertype,&servers,domain);
    1704             :         }
    1705             : 
    1706           0 :         data_len = fixed_len = string_len = 0;
    1707           0 :         missed = 0;
    1708             : 
    1709           0 :         TYPESAFE_QSORT(servers, total, srv_comp);
    1710             : 
    1711           0 :         if (first_name[0] != '\0') {
    1712           0 :                 struct srv_info_struct *first_server = NULL;
    1713             : 
    1714           0 :                 BINARY_ARRAY_SEARCH(servers, total, name, first_name,
    1715             :                                     srv_name_match, first_server);
    1716           0 :                 if (first_server) {
    1717           0 :                         first = PTR_DIFF(first_server, servers) / sizeof(*servers);
    1718             :                         /*
    1719             :                          * The binary search may not find the exact match
    1720             :                          * so we need to search backward to find the first match
    1721             :                          *
    1722             :                          * This implements the strange matching windows
    1723             :                          * implements. (see the comment in srv_name_match().
    1724             :                          */
    1725           0 :                         for (;first > 0;) {
    1726             :                                 int ret;
    1727           0 :                                 ret = strcasecmp_m(first_name,
    1728           0 :                                                  servers[first-1].name);
    1729           0 :                                 if (ret > 0) {
    1730           0 :                                         break;
    1731             :                                 }
    1732           0 :                                 first--;
    1733             :                         }
    1734             :                 } else {
    1735             :                         /* we should return no entries */
    1736           0 :                         first = total;
    1737             :                 }
    1738             :         }
    1739             : 
    1740             :         {
    1741           0 :                 char *lastname=NULL;
    1742             : 
    1743           0 :                 for (i=first;i<total;i++) {
    1744           0 :                         struct srv_info_struct *s = &servers[i];
    1745             : 
    1746           0 :                         if (lastname && strequal(lastname,s->name)) {
    1747           0 :                                 continue;
    1748             :                         }
    1749           0 :                         lastname = s->name;
    1750           0 :                         data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
    1751           0 :                         DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
    1752             :                                 i, s->name, s->type, s->comment, s->domain));
    1753             : 
    1754           0 :                         if (data_len < buf_len) {
    1755           0 :                                 counted++;
    1756           0 :                                 fixed_len += f_len;
    1757           0 :                                 string_len += s_len;
    1758             :                         } else {
    1759           0 :                                 missed++;
    1760             :                         }
    1761             :                 }
    1762             :         }
    1763             : 
    1764           0 :         *rdata_len = fixed_len + string_len;
    1765           0 :         *rdata = smb_realloc_limit(*rdata,*rdata_len);
    1766           0 :         if (!*rdata) {
    1767           0 :                 return False;
    1768             :         }
    1769             : 
    1770           0 :         p2 = (*rdata) + fixed_len;      /* auxilliary data (strings) will go here */
    1771           0 :         p = *rdata;
    1772           0 :         f_len = fixed_len;
    1773           0 :         s_len = string_len;
    1774             : 
    1775             :         {
    1776           0 :                 char *lastname=NULL;
    1777           0 :                 int count2 = counted;
    1778             : 
    1779           0 :                 for (i = first; i < total && count2;i++) {
    1780           0 :                         struct srv_info_struct *s = &servers[i];
    1781             : 
    1782           0 :                         if (lastname && strequal(lastname,s->name)) {
    1783           0 :                                 continue;
    1784             :                         }
    1785           0 :                         lastname = s->name;
    1786           0 :                         fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
    1787           0 :                         DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
    1788             :                                 i, s->name, s->type, s->comment, s->domain));
    1789           0 :                         count2--;
    1790             :                 }
    1791             :         }
    1792             : 
    1793           0 :         *rparam_len = 8;
    1794           0 :         *rparam = smb_realloc_limit(*rparam,*rparam_len);
    1795           0 :         if (!*rparam) {
    1796           0 :                 return False;
    1797             :         }
    1798           0 :         SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata));
    1799           0 :         SSVAL(*rparam,2,0);
    1800           0 :         SSVAL(*rparam,4,counted);
    1801           0 :         SSVAL(*rparam,6,counted+missed);
    1802             : 
    1803           0 :         DEBUG(3,("NetServerEnum3 domain = %s uLevel=%d first=%d[%s => %s] counted=%d total=%d\n",
    1804             :                 domain,uLevel,first,first_name,
    1805             :                 first < total ? servers[first].name : "",
    1806             :                 counted,counted+missed));
    1807             : 
    1808           0 :         SAFE_FREE(servers);
    1809             : 
    1810           0 :         return True;
    1811             : }
    1812             : 
    1813             : /****************************************************************************
    1814             :   command 0x34 - suspected of being a "Lookup Names" stub api
    1815             :   ****************************************************************************/
    1816             : 
    1817           0 : static bool api_RNetGroupGetUsers(struct smbd_server_connection *sconn,
    1818             :                                   connection_struct *conn, uint64_t vuid,
    1819             :                                 char *param, int tpscnt,
    1820             :                                 char *data, int tdscnt,
    1821             :                                 int mdrcnt, int mprcnt, char **rdata,
    1822             :                                 char **rparam, int *rdata_len, int *rparam_len)
    1823             : {
    1824           0 :         char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
    1825           0 :         char *str2 = skip_string(param,tpscnt,str1);
    1826           0 :         char *p = skip_string(param,tpscnt,str2);
    1827           0 :         int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
    1828           0 :         int buf_len = get_safe_SVAL(param,tpscnt,p,2,0);
    1829           0 :         int counted=0;
    1830           0 :         int missed=0;
    1831             : 
    1832           0 :         if (!str1 || !str2 || !p) {
    1833           0 :                 return False;
    1834             :         }
    1835             : 
    1836           0 :         DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
    1837             :                 str1, str2, p, uLevel, buf_len));
    1838             : 
    1839           0 :         if (!prefix_ok(str1,"zWrLeh")) {
    1840           0 :                 return False;
    1841             :         }
    1842             : 
    1843           0 :         *rdata_len = 0;
    1844             : 
    1845           0 :         *rparam_len = 8;
    1846           0 :         *rparam = smb_realloc_limit(*rparam,*rparam_len);
    1847           0 :         if (!*rparam) {
    1848           0 :                 return False;
    1849             :         }
    1850             : 
    1851           0 :         SSVAL(*rparam,0,0x08AC); /* informational warning message */
    1852           0 :         SSVAL(*rparam,2,0);
    1853           0 :         SSVAL(*rparam,4,counted);
    1854           0 :         SSVAL(*rparam,6,counted+missed);
    1855             : 
    1856           0 :         return True;
    1857             : }
    1858             : 
    1859             : /****************************************************************************
    1860             :   get info about a share
    1861             :   ****************************************************************************/
    1862             : 
    1863           0 : static bool check_share_info(int uLevel, char* id)
    1864             : {
    1865           0 :         switch( uLevel ) {
    1866           0 :                 case 0:
    1867           0 :                         if (strcmp(id,"B13") != 0) {
    1868           0 :                                 return False;
    1869             :                         }
    1870           0 :                         break;
    1871           0 :                 case 1:
    1872             :                         /* Level-2 descriptor is allowed (and ignored) */
    1873           0 :                         if (strcmp(id,"B13BWz") != 0 &&
    1874           0 :                             strcmp(id,"B13BWzWWWzB9B") != 0) {
    1875           0 :                                 return False;
    1876             :                         }
    1877           0 :                         break;
    1878           0 :                 case 2:
    1879           0 :                         if (strcmp(id,"B13BWzWWWzB9B") != 0) {
    1880           0 :                                 return False;
    1881             :                         }
    1882           0 :                         break;
    1883           0 :                 case 91:
    1884           0 :                         if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) {
    1885           0 :                                 return False;
    1886             :                         }
    1887           0 :                         break;
    1888           0 :                 default:
    1889           0 :                         return False;
    1890             :         }
    1891           0 :         return True;
    1892             : }
    1893             : 
    1894           0 : static int fill_share_info(connection_struct *conn, int snum, int uLevel,
    1895             :                            char** buf, int* buflen,
    1896             :                            char** stringbuf, int* stringspace, char* baseaddr)
    1897             : {
    1898           0 :         const struct loadparm_substitution *lp_sub =
    1899           0 :                 loadparm_s3_global_substitution();
    1900             :         int struct_len;
    1901             :         char* p;
    1902             :         char* p2;
    1903             :         int l2;
    1904             :         int len;
    1905             : 
    1906           0 :         switch( uLevel ) {
    1907           0 :                 case 0:
    1908           0 :                         struct_len = 13;
    1909           0 :                         break;
    1910           0 :                 case 1:
    1911           0 :                         struct_len = 20;
    1912           0 :                         break;
    1913           0 :                 case 2:
    1914           0 :                         struct_len = 40;
    1915           0 :                         break;
    1916           0 :                 case 91:
    1917           0 :                         struct_len = 68;
    1918           0 :                         break;
    1919           0 :                 default:
    1920           0 :                         return -1;
    1921             :         }
    1922             : 
    1923           0 :         if (!buf) {
    1924           0 :                 len = 0;
    1925             : 
    1926           0 :                 if (uLevel > 0) {
    1927           0 :                         len += StrlenExpanded(conn,snum,lp_comment(talloc_tos(), lp_sub, snum));
    1928             :                 }
    1929           0 :                 if (uLevel > 1) {
    1930           0 :                         len += strlen(lp_path(talloc_tos(), lp_sub, snum)) + 1;
    1931             :                 }
    1932           0 :                 if (buflen) {
    1933           0 :                         *buflen = struct_len;
    1934             :                 }
    1935           0 :                 if (stringspace) {
    1936           0 :                         *stringspace = len;
    1937             :                 }
    1938           0 :                 return struct_len + len;
    1939             :         }
    1940             : 
    1941           0 :         len = struct_len;
    1942           0 :         p = *buf;
    1943           0 :         if ((*buflen) < struct_len) {
    1944           0 :                 return -1;
    1945             :         }
    1946             : 
    1947           0 :         if (stringbuf) {
    1948           0 :                 p2 = *stringbuf;
    1949           0 :                 l2 = *stringspace;
    1950             :         } else {
    1951           0 :                 p2 = p + struct_len;
    1952           0 :                 l2 = (*buflen) - struct_len;
    1953             :         }
    1954             : 
    1955           0 :         if (!baseaddr) {
    1956           0 :                 baseaddr = p;
    1957             :         }
    1958             : 
    1959           0 :         push_ascii(p,lp_servicename(talloc_tos(), lp_sub, snum),13, STR_TERMINATE);
    1960             : 
    1961           0 :         if (uLevel > 0) {
    1962             :                 int type;
    1963             : 
    1964           0 :                 SCVAL(p,13,0);
    1965           0 :                 type = STYPE_DISKTREE;
    1966           0 :                 if (lp_printable(snum)) {
    1967           0 :                         type = STYPE_PRINTQ;
    1968             :                 }
    1969           0 :                 if (strequal("IPC",lp_fstype(snum))) {
    1970           0 :                         type = STYPE_IPC;
    1971             :                 }
    1972           0 :                 SSVAL(p,14,type);               /* device type */
    1973           0 :                 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
    1974           0 :                 len += CopyExpanded(conn,snum,&p2,lp_comment(talloc_tos(), lp_sub, snum),&l2);
    1975             :         }
    1976             : 
    1977           0 :         if (uLevel > 1) {
    1978           0 :                 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
    1979           0 :                 SSVALS(p,22,-1);                /* max uses */
    1980           0 :                 SSVAL(p,24,1); /* current uses */
    1981           0 :                 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
    1982           0 :                 len += CopyAndAdvance(&p2,lp_path(talloc_tos(),lp_sub, snum),&l2);
    1983           0 :                 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
    1984             :         }
    1985             : 
    1986           0 :         if (uLevel > 2) {
    1987           0 :                 memset(p+40,0,SHPWLEN+2);
    1988           0 :                 SSVAL(p,50,0);
    1989           0 :                 SIVAL(p,52,0);
    1990           0 :                 SSVAL(p,56,0);
    1991           0 :                 SSVAL(p,58,0);
    1992           0 :                 SIVAL(p,60,0);
    1993           0 :                 SSVAL(p,64,0);
    1994           0 :                 SSVAL(p,66,0);
    1995             :         }
    1996             : 
    1997           0 :         if (stringbuf) {
    1998           0 :                 (*buf) = p + struct_len;
    1999           0 :                 (*buflen) -= struct_len;
    2000           0 :                 (*stringbuf) = p2;
    2001           0 :                 (*stringspace) = l2;
    2002             :         } else {
    2003           0 :                 (*buf) = p2;
    2004           0 :                 (*buflen) -= len;
    2005             :         }
    2006             : 
    2007           0 :         return len;
    2008             : }
    2009             : 
    2010           0 : static bool api_RNetShareGetInfo(struct smbd_server_connection *sconn,
    2011             :                                  connection_struct *conn,uint64_t vuid,
    2012             :                                 char *param, int tpscnt,
    2013             :                                 char *data, int tdscnt,
    2014             :                                 int mdrcnt,int mprcnt,
    2015             :                                 char **rdata,char **rparam,
    2016             :                                 int *rdata_len,int *rparam_len)
    2017             : {
    2018           0 :         char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
    2019           0 :         char *str2 = skip_string(param,tpscnt,str1);
    2020           0 :         char *netname_in = skip_string(param,tpscnt,str2);
    2021           0 :         char *netname = NULL;
    2022           0 :         char *p = skip_string(param,tpscnt,netname);
    2023           0 :         int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
    2024             :         int snum;
    2025             : 
    2026           0 :         if (!str1 || !str2 || !netname_in || !p) {
    2027           0 :                 return False;
    2028             :         }
    2029             : 
    2030           0 :         snum = find_service(talloc_tos(), netname_in, &netname);
    2031           0 :         if (snum < 0 || !netname) {
    2032           0 :                 return False;
    2033             :         }
    2034             : 
    2035             :         /* check it's a supported varient */
    2036           0 :         if (!prefix_ok(str1,"zWrLh")) {
    2037           0 :                 return False;
    2038             :         }
    2039           0 :         if (!check_share_info(uLevel,str2)) {
    2040           0 :                 return False;
    2041             :         }
    2042             : 
    2043           0 :         *rdata = smb_realloc_limit(*rdata,mdrcnt);
    2044           0 :         if (!*rdata) {
    2045           0 :                 return False;
    2046             :         }
    2047           0 :         p = *rdata;
    2048           0 :         *rdata_len = fill_share_info(conn,snum,uLevel,&p,&mdrcnt,0,0,0);
    2049           0 :         if (*rdata_len < 0) {
    2050           0 :                 return False;
    2051             :         }
    2052             : 
    2053           0 :         *rparam_len = 6;
    2054           0 :         *rparam = smb_realloc_limit(*rparam,*rparam_len);
    2055           0 :         if (!*rparam) {
    2056           0 :                 return False;
    2057             :         }
    2058           0 :         SSVAL(*rparam,0,NERR_Success);
    2059           0 :         SSVAL(*rparam,2,0);             /* converter word */
    2060           0 :         SSVAL(*rparam,4,*rdata_len);
    2061             : 
    2062           0 :         return True;
    2063             : }
    2064             : 
    2065             : /****************************************************************************
    2066             :   View the list of available shares.
    2067             : 
    2068             :   This function is the server side of the NetShareEnum() RAP call.
    2069             :   It fills the return buffer with share names and share comments.
    2070             :   Note that the return buffer normally (in all known cases) allows only
    2071             :   twelve byte strings for share names (plus one for a nul terminator).
    2072             :   Share names longer than 12 bytes must be skipped.
    2073             :  ****************************************************************************/
    2074             : 
    2075           0 : static bool api_RNetShareEnum(struct smbd_server_connection *sconn,
    2076             :                               connection_struct *conn, uint64_t vuid,
    2077             :                                 char *param, int tpscnt,
    2078             :                                 char *data, int tdscnt,
    2079             :                                 int                mdrcnt,
    2080             :                                 int                mprcnt,
    2081             :                                 char             **rdata,
    2082             :                                 char             **rparam,
    2083             :                                 int               *rdata_len,
    2084             :                                 int               *rparam_len )
    2085             : {
    2086           0 :         const struct loadparm_substitution *lp_sub =
    2087           0 :                 loadparm_s3_global_substitution();
    2088           0 :         char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
    2089           0 :         char *str2 = skip_string(param,tpscnt,str1);
    2090           0 :         char *p = skip_string(param,tpscnt,str2);
    2091           0 :         int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
    2092           0 :         int buf_len = get_safe_SVAL(param,tpscnt,p,2,0);
    2093             :         char *p2;
    2094           0 :         int count = 0;
    2095           0 :         int total=0,counted=0;
    2096           0 :         bool missed = False;
    2097             :         int i;
    2098             :         int data_len, fixed_len, string_len;
    2099           0 :         int f_len = 0, s_len = 0;
    2100             : 
    2101           0 :         if (!str1 || !str2 || !p) {
    2102           0 :                 return False;
    2103             :         }
    2104             : 
    2105           0 :         if (!prefix_ok(str1,"WrLeh")) {
    2106           0 :                 return False;
    2107             :         }
    2108           0 :         if (!check_share_info(uLevel,str2)) {
    2109           0 :                 return False;
    2110             :         }
    2111             : 
    2112             :         /* Ensure all the usershares are loaded. */
    2113           0 :         become_root();
    2114           0 :         delete_and_reload_printers();
    2115           0 :         load_registry_shares();
    2116           0 :         count = load_usershare_shares(NULL, connections_snum_used);
    2117           0 :         unbecome_root();
    2118             : 
    2119           0 :         data_len = fixed_len = string_len = 0;
    2120           0 :         for (i=0;i<count;i++) {
    2121             :                 fstring servicename_dos;
    2122           0 :                 if (!(lp_browseable(i) && lp_snum_ok(i))) {
    2123           0 :                         continue;
    2124             :                 }
    2125           0 :                 push_ascii_fstring(servicename_dos, lp_servicename(talloc_tos(), lp_sub, i));
    2126             :                 /* Maximum name length = 13. */
    2127           0 :                 if( lp_browseable( i ) && lp_snum_ok( i ) && (strlen(servicename_dos) < 13)) {
    2128           0 :                         total++;
    2129           0 :                         data_len += fill_share_info(conn,i,uLevel,0,&f_len,0,&s_len,0);
    2130           0 :                         if (data_len < buf_len) {
    2131           0 :                                 counted++;
    2132           0 :                                 fixed_len += f_len;
    2133           0 :                                 string_len += s_len;
    2134             :                         } else {
    2135           0 :                                 missed = True;
    2136             :                         }
    2137             :                 }
    2138             :         }
    2139             : 
    2140           0 :         *rdata_len = fixed_len + string_len;
    2141           0 :         *rdata = smb_realloc_limit(*rdata,*rdata_len);
    2142           0 :         if (!*rdata) {
    2143           0 :                 return False;
    2144             :         }
    2145             : 
    2146           0 :         p2 = (*rdata) + fixed_len;      /* auxiliary data (strings) will go here */
    2147           0 :         p = *rdata;
    2148           0 :         f_len = fixed_len;
    2149           0 :         s_len = string_len;
    2150             : 
    2151           0 :         for( i = 0; i < count; i++ ) {
    2152             :                 fstring servicename_dos;
    2153           0 :                 if (!(lp_browseable(i) && lp_snum_ok(i))) {
    2154           0 :                         continue;
    2155             :                 }
    2156             : 
    2157           0 :                 push_ascii_fstring(servicename_dos,
    2158           0 :                                    lp_servicename(talloc_tos(), lp_sub, i));
    2159           0 :                 if (lp_browseable(i) && lp_snum_ok(i) && (strlen(servicename_dos) < 13)) {
    2160           0 :                         if (fill_share_info( conn,i,uLevel,&p,&f_len,&p2,&s_len,*rdata ) < 0) {
    2161           0 :                                 break;
    2162             :                         }
    2163             :                 }
    2164             :         }
    2165             : 
    2166           0 :         *rparam_len = 8;
    2167           0 :         *rparam = smb_realloc_limit(*rparam,*rparam_len);
    2168           0 :         if (!*rparam) {
    2169           0 :                 return False;
    2170             :         }
    2171           0 :         SSVAL(*rparam,0,missed ? ERRmoredata : NERR_Success);
    2172           0 :         SSVAL(*rparam,2,0);
    2173           0 :         SSVAL(*rparam,4,counted);
    2174           0 :         SSVAL(*rparam,6,total);
    2175             : 
    2176           0 :         DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
    2177             :                 counted,total,uLevel,
    2178             :                 buf_len,*rdata_len,mdrcnt));
    2179             : 
    2180           0 :         return True;
    2181             : }
    2182             : 
    2183             : /****************************************************************************
    2184             :   Add a share
    2185             :   ****************************************************************************/
    2186             : 
    2187           0 : static bool api_RNetShareAdd(struct smbd_server_connection *sconn,
    2188             :                              connection_struct *conn,uint64_t vuid,
    2189             :                                 char *param, int tpscnt,
    2190             :                                 char *data, int tdscnt,
    2191             :                                 int mdrcnt,int mprcnt,
    2192             :                                 char **rdata,char **rparam,
    2193             :                                 int *rdata_len,int *rparam_len)
    2194             : {
    2195           0 :         char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
    2196           0 :         char *str2 = skip_string(param,tpscnt,str1);
    2197           0 :         char *p = skip_string(param,tpscnt,str2);
    2198           0 :         int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
    2199             :         fstring sharename;
    2200             :         fstring comment;
    2201           0 :         char *pathname = NULL;
    2202             :         unsigned int offset;
    2203           0 :         int res = ERRunsup;
    2204             :         size_t converted_size;
    2205             : 
    2206           0 :         WERROR werr = WERR_OK;
    2207           0 :         TALLOC_CTX *mem_ctx = talloc_tos();
    2208             :         NTSTATUS status;
    2209           0 :         struct rpc_pipe_client *cli = NULL;
    2210             :         union srvsvc_NetShareInfo info;
    2211             :         struct srvsvc_NetShareInfo2 info2;
    2212             :         struct dcerpc_binding_handle *b;
    2213             : 
    2214           0 :         if (!str1 || !str2 || !p) {
    2215           0 :                 return False;
    2216             :         }
    2217             : 
    2218             :         /* check it's a supported varient */
    2219           0 :         if (!prefix_ok(str1,RAP_WShareAdd_REQ)) {
    2220           0 :                 return False;
    2221             :         }
    2222           0 :         if (!check_share_info(uLevel,str2)) {
    2223           0 :                 return False;
    2224             :         }
    2225           0 :         if (uLevel != 2) {
    2226           0 :                 return False;
    2227             :         }
    2228             : 
    2229             :         /* Do we have a string ? */
    2230           0 :         if (skip_string(data,mdrcnt,data) == NULL) {
    2231           0 :                 return False;
    2232             :         }
    2233           0 :         pull_ascii_fstring(sharename,data);
    2234             : 
    2235           0 :         if (mdrcnt < 28) {
    2236           0 :                 return False;
    2237             :         }
    2238             : 
    2239             :         /* only support disk share adds */
    2240           0 :         if (SVAL(data,14)!=STYPE_DISKTREE) {
    2241           0 :                 return False;
    2242             :         }
    2243             : 
    2244           0 :         offset = IVAL(data, 16);
    2245           0 :         if (offset >= mdrcnt) {
    2246           0 :                 res = ERRinvalidparam;
    2247           0 :                 goto out;
    2248             :         }
    2249             : 
    2250             :         /* Do we have a string ? */
    2251           0 :         if (skip_string(data,mdrcnt,data+offset) == NULL) {
    2252           0 :                 return False;
    2253             :         }
    2254           0 :         pull_ascii_fstring(comment, offset? (data+offset) : "");
    2255             : 
    2256           0 :         offset = IVAL(data, 26);
    2257             : 
    2258           0 :         if (offset >= mdrcnt) {
    2259           0 :                 res = ERRinvalidparam;
    2260           0 :                 goto out;
    2261             :         }
    2262             : 
    2263             :         /* Do we have a string ? */
    2264           0 :         if (skip_string(data,mdrcnt,data+offset) == NULL) {
    2265           0 :                 return False;
    2266             :         }
    2267             : 
    2268           0 :         if (!pull_ascii_talloc(talloc_tos(), &pathname,
    2269           0 :                                offset ? (data+offset) : "", &converted_size))
    2270             :         {
    2271           0 :                 DEBUG(0,("api_RNetShareAdd: pull_ascii_talloc failed: %s",
    2272             :                          strerror(errno)));
    2273             :         }
    2274             : 
    2275           0 :         if (!pathname) {
    2276           0 :                 return false;
    2277             :         }
    2278             : 
    2279           0 :         status = rpc_pipe_open_interface(mem_ctx, &ndr_table_srvsvc,
    2280           0 :                                         conn->session_info,
    2281           0 :                                         conn->sconn->remote_address,
    2282           0 :                                         conn->sconn->local_address,
    2283           0 :                                         conn->sconn->msg_ctx,
    2284             :                                         &cli);
    2285           0 :         if (!NT_STATUS_IS_OK(status)) {
    2286           0 :                 DEBUG(0,("api_RNetShareAdd: could not connect to srvsvc: %s\n",
    2287             :                           nt_errstr(status)));
    2288           0 :                 res = W_ERROR_V(ntstatus_to_werror(status));
    2289           0 :                 goto out;
    2290             :         }
    2291             : 
    2292           0 :         b = cli->binding_handle;
    2293             : 
    2294           0 :         info2.name              = sharename;
    2295           0 :         info2.type              = STYPE_DISKTREE;
    2296           0 :         info2.comment           = comment;
    2297           0 :         info2.permissions       = 0;
    2298           0 :         info2.max_users         = 0;
    2299           0 :         info2.current_users     = 0;
    2300           0 :         info2.path              = pathname;
    2301           0 :         info2.password          = NULL;
    2302             : 
    2303           0 :         info.info2 = &info2;
    2304             : 
    2305           0 :         status = dcerpc_srvsvc_NetShareAdd(b, mem_ctx,
    2306           0 :                                            cli->srv_name_slash,
    2307             :                                            2,
    2308             :                                            &info,
    2309             :                                            NULL,
    2310             :                                            &werr);
    2311           0 :         if (!NT_STATUS_IS_OK(status)) {
    2312           0 :                 res = W_ERROR_V(ntstatus_to_werror(status));
    2313           0 :                 goto out;
    2314             :         }
    2315           0 :         if (!W_ERROR_IS_OK(werr)) {
    2316           0 :                 res = W_ERROR_V(werr);
    2317           0 :                 goto out;
    2318             :         }
    2319             : 
    2320           0 :         *rparam_len = 6;
    2321           0 :         *rparam = smb_realloc_limit(*rparam,*rparam_len);
    2322           0 :         if (!*rparam) {
    2323           0 :                 return False;
    2324             :         }
    2325           0 :         SSVAL(*rparam,0,NERR_Success);
    2326           0 :         SSVAL(*rparam,2,0);             /* converter word */
    2327           0 :         SSVAL(*rparam,4,*rdata_len);
    2328           0 :         *rdata_len = 0;
    2329             : 
    2330           0 :         return True;
    2331             : 
    2332           0 :   out:
    2333             : 
    2334           0 :         *rparam_len = 4;
    2335           0 :         *rparam = smb_realloc_limit(*rparam,*rparam_len);
    2336           0 :         if (!*rparam) {
    2337           0 :                 return False;
    2338             :         }
    2339           0 :         *rdata_len = 0;
    2340           0 :         SSVAL(*rparam,0,res);
    2341           0 :         SSVAL(*rparam,2,0);
    2342           0 :         return True;
    2343             : }
    2344             : 
    2345             : /****************************************************************************
    2346             :   view list of groups available
    2347             :   ****************************************************************************/
    2348             : 
    2349           0 : static bool api_RNetGroupEnum(struct smbd_server_connection *sconn,
    2350             :                               connection_struct *conn,uint64_t vuid,
    2351             :                                 char *param, int tpscnt,
    2352             :                                 char *data, int tdscnt,
    2353             :                                 int mdrcnt,int mprcnt,
    2354             :                                 char **rdata,char **rparam,
    2355             :                                 int *rdata_len,int *rparam_len)
    2356             : {
    2357             :         int i;
    2358           0 :         int errflags=0;
    2359             :         int resume_context, cli_buf_size;
    2360           0 :         char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
    2361           0 :         char *str2 = skip_string(param,tpscnt,str1);
    2362           0 :         char *p = skip_string(param,tpscnt,str2);
    2363             : 
    2364             :         uint32_t num_groups;
    2365             :         uint32_t resume_handle;
    2366           0 :         struct rpc_pipe_client *samr_pipe = NULL;
    2367             :         struct policy_handle samr_handle, domain_handle;
    2368             :         NTSTATUS status, result;
    2369             :         struct dcerpc_binding_handle *b;
    2370             : 
    2371           0 :         if (!str1 || !str2 || !p) {
    2372           0 :                 return False;
    2373             :         }
    2374             : 
    2375           0 :         if (strcmp(str1,"WrLeh") != 0) {
    2376           0 :                 return False;
    2377             :         }
    2378             : 
    2379             :         /* parameters
    2380             :          * W-> resume context (number of users to skip)
    2381             :          * r -> return parameter pointer to receive buffer
    2382             :          * L -> length of receive buffer
    2383             :          * e -> return parameter number of entries
    2384             :          * h -> return parameter total number of users
    2385             :          */
    2386             : 
    2387           0 :         if (strcmp("B21",str2) != 0) {
    2388           0 :                 return False;
    2389             :         }
    2390             : 
    2391           0 :         status = rpc_pipe_open_interface(
    2392             :                 talloc_tos(), &ndr_table_samr,
    2393           0 :                 conn->session_info, conn->sconn->remote_address,
    2394           0 :                 conn->sconn->local_address, conn->sconn->msg_ctx, &samr_pipe);
    2395           0 :         if (!NT_STATUS_IS_OK(status)) {
    2396           0 :                 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
    2397             :                           nt_errstr(status)));
    2398           0 :                 return false;
    2399             :         }
    2400             : 
    2401           0 :         b = samr_pipe->binding_handle;
    2402             : 
    2403           0 :         status = dcerpc_samr_Connect2(b, talloc_tos(), lp_netbios_name(),
    2404             :                                       SAMR_ACCESS_LOOKUP_DOMAIN, &samr_handle,
    2405             :                                       &result);
    2406           0 :         if (!NT_STATUS_IS_OK(status)) {
    2407           0 :                 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
    2408             :                           nt_errstr(status)));
    2409           0 :                 return false;
    2410             :         }
    2411           0 :         if (!NT_STATUS_IS_OK(result)) {
    2412           0 :                 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
    2413             :                           nt_errstr(result)));
    2414           0 :                 return false;
    2415             :         }
    2416             : 
    2417           0 :         status = dcerpc_samr_OpenDomain(b, talloc_tos(), &samr_handle,
    2418             :                                         SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS,
    2419             :                                         get_global_sam_sid(), &domain_handle,
    2420             :                                         &result);
    2421           0 :         if (!NT_STATUS_IS_OK(status)) {
    2422           0 :                 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
    2423             :                           nt_errstr(status)));
    2424           0 :                 dcerpc_samr_Close(b, talloc_tos(), &samr_handle, &result);
    2425           0 :                 return false;
    2426             :         }
    2427           0 :         if (!NT_STATUS_IS_OK(result)) {
    2428           0 :                 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
    2429             :                           nt_errstr(result)));
    2430           0 :                 dcerpc_samr_Close(b, talloc_tos(), &samr_handle, &result);
    2431           0 :                 return false;
    2432             :         }
    2433             : 
    2434           0 :         resume_context = get_safe_SVAL(param,tpscnt,p,0,-1);
    2435           0 :         cli_buf_size= get_safe_SVAL(param,tpscnt,p,2,0);
    2436           0 :         DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: "
    2437             :                   "%d\n", resume_context, cli_buf_size));
    2438             : 
    2439           0 :         *rdata_len = cli_buf_size;
    2440           0 :         *rdata = smb_realloc_limit(*rdata,*rdata_len);
    2441           0 :         if (!*rdata) {
    2442           0 :                 return False;
    2443             :         }
    2444             : 
    2445           0 :         p = *rdata;
    2446             : 
    2447           0 :         errflags = NERR_Success;
    2448           0 :         num_groups = 0;
    2449           0 :         resume_handle = 0;
    2450             : 
    2451           0 :         while (true) {
    2452             :                 struct samr_SamArray *sam_entries;
    2453             :                 uint32_t num_entries;
    2454             : 
    2455           0 :                 status = dcerpc_samr_EnumDomainGroups(b, talloc_tos(),
    2456             :                                                       &domain_handle,
    2457             :                                                       &resume_handle,
    2458             :                                                       &sam_entries, 1,
    2459             :                                                       &num_entries,
    2460             :                                                       &result);
    2461           0 :                 if (!NT_STATUS_IS_OK(status)) {
    2462           0 :                         DEBUG(10, ("dcerpc_samr_EnumDomainGroups returned "
    2463             :                                    "%s\n", nt_errstr(status)));
    2464           0 :                         break;
    2465             :                 }
    2466           0 :                 if (!NT_STATUS_IS_OK(result)) {
    2467           0 :                         status = result;
    2468           0 :                         DEBUG(10, ("dcerpc_samr_EnumDomainGroups returned "
    2469             :                                    "%s\n", nt_errstr(result)));
    2470           0 :                         break;
    2471             :                 }
    2472             : 
    2473           0 :                 if (num_entries == 0) {
    2474           0 :                         DEBUG(10, ("dcerpc_samr_EnumDomainGroups returned "
    2475             :                                    "no entries -- done\n"));
    2476           0 :                         break;
    2477             :                 }
    2478             : 
    2479           0 :                 for(i=0; i<num_entries; i++) {
    2480             :                         const char *name;
    2481             : 
    2482           0 :                         name = sam_entries->entries[i].name.string;
    2483             : 
    2484           0 :                         if( ((PTR_DIFF(p,*rdata)+21) > *rdata_len) ) {
    2485             :                                 /* set overflow error */
    2486           0 :                                 DEBUG(3,("overflow on entry %d group %s\n", i,
    2487             :                                          name));
    2488           0 :                                 errflags=234;
    2489           0 :                                 break;
    2490             :                         }
    2491             : 
    2492             :                         /* truncate the name at 21 chars. */
    2493           0 :                         memset(p, 0, 21);
    2494           0 :                         strlcpy(p, name, 21);
    2495           0 :                         DEBUG(10,("adding entry %d group %s\n", i, p));
    2496           0 :                         p += 21;
    2497           0 :                         p += 5; /* Both NT4 and W2k3SP1 do padding here.  No
    2498             :                                  * idea why... */
    2499           0 :                         num_groups += 1;
    2500             :                 }
    2501             : 
    2502           0 :                 if (errflags != NERR_Success) {
    2503           0 :                         break;
    2504             :                 }
    2505             : 
    2506           0 :                 TALLOC_FREE(sam_entries);
    2507             :         }
    2508             : 
    2509           0 :         dcerpc_samr_Close(b, talloc_tos(), &domain_handle, &result);
    2510           0 :         dcerpc_samr_Close(b, talloc_tos(), &samr_handle, &result);
    2511             : 
    2512           0 :         *rdata_len = PTR_DIFF(p,*rdata);
    2513             : 
    2514           0 :         *rparam_len = 8;
    2515           0 :         *rparam = smb_realloc_limit(*rparam,*rparam_len);
    2516           0 :         if (!*rparam) {
    2517           0 :                 return False;
    2518             :         }
    2519           0 :         SSVAL(*rparam, 0, errflags);
    2520           0 :         SSVAL(*rparam, 2, 0);           /* converter word */
    2521           0 :         SSVAL(*rparam, 4, num_groups);  /* is this right?? */
    2522           0 :         SSVAL(*rparam, 6, resume_context+num_groups);   /* is this right?? */
    2523             : 
    2524           0 :         return(True);
    2525             : }
    2526             : 
    2527             : /*******************************************************************
    2528             :  Get groups that a user is a member of.
    2529             : ******************************************************************/
    2530             : 
    2531           0 : static bool api_NetUserGetGroups(struct smbd_server_connection *sconn,
    2532             :                                  connection_struct *conn,uint64_t vuid,
    2533             :                                 char *param, int tpscnt,
    2534             :                                 char *data, int tdscnt,
    2535             :                                 int mdrcnt,int mprcnt,
    2536             :                                 char **rdata,char **rparam,
    2537             :                                 int *rdata_len,int *rparam_len)
    2538             : {
    2539           0 :         char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
    2540           0 :         char *str2 = skip_string(param,tpscnt,str1);
    2541           0 :         char *UserName = skip_string(param,tpscnt,str2);
    2542           0 :         char *p = skip_string(param,tpscnt,UserName);
    2543           0 :         int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
    2544             :         const char *level_string;
    2545           0 :         int count=0;
    2546           0 :         bool ret = False;
    2547             :         uint32_t i;
    2548           0 :         char *endp = NULL;
    2549             : 
    2550           0 :         struct rpc_pipe_client *samr_pipe = NULL;
    2551             :         struct policy_handle samr_handle, domain_handle, user_handle;
    2552             :         struct lsa_String name;
    2553             :         struct lsa_Strings names;
    2554             :         struct samr_Ids type, rid;
    2555             :         struct samr_RidWithAttributeArray *rids;
    2556             :         NTSTATUS status, result;
    2557             :         struct dcerpc_binding_handle *b;
    2558             : 
    2559           0 :         if (!str1 || !str2 || !UserName || !p) {
    2560           0 :                 return False;
    2561             :         }
    2562             : 
    2563           0 :         *rparam_len = 8;
    2564           0 :         *rparam = smb_realloc_limit(*rparam,*rparam_len);
    2565           0 :         if (!*rparam) {
    2566           0 :                 return False;
    2567             :         }
    2568             : 
    2569             :         /* check it's a supported varient */
    2570             : 
    2571           0 :         if ( strcmp(str1,"zWrLeh") != 0 )
    2572           0 :                 return False;
    2573             : 
    2574           0 :         switch( uLevel ) {
    2575           0 :                 case 0:
    2576           0 :                         level_string = "B21";
    2577           0 :                         break;
    2578           0 :                 default:
    2579           0 :                         return False;
    2580             :         }
    2581             : 
    2582           0 :         if (strcmp(level_string,str2) != 0)
    2583           0 :                 return False;
    2584             : 
    2585           0 :         *rdata_len = mdrcnt + 1024;
    2586           0 :         *rdata = smb_realloc_limit(*rdata,*rdata_len);
    2587           0 :         if (!*rdata) {
    2588           0 :                 return False;
    2589             :         }
    2590             : 
    2591           0 :         SSVAL(*rparam,0,NERR_Success);
    2592           0 :         SSVAL(*rparam,2,0);             /* converter word */
    2593             : 
    2594           0 :         p = *rdata;
    2595           0 :         endp = *rdata + *rdata_len;
    2596             : 
    2597           0 :         status = rpc_pipe_open_interface(
    2598             :                 talloc_tos(), &ndr_table_samr,
    2599           0 :                 conn->session_info, conn->sconn->remote_address,
    2600           0 :                 conn->sconn->local_address, conn->sconn->msg_ctx, &samr_pipe);
    2601           0 :         if (!NT_STATUS_IS_OK(status)) {
    2602           0 :                 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
    2603             :                           nt_errstr(status)));
    2604           0 :                 return false;
    2605             :         }
    2606             : 
    2607           0 :         b = samr_pipe->binding_handle;
    2608             : 
    2609           0 :         status = dcerpc_samr_Connect2(b, talloc_tos(), lp_netbios_name(),
    2610             :                                       SAMR_ACCESS_LOOKUP_DOMAIN, &samr_handle,
    2611             :                                       &result);
    2612           0 :         if (!NT_STATUS_IS_OK(status)) {
    2613           0 :                 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
    2614             :                           nt_errstr(status)));
    2615           0 :                 return false;
    2616             :         }
    2617           0 :         if (!NT_STATUS_IS_OK(result)) {
    2618           0 :                 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
    2619             :                           nt_errstr(result)));
    2620           0 :                 return false;
    2621             :         }
    2622             : 
    2623           0 :         status = dcerpc_samr_OpenDomain(b, talloc_tos(), &samr_handle,
    2624             :                                         SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
    2625             :                                         get_global_sam_sid(), &domain_handle,
    2626             :                                         &result);
    2627           0 :         if (!NT_STATUS_IS_OK(status)) {
    2628           0 :                 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
    2629             :                           nt_errstr(status)));
    2630           0 :                 goto close_sam;
    2631             :         }
    2632           0 :         if (!NT_STATUS_IS_OK(result)) {
    2633           0 :                 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
    2634             :                           nt_errstr(result)));
    2635           0 :                 goto close_sam;
    2636             :         }
    2637             : 
    2638           0 :         name.string = UserName;
    2639             : 
    2640           0 :         status = dcerpc_samr_LookupNames(b, talloc_tos(),
    2641             :                                          &domain_handle, 1, &name,
    2642             :                                          &rid, &type,
    2643             :                                          &result);
    2644           0 :         if (!NT_STATUS_IS_OK(status)) {
    2645           0 :                 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
    2646             :                           nt_errstr(status)));
    2647           0 :                 goto close_domain;
    2648             :         }
    2649           0 :         if (!NT_STATUS_IS_OK(result)) {
    2650           0 :                 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
    2651             :                           nt_errstr(result)));
    2652           0 :                 goto close_domain;
    2653             :         }
    2654           0 :         if (rid.count != 1) {
    2655           0 :                 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
    2656           0 :                 goto close_domain;
    2657             :         }
    2658           0 :         if (type.count != 1) {
    2659           0 :                 status = NT_STATUS_INVALID_NETWORK_RESPONSE;
    2660           0 :                 goto close_domain;
    2661             :         }
    2662             : 
    2663           0 :         if (type.ids[0] != SID_NAME_USER) {
    2664           0 :                 DEBUG(10, ("%s is a %s, not a user\n", UserName,
    2665             :                            sid_type_lookup(type.ids[0])));
    2666           0 :                 goto close_domain;
    2667             :         }
    2668             : 
    2669           0 :         status = dcerpc_samr_OpenUser(b, talloc_tos(),
    2670             :                                       &domain_handle,
    2671             :                                       SAMR_USER_ACCESS_GET_GROUPS,
    2672           0 :                                       rid.ids[0], &user_handle,
    2673             :                                       &result);
    2674           0 :         if (!NT_STATUS_IS_OK(status)) {
    2675           0 :                 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
    2676             :                           nt_errstr(status)));
    2677           0 :                 goto close_domain;
    2678             :         }
    2679           0 :         if (!NT_STATUS_IS_OK(result)) {
    2680           0 :                 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
    2681             :                           nt_errstr(result)));
    2682           0 :                 goto close_domain;
    2683             :         }
    2684             : 
    2685           0 :         status = dcerpc_samr_GetGroupsForUser(b, talloc_tos(),
    2686             :                                               &user_handle, &rids,
    2687             :                                               &result);
    2688           0 :         if (!NT_STATUS_IS_OK(status)) {
    2689           0 :                 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
    2690             :                           nt_errstr(status)));
    2691           0 :                 goto close_user;
    2692             :         }
    2693           0 :         if (!NT_STATUS_IS_OK(result)) {
    2694           0 :                 DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
    2695             :                           nt_errstr(result)));
    2696           0 :                 goto close_user;
    2697             :         }
    2698             : 
    2699           0 :         for (i=0; i<rids->count; i++) {
    2700             : 
    2701           0 :                 status = dcerpc_samr_LookupRids(b, talloc_tos(),
    2702             :                                                 &domain_handle,
    2703           0 :                                                 1, &rids->rids[i].rid,
    2704             :                                                 &names, &type,
    2705             :                                                 &result);
    2706           0 :                 if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(result) && (names.count == 1)) {
    2707           0 :                         strlcpy(p, names.names[0].string, PTR_DIFF(endp,p));
    2708           0 :                         p += 21;
    2709           0 :                         count++;
    2710             :                 }
    2711             :         }
    2712             : 
    2713           0 :         *rdata_len = PTR_DIFF(p,*rdata);
    2714             : 
    2715           0 :         SSVAL(*rparam,4,count); /* is this right?? */
    2716           0 :         SSVAL(*rparam,6,count); /* is this right?? */
    2717             : 
    2718           0 :         ret = True;
    2719             : 
    2720           0 :  close_user:
    2721           0 :         dcerpc_samr_Close(b, talloc_tos(), &user_handle, &result);
    2722           0 :  close_domain:
    2723           0 :         dcerpc_samr_Close(b, talloc_tos(), &domain_handle, &result);
    2724           0 :  close_sam:
    2725           0 :         dcerpc_samr_Close(b, talloc_tos(), &samr_handle, &result);
    2726             : 
    2727           0 :         return ret;
    2728             : }
    2729             : 
    2730             : /*******************************************************************
    2731             :  Get all users.
    2732             : ******************************************************************/
    2733             : 
    2734           0 : static bool api_RNetUserEnum(struct smbd_server_connection *sconn,
    2735             :                              connection_struct *conn, uint64_t vuid,
    2736             :                                 char *param, int tpscnt,
    2737             :                                 char *data, int tdscnt,
    2738             :                                 int mdrcnt,int mprcnt,
    2739             :                                 char **rdata,char **rparam,
    2740             :                                 int *rdata_len,int *rparam_len)
    2741             : {
    2742           0 :         int count_sent=0;
    2743           0 :         int num_users=0;
    2744           0 :         int errflags=0;
    2745             :         int i, resume_context, cli_buf_size;
    2746             :         uint32_t resume_handle;
    2747             : 
    2748           0 :         struct rpc_pipe_client *samr_pipe = NULL;
    2749             :         struct policy_handle samr_handle, domain_handle;
    2750             :         NTSTATUS status, result;
    2751             : 
    2752           0 :         char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
    2753           0 :         char *str2 = skip_string(param,tpscnt,str1);
    2754           0 :         char *p = skip_string(param,tpscnt,str2);
    2755           0 :         char *endp = NULL;
    2756             : 
    2757             :         struct dcerpc_binding_handle *b;
    2758             : 
    2759           0 :         if (!str1 || !str2 || !p) {
    2760           0 :                 return False;
    2761             :         }
    2762             : 
    2763           0 :         if (strcmp(str1,"WrLeh") != 0)
    2764           0 :                 return False;
    2765             :         /* parameters
    2766             :           * W-> resume context (number of users to skip)
    2767             :           * r -> return parameter pointer to receive buffer
    2768             :           * L -> length of receive buffer
    2769             :           * e -> return parameter number of entries
    2770             :           * h -> return parameter total number of users
    2771             :           */
    2772             : 
    2773           0 :         resume_context = get_safe_SVAL(param,tpscnt,p,0,-1);
    2774           0 :         cli_buf_size= get_safe_SVAL(param,tpscnt,p,2,0);
    2775           0 :         DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n",
    2776             :                         resume_context, cli_buf_size));
    2777             : 
    2778           0 :         *rparam_len = 8;
    2779           0 :         *rparam = smb_realloc_limit(*rparam,*rparam_len);
    2780           0 :         if (!*rparam) {
    2781           0 :                 return False;
    2782             :         }
    2783             : 
    2784             :         /* check it's a supported varient */
    2785           0 :         if (strcmp("B21",str2) != 0)
    2786           0 :                 return False;
    2787             : 
    2788           0 :         *rdata_len = cli_buf_size;
    2789           0 :         *rdata = smb_realloc_limit(*rdata,*rdata_len);
    2790           0 :         if (!*rdata) {
    2791           0 :                 return False;
    2792             :         }
    2793             : 
    2794           0 :         p = *rdata;
    2795           0 :         endp = *rdata + *rdata_len;
    2796             : 
    2797           0 :         status = rpc_pipe_open_interface(
    2798             :                 talloc_tos(), &ndr_table_samr,
    2799           0 :                 conn->session_info, conn->sconn->remote_address,
    2800           0 :                 conn->sconn->local_address, conn->sconn->msg_ctx, &samr_pipe);
    2801           0 :         if (!NT_STATUS_IS_OK(status)) {
    2802           0 :                 DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
    2803             :                           nt_errstr(status)));
    2804           0 :                 return false;
    2805             :         }
    2806             : 
    2807           0 :         b = samr_pipe->binding_handle;
    2808             : 
    2809           0 :         status = dcerpc_samr_Connect2(b, talloc_tos(), lp_netbios_name(),
    2810             :                                       SAMR_ACCESS_LOOKUP_DOMAIN, &samr_handle,
    2811             :                                       &result);
    2812           0 :         if (!NT_STATUS_IS_OK(status)) {
    2813           0 :                 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
    2814             :                           nt_errstr(status)));
    2815           0 :                 return false;
    2816             :         }
    2817           0 :         if (!NT_STATUS_IS_OK(result)) {
    2818           0 :                 DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
    2819             :                           nt_errstr(result)));
    2820           0 :                 return false;
    2821             :         }
    2822             : 
    2823           0 :         status = dcerpc_samr_OpenDomain(b, talloc_tos(), &samr_handle,
    2824             :                                         SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS,
    2825             :                                         get_global_sam_sid(), &domain_handle,
    2826             :                                         &result);
    2827           0 :         if (!NT_STATUS_IS_OK(status)) {
    2828           0 :                 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
    2829             :                           nt_errstr(status)));
    2830           0 :                 dcerpc_samr_Close(b, talloc_tos(), &samr_handle, &result);
    2831           0 :                 return false;
    2832             :         }
    2833           0 :         if (!NT_STATUS_IS_OK(result)) {
    2834           0 :                 DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
    2835             :                           nt_errstr(result)));
    2836           0 :                 dcerpc_samr_Close(b, talloc_tos(), &samr_handle, &result);
    2837           0 :                 return false;
    2838             :         }
    2839             : 
    2840           0 :         errflags=NERR_Success;
    2841             : 
    2842           0 :         resume_handle = 0;
    2843             : 
    2844           0 :         while (true) {
    2845             :                 struct samr_SamArray *sam_entries;
    2846             :                 uint32_t num_entries;
    2847             : 
    2848           0 :                 status = dcerpc_samr_EnumDomainUsers(b, talloc_tos(),
    2849             :                                                      &domain_handle,
    2850             :                                                      &resume_handle,
    2851             :                                                      0, &sam_entries, 1,
    2852             :                                                      &num_entries,
    2853             :                                                      &result);
    2854             : 
    2855           0 :                 if (!NT_STATUS_IS_OK(status)) {
    2856           0 :                         DEBUG(10, ("dcerpc_samr_EnumDomainUsers returned "
    2857             :                                    "%s\n", nt_errstr(status)));
    2858           0 :                         break;
    2859             :                 }
    2860           0 :                 if (!NT_STATUS_IS_OK(result)) {
    2861           0 :                         DEBUG(10, ("dcerpc_samr_EnumDomainUsers returned "
    2862             :                                    "%s\n", nt_errstr(result)));
    2863           0 :                         break;
    2864             :                 }
    2865             : 
    2866           0 :                 if (num_entries == 0) {
    2867           0 :                         DEBUG(10, ("dcerpc_samr_EnumDomainUsers returned "
    2868             :                                    "no entries -- done\n"));
    2869           0 :                         break;
    2870             :                 }
    2871             : 
    2872           0 :                 for (i=0; i<num_entries; i++) {
    2873             :                         const char *name;
    2874             : 
    2875           0 :                         name = sam_entries->entries[i].name.string;
    2876             : 
    2877           0 :                         if(((PTR_DIFF(p,*rdata)+21)<=*rdata_len)
    2878           0 :                            &&(strlen(name)<=21)) {
    2879           0 :                                 strlcpy(p,name,PTR_DIFF(endp,p));
    2880           0 :                                 DEBUG(10,("api_RNetUserEnum:adding entry %d "
    2881             :                                           "username %s\n",count_sent,p));
    2882           0 :                                 p += 21;
    2883           0 :                                 count_sent++;
    2884             :                         } else {
    2885             :                                 /* set overflow error */
    2886           0 :                                 DEBUG(10,("api_RNetUserEnum:overflow on entry %d "
    2887             :                                           "username %s\n",count_sent,name));
    2888           0 :                                 errflags=234;
    2889           0 :                                 break;
    2890             :                         }
    2891             :                 }
    2892             : 
    2893           0 :                 if (errflags != NERR_Success) {
    2894           0 :                         break;
    2895             :                 }
    2896             : 
    2897           0 :                 TALLOC_FREE(sam_entries);
    2898             :         }
    2899             : 
    2900           0 :         dcerpc_samr_Close(b, talloc_tos(), &domain_handle, &result);
    2901           0 :         dcerpc_samr_Close(b, talloc_tos(), &samr_handle, &result);
    2902             : 
    2903           0 :         *rdata_len = PTR_DIFF(p,*rdata);
    2904             : 
    2905           0 :         SSVAL(*rparam,0,errflags);
    2906           0 :         SSVAL(*rparam,2,0);           /* converter word */
    2907           0 :         SSVAL(*rparam,4,count_sent);  /* is this right?? */
    2908           0 :         SSVAL(*rparam,6,num_users); /* is this right?? */
    2909             : 
    2910           0 :         return True;
    2911             : }
    2912             : 
    2913             : /****************************************************************************
    2914             :  Get the time of day info.
    2915             : ****************************************************************************/
    2916             : 
    2917           0 : static bool api_NetRemoteTOD(struct smbd_server_connection *sconn,
    2918             :                              connection_struct *conn,uint64_t vuid,
    2919             :                                 char *param, int tpscnt,
    2920             :                                 char *data, int tdscnt,
    2921             :                                 int mdrcnt,int mprcnt,
    2922             :                                 char **rdata,char **rparam,
    2923             :                                 int *rdata_len,int *rparam_len)
    2924             : {
    2925             :         struct tm *t;
    2926           0 :         time_t unixdate = time(NULL);
    2927             :         char *p;
    2928             : 
    2929           0 :         *rparam_len = 4;
    2930           0 :         *rparam = smb_realloc_limit(*rparam,*rparam_len);
    2931           0 :         if (!*rparam) {
    2932           0 :                 return False;
    2933             :         }
    2934             : 
    2935           0 :         *rdata_len = 21;
    2936           0 :         *rdata = smb_realloc_limit(*rdata,*rdata_len);
    2937           0 :         if (!*rdata) {
    2938           0 :                 return False;
    2939             :         }
    2940             : 
    2941           0 :         SSVAL(*rparam,0,NERR_Success);
    2942           0 :         SSVAL(*rparam,2,0);             /* converter word */
    2943             : 
    2944           0 :         p = *rdata;
    2945             : 
    2946           0 :         srv_put_dos_date3(p,0,unixdate); /* this is the time that is looked at
    2947             :                                             by NT in a "net time" operation,
    2948             :                                             it seems to ignore the one below */
    2949             : 
    2950             :         /* the client expects to get localtime, not GMT, in this bit
    2951             :                 (I think, this needs testing) */
    2952           0 :         t = localtime(&unixdate);
    2953           0 :         if (!t) {
    2954           0 :                 return False;
    2955             :         }
    2956             : 
    2957           0 :         SIVAL(p,4,0);           /* msecs ? */
    2958           0 :         SCVAL(p,8,t->tm_hour);
    2959           0 :         SCVAL(p,9,t->tm_min);
    2960           0 :         SCVAL(p,10,t->tm_sec);
    2961           0 :         SCVAL(p,11,0);          /* hundredths of seconds */
    2962           0 :         SSVALS(p,12,get_time_zone(unixdate)/60); /* timezone in minutes from GMT */
    2963           0 :         SSVAL(p,14,10000);              /* timer interval in 0.0001 of sec */
    2964           0 :         SCVAL(p,16,t->tm_mday);
    2965           0 :         SCVAL(p,17,t->tm_mon + 1);
    2966           0 :         SSVAL(p,18,1900+t->tm_year);
    2967           0 :         SCVAL(p,20,t->tm_wday);
    2968             : 
    2969           0 :         return True;
    2970             : }
    2971             : 
    2972             : /****************************************************************************
    2973             :   Set the user password (SamOEM version - gets plaintext).
    2974             : ****************************************************************************/
    2975             : 
    2976           0 : static bool api_SamOEMChangePassword(struct smbd_server_connection *sconn,
    2977             :                                      connection_struct *conn,uint64_t vuid,
    2978             :                                 char *param, int tpscnt,
    2979             :                                 char *data, int tdscnt,
    2980             :                                 int mdrcnt,int mprcnt,
    2981             :                                 char **rdata,char **rparam,
    2982             :                                 int *rdata_len,int *rparam_len)
    2983             : {
    2984             :         fstring user;
    2985           0 :         char *p = get_safe_str_ptr(param,tpscnt,param,2);
    2986             : 
    2987           0 :         TALLOC_CTX *mem_ctx = talloc_tos();
    2988             :         NTSTATUS status, result;
    2989           0 :         struct rpc_pipe_client *cli = NULL;
    2990             :         struct lsa_AsciiString server, account;
    2991             :         struct samr_CryptPassword password;
    2992             :         struct samr_Password hash;
    2993           0 :         int errcode = NERR_badpass;
    2994             :         int bufsize;
    2995             :         struct dcerpc_binding_handle *b;
    2996             : 
    2997           0 :         *rparam_len = 4;
    2998           0 :         *rparam = smb_realloc_limit(*rparam,*rparam_len);
    2999           0 :         if (!*rparam) {
    3000           0 :                 return False;
    3001             :         }
    3002             : 
    3003           0 :         if (!p) {
    3004           0 :                 return False;
    3005             :         }
    3006           0 :         *rdata_len = 0;
    3007             : 
    3008           0 :         SSVAL(*rparam,0,NERR_badpass);
    3009             : 
    3010             :         /*
    3011             :          * Check the parameter definition is correct.
    3012             :          */
    3013             : 
    3014             :         /* Do we have a string ? */
    3015           0 :         if (skip_string(param,tpscnt,p) == 0) {
    3016           0 :                 return False;
    3017             :         }
    3018           0 :         if(!strequal(p, "zsT")) {
    3019           0 :                 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", p));
    3020           0 :                 return False;
    3021             :         }
    3022           0 :         p = skip_string(param, tpscnt, p);
    3023           0 :         if (!p) {
    3024           0 :                 return False;
    3025             :         }
    3026             : 
    3027             :         /* Do we have a string ? */
    3028           0 :         if (skip_string(param,tpscnt,p) == 0) {
    3029           0 :                 return False;
    3030             :         }
    3031           0 :         if(!strequal(p, "B516B16")) {
    3032           0 :                 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p));
    3033           0 :                 return False;
    3034             :         }
    3035           0 :         p = skip_string(param,tpscnt,p);
    3036           0 :         if (!p) {
    3037           0 :                 return False;
    3038             :         }
    3039             :         /* Do we have a string ? */
    3040           0 :         if (skip_string(param,tpscnt,p) == 0) {
    3041           0 :                 return False;
    3042             :         }
    3043           0 :         p += pull_ascii_fstring(user,p);
    3044             : 
    3045           0 :         DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user));
    3046             : 
    3047           0 :         if (tdscnt != 532) {
    3048           0 :                 errcode = W_ERROR_V(WERR_INVALID_PARAMETER);
    3049           0 :                 goto out;
    3050             :         }
    3051             : 
    3052           0 :         bufsize = get_safe_SVAL(param,tpscnt,p,0,-1);
    3053           0 :         if (bufsize != 532) {
    3054           0 :                 errcode = W_ERROR_V(WERR_INVALID_PARAMETER);
    3055           0 :                 goto out;
    3056             :         }
    3057             : 
    3058           0 :         memcpy(password.data, data, 516);
    3059           0 :         memcpy(hash.hash, data+516, 16);
    3060             : 
    3061           0 :         status = rpc_pipe_open_interface(mem_ctx, &ndr_table_samr,
    3062           0 :                                         conn->session_info,
    3063           0 :                                         conn->sconn->remote_address,
    3064           0 :                                         conn->sconn->local_address,
    3065           0 :                                         conn->sconn->msg_ctx,
    3066             :                                         &cli);
    3067           0 :         if (!NT_STATUS_IS_OK(status)) {
    3068           0 :                 DEBUG(0,("api_SamOEMChangePassword: could not connect to samr: %s\n",
    3069             :                           nt_errstr(status)));
    3070           0 :                 errcode = W_ERROR_V(ntstatus_to_werror(status));
    3071           0 :                 goto out;
    3072             :         }
    3073             : 
    3074           0 :         b = cli->binding_handle;
    3075             : 
    3076           0 :         init_lsa_AsciiString(&server, lp_netbios_name());
    3077           0 :         init_lsa_AsciiString(&account, user);
    3078             : 
    3079           0 :         status = dcerpc_samr_OemChangePasswordUser2(b, mem_ctx,
    3080             :                                                     &server,
    3081             :                                                     &account,
    3082             :                                                     &password,
    3083             :                                                     &hash,
    3084             :                                                     &result);
    3085           0 :         if (!NT_STATUS_IS_OK(status)) {
    3086           0 :                 errcode = W_ERROR_V(ntstatus_to_werror(status));
    3087           0 :                 goto out;
    3088             :         }
    3089           0 :         if (!NT_STATUS_IS_OK(result)) {
    3090           0 :                 errcode = W_ERROR_V(ntstatus_to_werror(result));
    3091           0 :                 goto out;
    3092             :         }
    3093             : 
    3094           0 :         errcode = NERR_Success;
    3095           0 :  out:
    3096           0 :         SSVAL(*rparam,0,errcode);
    3097           0 :         SSVAL(*rparam,2,0);             /* converter word */
    3098             : 
    3099           0 :         return(True);
    3100             : }
    3101             : 
    3102             : /****************************************************************************
    3103             :   delete a print job
    3104             :   Form: <W> <>
    3105             :   ****************************************************************************/
    3106             : 
    3107           0 : static bool api_RDosPrintJobDel(struct smbd_server_connection *sconn,
    3108             :                                 connection_struct *conn,uint64_t vuid,
    3109             :                                 char *param, int tpscnt,
    3110             :                                 char *data, int tdscnt,
    3111             :                                 int mdrcnt,int mprcnt,
    3112             :                                 char **rdata,char **rparam,
    3113             :                                 int *rdata_len,int *rparam_len)
    3114             : {
    3115           0 :         int function = get_safe_SVAL(param,tpscnt,param,0,0);
    3116           0 :         char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
    3117           0 :         char *str2 = skip_string(param,tpscnt,str1);
    3118           0 :         char *p = skip_string(param,tpscnt,str2);
    3119             :         uint32_t jobid;
    3120             :         fstring sharename;
    3121             :         int errcode;
    3122           0 :         WERROR werr = WERR_OK;
    3123             : 
    3124           0 :         TALLOC_CTX *mem_ctx = talloc_tos();
    3125             :         NTSTATUS status;
    3126           0 :         struct rpc_pipe_client *cli = NULL;
    3127           0 :         struct dcerpc_binding_handle *b = NULL;
    3128             :         struct policy_handle handle;
    3129             :         struct spoolss_DevmodeContainer devmode_ctr;
    3130             :         enum spoolss_JobControl command;
    3131             : 
    3132           0 :         if (!str1 || !str2 || !p) {
    3133           0 :                 return False;
    3134             :         }
    3135             :         /*
    3136             :          * We use 1 here not 2 as we're checking
    3137             :          * the last byte we want to access is safe.
    3138             :          */
    3139           0 :         if (!is_offset_safe(param,tpscnt,p,1)) {
    3140           0 :                 return False;
    3141             :         }
    3142           0 :         if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
    3143           0 :                 return False;
    3144             : 
    3145             :         /* check it's a supported varient */
    3146           0 :         if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
    3147           0 :                 return(False);
    3148             : 
    3149           0 :         *rparam_len = 4;
    3150           0 :         *rparam = smb_realloc_limit(*rparam,*rparam_len);
    3151           0 :         if (!*rparam) {
    3152           0 :                 return False;
    3153             :         }
    3154           0 :         *rdata_len = 0;
    3155             : 
    3156           0 :         ZERO_STRUCT(handle);
    3157             : 
    3158           0 :         status = rpc_pipe_open_interface(mem_ctx,
    3159             :                                          &ndr_table_spoolss,
    3160           0 :                                          conn->session_info,
    3161           0 :                                          conn->sconn->remote_address,
    3162           0 :                                          conn->sconn->local_address,
    3163           0 :                                          conn->sconn->msg_ctx,
    3164             :                                          &cli);
    3165           0 :         if (!NT_STATUS_IS_OK(status)) {
    3166           0 :                 DEBUG(0,("api_RDosPrintJobDel: could not connect to spoolss: %s\n",
    3167             :                           nt_errstr(status)));
    3168           0 :                 errcode = W_ERROR_V(ntstatus_to_werror(status));
    3169           0 :                 goto out;
    3170             :         }
    3171           0 :         b = cli->binding_handle;
    3172             : 
    3173           0 :         ZERO_STRUCT(devmode_ctr);
    3174             : 
    3175           0 :         status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
    3176             :                                             sharename,
    3177             :                                             "RAW",
    3178             :                                             devmode_ctr,
    3179             :                                             JOB_ACCESS_ADMINISTER,
    3180             :                                             &handle,
    3181             :                                             &werr);
    3182           0 :         if (!NT_STATUS_IS_OK(status)) {
    3183           0 :                 errcode = W_ERROR_V(ntstatus_to_werror(status));
    3184           0 :                 goto out;
    3185             :         }
    3186           0 :         if (!W_ERROR_IS_OK(werr)) {
    3187           0 :                 errcode = W_ERROR_V(werr);
    3188           0 :                 goto out;
    3189             :         }
    3190             : 
    3191             :         /* FIXME: formerly NERR_JobNotFound was returned if job did not exist
    3192             :          * and NERR_DestNotFound if share did not exist */
    3193             : 
    3194           0 :         errcode = NERR_Success;
    3195             : 
    3196           0 :         switch (function) {
    3197           0 :         case 81:                /* delete */
    3198           0 :                 command = SPOOLSS_JOB_CONTROL_DELETE;
    3199           0 :                 break;
    3200           0 :         case 82:                /* pause */
    3201           0 :                 command = SPOOLSS_JOB_CONTROL_PAUSE;
    3202           0 :                 break;
    3203           0 :         case 83:                /* resume */
    3204           0 :                 command = SPOOLSS_JOB_CONTROL_RESUME;
    3205           0 :                 break;
    3206           0 :         default:
    3207           0 :                 errcode = NERR_notsupported;
    3208           0 :                 goto out;
    3209             :         }
    3210             : 
    3211           0 :         status = dcerpc_spoolss_SetJob(b, mem_ctx,
    3212             :                                        &handle,
    3213             :                                        jobid,
    3214             :                                        NULL, /* unique ptr ctr */
    3215             :                                        command,
    3216             :                                        &werr);
    3217           0 :         if (!NT_STATUS_IS_OK(status)) {
    3218           0 :                 errcode = W_ERROR_V(ntstatus_to_werror(status));
    3219           0 :                 goto out;
    3220             :         }
    3221           0 :         if (!W_ERROR_IS_OK(werr)) {
    3222           0 :                 errcode = W_ERROR_V(werr);
    3223           0 :                 goto out;
    3224             :         }
    3225             : 
    3226           0 :  out:
    3227           0 :         if (b && is_valid_policy_hnd(&handle)) {
    3228           0 :                 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
    3229             :         }
    3230             : 
    3231           0 :         SSVAL(*rparam,0,errcode);
    3232           0 :         SSVAL(*rparam,2,0);             /* converter word */
    3233             : 
    3234           0 :         return(True);
    3235             : }
    3236             : 
    3237             : /****************************************************************************
    3238             :   Purge a print queue - or pause or resume it.
    3239             :   ****************************************************************************/
    3240             : 
    3241           0 : static bool api_WPrintQueueCtrl(struct smbd_server_connection *sconn,
    3242             :                                 connection_struct *conn,uint64_t vuid,
    3243             :                                 char *param, int tpscnt,
    3244             :                                 char *data, int tdscnt,
    3245             :                                 int mdrcnt,int mprcnt,
    3246             :                                 char **rdata,char **rparam,
    3247             :                                 int *rdata_len,int *rparam_len)
    3248             : {
    3249           0 :         int function = get_safe_SVAL(param,tpscnt,param,0,0);
    3250           0 :         char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
    3251           0 :         char *str2 = skip_string(param,tpscnt,str1);
    3252           0 :         char *QueueName = skip_string(param,tpscnt,str2);
    3253           0 :         int errcode = NERR_notsupported;
    3254           0 :         WERROR werr = WERR_OK;
    3255             :         NTSTATUS status;
    3256             : 
    3257           0 :         TALLOC_CTX *mem_ctx = talloc_tos();
    3258           0 :         struct rpc_pipe_client *cli = NULL;
    3259           0 :         struct dcerpc_binding_handle *b = NULL;
    3260             :         struct policy_handle handle;
    3261             :         struct spoolss_SetPrinterInfoCtr info_ctr;
    3262             :         struct spoolss_DevmodeContainer devmode_ctr;
    3263             :         struct sec_desc_buf secdesc_ctr;
    3264           0 :         enum spoolss_PrinterControl command = SPOOLSS_PRINTER_CONTROL_UNPAUSE;
    3265             : 
    3266           0 :         if (!str1 || !str2 || !QueueName) {
    3267           0 :                 return False;
    3268             :         }
    3269             : 
    3270             :         /* check it's a supported varient */
    3271           0 :         if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
    3272           0 :                 return(False);
    3273             : 
    3274           0 :         *rparam_len = 4;
    3275           0 :         *rparam = smb_realloc_limit(*rparam,*rparam_len);
    3276           0 :         if (!*rparam) {
    3277           0 :                 return False;
    3278             :         }
    3279           0 :         *rdata_len = 0;
    3280             : 
    3281           0 :         if (skip_string(param,tpscnt,QueueName) == NULL) {
    3282           0 :                 return False;
    3283             :         }
    3284             : 
    3285           0 :         ZERO_STRUCT(handle);
    3286             : 
    3287           0 :         status = rpc_pipe_open_interface(mem_ctx,
    3288             :                                          &ndr_table_spoolss,
    3289           0 :                                          conn->session_info,
    3290           0 :                                          conn->sconn->remote_address,
    3291           0 :                                          conn->sconn->local_address,
    3292           0 :                                          conn->sconn->msg_ctx,
    3293             :                                          &cli);
    3294           0 :         if (!NT_STATUS_IS_OK(status)) {
    3295           0 :                 DEBUG(0,("api_WPrintQueueCtrl: could not connect to spoolss: %s\n",
    3296             :                           nt_errstr(status)));
    3297           0 :                 errcode = W_ERROR_V(ntstatus_to_werror(status));
    3298           0 :                 goto out;
    3299             :         }
    3300           0 :         b = cli->binding_handle;
    3301             : 
    3302           0 :         ZERO_STRUCT(devmode_ctr);
    3303             : 
    3304           0 :         status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
    3305             :                                             QueueName,
    3306             :                                             NULL,
    3307             :                                             devmode_ctr,
    3308             :                                             PRINTER_ACCESS_ADMINISTER,
    3309             :                                             &handle,
    3310             :                                             &werr);
    3311           0 :         if (!NT_STATUS_IS_OK(status)) {
    3312           0 :                 errcode = W_ERROR_V(ntstatus_to_werror(status));
    3313           0 :                 goto out;
    3314             :         }
    3315           0 :         if (!W_ERROR_IS_OK(werr)) {
    3316           0 :                 errcode = W_ERROR_V(werr);
    3317           0 :                 goto out;
    3318             :         }
    3319             : 
    3320           0 :         switch (function) {
    3321           0 :         case 74: /* Pause queue */
    3322           0 :                 command = SPOOLSS_PRINTER_CONTROL_PAUSE;
    3323           0 :                 break;
    3324           0 :         case 75: /* Resume queue */
    3325           0 :                 command = SPOOLSS_PRINTER_CONTROL_RESUME;
    3326           0 :                 break;
    3327           0 :         case 103: /* Purge */
    3328           0 :                 command = SPOOLSS_PRINTER_CONTROL_PURGE;
    3329           0 :                 break;
    3330           0 :         default:
    3331           0 :                 werr = WERR_NOT_SUPPORTED;
    3332           0 :                 break;
    3333             :         }
    3334             : 
    3335           0 :         if (!W_ERROR_IS_OK(werr)) {
    3336           0 :                 errcode = W_ERROR_V(werr);
    3337           0 :                 goto out;
    3338             :         }
    3339             : 
    3340           0 :         ZERO_STRUCT(info_ctr);
    3341           0 :         ZERO_STRUCT(secdesc_ctr);
    3342             : 
    3343           0 :         status = dcerpc_spoolss_SetPrinter(b, mem_ctx,
    3344             :                                            &handle,
    3345             :                                            &info_ctr,
    3346             :                                            &devmode_ctr,
    3347             :                                            &secdesc_ctr,
    3348             :                                            command,
    3349             :                                            &werr);
    3350           0 :         if (!NT_STATUS_IS_OK(status)) {
    3351           0 :                 errcode = W_ERROR_V(ntstatus_to_werror(status));
    3352           0 :                 goto out;
    3353             :         }
    3354           0 :         if (!W_ERROR_IS_OK(werr)) {
    3355           0 :                 errcode = W_ERROR_V(werr);
    3356           0 :                 goto out;
    3357             :         }
    3358             : 
    3359           0 :         errcode = W_ERROR_V(werr);
    3360             : 
    3361           0 :  out:
    3362             : 
    3363           0 :         if (b && is_valid_policy_hnd(&handle)) {
    3364           0 :                 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
    3365             :         }
    3366             : 
    3367           0 :         SSVAL(*rparam,0,errcode);
    3368           0 :         SSVAL(*rparam,2,0);             /* converter word */
    3369             : 
    3370           0 :         return(True);
    3371             : }
    3372             : 
    3373             : /****************************************************************************
    3374             :   set the property of a print job (undocumented?)
    3375             :   ? function = 0xb -> set name of print job
    3376             :   ? function = 0x6 -> move print job up/down
    3377             :   Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
    3378             :   or   <WWsTP> <WB21BB16B10zWWzDDz>
    3379             : ****************************************************************************/
    3380             : 
    3381           0 : static int check_printjob_info(struct pack_desc* desc,
    3382             :                                int uLevel, char* id)
    3383             : {
    3384           0 :         desc->subformat = NULL;
    3385           0 :         switch( uLevel ) {
    3386           0 :         case 0: desc->format = "W"; break;
    3387           0 :         case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
    3388           0 :         case 2: desc->format = "WWzWWDDzz"; break;
    3389           0 :         case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
    3390           0 :         case 4: desc->format = "WWzWWDDzzzzzDDDDDDD"; break;
    3391           0 :         default:
    3392           0 :                 DEBUG(0,("check_printjob_info: invalid level %d\n",
    3393             :                         uLevel ));
    3394           0 :                 return False;
    3395             :         }
    3396           0 :         if (id == NULL || strcmp(desc->format,id) != 0) {
    3397           0 :                 DEBUG(0,("check_printjob_info: invalid format %s\n",
    3398             :                         id ? id : "<NULL>" ));
    3399           0 :                 return False;
    3400             :         }
    3401           0 :         return True;
    3402             : }
    3403             : 
    3404           0 : static bool api_PrintJobInfo(struct smbd_server_connection *sconn,
    3405             :                              connection_struct *conn, uint64_t vuid,
    3406             :                                 char *param, int tpscnt,
    3407             :                                 char *data, int tdscnt,
    3408             :                                 int mdrcnt,int mprcnt,
    3409             :                                 char **rdata,char **rparam,
    3410             :                                 int *rdata_len,int *rparam_len)
    3411             : {
    3412             :         struct pack_desc desc;
    3413           0 :         char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
    3414           0 :         char *str2 = skip_string(param,tpscnt,str1);
    3415           0 :         char *p = skip_string(param,tpscnt,str2);
    3416             :         uint32_t jobid;
    3417             :         fstring sharename;
    3418           0 :         int uLevel = get_safe_SVAL(param,tpscnt,p,2,-1);
    3419           0 :         int function = get_safe_SVAL(param,tpscnt,p,4,-1);
    3420             :         int errcode;
    3421             : 
    3422           0 :         TALLOC_CTX *mem_ctx = talloc_tos();
    3423             :         WERROR werr;
    3424             :         NTSTATUS status;
    3425           0 :         struct rpc_pipe_client *cli = NULL;
    3426           0 :         struct dcerpc_binding_handle *b = NULL;
    3427             :         struct policy_handle handle;
    3428             :         struct spoolss_DevmodeContainer devmode_ctr;
    3429             :         struct spoolss_JobInfoContainer ctr;
    3430             :         union spoolss_JobInfo info;
    3431             :         struct spoolss_SetJobInfo1 info1;
    3432             : 
    3433           0 :         if (!str1 || !str2 || !p) {
    3434           0 :                 return False;
    3435             :         }
    3436             :         /*
    3437             :          * We use 1 here not 2 as we're checking
    3438             :          * the last byte we want to access is safe.
    3439             :          */
    3440           0 :         if (!is_offset_safe(param,tpscnt,p,1)) {
    3441           0 :                 return False;
    3442             :         }
    3443           0 :         if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
    3444           0 :                 return False;
    3445           0 :         *rparam_len = 4;
    3446           0 :         *rparam = smb_realloc_limit(*rparam,*rparam_len);
    3447           0 :         if (!*rparam) {
    3448           0 :                 return False;
    3449             :         }
    3450             : 
    3451           0 :         *rdata_len = 0;
    3452             : 
    3453             :         /* check it's a supported varient */
    3454           0 :         if ((strcmp(str1,"WWsTP")) ||
    3455           0 :             (!check_printjob_info(&desc,uLevel,str2)))
    3456           0 :                 return(False);
    3457             : 
    3458           0 :         errcode = NERR_notsupported;
    3459             : 
    3460           0 :         switch (function) {
    3461           0 :         case 0xb:
    3462             :                 /* change print job name, data gives the name */
    3463           0 :                 break;
    3464           0 :         default:
    3465           0 :                 goto out;
    3466             :         }
    3467             : 
    3468           0 :         ZERO_STRUCT(handle);
    3469             : 
    3470           0 :         status = rpc_pipe_open_interface(mem_ctx,
    3471             :                                          &ndr_table_spoolss,
    3472           0 :                                          conn->session_info,
    3473           0 :                                          conn->sconn->remote_address,
    3474           0 :                                          conn->sconn->local_address,
    3475           0 :                                          conn->sconn->msg_ctx,
    3476             :                                          &cli);
    3477           0 :         if (!NT_STATUS_IS_OK(status)) {
    3478           0 :                 DEBUG(0,("api_PrintJobInfo: could not connect to spoolss: %s\n",
    3479             :                           nt_errstr(status)));
    3480           0 :                 errcode = W_ERROR_V(ntstatus_to_werror(status));
    3481           0 :                 goto out;
    3482             :         }
    3483           0 :         b = cli->binding_handle;
    3484             : 
    3485           0 :         ZERO_STRUCT(devmode_ctr);
    3486             : 
    3487           0 :         status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
    3488             :                                             sharename,
    3489             :                                             "RAW",
    3490             :                                             devmode_ctr,
    3491             :                                             PRINTER_ACCESS_USE,
    3492             :                                             &handle,
    3493             :                                             &werr);
    3494           0 :         if (!NT_STATUS_IS_OK(status)) {
    3495           0 :                 errcode = W_ERROR_V(ntstatus_to_werror(status));
    3496           0 :                 goto out;
    3497             :         }
    3498           0 :         if (!W_ERROR_IS_OK(werr)) {
    3499           0 :                 errcode = W_ERROR_V(werr);
    3500           0 :                 goto out;
    3501             :         }
    3502             : 
    3503           0 :         werr = rpccli_spoolss_getjob(cli, mem_ctx,
    3504             :                                      &handle,
    3505             :                                      jobid,
    3506             :                                      1, /* level */
    3507             :                                      0, /* offered */
    3508             :                                      &info);
    3509           0 :         if (!W_ERROR_IS_OK(werr)) {
    3510           0 :                 errcode = W_ERROR_V(werr);
    3511           0 :                 goto out;
    3512             :         }
    3513             : 
    3514           0 :         ZERO_STRUCT(ctr);
    3515             : 
    3516           0 :         info1.job_id            = info.info1.job_id;
    3517           0 :         info1.printer_name      = info.info1.printer_name;
    3518           0 :         info1.user_name         = info.info1.user_name;
    3519           0 :         info1.document_name     = data;
    3520           0 :         info1.data_type         = info.info1.data_type;
    3521           0 :         info1.text_status       = info.info1.text_status;
    3522           0 :         info1.status            = info.info1.status;
    3523           0 :         info1.priority          = info.info1.priority;
    3524           0 :         info1.position          = info.info1.position;
    3525           0 :         info1.total_pages       = info.info1.total_pages;
    3526           0 :         info1.pages_printed     = info.info1.pages_printed;
    3527           0 :         info1.submitted         = info.info1.submitted;
    3528             : 
    3529           0 :         ctr.level = 1;
    3530           0 :         ctr.info.info1 = &info1;
    3531             : 
    3532           0 :         status = dcerpc_spoolss_SetJob(b, mem_ctx,
    3533             :                                        &handle,
    3534             :                                        jobid,
    3535             :                                        &ctr,
    3536             :                                        0,
    3537             :                                        &werr);
    3538           0 :         if (!NT_STATUS_IS_OK(status)) {
    3539           0 :                 errcode = W_ERROR_V(ntstatus_to_werror(status));
    3540           0 :                 goto out;
    3541             :         }
    3542           0 :         if (!W_ERROR_IS_OK(werr)) {
    3543           0 :                 errcode = W_ERROR_V(werr);
    3544           0 :                 goto out;
    3545             :         }
    3546             : 
    3547           0 :         errcode = NERR_Success;
    3548           0 :  out:
    3549             : 
    3550           0 :         if (b && is_valid_policy_hnd(&handle)) {
    3551           0 :                 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
    3552             :         }
    3553             : 
    3554           0 :         SSVALS(*rparam,0,errcode);
    3555           0 :         SSVAL(*rparam,2,0);             /* converter word */
    3556             : 
    3557           0 :         return(True);
    3558             : }
    3559             : 
    3560             : 
    3561             : /****************************************************************************
    3562             :  Get info about the server.
    3563             : ****************************************************************************/
    3564             : 
    3565           0 : static bool api_RNetServerGetInfo(struct smbd_server_connection *sconn,
    3566             :                                   connection_struct *conn,uint64_t vuid,
    3567             :                                 char *param, int tpscnt,
    3568             :                                 char *data, int tdscnt,
    3569             :                                 int mdrcnt,int mprcnt,
    3570             :                                 char **rdata,char **rparam,
    3571             :                                 int *rdata_len,int *rparam_len)
    3572             : {
    3573           0 :         char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
    3574           0 :         char *str2 = skip_string(param,tpscnt,str1);
    3575           0 :         char *p = skip_string(param,tpscnt,str2);
    3576           0 :         int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
    3577             :         char *p2;
    3578             :         int struct_len;
    3579             : 
    3580             :         NTSTATUS status;
    3581             :         WERROR werr;
    3582           0 :         TALLOC_CTX *mem_ctx = talloc_tos();
    3583           0 :         struct rpc_pipe_client *cli = NULL;
    3584             :         union srvsvc_NetSrvInfo info;
    3585             :         int errcode;
    3586             :         struct dcerpc_binding_handle *b;
    3587             : 
    3588           0 :         if (!str1 || !str2 || !p) {
    3589           0 :                 return False;
    3590             :         }
    3591             : 
    3592           0 :         DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
    3593             : 
    3594             :         /* check it's a supported varient */
    3595           0 :         if (!prefix_ok(str1,"WrLh")) {
    3596           0 :                 return False;
    3597             :         }
    3598             : 
    3599           0 :         switch( uLevel ) {
    3600           0 :                 case 0:
    3601           0 :                         if (strcmp(str2,"B16") != 0) {
    3602           0 :                                 return False;
    3603             :                         }
    3604           0 :                         struct_len = 16;
    3605           0 :                         break;
    3606           0 :                 case 1:
    3607           0 :                         if (strcmp(str2,"B16BBDz") != 0) {
    3608           0 :                                 return False;
    3609             :                         }
    3610           0 :                         struct_len = 26;
    3611           0 :                         break;
    3612           0 :                 case 2:
    3613           0 :                         if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")!= 0) {
    3614           0 :                                 return False;
    3615             :                         }
    3616           0 :                         struct_len = 134;
    3617           0 :                         break;
    3618           0 :                 case 3:
    3619           0 :                         if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz") != 0) {
    3620           0 :                                 return False;
    3621             :                         }
    3622           0 :                         struct_len = 144;
    3623           0 :                         break;
    3624           0 :                 case 20:
    3625           0 :                         if (strcmp(str2,"DN") != 0) {
    3626           0 :                                 return False;
    3627             :                         }
    3628           0 :                         struct_len = 6;
    3629           0 :                         break;
    3630           0 :                 case 50:
    3631           0 :                         if (strcmp(str2,"B16BBDzWWzzz") != 0) {
    3632           0 :                                 return False;
    3633             :                         }
    3634           0 :                         struct_len = 42;
    3635           0 :                         break;
    3636           0 :                 default:
    3637           0 :                         return False;
    3638             :         }
    3639             : 
    3640           0 :         *rdata_len = mdrcnt;
    3641           0 :         *rdata = smb_realloc_limit(*rdata,*rdata_len);
    3642           0 :         if (!*rdata) {
    3643           0 :                 return False;
    3644             :         }
    3645             : 
    3646           0 :         p = *rdata;
    3647           0 :         p2 = p + struct_len;
    3648             : 
    3649           0 :         status = rpc_pipe_open_interface(mem_ctx, &ndr_table_srvsvc,
    3650           0 :                                         conn->session_info,
    3651           0 :                                         conn->sconn->remote_address,
    3652           0 :                                         conn->sconn->local_address,
    3653           0 :                                         conn->sconn->msg_ctx,
    3654             :                                         &cli);
    3655           0 :         if (!NT_STATUS_IS_OK(status)) {
    3656           0 :                 DEBUG(0,("api_RNetServerGetInfo: could not connect to srvsvc: %s\n",
    3657             :                           nt_errstr(status)));
    3658           0 :                 errcode = W_ERROR_V(ntstatus_to_werror(status));
    3659           0 :                 goto out;
    3660             :         }
    3661             : 
    3662           0 :         b = cli->binding_handle;
    3663             : 
    3664           0 :         status = dcerpc_srvsvc_NetSrvGetInfo(b, mem_ctx,
    3665             :                                              NULL,
    3666             :                                              101,
    3667             :                                              &info,
    3668             :                                              &werr);
    3669           0 :         if (!NT_STATUS_IS_OK(status)) {
    3670           0 :                 errcode = W_ERROR_V(ntstatus_to_werror(status));
    3671           0 :                 goto out;
    3672             :         }
    3673           0 :         if (!W_ERROR_IS_OK(werr)) {
    3674           0 :                 errcode = W_ERROR_V(werr);
    3675           0 :                 goto out;
    3676             :         }
    3677             : 
    3678           0 :         if (info.info101 == NULL) {
    3679           0 :                 errcode = W_ERROR_V(WERR_INVALID_PARAMETER);
    3680           0 :                 goto out;
    3681             :         }
    3682             : 
    3683           0 :         if (uLevel != 20) {
    3684           0 :                 size_t len = 0;
    3685           0 :                 status = srvstr_push(NULL, 0, p, info.info101->server_name, 16,
    3686             :                         STR_ASCII|STR_UPPER|STR_TERMINATE, &len);
    3687           0 :                 if (!NT_STATUS_IS_OK(status)) {
    3688           0 :                         errcode = W_ERROR_V(ntstatus_to_werror(status));
    3689           0 :                         goto out;
    3690             :                 }
    3691             :         }
    3692           0 :         p += 16;
    3693           0 :         if (uLevel > 0) {
    3694           0 :                 SCVAL(p,0,info.info101->version_major);
    3695           0 :                 SCVAL(p,1,info.info101->version_minor);
    3696           0 :                 SIVAL(p,2,info.info101->server_type);
    3697             : 
    3698           0 :                 if (mdrcnt == struct_len) {
    3699           0 :                         SIVAL(p,6,0);
    3700             :                 } else {
    3701           0 :                         SIVAL(p,6,PTR_DIFF(p2,*rdata));
    3702           0 :                         if (mdrcnt - struct_len <= 0) {
    3703           0 :                                 return false;
    3704             :                         }
    3705           0 :                         push_ascii(p2,
    3706           0 :                                 info.info101->comment,
    3707           0 :                                 MIN(mdrcnt - struct_len,
    3708             :                                         MAX_SERVER_STRING_LENGTH),
    3709             :                                 STR_TERMINATE);
    3710           0 :                         p2 = skip_string(*rdata,*rdata_len,p2);
    3711           0 :                         if (!p2) {
    3712           0 :                                 return False;
    3713             :                         }
    3714             :                 }
    3715             :         }
    3716             : 
    3717           0 :         if (uLevel > 1) {
    3718           0 :                 return False;           /* not yet implemented */
    3719             :         }
    3720             : 
    3721           0 :         errcode = NERR_Success;
    3722             : 
    3723           0 :  out:
    3724             : 
    3725           0 :         *rdata_len = PTR_DIFF(p2,*rdata);
    3726             : 
    3727           0 :         *rparam_len = 6;
    3728           0 :         *rparam = smb_realloc_limit(*rparam,*rparam_len);
    3729           0 :         if (!*rparam) {
    3730           0 :                 return False;
    3731             :         }
    3732           0 :         SSVAL(*rparam,0,errcode);
    3733           0 :         SSVAL(*rparam,2,0);             /* converter word */
    3734           0 :         SSVAL(*rparam,4,*rdata_len);
    3735             : 
    3736           0 :         return True;
    3737             : }
    3738             : 
    3739             : /****************************************************************************
    3740             :  Get info about the server.
    3741             : ****************************************************************************/
    3742             : 
    3743           0 : static bool api_NetWkstaGetInfo(struct smbd_server_connection *sconn,
    3744             :                                 connection_struct *conn,uint64_t vuid,
    3745             :                                 char *param, int tpscnt,
    3746             :                                 char *data, int tdscnt,
    3747             :                                 int mdrcnt,int mprcnt,
    3748             :                                 char **rdata,char **rparam,
    3749             :                                 int *rdata_len,int *rparam_len)
    3750             : {
    3751           0 :         char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
    3752           0 :         char *str2 = skip_string(param,tpscnt,str1);
    3753           0 :         char *p = skip_string(param,tpscnt,str2);
    3754             :         char *p2;
    3755             :         char *endp;
    3756           0 :         int level = get_safe_SVAL(param,tpscnt,p,0,-1);
    3757             : 
    3758           0 :         if (!str1 || !str2 || !p) {
    3759           0 :                 return False;
    3760             :         }
    3761             : 
    3762           0 :         DEBUG(4,("NetWkstaGetInfo level %d\n",level));
    3763             : 
    3764           0 :         *rparam_len = 6;
    3765           0 :         *rparam = smb_realloc_limit(*rparam,*rparam_len);
    3766           0 :         if (!*rparam) {
    3767           0 :                 return False;
    3768             :         }
    3769             : 
    3770             :         /* check it's a supported varient */
    3771           0 :         if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz"))) {
    3772           0 :                 return False;
    3773             :         }
    3774             : 
    3775           0 :         *rdata_len = mdrcnt + 1024;
    3776           0 :         *rdata = smb_realloc_limit(*rdata,*rdata_len);
    3777           0 :         if (!*rdata) {
    3778           0 :                 return False;
    3779             :         }
    3780             : 
    3781           0 :         SSVAL(*rparam,0,NERR_Success);
    3782           0 :         SSVAL(*rparam,2,0);             /* converter word */
    3783             : 
    3784           0 :         p = *rdata;
    3785           0 :         endp = *rdata + *rdata_len;
    3786             : 
    3787           0 :         p2 = get_safe_ptr(*rdata,*rdata_len,p,22);
    3788           0 :         if (!p2) {
    3789           0 :                 return False;
    3790             :         }
    3791             : 
    3792           0 :         SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
    3793           0 :         strlcpy(p2,get_local_machine_name(),PTR_DIFF(endp,p2));
    3794           0 :         if (!strupper_m(p2)) {
    3795           0 :                 return false;
    3796             :         }
    3797           0 :         p2 = skip_string(*rdata,*rdata_len,p2);
    3798           0 :         if (!p2) {
    3799           0 :                 return False;
    3800             :         }
    3801           0 :         p += 4;
    3802             : 
    3803           0 :         SIVAL(p,0,PTR_DIFF(p2,*rdata));
    3804           0 :         strlcpy(p2,conn->session_info->unix_info->sanitized_username,PTR_DIFF(endp,p2));
    3805           0 :         p2 = skip_string(*rdata,*rdata_len,p2);
    3806           0 :         if (!p2) {
    3807           0 :                 return False;
    3808             :         }
    3809           0 :         p += 4;
    3810             : 
    3811           0 :         SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
    3812           0 :         strlcpy(p2,lp_workgroup(),PTR_DIFF(endp,p2));
    3813           0 :         if (!strupper_m(p2)) {
    3814           0 :                 return false;
    3815             :         }
    3816           0 :         p2 = skip_string(*rdata,*rdata_len,p2);
    3817           0 :         if (!p2) {
    3818           0 :                 return False;
    3819             :         }
    3820           0 :         p += 4;
    3821             : 
    3822           0 :         SCVAL(p,0,SAMBA_MAJOR_NBT_ANNOUNCE_VERSION); /* system version - e.g 4 in 4.1 */
    3823           0 :         SCVAL(p,1,SAMBA_MINOR_NBT_ANNOUNCE_VERSION); /* system version - e.g .1 in 4.1 */
    3824           0 :         p += 2;
    3825             : 
    3826           0 :         SIVAL(p,0,PTR_DIFF(p2,*rdata));
    3827           0 :         strlcpy(p2,lp_workgroup(),PTR_DIFF(endp,p2));   /* don't know.  login domain?? */
    3828           0 :         p2 = skip_string(*rdata,*rdata_len,p2);
    3829           0 :         if (!p2) {
    3830           0 :                 return False;
    3831             :         }
    3832           0 :         p += 4;
    3833             : 
    3834           0 :         SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
    3835           0 :         strlcpy(p2,"",PTR_DIFF(endp,p2));
    3836           0 :         p2 = skip_string(*rdata,*rdata_len,p2);
    3837           0 :         if (!p2) {
    3838           0 :                 return False;
    3839             :         }
    3840           0 :         p += 4;
    3841             : 
    3842           0 :         *rdata_len = PTR_DIFF(p2,*rdata);
    3843             : 
    3844           0 :         SSVAL(*rparam,4,*rdata_len);
    3845             : 
    3846           0 :         return True;
    3847             : }
    3848             : 
    3849             : /****************************************************************************
    3850             :   get info about a user
    3851             : 
    3852             :     struct user_info_11 {
    3853             :         char                usri11_name[21];  0-20
    3854             :         char                usri11_pad;       21
    3855             :         char                *usri11_comment;  22-25
    3856             :         char            *usri11_usr_comment;  26-29
    3857             :         unsigned short      usri11_priv;      30-31
    3858             :         unsigned long       usri11_auth_flags; 32-35
    3859             :         long                usri11_password_age; 36-39
    3860             :         char                *usri11_homedir; 40-43
    3861             :         char            *usri11_parms; 44-47
    3862             :         long                usri11_last_logon; 48-51
    3863             :         long                usri11_last_logoff; 52-55
    3864             :         unsigned short      usri11_bad_pw_count; 56-57
    3865             :         unsigned short      usri11_num_logons; 58-59
    3866             :         char                *usri11_logon_server; 60-63
    3867             :         unsigned short      usri11_country_code; 64-65
    3868             :         char            *usri11_workstations; 66-69
    3869             :         unsigned long       usri11_max_storage; 70-73
    3870             :         unsigned short      usri11_units_per_week; 74-75
    3871             :         unsigned char       *usri11_logon_hours; 76-79
    3872             :         unsigned short      usri11_code_page; 80-81
    3873             :     };
    3874             : 
    3875             : where:
    3876             : 
    3877             :   usri11_name specifies the user name for which information is retrieved
    3878             : 
    3879             :   usri11_pad aligns the next data structure element to a word boundary
    3880             : 
    3881             :   usri11_comment is a null terminated ASCII comment
    3882             : 
    3883             :   usri11_user_comment is a null terminated ASCII comment about the user
    3884             : 
    3885             :   usri11_priv specifies the level of the privilege assigned to the user.
    3886             :        The possible values are:
    3887             : 
    3888             : Name             Value  Description
    3889             : USER_PRIV_GUEST  0      Guest privilege
    3890             : USER_PRIV_USER   1      User privilege
    3891             : USER_PRV_ADMIN   2      Administrator privilege
    3892             : 
    3893             :   usri11_auth_flags specifies the account operator privileges. The
    3894             :        possible values are:
    3895             : 
    3896             : Name            Value   Description
    3897             : AF_OP_PRINT     0       Print operator
    3898             : 
    3899             : 
    3900             : Leach, Naik                                        [Page 28]
    3901             : 
    3902             : 
    3903             : 
    3904             : INTERNET-DRAFT   CIFS Remote Admin Protocol     January 10, 1997
    3905             : 
    3906             : 
    3907             : AF_OP_COMM      1       Communications operator
    3908             : AF_OP_SERVER    2       Server operator
    3909             : AF_OP_ACCOUNTS  3       Accounts operator
    3910             : 
    3911             : 
    3912             :   usri11_password_age specifies how many seconds have elapsed since the
    3913             :        password was last changed.
    3914             : 
    3915             :   usri11_home_dir points to a null terminated ASCII string that contains
    3916             :        the path name of the user's home directory.
    3917             : 
    3918             :   usri11_parms points to a null terminated ASCII string that is set
    3919             :        aside for use by applications.
    3920             : 
    3921             :   usri11_last_logon specifies the time when the user last logged on.
    3922             :        This value is stored as the number of seconds elapsed since
    3923             :        00:00:00, January 1, 1970.
    3924             : 
    3925             :   usri11_last_logoff specifies the time when the user last logged off.
    3926             :        This value is stored as the number of seconds elapsed since
    3927             :        00:00:00, January 1, 1970. A value of 0 means the last logoff
    3928             :        time is unknown.
    3929             : 
    3930             :   usri11_bad_pw_count specifies the number of incorrect passwords
    3931             :        entered since the last successful logon.
    3932             : 
    3933             :   usri11_log1_num_logons specifies the number of times this user has
    3934             :        logged on. A value of -1 means the number of logons is unknown.
    3935             : 
    3936             :   usri11_logon_server points to a null terminated ASCII string that
    3937             :        contains the name of the server to which logon requests are sent.
    3938             :        A null string indicates logon requests should be sent to the
    3939             :        domain controller.
    3940             : 
    3941             :   usri11_country_code specifies the country code for the user's language
    3942             :        of choice.
    3943             : 
    3944             :   usri11_workstations points to a null terminated ASCII string that
    3945             :        contains the names of workstations the user may log on from.
    3946             :        There may be up to 8 workstations, with the names separated by
    3947             :        commas. A null strings indicates there are no restrictions.
    3948             : 
    3949             :   usri11_max_storage specifies the maximum amount of disk space the user
    3950             :        can occupy. A value of 0xffffffff indicates there are no
    3951             :        restrictions.
    3952             : 
    3953             :   usri11_units_per_week specifies the equal number of time units into
    3954             :        which a week is divided. This value must be equal to 168.
    3955             : 
    3956             :   usri11_logon_hours points to a 21 byte (168 bits) string that
    3957             :        specifies the time during which the user can log on. Each bit
    3958             :        represents one unique hour in a week. The first bit (bit 0, word
    3959             :        0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
    3960             : 
    3961             : 
    3962             : 
    3963             : Leach, Naik                                        [Page 29]
    3964             : 
    3965             : 
    3966             : 
    3967             : INTERNET-DRAFT   CIFS Remote Admin Protocol     January 10, 1997
    3968             : 
    3969             : 
    3970             :        Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
    3971             :        are no restrictions.
    3972             : 
    3973             :   usri11_code_page specifies the code page for the user's language of
    3974             :        choice
    3975             : 
    3976             : All of the pointers in this data structure need to be treated
    3977             : specially. The  pointer is a 32 bit pointer. The higher 16 bits need
    3978             : to be ignored. The converter word returned in the parameters section
    3979             : needs to be subtracted from the lower 16 bits to calculate an offset
    3980             : into the return buffer where this ASCII string resides.
    3981             : 
    3982             : There is no auxiliary data in the response.
    3983             : 
    3984             :   ****************************************************************************/
    3985             : 
    3986             : #define usri11_name           0
    3987             : #define usri11_pad            21
    3988             : #define usri11_comment        22
    3989             : #define usri11_usr_comment    26
    3990             : #define usri11_full_name      30
    3991             : #define usri11_priv           34
    3992             : #define usri11_auth_flags     36
    3993             : #define usri11_password_age   40
    3994             : #define usri11_homedir        44
    3995             : #define usri11_parms          48
    3996             : #define usri11_last_logon     52
    3997             : #define usri11_last_logoff    56
    3998             : #define usri11_bad_pw_count   60
    3999             : #define usri11_num_logons     62
    4000             : #define usri11_logon_server   64
    4001             : #define usri11_country_code   68
    4002             : #define usri11_workstations   70
    4003             : #define usri11_max_storage    74
    4004             : #define usri11_units_per_week 78
    4005             : #define usri11_logon_hours    80
    4006             : #define usri11_code_page      84
    4007             : #define usri11_end            86
    4008             : 
    4009           0 : static bool api_RNetUserGetInfo(struct smbd_server_connection *sconn,
    4010             :                                 connection_struct *conn, uint64_t vuid,
    4011             :                                 char *param, int tpscnt,
    4012             :                                 char *data, int tdscnt,
    4013             :                                 int mdrcnt,int mprcnt,
    4014             :                                 char **rdata,char **rparam,
    4015             :                                 int *rdata_len,int *rparam_len)
    4016             : {
    4017           0 :         char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
    4018           0 :         char *str2 = skip_string(param,tpscnt,str1);
    4019           0 :         char *UserName = skip_string(param,tpscnt,str2);
    4020           0 :         char *p = skip_string(param,tpscnt,UserName);
    4021           0 :         int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
    4022             :         char *p2;
    4023             :         char *endp;
    4024             :         const char *level_string;
    4025             : 
    4026           0 :         TALLOC_CTX *mem_ctx = talloc_tos();
    4027             :         NTSTATUS status, result;
    4028           0 :         struct rpc_pipe_client *cli = NULL;
    4029             :         struct policy_handle connect_handle, domain_handle, user_handle;
    4030             :         struct lsa_String domain_name;
    4031             :         struct dom_sid2 *domain_sid;
    4032             :         struct lsa_String names;
    4033             :         struct samr_Ids rids;
    4034             :         struct samr_Ids types;
    4035           0 :         int errcode = W_ERROR_V(WERR_NERR_USERNOTFOUND);
    4036             :         uint32_t rid;
    4037             :         union samr_UserInfo *info;
    4038           0 :         struct dcerpc_binding_handle *b = NULL;
    4039             : 
    4040           0 :         if (!str1 || !str2 || !UserName || !p) {
    4041           0 :                 return False;
    4042             :         }
    4043             : 
    4044           0 :         *rparam_len = 6;
    4045           0 :         *rparam = smb_realloc_limit(*rparam,*rparam_len);
    4046           0 :         if (!*rparam) {
    4047           0 :                 return False;
    4048             :         }
    4049             : 
    4050           0 :         DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
    4051             : 
    4052             :         /* check it's a supported variant */
    4053           0 :         if (strcmp(str1,"zWrLh") != 0) {
    4054           0 :                 return False;
    4055             :         }
    4056           0 :         switch( uLevel ) {
    4057           0 :                 case 0: level_string = "B21"; break;
    4058           0 :                 case 1: level_string = "B21BB16DWzzWz"; break;
    4059           0 :                 case 2: level_string = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
    4060           0 :                 case 10: level_string = "B21Bzzz"; break;
    4061           0 :                 case 11: level_string = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
    4062           0 :                 default: return False;
    4063             :         }
    4064             : 
    4065           0 :         if (strcmp(level_string,str2) != 0) {
    4066           0 :                 return False;
    4067             :         }
    4068             : 
    4069           0 :         *rdata_len = mdrcnt + 1024;
    4070           0 :         *rdata = smb_realloc_limit(*rdata,*rdata_len);
    4071           0 :         if (!*rdata) {
    4072           0 :                 return False;
    4073             :         }
    4074             : 
    4075           0 :         p = *rdata;
    4076           0 :         endp = *rdata + *rdata_len;
    4077           0 :         p2 = get_safe_ptr(*rdata,*rdata_len,p,usri11_end);
    4078           0 :         if (!p2) {
    4079           0 :                 return False;
    4080             :         }
    4081             : 
    4082           0 :         ZERO_STRUCT(connect_handle);
    4083           0 :         ZERO_STRUCT(domain_handle);
    4084           0 :         ZERO_STRUCT(user_handle);
    4085             : 
    4086           0 :         status = rpc_pipe_open_interface(mem_ctx, &ndr_table_samr,
    4087           0 :                                         conn->session_info,
    4088           0 :                                         conn->sconn->remote_address,
    4089           0 :                                         conn->sconn->local_address,
    4090           0 :                                         conn->sconn->msg_ctx,
    4091             :                                         &cli);
    4092           0 :         if (!NT_STATUS_IS_OK(status)) {
    4093           0 :                 DEBUG(0,("api_RNetUserGetInfo: could not connect to samr: %s\n",
    4094             :                           nt_errstr(status)));
    4095           0 :                 errcode = W_ERROR_V(ntstatus_to_werror(status));
    4096           0 :                 goto out;
    4097             :         }
    4098             : 
    4099           0 :         b = cli->binding_handle;
    4100             : 
    4101           0 :         status = dcerpc_samr_Connect2(b, mem_ctx,
    4102             :                                       lp_netbios_name(),
    4103             :                                       SAMR_ACCESS_CONNECT_TO_SERVER |
    4104             :                                       SAMR_ACCESS_ENUM_DOMAINS |
    4105             :                                       SAMR_ACCESS_LOOKUP_DOMAIN,
    4106             :                                       &connect_handle,
    4107             :                                       &result);
    4108           0 :         if (!NT_STATUS_IS_OK(status)) {
    4109           0 :                 errcode = W_ERROR_V(ntstatus_to_werror(status));
    4110           0 :                 goto out;
    4111             :         }
    4112           0 :         if (!NT_STATUS_IS_OK(result)) {
    4113           0 :                 errcode = W_ERROR_V(ntstatus_to_werror(result));
    4114           0 :                 goto out;
    4115             :         }
    4116             : 
    4117           0 :         init_lsa_String(&domain_name, get_global_sam_name());
    4118             : 
    4119           0 :         status = dcerpc_samr_LookupDomain(b, mem_ctx,
    4120             :                                           &connect_handle,
    4121             :                                           &domain_name,
    4122             :                                           &domain_sid,
    4123             :                                           &result);
    4124           0 :         if (!NT_STATUS_IS_OK(status)) {
    4125           0 :                 errcode = W_ERROR_V(ntstatus_to_werror(status));
    4126           0 :                 goto out;
    4127             :         }
    4128           0 :         if (!NT_STATUS_IS_OK(result)) {
    4129           0 :                 errcode = W_ERROR_V(ntstatus_to_werror(result));
    4130           0 :                 goto out;
    4131             :         }
    4132             : 
    4133           0 :         status = dcerpc_samr_OpenDomain(b, mem_ctx,
    4134             :                                         &connect_handle,
    4135             :                                         SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
    4136             :                                         domain_sid,
    4137             :                                         &domain_handle,
    4138             :                                         &result);
    4139           0 :         if (!NT_STATUS_IS_OK(status)) {
    4140           0 :                 errcode = W_ERROR_V(ntstatus_to_werror(status));
    4141           0 :                 goto out;
    4142             :         }
    4143           0 :         if (!NT_STATUS_IS_OK(result)) {
    4144           0 :                 errcode = W_ERROR_V(ntstatus_to_werror(result));
    4145           0 :                 goto out;
    4146             :         }
    4147             : 
    4148           0 :         init_lsa_String(&names, UserName);
    4149             : 
    4150           0 :         status = dcerpc_samr_LookupNames(b, mem_ctx,
    4151             :                                          &domain_handle,
    4152             :                                          1,
    4153             :                                          &names,
    4154             :                                          &rids,
    4155             :                                          &types,
    4156             :                                          &result);
    4157           0 :         if (!NT_STATUS_IS_OK(status)) {
    4158           0 :                 errcode = W_ERROR_V(ntstatus_to_werror(status));
    4159           0 :                 goto out;
    4160             :         }
    4161           0 :         if (!NT_STATUS_IS_OK(result)) {
    4162           0 :                 errcode = W_ERROR_V(ntstatus_to_werror(result));
    4163           0 :                 goto out;
    4164             :         }
    4165             : 
    4166           0 :         if (rids.count != 1) {
    4167           0 :                 errcode = W_ERROR_V(WERR_NO_SUCH_USER);
    4168           0 :                 goto out;
    4169             :         }
    4170           0 :         if (rids.count != types.count) {
    4171           0 :                 errcode = W_ERROR_V(WERR_INVALID_PARAMETER);
    4172           0 :                 goto out;
    4173             :         }
    4174           0 :         if (types.ids[0] != SID_NAME_USER) {
    4175           0 :                 errcode = W_ERROR_V(WERR_INVALID_PARAMETER);
    4176           0 :                 goto out;
    4177             :         }
    4178             : 
    4179           0 :         rid = rids.ids[0];
    4180             : 
    4181           0 :         status = dcerpc_samr_OpenUser(b, mem_ctx,
    4182             :                                       &domain_handle,
    4183             :                                       SAMR_USER_ACCESS_GET_LOCALE |
    4184             :                                       SAMR_USER_ACCESS_GET_LOGONINFO |
    4185             :                                       SAMR_USER_ACCESS_GET_ATTRIBUTES |
    4186             :                                       SAMR_USER_ACCESS_GET_GROUPS |
    4187             :                                       SAMR_USER_ACCESS_GET_GROUP_MEMBERSHIP |
    4188             :                                       SEC_STD_READ_CONTROL,
    4189             :                                       rid,
    4190             :                                       &user_handle,
    4191             :                                       &result);
    4192           0 :         if (!NT_STATUS_IS_OK(status)) {
    4193           0 :                 errcode = W_ERROR_V(ntstatus_to_werror(status));
    4194           0 :                 goto out;
    4195             :         }
    4196           0 :         if (!NT_STATUS_IS_OK(result)) {
    4197           0 :                 errcode = W_ERROR_V(ntstatus_to_werror(result));
    4198           0 :                 goto out;
    4199             :         }
    4200             : 
    4201           0 :         status = dcerpc_samr_QueryUserInfo2(b, mem_ctx,
    4202             :                                             &user_handle,
    4203             :                                             UserAllInformation,
    4204             :                                             &info,
    4205             :                                             &result);
    4206           0 :         if (!NT_STATUS_IS_OK(status)) {
    4207           0 :                 errcode = W_ERROR_V(ntstatus_to_werror(status));
    4208           0 :                 goto out;
    4209             :         }
    4210           0 :         if (!NT_STATUS_IS_OK(result)) {
    4211           0 :                 errcode = W_ERROR_V(ntstatus_to_werror(result));
    4212           0 :                 goto out;
    4213             :         }
    4214             : 
    4215           0 :         memset(p,0,21);
    4216           0 :         fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
    4217             : 
    4218           0 :         if (uLevel > 0) {
    4219           0 :                 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
    4220           0 :                 *p2 = 0;
    4221             :         }
    4222             : 
    4223           0 :         if (uLevel >= 10) {
    4224           0 :                 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
    4225           0 :                 strlcpy(p2,"Comment",PTR_DIFF(endp,p2));
    4226           0 :                 p2 = skip_string(*rdata,*rdata_len,p2);
    4227           0 :                 if (!p2) {
    4228           0 :                         return False;
    4229             :                 }
    4230             : 
    4231           0 :                 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
    4232           0 :                 strlcpy(p2,"UserComment",PTR_DIFF(endp,p2));
    4233           0 :                 p2 = skip_string(*rdata,*rdata_len,p2);
    4234           0 :                 if (!p2) {
    4235           0 :                         return False;
    4236             :                 }
    4237             : 
    4238             :                 /* EEK! the cifsrap.txt doesn't have this in!!!! */
    4239           0 :                 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
    4240           0 :                 strlcpy(p2,info->info21.full_name.string,PTR_DIFF(endp,p2));
    4241           0 :                 p2 = skip_string(*rdata,*rdata_len,p2);
    4242           0 :                 if (!p2) {
    4243           0 :                         return False;
    4244             :                 }
    4245             :         }
    4246             : 
    4247           0 :         if (uLevel == 11) {
    4248           0 :                 const char *homedir = info->info21.home_directory.string;
    4249             :                 /* modelled after NTAS 3.51 reply */
    4250           0 :                 SSVAL(p,usri11_priv,
    4251             :                         (get_current_uid(conn) == sec_initial_uid())?
    4252             :                         USER_PRIV_ADMIN:USER_PRIV_USER);
    4253           0 :                 SIVAL(p,usri11_auth_flags,AF_OP_PRINT);         /* auth flags */
    4254           0 :                 SIVALS(p,usri11_password_age,-1);               /* password age */
    4255           0 :                 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
    4256           0 :                 strlcpy(p2, homedir, PTR_DIFF(endp,p2));
    4257           0 :                 p2 = skip_string(*rdata,*rdata_len,p2);
    4258           0 :                 if (!p2) {
    4259           0 :                         return False;
    4260             :                 }
    4261           0 :                 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
    4262           0 :                 strlcpy(p2,"",PTR_DIFF(endp,p2));
    4263           0 :                 p2 = skip_string(*rdata,*rdata_len,p2);
    4264           0 :                 if (!p2) {
    4265           0 :                         return False;
    4266             :                 }
    4267           0 :                 SIVAL(p,usri11_last_logon,0);           /* last logon */
    4268           0 :                 SIVAL(p,usri11_last_logoff,0);          /* last logoff */
    4269           0 :                 SSVALS(p,usri11_bad_pw_count,-1);       /* bad pw counts */
    4270           0 :                 SSVALS(p,usri11_num_logons,-1);         /* num logons */
    4271           0 :                 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
    4272           0 :                 strlcpy(p2,"\\\\*",PTR_DIFF(endp,p2));
    4273           0 :                 p2 = skip_string(*rdata,*rdata_len,p2);
    4274           0 :                 if (!p2) {
    4275           0 :                         return False;
    4276             :                 }
    4277           0 :                 SSVAL(p,usri11_country_code,0);         /* country code */
    4278             : 
    4279           0 :                 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
    4280           0 :                 strlcpy(p2,"",PTR_DIFF(endp,p2));
    4281           0 :                 p2 = skip_string(*rdata,*rdata_len,p2);
    4282           0 :                 if (!p2) {
    4283           0 :                         return False;
    4284             :                 }
    4285             : 
    4286           0 :                 SIVALS(p,usri11_max_storage,-1);                /* max storage */
    4287           0 :                 SSVAL(p,usri11_units_per_week,168);             /* units per week */
    4288           0 :                 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
    4289             : 
    4290             :                 /* a simple way to get logon hours at all times. */
    4291           0 :                 memset(p2,0xff,21);
    4292           0 :                 SCVAL(p2,21,0);           /* fix zero termination */
    4293           0 :                 p2 = skip_string(*rdata,*rdata_len,p2);
    4294           0 :                 if (!p2) {
    4295           0 :                         return False;
    4296             :                 }
    4297             : 
    4298           0 :                 SSVAL(p,usri11_code_page,0);            /* code page */
    4299             :         }
    4300             : 
    4301           0 :         if (uLevel == 1 || uLevel == 2) {
    4302           0 :                 memset(p+22,' ',16);    /* password */
    4303           0 :                 SIVALS(p,38,-1);                /* password age */
    4304           0 :                 SSVAL(p,42,
    4305             :                         (get_current_uid(conn) == sec_initial_uid())?
    4306             :                         USER_PRIV_ADMIN:USER_PRIV_USER);
    4307           0 :                 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
    4308           0 :                 strlcpy(p2, info->info21.home_directory.string,
    4309           0 :                         PTR_DIFF(endp,p2));
    4310           0 :                 p2 = skip_string(*rdata,*rdata_len,p2);
    4311           0 :                 if (!p2) {
    4312           0 :                         return False;
    4313             :                 }
    4314           0 :                 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
    4315           0 :                 *p2++ = 0;
    4316           0 :                 SSVAL(p,52,0);          /* flags */
    4317           0 :                 SIVAL(p,54,PTR_DIFF(p2,*rdata));                /* script_path */
    4318           0 :                 strlcpy(p2, info->info21.logon_script.string,
    4319           0 :                         PTR_DIFF(endp,p2));
    4320           0 :                 p2 = skip_string(*rdata,*rdata_len,p2);
    4321           0 :                 if (!p2) {
    4322           0 :                         return False;
    4323             :                 }
    4324           0 :                 if (uLevel == 2) {
    4325           0 :                         SIVAL(p,58,0);          /* auth_flags */
    4326           0 :                         SIVAL(p,62,PTR_DIFF(p2,*rdata)); /* full_name */
    4327           0 :                         strlcpy(p2,info->info21.full_name.string,PTR_DIFF(endp,p2));
    4328           0 :                         p2 = skip_string(*rdata,*rdata_len,p2);
    4329           0 :                         if (!p2) {
    4330           0 :                                 return False;
    4331             :                         }
    4332           0 :                         SIVAL(p,66,0);          /* urs_comment */
    4333           0 :                         SIVAL(p,70,PTR_DIFF(p2,*rdata)); /* parms */
    4334           0 :                         strlcpy(p2,"",PTR_DIFF(endp,p2));
    4335           0 :                         p2 = skip_string(*rdata,*rdata_len,p2);
    4336           0 :                         if (!p2) {
    4337           0 :                                 return False;
    4338             :                         }
    4339           0 :                         SIVAL(p,74,0);          /* workstations */
    4340           0 :                         SIVAL(p,78,0);          /* last_logon */
    4341           0 :                         SIVAL(p,82,0);          /* last_logoff */
    4342           0 :                         SIVALS(p,86,-1);                /* acct_expires */
    4343           0 :                         SIVALS(p,90,-1);                /* max_storage */
    4344           0 :                         SSVAL(p,94,168);        /* units_per_week */
    4345           0 :                         SIVAL(p,96,PTR_DIFF(p2,*rdata)); /* logon_hours */
    4346           0 :                         memset(p2,-1,21);
    4347           0 :                         p2 += 21;
    4348           0 :                         SSVALS(p,100,-1);       /* bad_pw_count */
    4349           0 :                         SSVALS(p,102,-1);       /* num_logons */
    4350           0 :                         SIVAL(p,104,PTR_DIFF(p2,*rdata)); /* logon_server */
    4351             :                         {
    4352           0 :                                 TALLOC_CTX *ctx = talloc_tos();
    4353           0 :                                 int space_rem = *rdata_len - (p2 - *rdata);
    4354             :                                 char *tmp;
    4355             : 
    4356           0 :                                 if (space_rem <= 0) {
    4357           0 :                                         return false;
    4358             :                                 }
    4359           0 :                                 tmp = talloc_strdup(ctx, "\\\\%L");
    4360           0 :                                 if (!tmp) {
    4361           0 :                                         return false;
    4362             :                                 }
    4363           0 :                                 tmp = talloc_sub_basic(ctx,
    4364             :                                                 "",
    4365             :                                                 "",
    4366             :                                                 tmp);
    4367           0 :                                 if (!tmp) {
    4368           0 :                                         return false;
    4369             :                                 }
    4370             : 
    4371           0 :                                 push_ascii(p2,
    4372             :                                         tmp,
    4373             :                                         space_rem,
    4374             :                                         STR_TERMINATE);
    4375             :                         }
    4376           0 :                         p2 = skip_string(*rdata,*rdata_len,p2);
    4377           0 :                         if (!p2) {
    4378           0 :                                 return False;
    4379             :                         }
    4380           0 :                         SSVAL(p,108,49);        /* country_code */
    4381           0 :                         SSVAL(p,110,860);       /* code page */
    4382             :                 }
    4383             :         }
    4384             : 
    4385           0 :         errcode = NERR_Success;
    4386             : 
    4387           0 :  out:
    4388           0 :         *rdata_len = PTR_DIFF(p2,*rdata);
    4389             : 
    4390           0 :         if (b && is_valid_policy_hnd(&user_handle)) {
    4391           0 :                 dcerpc_samr_Close(b, mem_ctx, &user_handle, &result);
    4392             :         }
    4393           0 :         if (b && is_valid_policy_hnd(&domain_handle)) {
    4394           0 :                 dcerpc_samr_Close(b, mem_ctx, &domain_handle, &result);
    4395             :         }
    4396           0 :         if (b && is_valid_policy_hnd(&connect_handle)) {
    4397           0 :                 dcerpc_samr_Close(b, mem_ctx, &connect_handle, &result);
    4398             :         }
    4399             : 
    4400           0 :         SSVAL(*rparam,0,errcode);
    4401           0 :         SSVAL(*rparam,2,0);             /* converter word */
    4402           0 :         SSVAL(*rparam,4,*rdata_len);    /* is this right?? */
    4403             : 
    4404           0 :         return(True);
    4405             : }
    4406             : 
    4407           0 : static bool api_WWkstaUserLogon(struct smbd_server_connection *sconn,
    4408             :                                 connection_struct *conn,uint64_t vuid,
    4409             :                                 char *param, int tpscnt,
    4410             :                                 char *data, int tdscnt,
    4411             :                                 int mdrcnt,int mprcnt,
    4412             :                                 char **rdata,char **rparam,
    4413             :                                 int *rdata_len,int *rparam_len)
    4414             : {
    4415           0 :         char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
    4416           0 :         char *str2 = skip_string(param,tpscnt,str1);
    4417           0 :         char *p = skip_string(param,tpscnt,str2);
    4418             :         int uLevel;
    4419             :         struct pack_desc desc;
    4420             :         char* name;
    4421           0 :         struct auth_session_info *si = NULL;
    4422             :         NTSTATUS status;
    4423             : 
    4424           0 :         status = smbXsrv_session_info_lookup(conn->sconn->client,
    4425             :                                              vuid,
    4426             :                                              &si);
    4427           0 :         if (!NT_STATUS_IS_OK(status)) {
    4428           0 :                 return false;
    4429             :         }
    4430             : 
    4431           0 :         if (!str1 || !str2 || !p) {
    4432           0 :                 return False;
    4433             :         }
    4434             : 
    4435           0 :         DBG_INFO("Username of UID %ju is %s\n",
    4436             :                  (uintmax_t)si->unix_token->uid,
    4437             :                  si->unix_info->unix_name);
    4438             : 
    4439           0 :         uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
    4440           0 :         name = get_safe_str_ptr(param,tpscnt,p,2);
    4441           0 :         if (!name) {
    4442           0 :                 return False;
    4443             :         }
    4444             : 
    4445           0 :         memset((char *)&desc,'\0',sizeof(desc));
    4446             : 
    4447           0 :         DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
    4448             : 
    4449             :         /* check it's a supported varient */
    4450           0 :         if (strcmp(str1,"OOWb54WrLh") != 0) {
    4451           0 :                 return False;
    4452             :         }
    4453           0 :         if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) {
    4454           0 :                 return False;
    4455             :         }
    4456           0 :         if (mdrcnt > 0) {
    4457           0 :                 *rdata = smb_realloc_limit(*rdata,mdrcnt);
    4458           0 :                 if (!*rdata) {
    4459           0 :                         return False;
    4460             :                 }
    4461             :         }
    4462             : 
    4463           0 :         desc.base = *rdata;
    4464           0 :         desc.buflen = mdrcnt;
    4465           0 :         desc.subformat = NULL;
    4466           0 :         desc.format = str2;
    4467             : 
    4468           0 :         if (init_package(&desc,1,0)) {
    4469           0 :                 PACKI(&desc,"W",0);               /* code */
    4470           0 :                 PACKS(&desc,"B21",name);  /* eff. name */
    4471           0 :                 PACKS(&desc,"B","");            /* pad */
    4472           0 :                 PACKI(&desc,"W",
    4473           0 :                         (get_current_uid(conn) == sec_initial_uid())?
    4474             :                         USER_PRIV_ADMIN:USER_PRIV_USER);
    4475           0 :                 PACKI(&desc,"D",0);               /* auth flags XXX */
    4476           0 :                 PACKI(&desc,"W",0);               /* num logons */
    4477           0 :                 PACKI(&desc,"W",0);               /* bad pw count */
    4478           0 :                 PACKI(&desc,"D",0);               /* last logon */
    4479           0 :                 PACKI(&desc,"D",-1);              /* last logoff */
    4480           0 :                 PACKI(&desc,"D",-1);              /* logoff time */
    4481           0 :                 PACKI(&desc,"D",-1);              /* kickoff time */
    4482           0 :                 PACKI(&desc,"D",0);               /* password age */
    4483           0 :                 PACKI(&desc,"D",0);               /* password can change */
    4484           0 :                 PACKI(&desc,"D",-1);              /* password must change */
    4485             : 
    4486             :                 {
    4487             :                         fstring mypath;
    4488           0 :                         fstrcpy(mypath,"\\\\");
    4489           0 :                         fstrcat(mypath,get_local_machine_name());
    4490           0 :                         if (!strupper_m(mypath)) {
    4491           0 :                                 return false;
    4492             :                         }
    4493           0 :                         PACKS(&desc,"z",mypath); /* computer */
    4494             :                 }
    4495             : 
    4496           0 :                 PACKS(&desc,"z",lp_workgroup());/* domain */
    4497           0 :                 PACKS(&desc,"z", si->info->logon_script); /* script path */
    4498           0 :                 PACKI(&desc,"D",0x00000000);              /* reserved */
    4499             :         }
    4500             : 
    4501           0 :         *rdata_len = desc.usedlen;
    4502           0 :         *rparam_len = 6;
    4503           0 :         *rparam = smb_realloc_limit(*rparam,*rparam_len);
    4504           0 :         if (!*rparam) {
    4505           0 :                 return False;
    4506             :         }
    4507           0 :         SSVALS(*rparam,0,desc.errcode);
    4508           0 :         SSVAL(*rparam,2,0);
    4509           0 :         SSVAL(*rparam,4,desc.neededlen);
    4510             : 
    4511           0 :         DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
    4512             : 
    4513           0 :         return True;
    4514             : }
    4515             : 
    4516             : /****************************************************************************
    4517             :  api_WAccessGetUserPerms
    4518             : ****************************************************************************/
    4519             : 
    4520           0 : static bool api_WAccessGetUserPerms(struct smbd_server_connection *sconn,
    4521             :                                     connection_struct *conn,uint64_t vuid,
    4522             :                                 char *param, int tpscnt,
    4523             :                                 char *data, int tdscnt,
    4524             :                                 int mdrcnt,int mprcnt,
    4525             :                                 char **rdata,char **rparam,
    4526             :                                 int *rdata_len,int *rparam_len)
    4527             : {
    4528           0 :         char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
    4529           0 :         char *str2 = skip_string(param,tpscnt,str1);
    4530           0 :         char *user = skip_string(param,tpscnt,str2);
    4531           0 :         char *resource = skip_string(param,tpscnt,user);
    4532             : 
    4533           0 :         if (!str1 || !str2 || !user || !resource) {
    4534           0 :                 return False;
    4535             :         }
    4536             : 
    4537           0 :         if (skip_string(param,tpscnt,resource) == NULL) {
    4538           0 :                 return False;
    4539             :         }
    4540           0 :         DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
    4541             : 
    4542             :         /* check it's a supported varient */
    4543           0 :         if (strcmp(str1,"zzh") != 0) {
    4544           0 :                 return False;
    4545             :         }
    4546           0 :         if (strcmp(str2,"") != 0) {
    4547           0 :                 return False;
    4548             :         }
    4549             : 
    4550           0 :         *rparam_len = 6;
    4551           0 :         *rparam = smb_realloc_limit(*rparam,*rparam_len);
    4552           0 :         if (!*rparam) {
    4553           0 :                 return False;
    4554             :         }
    4555           0 :         SSVALS(*rparam,0,0);            /* errorcode */
    4556           0 :         SSVAL(*rparam,2,0);             /* converter word */
    4557           0 :         SSVAL(*rparam,4,0x7f);  /* permission flags */
    4558             : 
    4559           0 :         return True;
    4560             : }
    4561             : 
    4562             : /****************************************************************************
    4563             :   api_WPrintJobEnumerate
    4564             :   ****************************************************************************/
    4565             : 
    4566           0 : static bool api_WPrintJobGetInfo(struct smbd_server_connection *sconn,
    4567             :                                  connection_struct *conn, uint64_t vuid,
    4568             :                                 char *param, int tpscnt,
    4569             :                                 char *data, int tdscnt,
    4570             :                                 int mdrcnt,int mprcnt,
    4571             :                                 char **rdata,char **rparam,
    4572             :                                 int *rdata_len,int *rparam_len)
    4573             : {
    4574           0 :         char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
    4575           0 :         char *str2 = skip_string(param,tpscnt,str1);
    4576           0 :         char *p = skip_string(param,tpscnt,str2);
    4577             :         int uLevel;
    4578             :         fstring sharename;
    4579             :         uint32_t jobid;
    4580             :         struct pack_desc desc;
    4581           0 :         char *tmpdata=NULL;
    4582             : 
    4583           0 :         TALLOC_CTX *mem_ctx = talloc_tos();
    4584             :         WERROR werr;
    4585             :         NTSTATUS status;
    4586           0 :         struct rpc_pipe_client *cli = NULL;
    4587           0 :         struct dcerpc_binding_handle *b = NULL;
    4588             :         struct policy_handle handle;
    4589             :         struct spoolss_DevmodeContainer devmode_ctr;
    4590             :         union spoolss_JobInfo info;
    4591             : 
    4592           0 :         if (!str1 || !str2 || !p) {
    4593           0 :                 return False;
    4594             :         }
    4595             : 
    4596           0 :         uLevel = get_safe_SVAL(param,tpscnt,p,2,-1);
    4597             : 
    4598           0 :         memset((char *)&desc,'\0',sizeof(desc));
    4599           0 :         memset((char *)&status,'\0',sizeof(status));
    4600             : 
    4601           0 :         DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
    4602             : 
    4603             :         /* check it's a supported varient */
    4604           0 :         if (strcmp(str1,"WWrLh") != 0) {
    4605           0 :                 return False;
    4606             :         }
    4607           0 :         if (!check_printjob_info(&desc,uLevel,str2)) {
    4608           0 :                 return False;
    4609             :         }
    4610             : 
    4611           0 :         if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid)) {
    4612           0 :                 return False;
    4613             :         }
    4614             : 
    4615           0 :         ZERO_STRUCT(handle);
    4616             : 
    4617           0 :         status = rpc_pipe_open_interface(mem_ctx,
    4618             :                                          &ndr_table_spoolss,
    4619           0 :                                          conn->session_info,
    4620           0 :                                          conn->sconn->remote_address,
    4621           0 :                                          conn->sconn->local_address,
    4622           0 :                                          conn->sconn->msg_ctx,
    4623             :                                          &cli);
    4624           0 :         if (!NT_STATUS_IS_OK(status)) {
    4625           0 :                 DEBUG(0,("api_WPrintJobGetInfo: could not connect to spoolss: %s\n",
    4626             :                           nt_errstr(status)));
    4627           0 :                 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
    4628           0 :                 goto out;
    4629             :         }
    4630           0 :         b = cli->binding_handle;
    4631             : 
    4632           0 :         ZERO_STRUCT(devmode_ctr);
    4633             : 
    4634           0 :         status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
    4635             :                                             sharename,
    4636             :                                             "RAW",
    4637             :                                             devmode_ctr,
    4638             :                                             PRINTER_ACCESS_USE,
    4639             :                                             &handle,
    4640             :                                             &werr);
    4641           0 :         if (!NT_STATUS_IS_OK(status)) {
    4642           0 :                 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
    4643           0 :                 goto out;
    4644             :         }
    4645           0 :         if (!W_ERROR_IS_OK(werr)) {
    4646           0 :                 desc.errcode = W_ERROR_V(werr);
    4647           0 :                 goto out;
    4648             :         }
    4649             : 
    4650           0 :         werr = rpccli_spoolss_getjob(cli, mem_ctx,
    4651             :                                      &handle,
    4652             :                                      jobid,
    4653             :                                      2, /* level */
    4654             :                                      0, /* offered */
    4655             :                                      &info);
    4656           0 :         if (!W_ERROR_IS_OK(werr)) {
    4657           0 :                 desc.errcode = W_ERROR_V(werr);
    4658           0 :                 goto out;
    4659             :         }
    4660             : 
    4661           0 :         if (mdrcnt > 0) {
    4662           0 :                 *rdata = smb_realloc_limit(*rdata,mdrcnt);
    4663           0 :                 if (!*rdata) {
    4664           0 :                         return False;
    4665             :                 }
    4666           0 :                 desc.base = *rdata;
    4667           0 :                 desc.buflen = mdrcnt;
    4668             :         } else {
    4669             :                 /*
    4670             :                  * Don't return data but need to get correct length
    4671             :                  *  init_package will return wrong size if buflen=0
    4672             :                  */
    4673           0 :                 desc.buflen = getlen(desc.format);
    4674           0 :                 desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen );
    4675             :         }
    4676             : 
    4677           0 :         if (init_package(&desc,1,0)) {
    4678           0 :                 fill_spoolss_printjob_info(uLevel, &desc, &info.info2, info.info2.position);
    4679           0 :                 *rdata_len = desc.usedlen;
    4680             :         } else {
    4681           0 :                 desc.errcode = NERR_JobNotFound;
    4682           0 :                 *rdata_len = 0;
    4683             :         }
    4684           0 :  out:
    4685           0 :         if (b && is_valid_policy_hnd(&handle)) {
    4686           0 :                 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
    4687             :         }
    4688             : 
    4689           0 :         *rparam_len = 6;
    4690           0 :         *rparam = smb_realloc_limit(*rparam,*rparam_len);
    4691           0 :         if (!*rparam) {
    4692           0 :                 return False;
    4693             :         }
    4694           0 :         SSVALS(*rparam,0,desc.errcode);
    4695           0 :         SSVAL(*rparam,2,0);
    4696           0 :         SSVAL(*rparam,4,desc.neededlen);
    4697             : 
    4698           0 :         SAFE_FREE(tmpdata);
    4699             : 
    4700           0 :         DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
    4701             : 
    4702           0 :         return True;
    4703             : }
    4704             : 
    4705           0 : static bool api_WPrintJobEnumerate(struct smbd_server_connection *sconn,
    4706             :                                    connection_struct *conn, uint64_t vuid,
    4707             :                                 char *param, int tpscnt,
    4708             :                                 char *data, int tdscnt,
    4709             :                                 int mdrcnt,int mprcnt,
    4710             :                                 char **rdata,char **rparam,
    4711             :                                 int *rdata_len,int *rparam_len)
    4712             : {
    4713           0 :         char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
    4714           0 :         char *str2 = skip_string(param,tpscnt,str1);
    4715           0 :         char *p = skip_string(param,tpscnt,str2);
    4716           0 :         char *name = p;
    4717             :         int uLevel;
    4718           0 :         int i, succnt=0;
    4719             :         struct pack_desc desc;
    4720             : 
    4721           0 :         TALLOC_CTX *mem_ctx = talloc_tos();
    4722             :         WERROR werr;
    4723             :         NTSTATUS status;
    4724           0 :         struct rpc_pipe_client *cli = NULL;
    4725           0 :         struct dcerpc_binding_handle *b = NULL;
    4726             :         struct policy_handle handle;
    4727             :         struct spoolss_DevmodeContainer devmode_ctr;
    4728           0 :         uint32_t count = 0;
    4729             :         union spoolss_JobInfo *info;
    4730             : 
    4731           0 :         if (!str1 || !str2 || !p) {
    4732           0 :                 return False;
    4733             :         }
    4734             : 
    4735           0 :         memset((char *)&desc,'\0',sizeof(desc));
    4736             : 
    4737           0 :         p = skip_string(param,tpscnt,p);
    4738           0 :         if (!p) {
    4739           0 :                 return False;
    4740             :         }
    4741           0 :         uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
    4742             : 
    4743           0 :         DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
    4744             : 
    4745             :         /* check it's a supported variant */
    4746           0 :         if (strcmp(str1,"zWrLeh") != 0) {
    4747           0 :                 return False;
    4748             :         }
    4749             : 
    4750           0 :         if (uLevel > 2) {
    4751           0 :                 return False;   /* defined only for uLevel 0,1,2 */
    4752             :         }
    4753             : 
    4754           0 :         if (!check_printjob_info(&desc,uLevel,str2)) {
    4755           0 :                 return False;
    4756             :         }
    4757             : 
    4758           0 :         ZERO_STRUCT(handle);
    4759             : 
    4760           0 :         status = rpc_pipe_open_interface(mem_ctx,
    4761             :                                          &ndr_table_spoolss,
    4762           0 :                                          conn->session_info,
    4763           0 :                                          conn->sconn->remote_address,
    4764           0 :                                          conn->sconn->local_address,
    4765           0 :                                          conn->sconn->msg_ctx,
    4766             :                                          &cli);
    4767           0 :         if (!NT_STATUS_IS_OK(status)) {
    4768           0 :                 DEBUG(0,("api_WPrintJobEnumerate: could not connect to spoolss: %s\n",
    4769             :                           nt_errstr(status)));
    4770           0 :                 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
    4771           0 :                 goto out;
    4772             :         }
    4773           0 :         b = cli->binding_handle;
    4774             : 
    4775           0 :         ZERO_STRUCT(devmode_ctr);
    4776             : 
    4777           0 :         status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
    4778             :                                             name,
    4779             :                                             NULL,
    4780             :                                             devmode_ctr,
    4781             :                                             PRINTER_ACCESS_USE,
    4782             :                                             &handle,
    4783             :                                             &werr);
    4784           0 :         if (!NT_STATUS_IS_OK(status)) {
    4785           0 :                 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
    4786           0 :                 goto out;
    4787             :         }
    4788           0 :         if (!W_ERROR_IS_OK(werr)) {
    4789           0 :                 desc.errcode = W_ERROR_V(werr);
    4790           0 :                 goto out;
    4791             :         }
    4792             : 
    4793           0 :         werr = rpccli_spoolss_enumjobs(cli, mem_ctx,
    4794             :                                        &handle,
    4795             :                                        0, /* firstjob */
    4796             :                                        0xff, /* numjobs */
    4797             :                                        2, /* level */
    4798             :                                        0, /* offered */
    4799             :                                        &count,
    4800             :                                        &info);
    4801           0 :         if (!W_ERROR_IS_OK(werr)) {
    4802           0 :                 desc.errcode = W_ERROR_V(werr);
    4803           0 :                 goto out;
    4804             :         }
    4805             : 
    4806           0 :         if (mdrcnt > 0) {
    4807           0 :                 *rdata = smb_realloc_limit(*rdata,mdrcnt);
    4808           0 :                 if (!*rdata) {
    4809           0 :                         return False;
    4810             :                 }
    4811             :         }
    4812           0 :         desc.base = *rdata;
    4813           0 :         desc.buflen = mdrcnt;
    4814             : 
    4815           0 :         if (init_package(&desc,count,0)) {
    4816           0 :                 succnt = 0;
    4817           0 :                 for (i = 0; i < count; i++) {
    4818           0 :                         fill_spoolss_printjob_info(uLevel, &desc, &info[i].info2, i);
    4819           0 :                         if (desc.errcode == NERR_Success) {
    4820           0 :                                 succnt = i+1;
    4821             :                         }
    4822             :                 }
    4823             :         }
    4824           0 :  out:
    4825           0 :         if (b && is_valid_policy_hnd(&handle)) {
    4826           0 :                 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
    4827             :         }
    4828             : 
    4829           0 :         *rdata_len = desc.usedlen;
    4830             : 
    4831           0 :         *rparam_len = 8;
    4832           0 :         *rparam = smb_realloc_limit(*rparam,*rparam_len);
    4833           0 :         if (!*rparam) {
    4834           0 :                 return False;
    4835             :         }
    4836           0 :         SSVALS(*rparam,0,desc.errcode);
    4837           0 :         SSVAL(*rparam,2,0);
    4838           0 :         SSVAL(*rparam,4,succnt);
    4839           0 :         SSVAL(*rparam,6,count);
    4840             : 
    4841           0 :         DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
    4842             : 
    4843           0 :         return True;
    4844             : }
    4845             : 
    4846           0 : static int check_printdest_info(struct pack_desc* desc,
    4847             :                                 int uLevel, char* id)
    4848             : {
    4849           0 :         desc->subformat = NULL;
    4850           0 :         switch( uLevel ) {
    4851           0 :                 case 0:
    4852           0 :                         desc->format = "B9";
    4853           0 :                         break;
    4854           0 :                 case 1:
    4855           0 :                         desc->format = "B9B21WWzW";
    4856           0 :                         break;
    4857           0 :                 case 2:
    4858           0 :                         desc->format = "z";
    4859           0 :                         break;
    4860           0 :                 case 3:
    4861           0 :                         desc->format = "zzzWWzzzWW";
    4862           0 :                         break;
    4863           0 :                 default:
    4864           0 :                         DEBUG(0,("check_printdest_info: invalid level %d\n",
    4865             :                                 uLevel));
    4866           0 :                         return False;
    4867             :         }
    4868           0 :         if (id == NULL || strcmp(desc->format,id) != 0) {
    4869           0 :                 DEBUG(0,("check_printdest_info: invalid string %s\n",
    4870             :                         id ? id : "<NULL>" ));
    4871           0 :                 return False;
    4872             :         }
    4873           0 :         return True;
    4874             : }
    4875             : 
    4876           0 : static void fill_printdest_info(struct spoolss_PrinterInfo2 *info2, int uLevel,
    4877             :                                 struct pack_desc* desc)
    4878             : {
    4879             :         char buf[100];
    4880             : 
    4881           0 :         strncpy(buf, info2->printername, sizeof(buf)-1);
    4882           0 :         buf[sizeof(buf)-1] = 0;
    4883           0 :         (void)strupper_m(buf);
    4884             : 
    4885           0 :         if (uLevel <= 1) {
    4886           0 :                 PACKS(desc,"B9",buf); /* szName */
    4887           0 :                 if (uLevel == 1) {
    4888           0 :                         PACKS(desc,"B21","");       /* szUserName */
    4889           0 :                         PACKI(desc,"W",0);            /* uJobId */
    4890           0 :                         PACKI(desc,"W",0);            /* fsStatus */
    4891           0 :                         PACKS(desc,"z",""); /* pszStatus */
    4892           0 :                         PACKI(desc,"W",0);            /* time */
    4893             :                 }
    4894             :         }
    4895             : 
    4896           0 :         if (uLevel == 2 || uLevel == 3) {
    4897           0 :                 PACKS(desc,"z",buf);          /* pszPrinterName */
    4898           0 :                 if (uLevel == 3) {
    4899           0 :                         PACKS(desc,"z",""); /* pszUserName */
    4900           0 :                         PACKS(desc,"z",""); /* pszLogAddr */
    4901           0 :                         PACKI(desc,"W",0);            /* uJobId */
    4902           0 :                         PACKI(desc,"W",0);            /* fsStatus */
    4903           0 :                         PACKS(desc,"z",""); /* pszStatus */
    4904           0 :                         PACKS(desc,"z",""); /* pszComment */
    4905           0 :                         PACKS(desc,"z","NULL"); /* pszDrivers */
    4906           0 :                         PACKI(desc,"W",0);            /* time */
    4907           0 :                         PACKI(desc,"W",0);            /* pad1 */
    4908             :                 }
    4909             :         }
    4910           0 : }
    4911             : 
    4912           0 : static bool api_WPrintDestGetInfo(struct smbd_server_connection *sconn,
    4913             :                                   connection_struct *conn, uint64_t vuid,
    4914             :                                 char *param, int tpscnt,
    4915             :                                 char *data, int tdscnt,
    4916             :                                 int mdrcnt,int mprcnt,
    4917             :                                 char **rdata,char **rparam,
    4918             :                                 int *rdata_len,int *rparam_len)
    4919             : {
    4920           0 :         char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
    4921           0 :         char *str2 = skip_string(param,tpscnt,str1);
    4922           0 :         char *p = skip_string(param,tpscnt,str2);
    4923           0 :         char* PrinterName = p;
    4924             :         int uLevel;
    4925             :         struct pack_desc desc;
    4926           0 :         char *tmpdata=NULL;
    4927             : 
    4928           0 :         TALLOC_CTX *mem_ctx = talloc_tos();
    4929             :         WERROR werr;
    4930             :         NTSTATUS status;
    4931           0 :         struct rpc_pipe_client *cli = NULL;
    4932           0 :         struct dcerpc_binding_handle *b = NULL;
    4933             :         struct policy_handle handle;
    4934             :         struct spoolss_DevmodeContainer devmode_ctr;
    4935             :         union spoolss_PrinterInfo info;
    4936             : 
    4937           0 :         if (!str1 || !str2 || !p) {
    4938           0 :                 return False;
    4939             :         }
    4940             : 
    4941           0 :         memset((char *)&desc,'\0',sizeof(desc));
    4942             : 
    4943           0 :         p = skip_string(param,tpscnt,p);
    4944           0 :         if (!p) {
    4945           0 :                 return False;
    4946             :         }
    4947           0 :         uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
    4948             : 
    4949           0 :         DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
    4950             : 
    4951             :         /* check it's a supported varient */
    4952           0 :         if (strcmp(str1,"zWrLh") != 0) {
    4953           0 :                 return False;
    4954             :         }
    4955           0 :         if (!check_printdest_info(&desc,uLevel,str2)) {
    4956           0 :                 return False;
    4957             :         }
    4958             : 
    4959           0 :         ZERO_STRUCT(handle);
    4960             : 
    4961           0 :         status = rpc_pipe_open_interface(mem_ctx,
    4962             :                                          &ndr_table_spoolss,
    4963           0 :                                          conn->session_info,
    4964           0 :                                          conn->sconn->remote_address,
    4965           0 :                                          conn->sconn->local_address,
    4966           0 :                                          conn->sconn->msg_ctx,
    4967             :                                          &cli);
    4968           0 :         if (!NT_STATUS_IS_OK(status)) {
    4969           0 :                 DEBUG(0,("api_WPrintDestGetInfo: could not connect to spoolss: %s\n",
    4970             :                           nt_errstr(status)));
    4971           0 :                 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
    4972           0 :                 goto out;
    4973             :         }
    4974           0 :         b = cli->binding_handle;
    4975             : 
    4976           0 :         ZERO_STRUCT(devmode_ctr);
    4977             : 
    4978           0 :         status = dcerpc_spoolss_OpenPrinter(b, mem_ctx,
    4979             :                                             PrinterName,
    4980             :                                             NULL,
    4981             :                                             devmode_ctr,
    4982             :                                             PRINTER_ACCESS_USE,
    4983             :                                             &handle,
    4984             :                                             &werr);
    4985           0 :         if (!NT_STATUS_IS_OK(status)) {
    4986           0 :                 *rdata_len = 0;
    4987           0 :                 desc.errcode = NERR_DestNotFound;
    4988           0 :                 desc.neededlen = 0;
    4989           0 :                 goto out;
    4990             :         }
    4991           0 :         if (!W_ERROR_IS_OK(werr)) {
    4992           0 :                 *rdata_len = 0;
    4993           0 :                 desc.errcode = NERR_DestNotFound;
    4994           0 :                 desc.neededlen = 0;
    4995           0 :                 goto out;
    4996             :         }
    4997             : 
    4998           0 :         werr = rpccli_spoolss_getprinter(cli, mem_ctx,
    4999             :                                          &handle,
    5000             :                                          2,
    5001             :                                          0,
    5002             :                                          &info);
    5003           0 :         if (!W_ERROR_IS_OK(werr)) {
    5004           0 :                 *rdata_len = 0;
    5005           0 :                 desc.errcode = NERR_DestNotFound;
    5006           0 :                 desc.neededlen = 0;
    5007           0 :                 goto out;
    5008             :         }
    5009             : 
    5010           0 :         if (mdrcnt > 0) {
    5011           0 :                 *rdata = smb_realloc_limit(*rdata,mdrcnt);
    5012           0 :                 if (!*rdata) {
    5013           0 :                         return False;
    5014             :                 }
    5015           0 :                 desc.base = *rdata;
    5016           0 :                 desc.buflen = mdrcnt;
    5017             :         } else {
    5018             :                 /*
    5019             :                  * Don't return data but need to get correct length
    5020             :                  * init_package will return wrong size if buflen=0
    5021             :                  */
    5022           0 :                 desc.buflen = getlen(desc.format);
    5023           0 :                 desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen );
    5024             :         }
    5025           0 :         if (init_package(&desc,1,0)) {
    5026           0 :                 fill_printdest_info(&info.info2, uLevel,&desc);
    5027             :         }
    5028             : 
    5029           0 :  out:
    5030           0 :         if (b && is_valid_policy_hnd(&handle)) {
    5031           0 :                 dcerpc_spoolss_ClosePrinter(b, mem_ctx, &handle, &werr);
    5032             :         }
    5033             : 
    5034           0 :         *rdata_len = desc.usedlen;
    5035             : 
    5036           0 :         *rparam_len = 6;
    5037           0 :         *rparam = smb_realloc_limit(*rparam,*rparam_len);
    5038           0 :         if (!*rparam) {
    5039           0 :                 return False;
    5040             :         }
    5041           0 :         SSVALS(*rparam,0,desc.errcode);
    5042           0 :         SSVAL(*rparam,2,0);
    5043           0 :         SSVAL(*rparam,4,desc.neededlen);
    5044             : 
    5045           0 :         DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
    5046           0 :         SAFE_FREE(tmpdata);
    5047             : 
    5048           0 :         return True;
    5049             : }
    5050             : 
    5051           0 : static bool api_WPrintDestEnum(struct smbd_server_connection *sconn,
    5052             :                                connection_struct *conn, uint64_t vuid,
    5053             :                                 char *param, int tpscnt,
    5054             :                                 char *data, int tdscnt,
    5055             :                                 int mdrcnt,int mprcnt,
    5056             :                                 char **rdata,char **rparam,
    5057             :                                 int *rdata_len,int *rparam_len)
    5058             : {
    5059           0 :         char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
    5060           0 :         char *str2 = skip_string(param,tpscnt,str1);
    5061           0 :         char *p = skip_string(param,tpscnt,str2);
    5062             :         int uLevel;
    5063             :         int queuecnt;
    5064           0 :         int i, n, succnt=0;
    5065             :         struct pack_desc desc;
    5066             : 
    5067           0 :         TALLOC_CTX *mem_ctx = talloc_tos();
    5068             :         WERROR werr;
    5069             :         NTSTATUS status;
    5070           0 :         struct rpc_pipe_client *cli = NULL;
    5071             :         union spoolss_PrinterInfo *info;
    5072             :         uint32_t count;
    5073             : 
    5074           0 :         if (!str1 || !str2 || !p) {
    5075           0 :                 return False;
    5076             :         }
    5077             : 
    5078           0 :         memset((char *)&desc,'\0',sizeof(desc));
    5079             : 
    5080           0 :         uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
    5081             : 
    5082           0 :         DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
    5083             : 
    5084             :         /* check it's a supported varient */
    5085           0 :         if (strcmp(str1,"WrLeh") != 0) {
    5086           0 :                 return False;
    5087             :         }
    5088           0 :         if (!check_printdest_info(&desc,uLevel,str2)) {
    5089           0 :                 return False;
    5090             :         }
    5091             : 
    5092           0 :         queuecnt = 0;
    5093             : 
    5094           0 :         status = rpc_pipe_open_interface(mem_ctx,
    5095             :                                          &ndr_table_spoolss,
    5096           0 :                                          conn->session_info,
    5097           0 :                                          conn->sconn->remote_address,
    5098           0 :                                          conn->sconn->local_address,
    5099           0 :                                          conn->sconn->msg_ctx,
    5100             :                                          &cli);
    5101           0 :         if (!NT_STATUS_IS_OK(status)) {
    5102           0 :                 DEBUG(0,("api_WPrintDestEnum: could not connect to spoolss: %s\n",
    5103             :                           nt_errstr(status)));
    5104           0 :                 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
    5105           0 :                 goto out;
    5106             :         }
    5107             : 
    5108           0 :         werr = rpccli_spoolss_enumprinters(cli, mem_ctx,
    5109             :                                            PRINTER_ENUM_LOCAL,
    5110           0 :                                            cli->srv_name_slash,
    5111             :                                            2,
    5112             :                                            0,
    5113             :                                            &count,
    5114             :                                            &info);
    5115           0 :         if (!W_ERROR_IS_OK(werr)) {
    5116           0 :                 desc.errcode = W_ERROR_V(werr);
    5117           0 :                 *rdata_len = 0;
    5118           0 :                 desc.errcode = NERR_DestNotFound;
    5119           0 :                 desc.neededlen = 0;
    5120           0 :                 goto out;
    5121             :         }
    5122             : 
    5123           0 :         queuecnt = count;
    5124             : 
    5125           0 :         if (mdrcnt > 0) {
    5126           0 :                 *rdata = smb_realloc_limit(*rdata,mdrcnt);
    5127           0 :                 if (!*rdata) {
    5128           0 :                         return False;
    5129             :                 }
    5130             :         }
    5131             : 
    5132           0 :         desc.base = *rdata;
    5133           0 :         desc.buflen = mdrcnt;
    5134           0 :         if (init_package(&desc,queuecnt,0)) {
    5135           0 :                 succnt = 0;
    5136           0 :                 n = 0;
    5137           0 :                 for (i = 0; i < count; i++) {
    5138           0 :                         fill_printdest_info(&info[i].info2, uLevel,&desc);
    5139           0 :                         n++;
    5140           0 :                         if (desc.errcode == NERR_Success) {
    5141           0 :                                 succnt = n;
    5142             :                         }
    5143             :                 }
    5144             :         }
    5145           0 :  out:
    5146           0 :         *rdata_len = desc.usedlen;
    5147             : 
    5148           0 :         *rparam_len = 8;
    5149           0 :         *rparam = smb_realloc_limit(*rparam,*rparam_len);
    5150           0 :         if (!*rparam) {
    5151           0 :                 return False;
    5152             :         }
    5153           0 :         SSVALS(*rparam,0,desc.errcode);
    5154           0 :         SSVAL(*rparam,2,0);
    5155           0 :         SSVAL(*rparam,4,succnt);
    5156           0 :         SSVAL(*rparam,6,queuecnt);
    5157             : 
    5158           0 :         DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
    5159             : 
    5160           0 :         return True;
    5161             : }
    5162             : 
    5163           0 : static bool api_WPrintDriverEnum(struct smbd_server_connection *sconn,
    5164             :                                  connection_struct *conn, uint64_t vuid,
    5165             :                                 char *param, int tpscnt,
    5166             :                                 char *data, int tdscnt,
    5167             :                                 int mdrcnt,int mprcnt,
    5168             :                                 char **rdata,char **rparam,
    5169             :                                 int *rdata_len,int *rparam_len)
    5170             : {
    5171           0 :         char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
    5172           0 :         char *str2 = skip_string(param,tpscnt,str1);
    5173           0 :         char *p = skip_string(param,tpscnt,str2);
    5174             :         int uLevel;
    5175             :         int succnt;
    5176             :         struct pack_desc desc;
    5177             : 
    5178           0 :         if (!str1 || !str2 || !p) {
    5179           0 :                 return False;
    5180             :         }
    5181             : 
    5182           0 :         memset((char *)&desc,'\0',sizeof(desc));
    5183             : 
    5184           0 :         uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
    5185             : 
    5186           0 :         DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
    5187             : 
    5188             :         /* check it's a supported varient */
    5189           0 :         if (strcmp(str1,"WrLeh") != 0) {
    5190           0 :                 return False;
    5191             :         }
    5192           0 :         if (uLevel != 0 || strcmp(str2,"B41") != 0) {
    5193           0 :                 return False;
    5194             :         }
    5195             : 
    5196           0 :         if (mdrcnt > 0) {
    5197           0 :                 *rdata = smb_realloc_limit(*rdata,mdrcnt);
    5198           0 :                 if (!*rdata) {
    5199           0 :                         return False;
    5200             :                 }
    5201             :         }
    5202           0 :         desc.base = *rdata;
    5203           0 :         desc.buflen = mdrcnt;
    5204           0 :         if (init_package(&desc,1,0)) {
    5205           0 :                 PACKS(&desc,"B41","NULL");
    5206             :         }
    5207             : 
    5208           0 :         succnt = (desc.errcode == NERR_Success ? 1 : 0);
    5209             : 
    5210           0 :         *rdata_len = desc.usedlen;
    5211             : 
    5212           0 :         *rparam_len = 8;
    5213           0 :         *rparam = smb_realloc_limit(*rparam,*rparam_len);
    5214           0 :         if (!*rparam) {
    5215           0 :                 return False;
    5216             :         }
    5217           0 :         SSVALS(*rparam,0,desc.errcode);
    5218           0 :         SSVAL(*rparam,2,0);
    5219           0 :         SSVAL(*rparam,4,succnt);
    5220           0 :         SSVAL(*rparam,6,1);
    5221             : 
    5222           0 :         DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
    5223             : 
    5224           0 :         return True;
    5225             : }
    5226             : 
    5227           0 : static bool api_WPrintQProcEnum(struct smbd_server_connection *sconn,
    5228             :                                 connection_struct *conn, uint64_t vuid,
    5229             :                                 char *param, int tpscnt,
    5230             :                                 char *data, int tdscnt,
    5231             :                                 int mdrcnt,int mprcnt,
    5232             :                                 char **rdata,char **rparam,
    5233             :                                 int *rdata_len,int *rparam_len)
    5234             : {
    5235           0 :         char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
    5236           0 :         char *str2 = skip_string(param,tpscnt,str1);
    5237           0 :         char *p = skip_string(param,tpscnt,str2);
    5238             :         int uLevel;
    5239             :         int succnt;
    5240             :         struct pack_desc desc;
    5241             : 
    5242           0 :         if (!str1 || !str2 || !p) {
    5243           0 :                 return False;
    5244             :         }
    5245           0 :         memset((char *)&desc,'\0',sizeof(desc));
    5246             : 
    5247           0 :         uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
    5248             : 
    5249           0 :         DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
    5250             : 
    5251             :         /* check it's a supported varient */
    5252           0 :         if (strcmp(str1,"WrLeh") != 0) {
    5253           0 :                 return False;
    5254             :         }
    5255           0 :         if (uLevel != 0 || strcmp(str2,"B13") != 0) {
    5256           0 :                 return False;
    5257             :         }
    5258             : 
    5259           0 :         if (mdrcnt > 0) {
    5260           0 :                 *rdata = smb_realloc_limit(*rdata,mdrcnt);
    5261           0 :                 if (!*rdata) {
    5262           0 :                         return False;
    5263             :                 }
    5264             :         }
    5265           0 :         desc.base = *rdata;
    5266           0 :         desc.buflen = mdrcnt;
    5267           0 :         desc.format = str2;
    5268           0 :         if (init_package(&desc,1,0)) {
    5269           0 :                 PACKS(&desc,"B13","lpd");
    5270             :         }
    5271             : 
    5272           0 :         succnt = (desc.errcode == NERR_Success ? 1 : 0);
    5273             : 
    5274           0 :         *rdata_len = desc.usedlen;
    5275             : 
    5276           0 :         *rparam_len = 8;
    5277           0 :         *rparam = smb_realloc_limit(*rparam,*rparam_len);
    5278           0 :         if (!*rparam) {
    5279           0 :                 return False;
    5280             :         }
    5281           0 :         SSVALS(*rparam,0,desc.errcode);
    5282           0 :         SSVAL(*rparam,2,0);
    5283           0 :         SSVAL(*rparam,4,succnt);
    5284           0 :         SSVAL(*rparam,6,1);
    5285             : 
    5286           0 :         DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
    5287             : 
    5288           0 :         return True;
    5289             : }
    5290             : 
    5291           0 : static bool api_WPrintPortEnum(struct smbd_server_connection *sconn,
    5292             :                                connection_struct *conn, uint64_t vuid,
    5293             :                                 char *param, int tpscnt,
    5294             :                                 char *data, int tdscnt,
    5295             :                                 int mdrcnt,int mprcnt,
    5296             :                                 char **rdata,char **rparam,
    5297             :                                 int *rdata_len,int *rparam_len)
    5298             : {
    5299           0 :         char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
    5300           0 :         char *str2 = skip_string(param,tpscnt,str1);
    5301           0 :         char *p = skip_string(param,tpscnt,str2);
    5302             :         int uLevel;
    5303             :         int succnt;
    5304             :         struct pack_desc desc;
    5305             : 
    5306           0 :         if (!str1 || !str2 || !p) {
    5307           0 :                 return False;
    5308             :         }
    5309             : 
    5310           0 :         memset((char *)&desc,'\0',sizeof(desc));
    5311             : 
    5312           0 :         uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
    5313             : 
    5314           0 :         DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
    5315             : 
    5316             :         /* check it's a supported varient */
    5317           0 :         if (strcmp(str1,"WrLeh") != 0) {
    5318           0 :                 return False;
    5319             :         }
    5320           0 :         if (uLevel != 0 || strcmp(str2,"B9") != 0) {
    5321           0 :                 return False;
    5322             :         }
    5323             : 
    5324           0 :         if (mdrcnt > 0) {
    5325           0 :                 *rdata = smb_realloc_limit(*rdata,mdrcnt);
    5326           0 :                 if (!*rdata) {
    5327           0 :                         return False;
    5328             :                 }
    5329             :         }
    5330           0 :         memset((char *)&desc,'\0',sizeof(desc));
    5331           0 :         desc.base = *rdata;
    5332           0 :         desc.buflen = mdrcnt;
    5333           0 :         desc.format = str2;
    5334           0 :         if (init_package(&desc,1,0)) {
    5335           0 :                 PACKS(&desc,"B13","lp0");
    5336             :         }
    5337             : 
    5338           0 :         succnt = (desc.errcode == NERR_Success ? 1 : 0);
    5339             : 
    5340           0 :         *rdata_len = desc.usedlen;
    5341             : 
    5342           0 :         *rparam_len = 8;
    5343           0 :         *rparam = smb_realloc_limit(*rparam,*rparam_len);
    5344           0 :         if (!*rparam) {
    5345           0 :                 return False;
    5346             :         }
    5347           0 :         SSVALS(*rparam,0,desc.errcode);
    5348           0 :         SSVAL(*rparam,2,0);
    5349           0 :         SSVAL(*rparam,4,succnt);
    5350           0 :         SSVAL(*rparam,6,1);
    5351             : 
    5352           0 :         DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
    5353             : 
    5354           0 :         return True;
    5355             : }
    5356             : 
    5357             : /****************************************************************************
    5358             :  List open sessions
    5359             :  ****************************************************************************/
    5360             : 
    5361           0 : static bool api_RNetSessionEnum(struct smbd_server_connection *sconn,
    5362             :                                 connection_struct *conn, uint64_t vuid,
    5363             :                                 char *param, int tpscnt,
    5364             :                                 char *data, int tdscnt,
    5365             :                                 int mdrcnt,int mprcnt,
    5366             :                                 char **rdata,char **rparam,
    5367             :                                 int *rdata_len,int *rparam_len)
    5368             : 
    5369             : {
    5370           0 :         char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
    5371           0 :         char *str2 = skip_string(param,tpscnt,str1);
    5372           0 :         char *p = skip_string(param,tpscnt,str2);
    5373             :         int uLevel;
    5374             :         struct pack_desc desc;
    5375             :         int i;
    5376             : 
    5377           0 :         TALLOC_CTX *mem_ctx = talloc_tos();
    5378             :         WERROR werr;
    5379             :         NTSTATUS status;
    5380           0 :         struct rpc_pipe_client *cli = NULL;
    5381           0 :         struct dcerpc_binding_handle *b = NULL;
    5382             :         struct srvsvc_NetSessInfoCtr info_ctr;
    5383           0 :         uint32_t totalentries, resume_handle = 0;
    5384           0 :         uint32_t count = 0;
    5385             : 
    5386           0 :         if (!str1 || !str2 || !p) {
    5387           0 :                 return False;
    5388             :         }
    5389             : 
    5390           0 :         ZERO_STRUCT(desc);
    5391             : 
    5392           0 :         uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
    5393             : 
    5394           0 :         DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel));
    5395           0 :         DEBUG(7,("RNetSessionEnum req string=%s\n",str1));
    5396           0 :         DEBUG(7,("RNetSessionEnum ret string=%s\n",str2));
    5397             : 
    5398             :         /* check it's a supported varient */
    5399           0 :         if (strcmp(str1,RAP_NetSessionEnum_REQ) != 0) {
    5400           0 :                 return False;
    5401             :         }
    5402           0 :         if (uLevel != 2 || strcmp(str2,RAP_SESSION_INFO_L2) != 0) {
    5403           0 :                 return False;
    5404             :         }
    5405             : 
    5406           0 :         status = rpc_pipe_open_interface(mem_ctx,
    5407             :                                          &ndr_table_srvsvc,
    5408           0 :                                          conn->session_info,
    5409           0 :                                          conn->sconn->remote_address,
    5410           0 :                                          conn->sconn->local_address,
    5411           0 :                                          conn->sconn->msg_ctx,
    5412             :                                          &cli);
    5413           0 :         if (!NT_STATUS_IS_OK(status)) {
    5414           0 :                 DEBUG(0,("RNetSessionEnum: could not connect to srvsvc: %s\n",
    5415             :                           nt_errstr(status)));
    5416           0 :                 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
    5417           0 :                 goto out;
    5418             :         }
    5419           0 :         b = cli->binding_handle;
    5420             : 
    5421           0 :         info_ctr.level = 1;
    5422           0 :         info_ctr.ctr.ctr1 = talloc_zero(talloc_tos(), struct srvsvc_NetSessCtr1);
    5423           0 :         if (info_ctr.ctr.ctr1 == NULL) {
    5424           0 :                 desc.errcode = W_ERROR_V(WERR_NOT_ENOUGH_MEMORY);
    5425           0 :                 goto out;
    5426             :         }
    5427             : 
    5428           0 :         status = dcerpc_srvsvc_NetSessEnum(b, mem_ctx,
    5429           0 :                                            cli->srv_name_slash,
    5430             :                                            NULL, /* client */
    5431             :                                            NULL, /* user */
    5432             :                                            &info_ctr,
    5433             :                                            (uint32_t)-1, /* max_buffer */
    5434             :                                            &totalentries,
    5435             :                                            &resume_handle,
    5436             :                                            &werr);
    5437           0 :         if (!NT_STATUS_IS_OK(status)) {
    5438           0 :                 DEBUG(0,("RNetSessionEnum: dcerpc_srvsvc_NetSessEnum failed: %s\n",
    5439             :                           nt_errstr(status)));
    5440           0 :                 desc.errcode = W_ERROR_V(ntstatus_to_werror(status));
    5441           0 :                 goto out;
    5442             :         }
    5443             : 
    5444           0 :         if (!W_ERROR_IS_OK(werr)) {
    5445           0 :                 DEBUG(0,("RNetSessionEnum: dcerpc_srvsvc_NetSessEnum failed: %s\n",
    5446             :                           win_errstr(werr)));
    5447           0 :                 desc.errcode = W_ERROR_V(werr);
    5448           0 :                 goto out;
    5449             :         }
    5450             : 
    5451           0 :         count = info_ctr.ctr.ctr1->count;
    5452             : 
    5453           0 :  out:
    5454           0 :         if (mdrcnt > 0) {
    5455           0 :                 *rdata = smb_realloc_limit(*rdata,mdrcnt);
    5456           0 :                 if (!*rdata) {
    5457           0 :                         return False;
    5458             :                 }
    5459             :         }
    5460             : 
    5461           0 :         desc.base = *rdata;
    5462           0 :         desc.buflen = mdrcnt;
    5463           0 :         desc.format = str2;
    5464           0 :         if (!init_package(&desc, count,0)) {
    5465           0 :                 return False;
    5466             :         }
    5467             : 
    5468           0 :         for(i=0; i < count; i++) {
    5469           0 :                 PACKS(&desc, "z", info_ctr.ctr.ctr1->array[i].client);
    5470           0 :                 PACKS(&desc, "z", info_ctr.ctr.ctr1->array[i].user);
    5471           0 :                 PACKI(&desc, "W", 1); /* num conns */
    5472           0 :                 PACKI(&desc, "W", info_ctr.ctr.ctr1->array[i].num_open);
    5473           0 :                 PACKI(&desc, "W", 1); /* num users */
    5474           0 :                 PACKI(&desc, "D", 0); /* session time */
    5475           0 :                 PACKI(&desc, "D", 0); /* idle time */
    5476           0 :                 PACKI(&desc, "D", 0); /* flags */
    5477           0 :                 PACKS(&desc, "z", "Unknown Client"); /* client type string */
    5478             :         }
    5479             : 
    5480           0 :         *rdata_len = desc.usedlen;
    5481             : 
    5482           0 :         *rparam_len = 8;
    5483           0 :         *rparam = smb_realloc_limit(*rparam,*rparam_len);
    5484           0 :         if (!*rparam) {
    5485           0 :                 return False;
    5486             :         }
    5487           0 :         SSVALS(*rparam,0,desc.errcode);
    5488           0 :         SSVAL(*rparam,2,0); /* converter */
    5489           0 :         SSVAL(*rparam,4, count); /* count */
    5490             : 
    5491           0 :         DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc.errcode));
    5492             : 
    5493           0 :         return True;
    5494             : }
    5495             : 
    5496             : 
    5497             : /****************************************************************************
    5498             :  The buffer was too small.
    5499             :  ****************************************************************************/
    5500             : 
    5501           0 : static bool api_TooSmall(struct smbd_server_connection *sconn,
    5502             :                          connection_struct *conn,uint64_t vuid, char *param, char *data,
    5503             :                          int mdrcnt, int mprcnt,
    5504             :                          char **rdata, char **rparam,
    5505             :                          int *rdata_len, int *rparam_len)
    5506             : {
    5507           0 :         *rparam_len = MIN(*rparam_len,mprcnt);
    5508           0 :         *rparam = smb_realloc_limit(*rparam,*rparam_len);
    5509           0 :         if (!*rparam) {
    5510           0 :                 return False;
    5511             :         }
    5512             : 
    5513           0 :         *rdata_len = 0;
    5514             : 
    5515           0 :         SSVAL(*rparam,0,NERR_BufTooSmall);
    5516             : 
    5517           0 :         DEBUG(3,("Supplied buffer too small in API command\n"));
    5518             : 
    5519           0 :         return True;
    5520             : }
    5521             : 
    5522             : /****************************************************************************
    5523             :  The request is not supported.
    5524             :  ****************************************************************************/
    5525             : 
    5526           0 : static bool api_Unsupported(struct smbd_server_connection *sconn,
    5527             :                             connection_struct *conn, uint64_t vuid,
    5528             :                                 char *param, int tpscnt,
    5529             :                                 char *data, int tdscnt,
    5530             :                                 int mdrcnt, int mprcnt,
    5531             :                                 char **rdata, char **rparam,
    5532             :                                 int *rdata_len, int *rparam_len)
    5533             : {
    5534           0 :         *rparam_len = 4;
    5535           0 :         *rparam = smb_realloc_limit(*rparam,*rparam_len);
    5536           0 :         if (!*rparam) {
    5537           0 :                 return False;
    5538             :         }
    5539             : 
    5540           0 :         *rdata_len = 0;
    5541             : 
    5542           0 :         SSVAL(*rparam,0,NERR_notsupported);
    5543           0 :         SSVAL(*rparam,2,0);             /* converter word */
    5544             : 
    5545           0 :         DEBUG(3,("Unsupported API command\n"));
    5546             : 
    5547           0 :         return True;
    5548             : }
    5549             : 
    5550             : static const struct {
    5551             :         const char *name;
    5552             :         int id;
    5553             :         bool (*fn)(struct smbd_server_connection *sconn,
    5554             :                    connection_struct *, uint64_t,
    5555             :                         char *, int,
    5556             :                         char *, int,
    5557             :                         int,int,char **,char **,int *,int *);
    5558             :         bool auth_user;         /* Deny anonymous access? */
    5559             : } api_commands[] = {
    5560             :         {
    5561             :                 .name = "RNetShareEnum",
    5562             :                 .id = RAP_WshareEnum,
    5563             :                 .fn = api_RNetShareEnum,
    5564             :                 .auth_user = true,
    5565             :         },
    5566             :         {
    5567             :                 .name = "RNetShareGetInfo",
    5568             :                 .id = RAP_WshareGetInfo,
    5569             :                 .fn = api_RNetShareGetInfo
    5570             :         },
    5571             :         {
    5572             :                 .name = "RNetShareAdd",
    5573             :                 .id = RAP_WshareAdd,
    5574             :                 .fn = api_RNetShareAdd
    5575             :         },
    5576             :         {
    5577             :                 .name = "RNetSessionEnum",
    5578             :                 .id = RAP_WsessionEnum,
    5579             :                 .fn = api_RNetSessionEnum,
    5580             :                 .auth_user = true,
    5581             :         },
    5582             :         {
    5583             :                 .name = "RNetServerGetInfo",
    5584             :                 .id = RAP_WserverGetInfo,
    5585             :                 .fn = api_RNetServerGetInfo
    5586             :         },
    5587             :         {
    5588             :                 .name = "RNetGroupEnum",
    5589             :                 .id = RAP_WGroupEnum,
    5590             :                 .fn = api_RNetGroupEnum, True
    5591             :         },
    5592             :         {
    5593             :                 .name = "RNetGroupGetUsers",
    5594             :                 .id = RAP_WGroupGetUsers,
    5595             :                 .fn = api_RNetGroupGetUsers,
    5596             :                 .auth_user = true},
    5597             :         {
    5598             :                 .name = "RNetUserEnum",
    5599             :                 .id = RAP_WUserEnum,
    5600             :                 .fn = api_RNetUserEnum,
    5601             :                 .auth_user = true,
    5602             :         },
    5603             :         {
    5604             :                 .name = "RNetUserGetInfo",
    5605             :                 .id = RAP_WUserGetInfo,
    5606             :                 .fn = api_RNetUserGetInfo
    5607             :         },
    5608             :         {
    5609             :                 .name = "NetUserGetGroups",
    5610             :                 .id = RAP_WUserGetGroups,
    5611             :                 .fn = api_NetUserGetGroups
    5612             :         },
    5613             :         {
    5614             :                 .name = "NetWkstaGetInfo",
    5615             :                 .id = RAP_WWkstaGetInfo,
    5616             :                 .fn = api_NetWkstaGetInfo
    5617             :         },
    5618             :         {
    5619             :                 .name = "DosPrintQEnum",
    5620             :                 .id = RAP_WPrintQEnum,
    5621             :                 .fn = api_DosPrintQEnum,
    5622             :                 .auth_user = true,
    5623             :         },
    5624             :         {
    5625             :                 .name = "DosPrintQGetInfo",
    5626             :                 .id = RAP_WPrintQGetInfo,
    5627             :                 .fn = api_DosPrintQGetInfo
    5628             :         },
    5629             :         {
    5630             :                 .name = "WPrintQueuePause",
    5631             :                 .id = RAP_WPrintQPause,
    5632             :                 .fn = api_WPrintQueueCtrl
    5633             :         },
    5634             :         {
    5635             :                 .name = "WPrintQueueResume",
    5636             :                 .id = RAP_WPrintQContinue,
    5637             :                 .fn = api_WPrintQueueCtrl
    5638             :         },
    5639             :         {
    5640             :                 .name = "WPrintJobEnumerate",
    5641             :                 .id = RAP_WPrintJobEnum,
    5642             :                 .fn = api_WPrintJobEnumerate
    5643             :         },
    5644             :         {
    5645             :                 .name = "WPrintJobGetInfo",
    5646             :                 .id = RAP_WPrintJobGetInfo,
    5647             :                 .fn = api_WPrintJobGetInfo
    5648             :         },
    5649             :         {
    5650             :                 .name = "RDosPrintJobDel",
    5651             :                 .id = RAP_WPrintJobDel,
    5652             :                 .fn = api_RDosPrintJobDel
    5653             :         },
    5654             :         {
    5655             :                 .name = "RDosPrintJobPause",
    5656             :                 .id = RAP_WPrintJobPause,
    5657             :                 .fn = api_RDosPrintJobDel
    5658             :         },
    5659             :         {
    5660             :                 .name = "RDosPrintJobResume",
    5661             :                 .id = RAP_WPrintJobContinue,
    5662             :                 .fn = api_RDosPrintJobDel
    5663             :         },
    5664             :         {
    5665             :                 .name = "WPrintDestEnum",
    5666             :                 .id = RAP_WPrintDestEnum,
    5667             :                 .fn = api_WPrintDestEnum
    5668             :         },
    5669             :         {
    5670             :                 .name = "WPrintDestGetInfo",
    5671             :                 .id = RAP_WPrintDestGetInfo,
    5672             :                 .fn = api_WPrintDestGetInfo
    5673             :         },
    5674             :         {
    5675             :                 .name = "NetRemoteTOD",
    5676             :                 .id = RAP_NetRemoteTOD,
    5677             :                 .fn = api_NetRemoteTOD
    5678             :         },
    5679             :         {
    5680             :                 .name = "WPrintQueuePurge",
    5681             :                 .id = RAP_WPrintQPurge,
    5682             :                 .fn = api_WPrintQueueCtrl
    5683             :         },
    5684             :         {
    5685             :                 .name = "NetServerEnum2",
    5686             :                 .id = RAP_NetServerEnum2,
    5687             :                 .fn = api_RNetServerEnum2
    5688             :         }, /* anon OK */
    5689             :         {
    5690             :                 .name = "NetServerEnum3",
    5691             :                 .id = RAP_NetServerEnum3,
    5692             :                 .fn = api_RNetServerEnum3
    5693             :         }, /* anon OK */
    5694             :         {
    5695             :                 .name = "WAccessGetUserPerms",
    5696             :                 .id = RAP_WAccessGetUserPerms,
    5697             :                 .fn = api_WAccessGetUserPerms
    5698             :         },
    5699             :         {
    5700             :                 .name = "WWkstaUserLogon",
    5701             :                 .id = RAP_WWkstaUserLogon,
    5702             :                 .fn = api_WWkstaUserLogon
    5703             :         },
    5704             :         {
    5705             :                 .name = "PrintJobInfo",
    5706             :                 .id = RAP_WPrintJobSetInfo,
    5707             :                 .fn = api_PrintJobInfo
    5708             :         },
    5709             :         {
    5710             :                 .name = "WPrintDriverEnum",
    5711             :                 .id = RAP_WPrintDriverEnum,
    5712             :                 .fn = api_WPrintDriverEnum
    5713             :         },
    5714             :         {
    5715             :                 .name = "WPrintQProcEnum",
    5716             :                 .id = RAP_WPrintQProcessorEnum,
    5717             :                 .fn = api_WPrintQProcEnum
    5718             :         },
    5719             :         {
    5720             :                 .name = "WPrintPortEnum",
    5721             :                 .id = RAP_WPrintPortEnum,
    5722             :                 .fn = api_WPrintPortEnum
    5723             :         },
    5724             :         {
    5725             :                 .name = "SamOEMChangePassword",
    5726             :                 .id = RAP_SamOEMChgPasswordUser2_P,
    5727             :                 .fn = api_SamOEMChangePassword
    5728             :         }, /* anon OK */
    5729             :         {
    5730             :                 .name = NULL,
    5731             :                 .id   = -1,
    5732             :                 .fn   = api_Unsupported}
    5733             :         /*
    5734             :          * The following RAP calls are not implemented by Samba:
    5735             :          *   RAP_WFileEnum2 - anon not OK
    5736             :          */
    5737             : };
    5738             : 
    5739             : 
    5740             : /****************************************************************************
    5741             :  Handle remote api calls.
    5742             : ****************************************************************************/
    5743             : 
    5744           4 : void api_reply(connection_struct *conn, uint64_t vuid,
    5745             :                struct smb_request *req,
    5746             :                char *data, char *params,
    5747             :                int tdscnt, int tpscnt,
    5748             :                int mdrcnt, int mprcnt)
    5749             : {
    5750             :         int api_command;
    5751           4 :         char *rdata = NULL;
    5752           4 :         char *rparam = NULL;
    5753           4 :         const char *name1 = NULL;
    5754           4 :         const char *name2 = NULL;
    5755           4 :         int rdata_len = 0;
    5756           4 :         int rparam_len = 0;
    5757           4 :         bool reply=False;
    5758             :         int i;
    5759             : 
    5760           4 :         if (!params) {
    5761           0 :                 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
    5762           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    5763           0 :                 return;
    5764             :         }
    5765             : 
    5766           4 :         if (tpscnt < 2) {
    5767           0 :                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
    5768           0 :                 return;
    5769             :         }
    5770           4 :         api_command = SVAL(params,0);
    5771             :         /* Is there a string at position params+2 ? */
    5772           4 :         if (skip_string(params,tpscnt,params+2)) {
    5773           4 :                 name1 = params + 2;
    5774             :         } else {
    5775           0 :                 name1 = "";
    5776             :         }
    5777           4 :         name2 = skip_string(params,tpscnt,params+2);
    5778           4 :         if (!name2) {
    5779           0 :                 name2 = "";
    5780             :         }
    5781             : 
    5782           4 :         DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
    5783             :                 api_command,
    5784             :                 name1,
    5785             :                 name2,
    5786             :                 tdscnt,tpscnt,mdrcnt,mprcnt));
    5787             : 
    5788         100 :         for (i=0;api_commands[i].name;i++) {
    5789         100 :                 if (api_commands[i].id == api_command && api_commands[i].fn) {
    5790           4 :                         DEBUG(3,("Doing %s\n",api_commands[i].name));
    5791           4 :                         break;
    5792             :                 }
    5793             :         }
    5794             : 
    5795             :         /* Check whether this api call can be done anonymously */
    5796             : 
    5797           4 :         if (api_commands[i].auth_user && lp_restrict_anonymous()) {
    5798           0 :                 struct auth_session_info *si = NULL;
    5799             :                 NTSTATUS status;
    5800             : 
    5801           0 :                 status = smbXsrv_session_info_lookup(conn->sconn->client,
    5802             :                                                      vuid,
    5803             :                                                      &si);
    5804           0 :                 if (!NT_STATUS_IS_OK(status)) {
    5805           0 :                         reply_nterror(req, NT_STATUS_ACCESS_DENIED);
    5806           0 :                         return;
    5807             :                 }
    5808             : 
    5809           0 :                 if (security_session_user_level(si, NULL) < SECURITY_USER) {
    5810           0 :                         reply_nterror(req, NT_STATUS_ACCESS_DENIED);
    5811           0 :                         return;
    5812             :                 }
    5813             :         }
    5814             : 
    5815           4 :         rdata = (char *)SMB_MALLOC(1024);
    5816           4 :         if (rdata) {
    5817           4 :                 memset(rdata,'\0',1024);
    5818             :         }
    5819             : 
    5820           4 :         rparam = (char *)SMB_MALLOC(1024);
    5821           4 :         if (rparam) {
    5822           4 :                 memset(rparam,'\0',1024);
    5823             :         }
    5824             : 
    5825           4 :         if(!rdata || !rparam) {
    5826           0 :                 DEBUG(0,("api_reply: malloc fail !\n"));
    5827           0 :                 SAFE_FREE(rdata);
    5828           0 :                 SAFE_FREE(rparam);
    5829           0 :                 reply_nterror(req, NT_STATUS_NO_MEMORY);
    5830           0 :                 return;
    5831             :         }
    5832             : 
    5833           4 :         reply = api_commands[i].fn(req->sconn, conn,
    5834             :                                 vuid,
    5835             :                                 params,tpscnt,  /* params + length */
    5836             :                                 data,tdscnt,    /* data + length */
    5837             :                                 mdrcnt,mprcnt,
    5838             :                                 &rdata,&rparam,&rdata_len,&rparam_len);
    5839             : 
    5840             : 
    5841           4 :         if (rdata_len > mdrcnt || rparam_len > mprcnt) {
    5842           0 :                 reply = api_TooSmall(req->sconn,conn,vuid,params,data,
    5843             :                                      mdrcnt,mprcnt,
    5844             :                                         &rdata,&rparam,&rdata_len,&rparam_len);
    5845             :         }
    5846             : 
    5847             :         /* if we get False back then it's actually unsupported */
    5848           4 :         if (!reply) {
    5849           0 :                 reply = api_Unsupported(req->sconn,conn,vuid,params,tpscnt,
    5850             :                                         data,
    5851             :                                         tdscnt,mdrcnt,mprcnt,
    5852             :                         &rdata,&rparam,&rdata_len,&rparam_len);
    5853             :         }
    5854             : 
    5855             :         /* If api_Unsupported returns false we can't return anything. */
    5856           4 :         if (reply) {
    5857           4 :                 send_trans_reply(conn, req, rparam, rparam_len,
    5858             :                                  rdata, rdata_len, False);
    5859             :         }
    5860             : 
    5861           4 :         SAFE_FREE(rdata);
    5862           4 :         SAFE_FREE(rparam);
    5863           4 :         return;
    5864             : }

Generated by: LCOV version 1.13