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