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