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