Coverage Report

Created: 2025-12-31 06:20

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