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