LCOV - code coverage report
Current view: top level - source3/smbd - smb1_lanman.c (source / functions) Hit Total Coverage
Test: coverage report for master 7edf5467 Lines: 850 3158 26.9 %
Date: 2024-03-23 18:40:31 Functions: 28 65 43.1 %

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

Generated by: LCOV version 1.14