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