LCOV - code coverage report
Current view: top level - source3/smbd - lanman.c (source / functions) Hit Total Coverage
Test: coverage report for master 6248eab5 Lines: 841 2929 28.7 %
Date: 2021-08-25 13:27:56 Functions: 25 67 37.3 %

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

Generated by: LCOV version 1.13