source: branches/samba-3.3.x/source/smbd/lanman.c@ 221

Last change on this file since 221 was 206, checked in by Herwig Bauernfeind, 16 years ago

Import Samba 3.3 branch at 3.0.0 level (psmedley's port)

File size: 113.1 KB
Line 
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
30#ifdef CHECK_TYPES
31#undef CHECK_TYPES
32#endif
33#define CHECK_TYPES 0
34
35#define NERR_Success 0
36#define NERR_badpass 86
37#define NERR_notsupported 50
38
39#define NERR_BASE (2100)
40#define NERR_BufTooSmall (NERR_BASE+23)
41#define NERR_JobNotFound (NERR_BASE+51)
42#define NERR_DestNotFound (NERR_BASE+52)
43
44#define ACCESS_READ 0x01
45#define ACCESS_WRITE 0x02
46#define ACCESS_CREATE 0x04
47
48#define SHPWLEN 8 /* share password length */
49
50/* Limit size of ipc replies */
51
52static char *smb_realloc_limit(void *ptr, size_t size)
53{
54 char *val;
55
56 size = MAX((size),4*1024);
57 val = (char *)SMB_REALLOC(ptr,size);
58 if (val) {
59 memset(val,'\0',size);
60 }
61 return val;
62}
63
64static bool api_Unsupported(connection_struct *conn, uint16 vuid,
65 char *param, int tpscnt,
66 char *data, int tdscnt,
67 int mdrcnt, int mprcnt,
68 char **rdata, char **rparam,
69 int *rdata_len, int *rparam_len);
70
71static bool api_TooSmall(connection_struct *conn, uint16 vuid, char *param, char *data,
72 int mdrcnt, int mprcnt,
73 char **rdata, char **rparam,
74 int *rdata_len, int *rparam_len);
75
76
77static int CopyExpanded(connection_struct *conn,
78 int snum, char **dst, char *src, int *p_space_remaining)
79{
80 TALLOC_CTX *ctx = talloc_tos();
81 char *buf = NULL;
82 int l;
83
84 if (!src || !dst || !p_space_remaining || !(*dst) ||
85 *p_space_remaining <= 0) {
86 return 0;
87 }
88
89 buf = talloc_strdup(ctx, src);
90 if (!buf) {
91 *p_space_remaining = 0;
92 return 0;
93 }
94 buf = talloc_string_sub(ctx, buf,"%S",lp_servicename(snum));
95 if (!buf) {
96 *p_space_remaining = 0;
97 return 0;
98 }
99 buf = talloc_sub_advanced(ctx,
100 lp_servicename(SNUM(conn)),
101 conn->server_info->unix_name,
102 conn->connectpath,
103 conn->server_info->utok.gid,
104 conn->server_info->sanitized_username,
105 pdb_get_domain(conn->server_info->sam_account),
106 buf);
107 if (!buf) {
108 *p_space_remaining = 0;
109 return 0;
110 }
111 l = push_ascii(*dst,buf,*p_space_remaining, STR_TERMINATE);
112 if (l == -1) {
113 return 0;
114 }
115 (*dst) += l;
116 (*p_space_remaining) -= l;
117 return l;
118}
119
120static int CopyAndAdvance(char **dst, char *src, int *n)
121{
122 int l;
123 if (!src || !dst || !n || !(*dst)) {
124 return 0;
125 }
126 l = push_ascii(*dst,src,*n, STR_TERMINATE);
127 if (l == -1) {
128 return 0;
129 }
130 (*dst) += l;
131 (*n) -= l;
132 return l;
133}
134
135static int StrlenExpanded(connection_struct *conn, int snum, char *s)
136{
137 TALLOC_CTX *ctx = talloc_tos();
138 char *buf = NULL;
139 if (!s) {
140 return 0;
141 }
142 buf = talloc_strdup(ctx,s);
143 if (!buf) {
144 return 0;
145 }
146 buf = talloc_string_sub(ctx,buf,"%S",lp_servicename(snum));
147 if (!buf) {
148 return 0;
149 }
150 buf = talloc_sub_advanced(ctx,
151 lp_servicename(SNUM(conn)),
152 conn->server_info->unix_name,
153 conn->connectpath,
154 conn->server_info->utok.gid,
155 conn->server_info->sanitized_username,
156 pdb_get_domain(conn->server_info->sam_account),
157 buf);
158 if (!buf) {
159 return 0;
160 }
161 return strlen(buf) + 1;
162}
163
164static char *Expand(connection_struct *conn, int snum, char *s)
165{
166 TALLOC_CTX *ctx = talloc_tos();
167 char *buf = NULL;
168
169 if (!s) {
170 return NULL;
171 }
172 buf = talloc_strdup(ctx,s);
173 if (!buf) {
174 return 0;
175 }
176 buf = talloc_string_sub(ctx,buf,"%S",lp_servicename(snum));
177 if (!buf) {
178 return 0;
179 }
180 return talloc_sub_advanced(ctx,
181 lp_servicename(SNUM(conn)),
182 conn->server_info->unix_name,
183 conn->connectpath,
184 conn->server_info->utok.gid,
185 conn->server_info->sanitized_username,
186 pdb_get_domain(conn->server_info->sam_account),
187 buf);
188}
189
190/*******************************************************************
191 Check a API string for validity when we only need to check the prefix.
192******************************************************************/
193
194static bool prefix_ok(const char *str, const char *prefix)
195{
196 return(strncmp(str,prefix,strlen(prefix)) == 0);
197}
198
199struct pack_desc {
200 const char *format; /* formatstring for structure */
201 const char *subformat; /* subformat for structure */
202 char *base; /* baseaddress of buffer */
203 int buflen; /* remaining size for fixed part; on init: length of base */
204 int subcount; /* count of substructures */
205 char *structbuf; /* pointer into buffer for remaining fixed part */
206 int stringlen; /* remaining size for variable part */
207 char *stringbuf; /* pointer into buffer for remaining variable part */
208 int neededlen; /* total needed size */
209 int usedlen; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
210 const char *curpos; /* current position; pointer into format or subformat */
211 int errcode;
212};
213
214static int get_counter(const char **p)
215{
216 int i, n;
217 if (!p || !(*p)) {
218 return 1;
219 }
220 if (!isdigit((int)**p)) {
221 return 1;
222 }
223 for (n = 0;;) {
224 i = **p;
225 if (isdigit(i)) {
226 n = 10 * n + (i - '0');
227 } else {
228 return n;
229 }
230 (*p)++;
231 }
232}
233
234static int getlen(const char *p)
235{
236 int n = 0;
237 if (!p) {
238 return 0;
239 }
240
241 while (*p) {
242 switch( *p++ ) {
243 case 'W': /* word (2 byte) */
244 n += 2;
245 break;
246 case 'K': /* status word? (2 byte) */
247 n += 2;
248 break;
249 case 'N': /* count of substructures (word) at end */
250 n += 2;
251 break;
252 case 'D': /* double word (4 byte) */
253 case 'z': /* offset to zero terminated string (4 byte) */
254 case 'l': /* offset to user data (4 byte) */
255 n += 4;
256 break;
257 case 'b': /* offset to data (with counter) (4 byte) */
258 n += 4;
259 get_counter(&p);
260 break;
261 case 'B': /* byte (with optional counter) */
262 n += get_counter(&p);
263 break;
264 }
265 }
266 return n;
267}
268
269static bool init_package(struct pack_desc *p, int count, int subcount)
270{
271 int n = p->buflen;
272 int i;
273
274 if (!p->format || !p->base) {
275 return False;
276 }
277
278 i = count * getlen(p->format);
279 if (p->subformat) {
280 i += subcount * getlen(p->subformat);
281 }
282 p->structbuf = p->base;
283 p->neededlen = 0;
284 p->usedlen = 0;
285 p->subcount = 0;
286 p->curpos = p->format;
287 if (i > n) {
288 p->neededlen = i;
289 i = n = 0;
290#if 0
291 /*
292 * This is the old error code we used. Aparently
293 * WinNT/2k systems return ERRbuftoosmall (2123) and
294 * OS/2 needs this. I'm leaving this here so we can revert
295 * if needed. JRA.
296 */
297 p->errcode = ERRmoredata;
298#else
299 p->errcode = ERRbuftoosmall;
300#endif
301 } else {
302 p->errcode = NERR_Success;
303 }
304 p->buflen = i;
305 n -= i;
306 p->stringbuf = p->base + i;
307 p->stringlen = n;
308 return (p->errcode == NERR_Success);
309}
310
311static int package(struct pack_desc *p, ...)
312{
313 va_list args;
314 int needed=0, stringneeded;
315 const char *str=NULL;
316 int is_string=0, stringused;
317 int32 temp;
318
319 va_start(args,p);
320
321 if (!*p->curpos) {
322 if (!p->subcount) {
323 p->curpos = p->format;
324 } else {
325 p->curpos = p->subformat;
326 p->subcount--;
327 }
328 }
329#if CHECK_TYPES
330 str = va_arg(args,char*);
331 SMB_ASSERT(strncmp(str,p->curpos,strlen(str)) == 0);
332#endif
333 stringneeded = -1;
334
335 if (!p->curpos) {
336 va_end(args);
337 return 0;
338 }
339
340 switch( *p->curpos++ ) {
341 case 'W': /* word (2 byte) */
342 needed = 2;
343 temp = va_arg(args,int);
344 if (p->buflen >= needed) {
345 SSVAL(p->structbuf,0,temp);
346 }
347 break;
348 case 'K': /* status word? (2 byte) */
349 needed = 2;
350 temp = va_arg(args,int);
351 if (p->buflen >= needed) {
352 SSVAL(p->structbuf,0,temp);
353 }
354 break;
355 case 'N': /* count of substructures (word) at end */
356 needed = 2;
357 p->subcount = va_arg(args,int);
358 if (p->buflen >= needed) {
359 SSVAL(p->structbuf,0,p->subcount);
360 }
361 break;
362 case 'D': /* double word (4 byte) */
363 needed = 4;
364 temp = va_arg(args,int);
365 if (p->buflen >= needed) {
366 SIVAL(p->structbuf,0,temp);
367 }
368 break;
369 case 'B': /* byte (with optional counter) */
370 needed = get_counter(&p->curpos);
371 {
372 char *s = va_arg(args,char*);
373 if (p->buflen >= needed) {
374 StrnCpy(p->structbuf,s?s:"",needed-1);
375 }
376 }
377 break;
378 case 'z': /* offset to zero terminated string (4 byte) */
379 str = va_arg(args,char*);
380 stringneeded = (str ? strlen(str)+1 : 0);
381 is_string = 1;
382 break;
383 case 'l': /* offset to user data (4 byte) */
384 str = va_arg(args,char*);
385 stringneeded = va_arg(args,int);
386 is_string = 0;
387 break;
388 case 'b': /* offset to data (with counter) (4 byte) */
389 str = va_arg(args,char*);
390 stringneeded = get_counter(&p->curpos);
391 is_string = 0;
392 break;
393 }
394
395 va_end(args);
396 if (stringneeded >= 0) {
397 needed = 4;
398 if (p->buflen >= needed) {
399 stringused = stringneeded;
400 if (stringused > p->stringlen) {
401 stringused = (is_string ? p->stringlen : 0);
402 if (p->errcode == NERR_Success) {
403 p->errcode = ERRmoredata;
404 }
405 }
406 if (!stringused) {
407 SIVAL(p->structbuf,0,0);
408 } else {
409 SIVAL(p->structbuf,0,PTR_DIFF(p->stringbuf,p->base));
410 memcpy(p->stringbuf,str?str:"",stringused);
411 if (is_string) {
412 p->stringbuf[stringused-1] = '\0';
413 }
414 p->stringbuf += stringused;
415 p->stringlen -= stringused;
416 p->usedlen += stringused;
417 }
418 }
419 p->neededlen += stringneeded;
420 }
421
422 p->neededlen += needed;
423 if (p->buflen >= needed) {
424 p->structbuf += needed;
425 p->buflen -= needed;
426 p->usedlen += needed;
427 } else {
428 if (p->errcode == NERR_Success) {
429 p->errcode = ERRmoredata;
430 }
431 }
432 return 1;
433}
434
435#if CHECK_TYPES
436#define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
437#define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
438#else
439#define PACK(desc,t,v) package(desc,v)
440#define PACKl(desc,t,v,l) package(desc,v,l)
441#endif
442
443static void PACKI(struct pack_desc* desc, const char *t,int v)
444{
445 PACK(desc,t,v);
446}
447
448static void PACKS(struct pack_desc* desc,const char *t,const char *v)
449{
450 PACK(desc,t,v);
451}
452
453/****************************************************************************
454 Get a print queue.
455****************************************************************************/
456
457static void PackDriverData(struct pack_desc* desc)
458{
459 char drivdata[4+4+32];
460 SIVAL(drivdata,0,sizeof drivdata); /* cb */
461 SIVAL(drivdata,4,1000); /* lVersion */
462 memset(drivdata+8,0,32); /* szDeviceName */
463 push_ascii(drivdata+8,"NULL",32, STR_TERMINATE);
464 PACKl(desc,"l",drivdata,sizeof drivdata); /* pDriverData */
465}
466
467static int check_printq_info(struct pack_desc* desc,
468 unsigned int uLevel, char *id1, char *id2)
469{
470 desc->subformat = NULL;
471 switch( uLevel ) {
472 case 0:
473 desc->format = "B13";
474 break;
475 case 1:
476 desc->format = "B13BWWWzzzzzWW";
477 break;
478 case 2:
479 desc->format = "B13BWWWzzzzzWN";
480 desc->subformat = "WB21BB16B10zWWzDDz";
481 break;
482 case 3:
483 desc->format = "zWWWWzzzzWWzzl";
484 break;
485 case 4:
486 desc->format = "zWWWWzzzzWNzzl";
487 desc->subformat = "WWzWWDDzz";
488 break;
489 case 5:
490 desc->format = "z";
491 break;
492 case 51:
493 desc->format = "K";
494 break;
495 case 52:
496 desc->format = "WzzzzzzzzN";
497 desc->subformat = "z";
498 break;
499 default:
500 DEBUG(0,("check_printq_info: invalid level %d\n",
501 uLevel ));
502 return False;
503 }
504 if (id1 == NULL || strcmp(desc->format,id1) != 0) {
505 DEBUG(0,("check_printq_info: invalid format %s\n",
506 id1 ? id1 : "<NULL>" ));
507 return False;
508 }
509 if (desc->subformat && (id2 == NULL || strcmp(desc->subformat,id2) != 0)) {
510 DEBUG(0,("check_printq_info: invalid subformat %s\n",
511 id2 ? id2 : "<NULL>" ));
512 return False;
513 }
514 return True;
515}
516
517
518#define RAP_JOB_STATUS_QUEUED 0
519#define RAP_JOB_STATUS_PAUSED 1
520#define RAP_JOB_STATUS_SPOOLING 2
521#define RAP_JOB_STATUS_PRINTING 3
522#define RAP_JOB_STATUS_PRINTED 4
523
524#define RAP_QUEUE_STATUS_PAUSED 1
525#define RAP_QUEUE_STATUS_ERROR 2
526
527/* turn a print job status into a on the wire status
528*/
529static int printj_status(int v)
530{
531 switch (v) {
532 case LPQ_QUEUED:
533 return RAP_JOB_STATUS_QUEUED;
534 case LPQ_PAUSED:
535 return RAP_JOB_STATUS_PAUSED;
536 case LPQ_SPOOLING:
537 return RAP_JOB_STATUS_SPOOLING;
538 case LPQ_PRINTING:
539 return RAP_JOB_STATUS_PRINTING;
540 }
541 return 0;
542}
543
544/* turn a print queue status into a on the wire status
545*/
546static int printq_status(int v)
547{
548 switch (v) {
549 case LPQ_QUEUED:
550 return 0;
551 case LPQ_PAUSED:
552 return RAP_QUEUE_STATUS_PAUSED;
553 }
554 return RAP_QUEUE_STATUS_ERROR;
555}
556
557static void fill_printjob_info(connection_struct *conn, int snum, int uLevel,
558 struct pack_desc *desc,
559 print_queue_struct *queue, int n)
560{
561 time_t t = queue->time;
562
563 /* the client expects localtime */
564 t -= get_time_zone(t);
565
566 PACKI(desc,"W",pjobid_to_rap(lp_const_servicename(snum),queue->job)); /* uJobId */
567 if (uLevel == 1) {
568 PACKS(desc,"B21",queue->fs_user); /* szUserName */
569 PACKS(desc,"B",""); /* pad */
570 PACKS(desc,"B16",""); /* szNotifyName */
571 PACKS(desc,"B10","PM_Q_RAW"); /* szDataType */
572 PACKS(desc,"z",""); /* pszParms */
573 PACKI(desc,"W",n+1); /* uPosition */
574 PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */
575 PACKS(desc,"z",""); /* pszStatus */
576 PACKI(desc,"D",t); /* ulSubmitted */
577 PACKI(desc,"D",queue->size); /* ulSize */
578 PACKS(desc,"z",queue->fs_file); /* pszComment */
579 }
580 if (uLevel == 2 || uLevel == 3 || uLevel == 4) {
581 PACKI(desc,"W",queue->priority); /* uPriority */
582 PACKS(desc,"z",queue->fs_user); /* pszUserName */
583 PACKI(desc,"W",n+1); /* uPosition */
584 PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */
585 PACKI(desc,"D",t); /* ulSubmitted */
586 PACKI(desc,"D",queue->size); /* ulSize */
587 PACKS(desc,"z","Samba"); /* pszComment */
588 PACKS(desc,"z",queue->fs_file); /* pszDocument */
589 if (uLevel == 3) {
590 PACKS(desc,"z",""); /* pszNotifyName */
591 PACKS(desc,"z","PM_Q_RAW"); /* pszDataType */
592 PACKS(desc,"z",""); /* pszParms */
593 PACKS(desc,"z",""); /* pszStatus */
594 PACKS(desc,"z",SERVICE(snum)); /* pszQueue */
595 PACKS(desc,"z","lpd"); /* pszQProcName */
596 PACKS(desc,"z",""); /* pszQProcParms */
597 PACKS(desc,"z","NULL"); /* pszDriverName */
598 PackDriverData(desc); /* pDriverData */
599 PACKS(desc,"z",""); /* pszPrinterName */
600 } else if (uLevel == 4) { /* OS2 */
601 PACKS(desc,"z",""); /* pszSpoolFileName */
602 PACKS(desc,"z",""); /* pszPortName */
603 PACKS(desc,"z",""); /* pszStatus */
604 PACKI(desc,"D",0); /* ulPagesSpooled */
605 PACKI(desc,"D",0); /* ulPagesSent */
606 PACKI(desc,"D",0); /* ulPagesPrinted */
607 PACKI(desc,"D",0); /* ulTimePrinted */
608 PACKI(desc,"D",0); /* ulExtendJobStatus */
609 PACKI(desc,"D",0); /* ulStartPage */
610 PACKI(desc,"D",0); /* ulEndPage */
611 }
612 }
613}
614
615/********************************************************************
616 Return a driver name given an snum.
617 Returns True if from tdb, False otherwise.
618 ********************************************************************/
619
620static bool get_driver_name(int snum, char **pp_drivername)
621{
622 NT_PRINTER_INFO_LEVEL *info = NULL;
623 bool in_tdb = false;
624
625 get_a_printer (NULL, &info, 2, lp_servicename(snum));
626 if (info != NULL) {
627 *pp_drivername = talloc_strdup(talloc_tos(),
628 info->info_2->drivername);
629 in_tdb = true;
630 free_a_printer(&info, 2);
631 if (!*pp_drivername) {
632 return false;
633 }
634 }
635
636 return in_tdb;
637}
638
639/********************************************************************
640 Respond to the DosPrintQInfo command with a level of 52
641 This is used to get printer driver information for Win9x clients
642 ********************************************************************/
643static void fill_printq_info_52(connection_struct *conn, int snum,
644 struct pack_desc* desc, int count )
645{
646 int i;
647 fstring location;
648 NT_PRINTER_DRIVER_INFO_LEVEL driver;
649 NT_PRINTER_INFO_LEVEL *printer = NULL;
650
651 ZERO_STRUCT(driver);
652
653 if ( !W_ERROR_IS_OK(get_a_printer( NULL, &printer, 2, lp_servicename(snum))) ) {
654 DEBUG(3,("fill_printq_info_52: Failed to lookup printer [%s]\n",
655 lp_servicename(snum)));
656 goto err;
657 }
658
659 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername,
660 "Windows 4.0", 0)) )
661 {
662 DEBUG(3,("fill_printq_info_52: Failed to lookup driver [%s]\n",
663 printer->info_2->drivername));
664 goto err;
665 }
666
667 trim_string(driver.info_3->driverpath, "\\print$\\WIN40\\0\\", 0);
668 trim_string(driver.info_3->datafile, "\\print$\\WIN40\\0\\", 0);
669 trim_string(driver.info_3->helpfile, "\\print$\\WIN40\\0\\", 0);
670
671 PACKI(desc, "W", 0x0400); /* don't know */
672 PACKS(desc, "z", driver.info_3->name); /* long printer name */
673 PACKS(desc, "z", driver.info_3->driverpath); /* Driverfile Name */
674 PACKS(desc, "z", driver.info_3->datafile); /* Datafile name */
675 PACKS(desc, "z", driver.info_3->monitorname); /* language monitor */
676
677 fstrcpy(location, "\\\\%L\\print$\\WIN40\\0");
678 standard_sub_basic( "", "", location, sizeof(location)-1 );
679 PACKS(desc,"z", location); /* share to retrieve files */
680
681 PACKS(desc,"z", driver.info_3->defaultdatatype); /* default data type */
682 PACKS(desc,"z", driver.info_3->helpfile); /* helpfile name */
683 PACKS(desc,"z", driver.info_3->driverpath); /* driver name */
684
685 DEBUG(3,("Printer Driver Name: %s:\n",driver.info_3->name));
686 DEBUG(3,("Driver: %s:\n",driver.info_3->driverpath));
687 DEBUG(3,("Data File: %s:\n",driver.info_3->datafile));
688 DEBUG(3,("Language Monitor: %s:\n",driver.info_3->monitorname));
689 DEBUG(3,("Driver Location: %s:\n",location));
690 DEBUG(3,("Data Type: %s:\n",driver.info_3->defaultdatatype));
691 DEBUG(3,("Help File: %s:\n",driver.info_3->helpfile));
692 PACKI(desc,"N",count); /* number of files to copy */
693
694 for ( i=0; i<count && driver.info_3->dependentfiles && *driver.info_3->dependentfiles[i]; i++)
695 {
696 trim_string(driver.info_3->dependentfiles[i], "\\print$\\WIN40\\0\\", 0);
697 PACKS(desc,"z",driver.info_3->dependentfiles[i]); /* driver files to copy */
698 DEBUG(3,("Dependent File: %s:\n",driver.info_3->dependentfiles[i]));
699 }
700
701 /* sanity check */
702 if ( i != count )
703 DEBUG(3,("fill_printq_info_52: file count specified by client [%d] != number of dependent files [%i]\n",
704 count, i));
705
706 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n", SERVICE(snum),i));
707
708 desc->errcode=NERR_Success;
709 goto done;
710
711err:
712 DEBUG(3,("fill_printq_info: Can't supply driver files\n"));
713 desc->errcode=NERR_notsupported;
714
715done:
716 if ( printer )
717 free_a_printer( &printer, 2 );
718
719 if ( driver.info_3 )
720 free_a_printer_driver( driver, 3 );
721}
722
723
724static void fill_printq_info(connection_struct *conn, int snum, int uLevel,
725 struct pack_desc* desc,
726 int count, print_queue_struct* queue,
727 print_status_struct* status)
728{
729 switch (uLevel) {
730 case 1:
731 case 2:
732 PACKS(desc,"B13",SERVICE(snum));
733 break;
734 case 3:
735 case 4:
736 case 5:
737 PACKS(desc,"z",Expand(conn,snum,SERVICE(snum)));
738 break;
739 case 51:
740 PACKI(desc,"K",printq_status(status->status));
741 break;
742 }
743
744 if (uLevel == 1 || uLevel == 2) {
745 PACKS(desc,"B",""); /* alignment */
746 PACKI(desc,"W",5); /* priority */
747 PACKI(desc,"W",0); /* start time */
748 PACKI(desc,"W",0); /* until time */
749 PACKS(desc,"z",""); /* pSepFile */
750 PACKS(desc,"z","lpd"); /* pPrProc */
751 PACKS(desc,"z",SERVICE(snum)); /* pDestinations */
752 PACKS(desc,"z",""); /* pParms */
753 if (snum < 0) {
754 PACKS(desc,"z","UNKNOWN PRINTER");
755 PACKI(desc,"W",LPSTAT_ERROR);
756 }
757 else if (!status || !status->message[0]) {
758 PACKS(desc,"z",Expand(conn,snum,lp_comment(snum)));
759 PACKI(desc,"W",LPSTAT_OK); /* status */
760 } else {
761 PACKS(desc,"z",status->message);
762 PACKI(desc,"W",printq_status(status->status)); /* status */
763 }
764 PACKI(desc,(uLevel == 1 ? "W" : "N"),count);
765 }
766
767 if (uLevel == 3 || uLevel == 4) {
768 char *drivername = NULL;
769
770 PACKI(desc,"W",5); /* uPriority */
771 PACKI(desc,"W",0); /* uStarttime */
772 PACKI(desc,"W",0); /* uUntiltime */
773 PACKI(desc,"W",5); /* pad1 */
774 PACKS(desc,"z",""); /* pszSepFile */
775 PACKS(desc,"z","WinPrint"); /* pszPrProc */
776 PACKS(desc,"z",NULL); /* pszParms */
777 PACKS(desc,"z",NULL); /* pszComment - don't ask.... JRA */
778 /* "don't ask" that it's done this way to fix corrupted
779 Win9X/ME printer comments. */
780 if (!status) {
781 PACKI(desc,"W",LPSTAT_OK); /* fsStatus */
782 } else {
783 PACKI(desc,"W",printq_status(status->status)); /* fsStatus */
784 }
785 PACKI(desc,(uLevel == 3 ? "W" : "N"),count); /* cJobs */
786 PACKS(desc,"z",SERVICE(snum)); /* pszPrinters */
787 get_driver_name(snum,&drivername);
788 if (!drivername) {
789 return;
790 }
791 PACKS(desc,"z",drivername); /* pszDriverName */
792 PackDriverData(desc); /* pDriverData */
793 }
794
795 if (uLevel == 2 || uLevel == 4) {
796 int i;
797 for (i=0;i<count;i++)
798 fill_printjob_info(conn,snum,uLevel == 2 ? 1 : 2,desc,&queue[i],i);
799 }
800
801 if (uLevel==52)
802 fill_printq_info_52( conn, snum, desc, count );
803}
804
805/* This function returns the number of files for a given driver */
806static int get_printerdrivernumber(int snum)
807{
808 int result = 0;
809 NT_PRINTER_DRIVER_INFO_LEVEL driver;
810 NT_PRINTER_INFO_LEVEL *printer = NULL;
811
812 ZERO_STRUCT(driver);
813
814 if ( !W_ERROR_IS_OK(get_a_printer( NULL, &printer, 2, lp_servicename(snum))) ) {
815 DEBUG(3,("get_printerdrivernumber: Failed to lookup printer [%s]\n",
816 lp_servicename(snum)));
817 goto done;
818 }
819
820 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername,
821 "Windows 4.0", 0)) )
822 {
823 DEBUG(3,("get_printerdrivernumber: Failed to lookup driver [%s]\n",
824 printer->info_2->drivername));
825 goto done;
826 }
827
828 /* count the number of files */
829 while ( driver.info_3->dependentfiles && *driver.info_3->dependentfiles[result] )
830 result++;
831 \
832 done:
833 if ( printer )
834 free_a_printer( &printer, 2 );
835
836 if ( driver.info_3 )
837 free_a_printer_driver( driver, 3 );
838
839 return result;
840}
841
842static bool api_DosPrintQGetInfo(connection_struct *conn, uint16 vuid,
843 char *param, int tpscnt,
844 char *data, int tdscnt,
845 int mdrcnt,int mprcnt,
846 char **rdata,char **rparam,
847 int *rdata_len,int *rparam_len)
848{
849 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
850 char *str2 = skip_string(param,tpscnt,str1);
851 char *p = skip_string(param,tpscnt,str2);
852 char *QueueName = p;
853 unsigned int uLevel;
854 int count=0;
855 int snum;
856 char *str3;
857 struct pack_desc desc;
858 print_queue_struct *queue=NULL;
859 print_status_struct status;
860 char* tmpdata=NULL;
861
862 if (!str1 || !str2 || !p) {
863 return False;
864 }
865 memset((char *)&status,'\0',sizeof(status));
866 memset((char *)&desc,'\0',sizeof(desc));
867
868 p = skip_string(param,tpscnt,p);
869 if (!p) {
870 return False;
871 }
872 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
873 str3 = get_safe_str_ptr(param,tpscnt,p,4);
874 /* str3 may be null here and is checked in check_printq_info(). */
875
876 /* remove any trailing username */
877 if ((p = strchr_m(QueueName,'%')))
878 *p = 0;
879
880 DEBUG(3,("api_DosPrintQGetInfo uLevel=%d name=%s\n",uLevel,QueueName));
881
882 /* check it's a supported varient */
883 if (!prefix_ok(str1,"zWrLh"))
884 return False;
885 if (!check_printq_info(&desc,uLevel,str2,str3)) {
886 /*
887 * Patch from Scott Moomaw <scott@bridgewater.edu>
888 * to return the 'invalid info level' error if an
889 * unknown level was requested.
890 */
891 *rdata_len = 0;
892 *rparam_len = 6;
893 *rparam = smb_realloc_limit(*rparam,*rparam_len);
894 if (!*rparam) {
895 return False;
896 }
897 SSVALS(*rparam,0,ERRunknownlevel);
898 SSVAL(*rparam,2,0);
899 SSVAL(*rparam,4,0);
900 return(True);
901 }
902
903 snum = find_service(QueueName);
904 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
905 return False;
906
907 if (uLevel==52) {
908 count = get_printerdrivernumber(snum);
909 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count));
910 } else {
911 count = print_queue_status(snum, &queue,&status);
912 }
913
914 if (mdrcnt > 0) {
915 *rdata = smb_realloc_limit(*rdata,mdrcnt);
916 if (!*rdata) {
917 SAFE_FREE(queue);
918 return False;
919 }
920 desc.base = *rdata;
921 desc.buflen = mdrcnt;
922 } else {
923 /*
924 * Don't return data but need to get correct length
925 * init_package will return wrong size if buflen=0
926 */
927 desc.buflen = getlen(desc.format);
928 desc.base = tmpdata = (char *) SMB_MALLOC (desc.buflen);
929 }
930
931 if (init_package(&desc,1,count)) {
932 desc.subcount = count;
933 fill_printq_info(conn,snum,uLevel,&desc,count,queue,&status);
934 }
935
936 *rdata_len = desc.usedlen;
937
938 /*
939 * We must set the return code to ERRbuftoosmall
940 * in order to support lanman style printing with Win NT/2k
941 * clients --jerry
942 */
943 if (!mdrcnt && lp_disable_spoolss())
944 desc.errcode = ERRbuftoosmall;
945
946 *rdata_len = desc.usedlen;
947 *rparam_len = 6;
948 *rparam = smb_realloc_limit(*rparam,*rparam_len);
949 if (!*rparam) {
950 SAFE_FREE(queue);
951 SAFE_FREE(tmpdata);
952 return False;
953 }
954 SSVALS(*rparam,0,desc.errcode);
955 SSVAL(*rparam,2,0);
956 SSVAL(*rparam,4,desc.neededlen);
957
958 DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode));
959
960 SAFE_FREE(queue);
961 SAFE_FREE(tmpdata);
962
963 return(True);
964}
965
966/****************************************************************************
967 View list of all print jobs on all queues.
968****************************************************************************/
969
970static bool api_DosPrintQEnum(connection_struct *conn, uint16 vuid,
971 char *param, int tpscnt,
972 char *data, int tdscnt,
973 int mdrcnt, int mprcnt,
974 char **rdata, char** rparam,
975 int *rdata_len, int *rparam_len)
976{
977 char *param_format = get_safe_str_ptr(param,tpscnt,param,2);
978 char *output_format1 = skip_string(param,tpscnt,param_format);
979 char *p = skip_string(param,tpscnt,output_format1);
980 unsigned int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
981 char *output_format2 = get_safe_str_ptr(param,tpscnt,p,4);
982 int services = lp_numservices();
983 int i, n;
984 struct pack_desc desc;
985 print_queue_struct **queue = NULL;
986 print_status_struct *status = NULL;
987 int *subcntarr = NULL;
988 int queuecnt = 0, subcnt = 0, succnt = 0;
989
990 if (!param_format || !output_format1 || !p) {
991 return False;
992 }
993
994 memset((char *)&desc,'\0',sizeof(desc));
995
996 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
997
998 if (!prefix_ok(param_format,"WrLeh")) {
999 return False;
1000 }
1001 if (!check_printq_info(&desc,uLevel,output_format1,output_format2)) {
1002 /*
1003 * Patch from Scott Moomaw <scott@bridgewater.edu>
1004 * to return the 'invalid info level' error if an
1005 * unknown level was requested.
1006 */
1007 *rdata_len = 0;
1008 *rparam_len = 6;
1009 *rparam = smb_realloc_limit(*rparam,*rparam_len);
1010 if (!*rparam) {
1011 return False;
1012 }
1013 SSVALS(*rparam,0,ERRunknownlevel);
1014 SSVAL(*rparam,2,0);
1015 SSVAL(*rparam,4,0);
1016 return(True);
1017 }
1018
1019 for (i = 0; i < services; i++) {
1020 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
1021 queuecnt++;
1022 }
1023 }
1024
1025 if((queue = SMB_MALLOC_ARRAY(print_queue_struct*, queuecnt)) == NULL) {
1026 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
1027 goto err;
1028 }
1029 memset(queue,0,queuecnt*sizeof(print_queue_struct*));
1030 if((status = SMB_MALLOC_ARRAY(print_status_struct,queuecnt)) == NULL) {
1031 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
1032 goto err;
1033 }
1034 memset(status,0,queuecnt*sizeof(print_status_struct));
1035 if((subcntarr = SMB_MALLOC_ARRAY(int,queuecnt)) == NULL) {
1036 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
1037 goto err;
1038 }
1039
1040 subcnt = 0;
1041 n = 0;
1042 for (i = 0; i < services; i++) {
1043 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
1044 subcntarr[n] = print_queue_status(i, &queue[n],&status[n]);
1045 subcnt += subcntarr[n];
1046 n++;
1047 }
1048 }
1049
1050 if (mdrcnt > 0) {
1051 *rdata = smb_realloc_limit(*rdata,mdrcnt);
1052 if (!*rdata) {
1053 goto err;
1054 }
1055 }
1056 desc.base = *rdata;
1057 desc.buflen = mdrcnt;
1058
1059 if (init_package(&desc,queuecnt,subcnt)) {
1060 n = 0;
1061 succnt = 0;
1062 for (i = 0; i < services; i++) {
1063 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
1064 fill_printq_info(conn,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]);
1065 n++;
1066 if (desc.errcode == NERR_Success) {
1067 succnt = n;
1068 }
1069 }
1070 }
1071 }
1072
1073 SAFE_FREE(subcntarr);
1074
1075 *rdata_len = desc.usedlen;
1076 *rparam_len = 8;
1077 *rparam = smb_realloc_limit(*rparam,*rparam_len);
1078 if (!*rparam) {
1079 goto err;
1080 }
1081 SSVALS(*rparam,0,desc.errcode);
1082 SSVAL(*rparam,2,0);
1083 SSVAL(*rparam,4,succnt);
1084 SSVAL(*rparam,6,queuecnt);
1085
1086 for (i = 0; i < queuecnt; i++) {
1087 if (queue) {
1088 SAFE_FREE(queue[i]);
1089 }
1090 }
1091
1092 SAFE_FREE(queue);
1093 SAFE_FREE(status);
1094
1095 return True;
1096
1097 err:
1098
1099 SAFE_FREE(subcntarr);
1100 for (i = 0; i < queuecnt; i++) {
1101 if (queue) {
1102 SAFE_FREE(queue[i]);
1103 }
1104 }
1105 SAFE_FREE(queue);
1106 SAFE_FREE(status);
1107
1108 return False;
1109}
1110
1111/****************************************************************************
1112 Get info level for a server list query.
1113****************************************************************************/
1114
1115static bool check_server_info(int uLevel, char* id)
1116{
1117 switch( uLevel ) {
1118 case 0:
1119 if (strcmp(id,"B16") != 0) {
1120 return False;
1121 }
1122 break;
1123 case 1:
1124 if (strcmp(id,"B16BBDz") != 0) {
1125 return False;
1126 }
1127 break;
1128 default:
1129 return False;
1130 }
1131 return True;
1132}
1133
1134struct srv_info_struct {
1135 fstring name;
1136 uint32 type;
1137 fstring comment;
1138 fstring domain;
1139 bool server_added;
1140};
1141
1142/*******************************************************************
1143 Get server info lists from the files saved by nmbd. Return the
1144 number of entries.
1145******************************************************************/
1146
1147static int get_server_info(uint32 servertype,
1148 struct srv_info_struct **servers,
1149 const char *domain)
1150{
1151 int count=0;
1152 int alloced=0;
1153 char **lines;
1154 bool local_list_only;
1155 int i;
1156
1157 lines = file_lines_load(lock_path(SERVER_LIST), NULL, 0);
1158 if (!lines) {
1159 DEBUG(4,("Can't open %s - %s\n",lock_path(SERVER_LIST),strerror(errno)));
1160 return 0;
1161 }
1162
1163 /* request for everything is code for request all servers */
1164 if (servertype == SV_TYPE_ALL) {
1165 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1166 }
1167
1168 local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY);
1169
1170 DEBUG(4,("Servertype search: %8x\n",servertype));
1171
1172 for (i=0;lines[i];i++) {
1173 fstring stype;
1174 struct srv_info_struct *s;
1175 const char *ptr = lines[i];
1176 bool ok = True;
1177 TALLOC_CTX *frame = NULL;
1178 char *p;
1179
1180 if (!*ptr) {
1181 continue;
1182 }
1183
1184 if (count == alloced) {
1185 alloced += 10;
1186 *servers = SMB_REALLOC_ARRAY(*servers,struct srv_info_struct, alloced);
1187 if (!*servers) {
1188 DEBUG(0,("get_server_info: failed to enlarge servers info struct!\n"));
1189 file_lines_free(lines);
1190 return 0;
1191 }
1192 memset((char *)((*servers)+count),'\0',sizeof(**servers)*(alloced-count));
1193 }
1194 s = &(*servers)[count];
1195
1196 frame = talloc_stackframe();
1197 s->name[0] = '\0';
1198 if (!next_token_talloc(frame,&ptr,&p, NULL)) {
1199 TALLOC_FREE(frame);
1200 continue;
1201 }
1202 fstrcpy(s->name, p);
1203
1204 stype[0] = '\0';
1205 if (!next_token_talloc(frame,&ptr, &p, NULL)) {
1206 TALLOC_FREE(frame);
1207 continue;
1208 }
1209 fstrcpy(stype, p);
1210
1211 s->comment[0] = '\0';
1212 if (!next_token_talloc(frame,&ptr, &p, NULL)) {
1213 TALLOC_FREE(frame);
1214 continue;
1215 }
1216 fstrcpy(s->comment, p);
1217
1218 s->domain[0] = '\0';
1219 if (!next_token_talloc(frame,&ptr,&p, NULL)) {
1220 /* this allows us to cope with an old nmbd */
1221 fstrcpy(s->domain,lp_workgroup());
1222 } else {
1223 fstrcpy(s->domain, p);
1224 }
1225 TALLOC_FREE(frame);
1226
1227 if (sscanf(stype,"%X",&s->type) != 1) {
1228 DEBUG(4,("r:host file "));
1229 ok = False;
1230 }
1231
1232 /* Filter the servers/domains we return based on what was asked for. */
1233
1234 /* Check to see if we are being asked for a local list only. */
1235 if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) {
1236 DEBUG(4,("r: local list only"));
1237 ok = False;
1238 }
1239
1240 /* doesn't match up: don't want it */
1241 if (!(servertype & s->type)) {
1242 DEBUG(4,("r:serv type "));
1243 ok = False;
1244 }
1245
1246 if ((servertype & SV_TYPE_DOMAIN_ENUM) !=
1247 (s->type & SV_TYPE_DOMAIN_ENUM)) {
1248 DEBUG(4,("s: dom mismatch "));
1249 ok = False;
1250 }
1251
1252 if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM)) {
1253 ok = False;
1254 }
1255
1256 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1257 s->type &= ~SV_TYPE_LOCAL_LIST_ONLY;
1258
1259 if (ok) {
1260 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1261 s->name, s->type, s->comment, s->domain));
1262 s->server_added = True;
1263 count++;
1264 } else {
1265 DEBUG(4,("%20s %8x %25s %15s\n",
1266 s->name, s->type, s->comment, s->domain));
1267 }
1268 }
1269
1270 file_lines_free(lines);
1271 return count;
1272}
1273
1274/*******************************************************************
1275 Fill in a server info structure.
1276******************************************************************/
1277
1278static int fill_srv_info(struct srv_info_struct *service,
1279 int uLevel, char **buf, int *buflen,
1280 char **stringbuf, int *stringspace, char *baseaddr)
1281{
1282 int struct_len;
1283 char* p;
1284 char* p2;
1285 int l2;
1286 int len;
1287
1288 switch (uLevel) {
1289 case 0:
1290 struct_len = 16;
1291 break;
1292 case 1:
1293 struct_len = 26;
1294 break;
1295 default:
1296 return -1;
1297 }
1298
1299 if (!buf) {
1300 len = 0;
1301 switch (uLevel) {
1302 case 1:
1303 len = strlen(service->comment)+1;
1304 break;
1305 }
1306
1307 *buflen = struct_len;
1308 *stringspace = len;
1309 return struct_len + len;
1310 }
1311
1312 len = struct_len;
1313 p = *buf;
1314 if (*buflen < struct_len) {
1315 return -1;
1316 }
1317 if (stringbuf) {
1318 p2 = *stringbuf;
1319 l2 = *stringspace;
1320 } else {
1321 p2 = p + struct_len;
1322 l2 = *buflen - struct_len;
1323 }
1324 if (!baseaddr) {
1325 baseaddr = p;
1326 }
1327
1328 switch (uLevel) {
1329 case 0:
1330 push_ascii(p,service->name, MAX_NETBIOSNAME_LEN, STR_TERMINATE);
1331 break;
1332
1333 case 1:
1334 push_ascii(p,service->name,MAX_NETBIOSNAME_LEN, STR_TERMINATE);
1335 SIVAL(p,18,service->type);
1336 SIVAL(p,22,PTR_DIFF(p2,baseaddr));
1337 len += CopyAndAdvance(&p2,service->comment,&l2);
1338 break;
1339 }
1340
1341 if (stringbuf) {
1342 *buf = p + struct_len;
1343 *buflen -= struct_len;
1344 *stringbuf = p2;
1345 *stringspace = l2;
1346 } else {
1347 *buf = p2;
1348 *buflen -= len;
1349 }
1350 return len;
1351}
1352
1353
1354static bool srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
1355{
1356 return(strcmp(s1->name,s2->name));
1357}
1358
1359/****************************************************************************
1360 View list of servers available (or possibly domains). The info is
1361 extracted from lists saved by nmbd on the local host.
1362****************************************************************************/
1363
1364static bool api_RNetServerEnum(connection_struct *conn, uint16 vuid,
1365 char *param, int tpscnt,
1366 char *data, int tdscnt,
1367 int mdrcnt, int mprcnt, char **rdata,
1368 char **rparam, int *rdata_len, int *rparam_len)
1369{
1370 char *str1 = get_safe_str_ptr(param, tpscnt, param, 2);
1371 char *str2 = skip_string(param,tpscnt,str1);
1372 char *p = skip_string(param,tpscnt,str2);
1373 int uLevel = get_safe_SVAL(param, tpscnt, p, 0, -1);
1374 int buf_len = get_safe_SVAL(param,tpscnt, p, 2, 0);
1375 uint32 servertype = get_safe_IVAL(param,tpscnt,p,4, 0);
1376 char *p2;
1377 int data_len, fixed_len, string_len;
1378 int f_len = 0, s_len = 0;
1379 struct srv_info_struct *servers=NULL;
1380 int counted=0,total=0;
1381 int i,missed;
1382 fstring domain;
1383 bool domain_request;
1384 bool local_request;
1385
1386 if (!str1 || !str2 || !p) {
1387 return False;
1388 }
1389
1390 /* If someone sets all the bits they don't really mean to set
1391 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1392 known servers. */
1393
1394 if (servertype == SV_TYPE_ALL) {
1395 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1396 }
1397
1398 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1399 any other bit (they may just set this bit on its own) they
1400 want all the locally seen servers. However this bit can be
1401 set on its own so set the requested servers to be
1402 ALL - DOMAIN_ENUM. */
1403
1404 if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM)) {
1405 servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
1406 }
1407
1408 domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
1409 local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
1410
1411 p += 8;
1412
1413 if (!prefix_ok(str1,"WrLehD")) {
1414 return False;
1415 }
1416 if (!check_server_info(uLevel,str2)) {
1417 return False;
1418 }
1419
1420 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1421 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1422 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1423
1424 if (strcmp(str1, "WrLehDz") == 0) {
1425 if (skip_string(param,tpscnt,p) == NULL) {
1426 return False;
1427 }
1428 pull_ascii_fstring(domain, p);
1429 } else {
1430 fstrcpy(domain, lp_workgroup());
1431 }
1432
1433 if (lp_browse_list()) {
1434 total = get_server_info(servertype,&servers,domain);
1435 }
1436
1437 data_len = fixed_len = string_len = 0;
1438 missed = 0;
1439
1440 if (total > 0) {
1441 qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
1442 }
1443
1444 {
1445 char *lastname=NULL;
1446
1447 for (i=0;i<total;i++) {
1448 struct srv_info_struct *s = &servers[i];
1449
1450 if (lastname && strequal(lastname,s->name)) {
1451 continue;
1452 }
1453 lastname = s->name;
1454 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1455 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1456 s->name, s->type, s->comment, s->domain));
1457
1458 if (data_len <= buf_len) {
1459 counted++;
1460 fixed_len += f_len;
1461 string_len += s_len;
1462 } else {
1463 missed++;
1464 }
1465 }
1466 }
1467
1468 *rdata_len = fixed_len + string_len;
1469 *rdata = smb_realloc_limit(*rdata,*rdata_len);
1470 if (!*rdata) {
1471 return False;
1472 }
1473
1474 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1475 p = *rdata;
1476 f_len = fixed_len;
1477 s_len = string_len;
1478
1479 {
1480 char *lastname=NULL;
1481 int count2 = counted;
1482
1483 for (i = 0; i < total && count2;i++) {
1484 struct srv_info_struct *s = &servers[i];
1485
1486 if (lastname && strequal(lastname,s->name)) {
1487 continue;
1488 }
1489 lastname = s->name;
1490 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1491 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1492 s->name, s->type, s->comment, s->domain));
1493 count2--;
1494 }
1495 }
1496
1497 *rparam_len = 8;
1498 *rparam = smb_realloc_limit(*rparam,*rparam_len);
1499 if (!*rparam) {
1500 return False;
1501 }
1502 SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata));
1503 SSVAL(*rparam,2,0);
1504 SSVAL(*rparam,4,counted);
1505 SSVAL(*rparam,6,counted+missed);
1506
1507 SAFE_FREE(servers);
1508
1509 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1510 domain,uLevel,counted,counted+missed));
1511
1512 return True;
1513}
1514
1515/****************************************************************************
1516 command 0x34 - suspected of being a "Lookup Names" stub api
1517 ****************************************************************************/
1518
1519static bool api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid,
1520 char *param, int tpscnt,
1521 char *data, int tdscnt,
1522 int mdrcnt, int mprcnt, char **rdata,
1523 char **rparam, int *rdata_len, int *rparam_len)
1524{
1525 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
1526 char *str2 = skip_string(param,tpscnt,str1);
1527 char *p = skip_string(param,tpscnt,str2);
1528 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
1529 int buf_len = get_safe_SVAL(param,tpscnt,p,2,0);
1530 int counted=0;
1531 int missed=0;
1532
1533 if (!str1 || !str2 || !p) {
1534 return False;
1535 }
1536
1537 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1538 str1, str2, p, uLevel, buf_len));
1539
1540 if (!prefix_ok(str1,"zWrLeh")) {
1541 return False;
1542 }
1543
1544 *rdata_len = 0;
1545
1546 *rparam_len = 8;
1547 *rparam = smb_realloc_limit(*rparam,*rparam_len);
1548 if (!*rparam) {
1549 return False;
1550 }
1551
1552 SSVAL(*rparam,0,0x08AC); /* informational warning message */
1553 SSVAL(*rparam,2,0);
1554 SSVAL(*rparam,4,counted);
1555 SSVAL(*rparam,6,counted+missed);
1556
1557 return True;
1558}
1559
1560/****************************************************************************
1561 get info about a share
1562 ****************************************************************************/
1563
1564static bool check_share_info(int uLevel, char* id)
1565{
1566 switch( uLevel ) {
1567 case 0:
1568 if (strcmp(id,"B13") != 0) {
1569 return False;
1570 }
1571 break;
1572 case 1:
1573 if (strcmp(id,"B13BWz") != 0) {
1574 return False;
1575 }
1576 break;
1577 case 2:
1578 if (strcmp(id,"B13BWzWWWzB9B") != 0) {
1579 return False;
1580 }
1581 break;
1582 case 91:
1583 if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) {
1584 return False;
1585 }
1586 break;
1587 default:
1588 return False;
1589 }
1590 return True;
1591}
1592
1593static int fill_share_info(connection_struct *conn, int snum, int uLevel,
1594 char** buf, int* buflen,
1595 char** stringbuf, int* stringspace, char* baseaddr)
1596{
1597 int struct_len;
1598 char* p;
1599 char* p2;
1600 int l2;
1601 int len;
1602
1603 switch( uLevel ) {
1604 case 0:
1605 struct_len = 13;
1606 break;
1607 case 1:
1608 struct_len = 20;
1609 break;
1610 case 2:
1611 struct_len = 40;
1612 break;
1613 case 91:
1614 struct_len = 68;
1615 break;
1616 default:
1617 return -1;
1618 }
1619
1620
1621 if (!buf) {
1622 len = 0;
1623
1624 if (uLevel > 0) {
1625 len += StrlenExpanded(conn,snum,lp_comment(snum));
1626 }
1627 if (uLevel > 1) {
1628 len += strlen(lp_pathname(snum)) + 1;
1629 }
1630 if (buflen) {
1631 *buflen = struct_len;
1632 }
1633 if (stringspace) {
1634 *stringspace = len;
1635 }
1636 return struct_len + len;
1637 }
1638
1639 len = struct_len;
1640 p = *buf;
1641 if ((*buflen) < struct_len) {
1642 return -1;
1643 }
1644
1645 if (stringbuf) {
1646 p2 = *stringbuf;
1647 l2 = *stringspace;
1648 } else {
1649 p2 = p + struct_len;
1650 l2 = (*buflen) - struct_len;
1651 }
1652
1653 if (!baseaddr) {
1654 baseaddr = p;
1655 }
1656
1657 push_ascii(p,lp_servicename(snum),13, STR_TERMINATE);
1658
1659 if (uLevel > 0) {
1660 int type;
1661
1662 SCVAL(p,13,0);
1663 type = STYPE_DISKTREE;
1664 if (lp_print_ok(snum)) {
1665 type = STYPE_PRINTQ;
1666 }
1667 if (strequal("IPC",lp_fstype(snum))) {
1668 type = STYPE_IPC;
1669 }
1670 SSVAL(p,14,type); /* device type */
1671 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1672 len += CopyExpanded(conn,snum,&p2,lp_comment(snum),&l2);
1673 }
1674
1675 if (uLevel > 1) {
1676 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1677 SSVALS(p,22,-1); /* max uses */
1678 SSVAL(p,24,1); /* current uses */
1679 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1680 len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1681 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1682 }
1683
1684 if (uLevel > 2) {
1685 memset(p+40,0,SHPWLEN+2);
1686 SSVAL(p,50,0);
1687 SIVAL(p,52,0);
1688 SSVAL(p,56,0);
1689 SSVAL(p,58,0);
1690 SIVAL(p,60,0);
1691 SSVAL(p,64,0);
1692 SSVAL(p,66,0);
1693 }
1694
1695 if (stringbuf) {
1696 (*buf) = p + struct_len;
1697 (*buflen) -= struct_len;
1698 (*stringbuf) = p2;
1699 (*stringspace) = l2;
1700 } else {
1701 (*buf) = p2;
1702 (*buflen) -= len;
1703 }
1704
1705 return len;
1706}
1707
1708static bool api_RNetShareGetInfo(connection_struct *conn,uint16 vuid,
1709 char *param, int tpscnt,
1710 char *data, int tdscnt,
1711 int mdrcnt,int mprcnt,
1712 char **rdata,char **rparam,
1713 int *rdata_len,int *rparam_len)
1714{
1715 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
1716 char *str2 = skip_string(param,tpscnt,str1);
1717 char *netname = skip_string(param,tpscnt,str2);
1718 char *p = skip_string(param,tpscnt,netname);
1719 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
1720 int snum;
1721
1722 if (!str1 || !str2 || !netname || !p) {
1723 return False;
1724 }
1725
1726 snum = find_service(netname);
1727 if (snum < 0) {
1728 return False;
1729 }
1730
1731 /* check it's a supported varient */
1732 if (!prefix_ok(str1,"zWrLh")) {
1733 return False;
1734 }
1735 if (!check_share_info(uLevel,str2)) {
1736 return False;
1737 }
1738
1739 *rdata = smb_realloc_limit(*rdata,mdrcnt);
1740 if (!*rdata) {
1741 return False;
1742 }
1743 p = *rdata;
1744 *rdata_len = fill_share_info(conn,snum,uLevel,&p,&mdrcnt,0,0,0);
1745 if (*rdata_len < 0) {
1746 return False;
1747 }
1748
1749 *rparam_len = 6;
1750 *rparam = smb_realloc_limit(*rparam,*rparam_len);
1751 if (!*rparam) {
1752 return False;
1753 }
1754 SSVAL(*rparam,0,NERR_Success);
1755 SSVAL(*rparam,2,0); /* converter word */
1756 SSVAL(*rparam,4,*rdata_len);
1757
1758 return True;
1759}
1760
1761/****************************************************************************
1762 View the list of available shares.
1763
1764 This function is the server side of the NetShareEnum() RAP call.
1765 It fills the return buffer with share names and share comments.
1766 Note that the return buffer normally (in all known cases) allows only
1767 twelve byte strings for share names (plus one for a nul terminator).
1768 Share names longer than 12 bytes must be skipped.
1769 ****************************************************************************/
1770
1771static bool api_RNetShareEnum( connection_struct *conn, uint16 vuid,
1772 char *param, int tpscnt,
1773 char *data, int tdscnt,
1774 int mdrcnt,
1775 int mprcnt,
1776 char **rdata,
1777 char **rparam,
1778 int *rdata_len,
1779 int *rparam_len )
1780{
1781 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
1782 char *str2 = skip_string(param,tpscnt,str1);
1783 char *p = skip_string(param,tpscnt,str2);
1784 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
1785 int buf_len = get_safe_SVAL(param,tpscnt,p,2,0);
1786 char *p2;
1787 int count = 0;
1788 int total=0,counted=0;
1789 bool missed = False;
1790 int i;
1791 int data_len, fixed_len, string_len;
1792 int f_len = 0, s_len = 0;
1793
1794 if (!str1 || !str2 || !p) {
1795 return False;
1796 }
1797
1798 if (!prefix_ok(str1,"WrLeh")) {
1799 return False;
1800 }
1801 if (!check_share_info(uLevel,str2)) {
1802 return False;
1803 }
1804
1805 /* Ensure all the usershares are loaded. */
1806 become_root();
1807 load_registry_shares();
1808 count = load_usershare_shares();
1809 unbecome_root();
1810
1811 data_len = fixed_len = string_len = 0;
1812 for (i=0;i<count;i++) {
1813 fstring servicename_dos;
1814 if (!(lp_browseable(i) && lp_snum_ok(i))) {
1815 continue;
1816 }
1817 push_ascii_fstring(servicename_dos, lp_servicename(i));
1818 /* Maximum name length = 13. */
1819 if( lp_browseable( i ) && lp_snum_ok( i ) && (strlen(servicename_dos) < 13)) {
1820 total++;
1821 data_len += fill_share_info(conn,i,uLevel,0,&f_len,0,&s_len,0);
1822 if (data_len <= buf_len) {
1823 counted++;
1824 fixed_len += f_len;
1825 string_len += s_len;
1826 } else {
1827 missed = True;
1828 }
1829 }
1830 }
1831
1832 *rdata_len = fixed_len + string_len;
1833 *rdata = smb_realloc_limit(*rdata,*rdata_len);
1834 if (!*rdata) {
1835 return False;
1836 }
1837
1838 p2 = (*rdata) + fixed_len; /* auxiliary data (strings) will go here */
1839 p = *rdata;
1840 f_len = fixed_len;
1841 s_len = string_len;
1842
1843 for( i = 0; i < count; i++ ) {
1844 fstring servicename_dos;
1845 if (!(lp_browseable(i) && lp_snum_ok(i))) {
1846 continue;
1847 }
1848
1849 push_ascii_fstring(servicename_dos, lp_servicename(i));
1850 if (lp_browseable(i) && lp_snum_ok(i) && (strlen(servicename_dos) < 13)) {
1851 if (fill_share_info( conn,i,uLevel,&p,&f_len,&p2,&s_len,*rdata ) < 0) {
1852 break;
1853 }
1854 }
1855 }
1856
1857 *rparam_len = 8;
1858 *rparam = smb_realloc_limit(*rparam,*rparam_len);
1859 if (!*rparam) {
1860 return False;
1861 }
1862 SSVAL(*rparam,0,missed ? ERRmoredata : NERR_Success);
1863 SSVAL(*rparam,2,0);
1864 SSVAL(*rparam,4,counted);
1865 SSVAL(*rparam,6,total);
1866
1867 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1868 counted,total,uLevel,
1869 buf_len,*rdata_len,mdrcnt));
1870
1871 return True;
1872}
1873
1874/****************************************************************************
1875 Add a share
1876 ****************************************************************************/
1877
1878static bool api_RNetShareAdd(connection_struct *conn,uint16 vuid,
1879 char *param, int tpscnt,
1880 char *data, int tdscnt,
1881 int mdrcnt,int mprcnt,
1882 char **rdata,char **rparam,
1883 int *rdata_len,int *rparam_len)
1884{
1885 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
1886 char *str2 = skip_string(param,tpscnt,str1);
1887 char *p = skip_string(param,tpscnt,str2);
1888 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
1889 fstring sharename;
1890 fstring comment;
1891 char *pathname = NULL;
1892 char *command, *cmdname;
1893 unsigned int offset;
1894 int snum;
1895 int res = ERRunsup;
1896 size_t converted_size;
1897
1898 if (!str1 || !str2 || !p) {
1899 return False;
1900 }
1901
1902 /* check it's a supported varient */
1903 if (!prefix_ok(str1,RAP_WShareAdd_REQ)) {
1904 return False;
1905 }
1906 if (!check_share_info(uLevel,str2)) {
1907 return False;
1908 }
1909 if (uLevel != 2) {
1910 return False;
1911 }
1912
1913 /* Do we have a string ? */
1914 if (skip_string(data,mdrcnt,data) == NULL) {
1915 return False;
1916 }
1917 pull_ascii_fstring(sharename,data);
1918 snum = find_service(sharename);
1919 if (snum >= 0) { /* already exists */
1920 res = ERRfilexists;
1921 goto error_exit;
1922 }
1923
1924 if (mdrcnt < 28) {
1925 return False;
1926 }
1927
1928 /* only support disk share adds */
1929 if (SVAL(data,14)!=STYPE_DISKTREE) {
1930 return False;
1931 }
1932
1933 offset = IVAL(data, 16);
1934 if (offset >= mdrcnt) {
1935 res = ERRinvalidparam;
1936 goto error_exit;
1937 }
1938
1939 /* Do we have a string ? */
1940 if (skip_string(data,mdrcnt,data+offset) == NULL) {
1941 return False;
1942 }
1943 pull_ascii_fstring(comment, offset? (data+offset) : "");
1944
1945 offset = IVAL(data, 26);
1946
1947 if (offset >= mdrcnt) {
1948 res = ERRinvalidparam;
1949 goto error_exit;
1950 }
1951
1952 /* Do we have a string ? */
1953 if (skip_string(data,mdrcnt,data+offset) == NULL) {
1954 return False;
1955 }
1956
1957 if (!pull_ascii_talloc(talloc_tos(), &pathname,
1958 offset ? (data+offset) : "", &converted_size))
1959 {
1960 DEBUG(0,("api_RNetShareAdd: pull_ascii_talloc failed: %s",
1961 strerror(errno)));
1962 }
1963
1964 if (!pathname) {
1965 return false;
1966 }
1967
1968 string_replace(sharename, '"', ' ');
1969 string_replace(pathname, '"', ' ');
1970 string_replace(comment, '"', ' ');
1971
1972 cmdname = lp_add_share_cmd();
1973
1974 if (!cmdname || *cmdname == '\0') {
1975 return False;
1976 }
1977
1978 if (asprintf(&command, "%s \"%s\" \"%s\" \"%s\" \"%s\"",
1979 lp_add_share_cmd(), get_dyn_CONFIGFILE(), sharename,
1980 pathname, comment) == -1) {
1981 return false;
1982 }
1983
1984 DEBUG(10,("api_RNetShareAdd: Running [%s]\n", command ));
1985
1986 if ((res = smbrun(command, NULL)) != 0) {
1987 DEBUG(1,("api_RNetShareAdd: Running [%s] returned (%d)\n",
1988 command, res ));
1989 SAFE_FREE(command);
1990 res = ERRnoaccess;
1991 goto error_exit;
1992 } else {
1993 SAFE_FREE(command);
1994 message_send_all(smbd_messaging_context(),
1995 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
1996 }
1997
1998 *rparam_len = 6;
1999 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2000 if (!*rparam) {
2001 return False;
2002 }
2003 SSVAL(*rparam,0,NERR_Success);
2004 SSVAL(*rparam,2,0); /* converter word */
2005 SSVAL(*rparam,4,*rdata_len);
2006 *rdata_len = 0;
2007
2008 return True;
2009
2010 error_exit:
2011
2012 *rparam_len = 4;
2013 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2014 if (!*rparam) {
2015 return False;
2016 }
2017 *rdata_len = 0;
2018 SSVAL(*rparam,0,res);
2019 SSVAL(*rparam,2,0);
2020 return True;
2021}
2022
2023/****************************************************************************
2024 view list of groups available
2025 ****************************************************************************/
2026
2027static bool api_RNetGroupEnum(connection_struct *conn,uint16 vuid,
2028 char *param, int tpscnt,
2029 char *data, int tdscnt,
2030 int mdrcnt,int mprcnt,
2031 char **rdata,char **rparam,
2032 int *rdata_len,int *rparam_len)
2033{
2034 int i;
2035 int errflags=0;
2036 int resume_context, cli_buf_size;
2037 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2038 char *str2 = skip_string(param,tpscnt,str1);
2039 char *p = skip_string(param,tpscnt,str2);
2040
2041 struct pdb_search *search;
2042 struct samr_displayentry *entries;
2043
2044 int num_entries;
2045
2046 if (!str1 || !str2 || !p) {
2047 return False;
2048 }
2049
2050 if (strcmp(str1,"WrLeh") != 0) {
2051 return False;
2052 }
2053
2054 /* parameters
2055 * W-> resume context (number of users to skip)
2056 * r -> return parameter pointer to receive buffer
2057 * L -> length of receive buffer
2058 * e -> return parameter number of entries
2059 * h -> return parameter total number of users
2060 */
2061
2062 if (strcmp("B21",str2) != 0) {
2063 return False;
2064 }
2065
2066 /* get list of domain groups SID_DOMAIN_GRP=2 */
2067 become_root();
2068 search = pdb_search_groups();
2069 unbecome_root();
2070
2071 if (search == NULL) {
2072 DEBUG(3,("api_RNetGroupEnum:failed to get group list"));
2073 return False;
2074 }
2075
2076 resume_context = get_safe_SVAL(param,tpscnt,p,0,-1);
2077 cli_buf_size= get_safe_SVAL(param,tpscnt,p,2,0);
2078 DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: "
2079 "%d\n", resume_context, cli_buf_size));
2080
2081 become_root();
2082 num_entries = pdb_search_entries(search, resume_context, 0xffffffff,
2083 &entries);
2084 unbecome_root();
2085
2086 *rdata_len = cli_buf_size;
2087 *rdata = smb_realloc_limit(*rdata,*rdata_len);
2088 if (!*rdata) {
2089 return False;
2090 }
2091
2092 p = *rdata;
2093
2094 for(i=0; i<num_entries; i++) {
2095 fstring name;
2096 fstrcpy(name, entries[i].account_name);
2097 if( ((PTR_DIFF(p,*rdata)+21) <= *rdata_len) ) {
2098 /* truncate the name at 21 chars. */
2099 memcpy(p, name, 21);
2100 DEBUG(10,("adding entry %d group %s\n", i, p));
2101 p += 21;
2102 p += 5; /* Both NT4 and W2k3SP1 do padding here.
2103 No idea why... */
2104 } else {
2105 /* set overflow error */
2106 DEBUG(3,("overflow on entry %d group %s\n", i, name));
2107 errflags=234;
2108 break;
2109 }
2110 }
2111
2112 pdb_search_destroy(search);
2113
2114 *rdata_len = PTR_DIFF(p,*rdata);
2115
2116 *rparam_len = 8;
2117 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2118 if (!*rparam) {
2119 return False;
2120 }
2121 SSVAL(*rparam, 0, errflags);
2122 SSVAL(*rparam, 2, 0); /* converter word */
2123 SSVAL(*rparam, 4, i); /* is this right?? */
2124 SSVAL(*rparam, 6, resume_context+num_entries); /* is this right?? */
2125
2126 return(True);
2127}
2128
2129/*******************************************************************
2130 Get groups that a user is a member of.
2131******************************************************************/
2132
2133static bool api_NetUserGetGroups(connection_struct *conn,uint16 vuid,
2134 char *param, int tpscnt,
2135 char *data, int tdscnt,
2136 int mdrcnt,int mprcnt,
2137 char **rdata,char **rparam,
2138 int *rdata_len,int *rparam_len)
2139{
2140 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2141 char *str2 = skip_string(param,tpscnt,str1);
2142 char *UserName = skip_string(param,tpscnt,str2);
2143 char *p = skip_string(param,tpscnt,UserName);
2144 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
2145 const char *level_string;
2146 int count=0;
2147 struct samu *sampw = NULL;
2148 bool ret = False;
2149 DOM_SID *sids;
2150 gid_t *gids;
2151 size_t num_groups;
2152 size_t i;
2153 NTSTATUS result;
2154 DOM_SID user_sid;
2155 enum lsa_SidType type;
2156 char *endp = NULL;
2157 TALLOC_CTX *mem_ctx;
2158
2159 if (!str1 || !str2 || !UserName || !p) {
2160 return False;
2161 }
2162
2163 *rparam_len = 8;
2164 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2165 if (!*rparam) {
2166 return False;
2167 }
2168
2169 /* check it's a supported varient */
2170
2171 if ( strcmp(str1,"zWrLeh") != 0 )
2172 return False;
2173
2174 switch( uLevel ) {
2175 case 0:
2176 level_string = "B21";
2177 break;
2178 default:
2179 return False;
2180 }
2181
2182 if (strcmp(level_string,str2) != 0)
2183 return False;
2184
2185 *rdata_len = mdrcnt + 1024;
2186 *rdata = smb_realloc_limit(*rdata,*rdata_len);
2187 if (!*rdata) {
2188 return False;
2189 }
2190
2191 SSVAL(*rparam,0,NERR_Success);
2192 SSVAL(*rparam,2,0); /* converter word */
2193
2194 p = *rdata;
2195 endp = *rdata + *rdata_len;
2196
2197 mem_ctx = talloc_new(NULL);
2198 if (mem_ctx == NULL) {
2199 DEBUG(0, ("talloc_new failed\n"));
2200 return False;
2201 }
2202
2203 if ( !(sampw = samu_new(mem_ctx)) ) {
2204 DEBUG(0, ("samu_new() failed!\n"));
2205 TALLOC_FREE(mem_ctx);
2206 return False;
2207 }
2208
2209 /* Lookup the user information; This should only be one of
2210 our accounts (not remote domains) */
2211
2212 become_root(); /* ROOT BLOCK */
2213
2214 if (!lookup_name(mem_ctx, UserName, LOOKUP_NAME_ALL,
2215 NULL, NULL, &user_sid, &type)) {
2216 DEBUG(10, ("lookup_name(%s) failed\n", UserName));
2217 goto done;
2218 }
2219
2220 if (type != SID_NAME_USER) {
2221 DEBUG(10, ("%s is a %s, not a user\n", UserName,
2222 sid_type_lookup(type)));
2223 goto done;
2224 }
2225
2226 if ( !pdb_getsampwsid(sampw, &user_sid) ) {
2227 DEBUG(10, ("pdb_getsampwsid(%s) failed for user %s\n",
2228 sid_string_dbg(&user_sid), UserName));
2229 goto done;
2230 }
2231
2232 gids = NULL;
2233 sids = NULL;
2234 num_groups = 0;
2235
2236 result = pdb_enum_group_memberships(mem_ctx, sampw,
2237 &sids, &gids, &num_groups);
2238
2239 if (!NT_STATUS_IS_OK(result)) {
2240 DEBUG(10, ("pdb_enum_group_memberships failed for %s\n",
2241 UserName));
2242 goto done;
2243 }
2244
2245 for (i=0; i<num_groups; i++) {
2246 const char *grp_name;
2247
2248 if ( lookup_sid(mem_ctx, &sids[i], NULL, &grp_name, NULL) ) {
2249 strlcpy(p, grp_name, PTR_DIFF(endp,p));
2250 p += 21;
2251 count++;
2252 }
2253 }
2254
2255 *rdata_len = PTR_DIFF(p,*rdata);
2256
2257 SSVAL(*rparam,4,count); /* is this right?? */
2258 SSVAL(*rparam,6,count); /* is this right?? */
2259
2260 ret = True;
2261
2262done:
2263 unbecome_root(); /* END ROOT BLOCK */
2264
2265 TALLOC_FREE(mem_ctx);
2266
2267 return ret;
2268}
2269
2270/*******************************************************************
2271 Get all users.
2272******************************************************************/
2273
2274static bool api_RNetUserEnum(connection_struct *conn, uint16 vuid,
2275 char *param, int tpscnt,
2276 char *data, int tdscnt,
2277 int mdrcnt,int mprcnt,
2278 char **rdata,char **rparam,
2279 int *rdata_len,int *rparam_len)
2280{
2281 int count_sent=0;
2282 int num_users=0;
2283 int errflags=0;
2284 int i, resume_context, cli_buf_size;
2285 struct pdb_search *search;
2286 struct samr_displayentry *users;
2287
2288 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2289 char *str2 = skip_string(param,tpscnt,str1);
2290 char *p = skip_string(param,tpscnt,str2);
2291 char *endp = NULL;
2292
2293 if (!str1 || !str2 || !p) {
2294 return False;
2295 }
2296
2297 if (strcmp(str1,"WrLeh") != 0)
2298 return False;
2299 /* parameters
2300 * W-> resume context (number of users to skip)
2301 * r -> return parameter pointer to receive buffer
2302 * L -> length of receive buffer
2303 * e -> return parameter number of entries
2304 * h -> return parameter total number of users
2305 */
2306
2307 resume_context = get_safe_SVAL(param,tpscnt,p,0,-1);
2308 cli_buf_size= get_safe_SVAL(param,tpscnt,p,2,0);
2309 DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n",
2310 resume_context, cli_buf_size));
2311
2312 *rparam_len = 8;
2313 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2314 if (!*rparam) {
2315 return False;
2316 }
2317
2318 /* check it's a supported varient */
2319 if (strcmp("B21",str2) != 0)
2320 return False;
2321
2322 *rdata_len = cli_buf_size;
2323 *rdata = smb_realloc_limit(*rdata,*rdata_len);
2324 if (!*rdata) {
2325 return False;
2326 }
2327
2328 p = *rdata;
2329 endp = *rdata + *rdata_len;
2330
2331 become_root();
2332 search = pdb_search_users(ACB_NORMAL);
2333 unbecome_root();
2334 if (search == NULL) {
2335 DEBUG(0, ("api_RNetUserEnum:unable to open sam database.\n"));
2336 return False;
2337 }
2338
2339 become_root();
2340 num_users = pdb_search_entries(search, resume_context, 0xffffffff,
2341 &users);
2342 unbecome_root();
2343
2344 errflags=NERR_Success;
2345
2346 for (i=0; i<num_users; i++) {
2347 const char *name = users[i].account_name;
2348
2349 if(((PTR_DIFF(p,*rdata)+21)<=*rdata_len)&&(strlen(name)<=21)) {
2350 strlcpy(p,name,PTR_DIFF(endp,p));
2351 DEBUG(10,("api_RNetUserEnum:adding entry %d username "
2352 "%s\n",count_sent,p));
2353 p += 21;
2354 count_sent++;
2355 } else {
2356 /* set overflow error */
2357 DEBUG(10,("api_RNetUserEnum:overflow on entry %d "
2358 "username %s\n",count_sent,name));
2359 errflags=234;
2360 break;
2361 }
2362 }
2363
2364 pdb_search_destroy(search);
2365
2366 *rdata_len = PTR_DIFF(p,*rdata);
2367
2368 SSVAL(*rparam,0,errflags);
2369 SSVAL(*rparam,2,0); /* converter word */
2370 SSVAL(*rparam,4,count_sent); /* is this right?? */
2371 SSVAL(*rparam,6,num_users); /* is this right?? */
2372
2373 return True;
2374}
2375
2376/****************************************************************************
2377 Get the time of day info.
2378****************************************************************************/
2379
2380static bool api_NetRemoteTOD(connection_struct *conn,uint16 vuid,
2381 char *param, int tpscnt,
2382 char *data, int tdscnt,
2383 int mdrcnt,int mprcnt,
2384 char **rdata,char **rparam,
2385 int *rdata_len,int *rparam_len)
2386{
2387 struct tm *t;
2388 time_t unixdate = time(NULL);
2389 char *p;
2390
2391 *rparam_len = 4;
2392 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2393 if (!*rparam) {
2394 return False;
2395 }
2396
2397 *rdata_len = 21;
2398 *rdata = smb_realloc_limit(*rdata,*rdata_len);
2399 if (!*rdata) {
2400 return False;
2401 }
2402
2403 SSVAL(*rparam,0,NERR_Success);
2404 SSVAL(*rparam,2,0); /* converter word */
2405
2406 p = *rdata;
2407
2408 srv_put_dos_date3(p,0,unixdate); /* this is the time that is looked at
2409 by NT in a "net time" operation,
2410 it seems to ignore the one below */
2411
2412 /* the client expects to get localtime, not GMT, in this bit
2413 (I think, this needs testing) */
2414 t = localtime(&unixdate);
2415 if (!t) {
2416 return False;
2417 }
2418
2419 SIVAL(p,4,0); /* msecs ? */
2420 SCVAL(p,8,t->tm_hour);
2421 SCVAL(p,9,t->tm_min);
2422 SCVAL(p,10,t->tm_sec);
2423 SCVAL(p,11,0); /* hundredths of seconds */
2424 SSVALS(p,12,get_time_zone(unixdate)/60); /* timezone in minutes from GMT */
2425 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
2426 SCVAL(p,16,t->tm_mday);
2427 SCVAL(p,17,t->tm_mon + 1);
2428 SSVAL(p,18,1900+t->tm_year);
2429 SCVAL(p,20,t->tm_wday);
2430
2431 return True;
2432}
2433
2434/****************************************************************************
2435 Set the user password.
2436*****************************************************************************/
2437
2438static bool api_SetUserPassword(connection_struct *conn,uint16 vuid,
2439 char *param, int tpscnt,
2440 char *data, int tdscnt,
2441 int mdrcnt,int mprcnt,
2442 char **rdata,char **rparam,
2443 int *rdata_len,int *rparam_len)
2444{
2445 char *np = get_safe_str_ptr(param,tpscnt,param,2);
2446 char *p = NULL;
2447 fstring user;
2448 fstring pass1,pass2;
2449
2450 /* Skip 2 strings. */
2451 p = skip_string(param,tpscnt,np);
2452 p = skip_string(param,tpscnt,p);
2453
2454 if (!np || !p) {
2455 return False;
2456 }
2457
2458 /* Do we have a string ? */
2459 if (skip_string(param,tpscnt,p) == NULL) {
2460 return False;
2461 }
2462 pull_ascii_fstring(user,p);
2463
2464 p = skip_string(param,tpscnt,p);
2465 if (!p) {
2466 return False;
2467 }
2468
2469 memset(pass1,'\0',sizeof(pass1));
2470 memset(pass2,'\0',sizeof(pass2));
2471 /*
2472 * We use 31 here not 32 as we're checking
2473 * the last byte we want to access is safe.
2474 */
2475 if (!is_offset_safe(param,tpscnt,p,31)) {
2476 return False;
2477 }
2478 memcpy(pass1,p,16);
2479 memcpy(pass2,p+16,16);
2480
2481 *rparam_len = 4;
2482 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2483 if (!*rparam) {
2484 return False;
2485 }
2486
2487 *rdata_len = 0;
2488
2489 SSVAL(*rparam,0,NERR_badpass);
2490 SSVAL(*rparam,2,0); /* converter word */
2491
2492 DEBUG(3,("Set password for <%s>\n",user));
2493
2494 /*
2495 * Attempt to verify the old password against smbpasswd entries
2496 * Win98 clients send old and new password in plaintext for this call.
2497 */
2498
2499 {
2500 auth_serversupplied_info *server_info = NULL;
2501 DATA_BLOB password = data_blob(pass1, strlen(pass1)+1);
2502
2503 if (NT_STATUS_IS_OK(check_plaintext_password(user,password,&server_info))) {
2504
2505 become_root();
2506 if (NT_STATUS_IS_OK(change_oem_password(server_info->sam_account, pass1, pass2, False, NULL))) {
2507 SSVAL(*rparam,0,NERR_Success);
2508 }
2509 unbecome_root();
2510
2511 TALLOC_FREE(server_info);
2512 }
2513 data_blob_clear_free(&password);
2514 }
2515
2516 /*
2517 * If the plaintext change failed, attempt
2518 * the old encrypted method. NT will generate this
2519 * after trying the samr method. Note that this
2520 * method is done as a last resort as this
2521 * password change method loses the NT password hash
2522 * and cannot change the UNIX password as no plaintext
2523 * is received.
2524 */
2525
2526 if(SVAL(*rparam,0) != NERR_Success) {
2527 struct samu *hnd = NULL;
2528
2529 if (check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &hnd)) {
2530 become_root();
2531 if (change_lanman_password(hnd,(uchar *)pass2)) {
2532 SSVAL(*rparam,0,NERR_Success);
2533 }
2534 unbecome_root();
2535 TALLOC_FREE(hnd);
2536 }
2537 }
2538
2539 memset((char *)pass1,'\0',sizeof(fstring));
2540 memset((char *)pass2,'\0',sizeof(fstring));
2541
2542 return(True);
2543}
2544
2545/****************************************************************************
2546 Set the user password (SamOEM version - gets plaintext).
2547****************************************************************************/
2548
2549static bool api_SamOEMChangePassword(connection_struct *conn,uint16 vuid,
2550 char *param, int tpscnt,
2551 char *data, int tdscnt,
2552 int mdrcnt,int mprcnt,
2553 char **rdata,char **rparam,
2554 int *rdata_len,int *rparam_len)
2555{
2556 fstring user;
2557 char *p = get_safe_str_ptr(param,tpscnt,param,2);
2558 *rparam_len = 2;
2559 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2560 if (!*rparam) {
2561 return False;
2562 }
2563
2564 if (!p) {
2565 return False;
2566 }
2567 *rdata_len = 0;
2568
2569 SSVAL(*rparam,0,NERR_badpass);
2570
2571 /*
2572 * Check the parameter definition is correct.
2573 */
2574
2575 /* Do we have a string ? */
2576 if (skip_string(param,tpscnt,p) == 0) {
2577 return False;
2578 }
2579 if(!strequal(p, "zsT")) {
2580 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", p));
2581 return False;
2582 }
2583 p = skip_string(param, tpscnt, p);
2584 if (!p) {
2585 return False;
2586 }
2587
2588 /* Do we have a string ? */
2589 if (skip_string(param,tpscnt,p) == 0) {
2590 return False;
2591 }
2592 if(!strequal(p, "B516B16")) {
2593 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p));
2594 return False;
2595 }
2596 p = skip_string(param,tpscnt,p);
2597 if (!p) {
2598 return False;
2599 }
2600 /* Do we have a string ? */
2601 if (skip_string(param,tpscnt,p) == 0) {
2602 return False;
2603 }
2604 p += pull_ascii_fstring(user,p);
2605
2606 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user));
2607
2608 /*
2609 * Pass the user through the NT -> unix user mapping
2610 * function.
2611 */
2612
2613 (void)map_username(user);
2614
2615 if (NT_STATUS_IS_OK(pass_oem_change(user, (uchar*) data, (uchar *)&data[516], NULL, NULL, NULL))) {
2616 SSVAL(*rparam,0,NERR_Success);
2617 }
2618
2619 return(True);
2620}
2621
2622/****************************************************************************
2623 delete a print job
2624 Form: <W> <>
2625 ****************************************************************************/
2626
2627static bool api_RDosPrintJobDel(connection_struct *conn,uint16 vuid,
2628 char *param, int tpscnt,
2629 char *data, int tdscnt,
2630 int mdrcnt,int mprcnt,
2631 char **rdata,char **rparam,
2632 int *rdata_len,int *rparam_len)
2633{
2634 int function = get_safe_SVAL(param,tpscnt,param,0,0);
2635 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2636 char *str2 = skip_string(param,tpscnt,str1);
2637 char *p = skip_string(param,tpscnt,str2);
2638 uint32 jobid;
2639 int snum;
2640 fstring sharename;
2641 int errcode;
2642 WERROR werr = WERR_OK;
2643
2644 if (!str1 || !str2 || !p) {
2645 return False;
2646 }
2647 /*
2648 * We use 1 here not 2 as we're checking
2649 * the last byte we want to access is safe.
2650 */
2651 if (!is_offset_safe(param,tpscnt,p,1)) {
2652 return False;
2653 }
2654 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
2655 return False;
2656
2657 /* check it's a supported varient */
2658 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
2659 return(False);
2660
2661 *rparam_len = 4;
2662 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2663 if (!*rparam) {
2664 return False;
2665 }
2666 *rdata_len = 0;
2667
2668 if (!print_job_exists(sharename, jobid)) {
2669 errcode = NERR_JobNotFound;
2670 goto out;
2671 }
2672
2673 snum = lp_servicenumber( sharename);
2674 if (snum == -1) {
2675 errcode = NERR_DestNotFound;
2676 goto out;
2677 }
2678
2679 errcode = NERR_notsupported;
2680
2681 switch (function) {
2682 case 81: /* delete */
2683 if (print_job_delete(conn->server_info, snum, jobid, &werr))
2684 errcode = NERR_Success;
2685 break;
2686 case 82: /* pause */
2687 if (print_job_pause(conn->server_info, snum, jobid, &werr))
2688 errcode = NERR_Success;
2689 break;
2690 case 83: /* resume */
2691 if (print_job_resume(conn->server_info, snum, jobid, &werr))
2692 errcode = NERR_Success;
2693 break;
2694 }
2695
2696 if (!W_ERROR_IS_OK(werr))
2697 errcode = W_ERROR_V(werr);
2698
2699 out:
2700 SSVAL(*rparam,0,errcode);
2701 SSVAL(*rparam,2,0); /* converter word */
2702
2703 return(True);
2704}
2705
2706/****************************************************************************
2707 Purge a print queue - or pause or resume it.
2708 ****************************************************************************/
2709
2710static bool api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid,
2711 char *param, int tpscnt,
2712 char *data, int tdscnt,
2713 int mdrcnt,int mprcnt,
2714 char **rdata,char **rparam,
2715 int *rdata_len,int *rparam_len)
2716{
2717 int function = get_safe_SVAL(param,tpscnt,param,0,0);
2718 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2719 char *str2 = skip_string(param,tpscnt,str1);
2720 char *QueueName = skip_string(param,tpscnt,str2);
2721 int errcode = NERR_notsupported;
2722 int snum;
2723 WERROR werr = WERR_OK;
2724
2725 if (!str1 || !str2 || !QueueName) {
2726 return False;
2727 }
2728
2729 /* check it's a supported varient */
2730 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
2731 return(False);
2732
2733 *rparam_len = 4;
2734 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2735 if (!*rparam) {
2736 return False;
2737 }
2738 *rdata_len = 0;
2739
2740 if (skip_string(param,tpscnt,QueueName) == NULL) {
2741 return False;
2742 }
2743 snum = print_queue_snum(QueueName);
2744
2745 if (snum == -1) {
2746 errcode = NERR_JobNotFound;
2747 goto out;
2748 }
2749
2750 switch (function) {
2751 case 74: /* Pause queue */
2752 if (print_queue_pause(conn->server_info, snum, &werr)) {
2753 errcode = NERR_Success;
2754 }
2755 break;
2756 case 75: /* Resume queue */
2757 if (print_queue_resume(conn->server_info, snum, &werr)) {
2758 errcode = NERR_Success;
2759 }
2760 break;
2761 case 103: /* Purge */
2762 if (print_queue_purge(conn->server_info, snum, &werr)) {
2763 errcode = NERR_Success;
2764 }
2765 break;
2766 }
2767
2768 if (!W_ERROR_IS_OK(werr)) errcode = W_ERROR_V(werr);
2769
2770 out:
2771 SSVAL(*rparam,0,errcode);
2772 SSVAL(*rparam,2,0); /* converter word */
2773
2774 return(True);
2775}
2776
2777/****************************************************************************
2778 set the property of a print job (undocumented?)
2779 ? function = 0xb -> set name of print job
2780 ? function = 0x6 -> move print job up/down
2781 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
2782 or <WWsTP> <WB21BB16B10zWWzDDz>
2783****************************************************************************/
2784
2785static int check_printjob_info(struct pack_desc* desc,
2786 int uLevel, char* id)
2787{
2788 desc->subformat = NULL;
2789 switch( uLevel ) {
2790 case 0: desc->format = "W"; break;
2791 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
2792 case 2: desc->format = "WWzWWDDzz"; break;
2793 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
2794 case 4: desc->format = "WWzWWDDzzzzzDDDDDDD"; break;
2795 default:
2796 DEBUG(0,("check_printjob_info: invalid level %d\n",
2797 uLevel ));
2798 return False;
2799 }
2800 if (id == NULL || strcmp(desc->format,id) != 0) {
2801 DEBUG(0,("check_printjob_info: invalid format %s\n",
2802 id ? id : "<NULL>" ));
2803 return False;
2804 }
2805 return True;
2806}
2807
2808static bool api_PrintJobInfo(connection_struct *conn, uint16 vuid,
2809 char *param, int tpscnt,
2810 char *data, int tdscnt,
2811 int mdrcnt,int mprcnt,
2812 char **rdata,char **rparam,
2813 int *rdata_len,int *rparam_len)
2814{
2815 struct pack_desc desc;
2816 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2817 char *str2 = skip_string(param,tpscnt,str1);
2818 char *p = skip_string(param,tpscnt,str2);
2819 uint32 jobid;
2820 fstring sharename;
2821 int uLevel = get_safe_SVAL(param,tpscnt,p,2,-1);
2822 int function = get_safe_SVAL(param,tpscnt,p,4,-1);
2823 int place, errcode;
2824
2825 if (!str1 || !str2 || !p) {
2826 return False;
2827 }
2828 /*
2829 * We use 1 here not 2 as we're checking
2830 * the last byte we want to access is safe.
2831 */
2832 if (!is_offset_safe(param,tpscnt,p,1)) {
2833 return False;
2834 }
2835 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
2836 return False;
2837 *rparam_len = 4;
2838 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2839 if (!*rparam) {
2840 return False;
2841 }
2842
2843 if (!share_defined(sharename)) {
2844 DEBUG(0,("api_PrintJobInfo: sharen [%s] not defined\n",
2845 sharename));
2846 return False;
2847 }
2848
2849 *rdata_len = 0;
2850
2851 /* check it's a supported varient */
2852 if ((strcmp(str1,"WWsTP")) ||
2853 (!check_printjob_info(&desc,uLevel,str2)))
2854 return(False);
2855
2856 if (!print_job_exists(sharename, jobid)) {
2857 errcode=NERR_JobNotFound;
2858 goto out;
2859 }
2860
2861 errcode = NERR_notsupported;
2862
2863 switch (function) {
2864 case 0x6:
2865 /* change job place in the queue,
2866 data gives the new place */
2867 place = SVAL(data,0);
2868 if (print_job_set_place(sharename, jobid, place)) {
2869 errcode=NERR_Success;
2870 }
2871 break;
2872
2873 case 0xb:
2874 /* change print job name, data gives the name */
2875 if (print_job_set_name(sharename, jobid, data)) {
2876 errcode=NERR_Success;
2877 }
2878 break;
2879
2880 default:
2881 return False;
2882 }
2883
2884 out:
2885 SSVALS(*rparam,0,errcode);
2886 SSVAL(*rparam,2,0); /* converter word */
2887
2888 return(True);
2889}
2890
2891
2892/****************************************************************************
2893 Get info about the server.
2894****************************************************************************/
2895
2896static bool api_RNetServerGetInfo(connection_struct *conn,uint16 vuid,
2897 char *param, int tpscnt,
2898 char *data, int tdscnt,
2899 int mdrcnt,int mprcnt,
2900 char **rdata,char **rparam,
2901 int *rdata_len,int *rparam_len)
2902{
2903 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2904 char *str2 = skip_string(param,tpscnt,str1);
2905 char *p = skip_string(param,tpscnt,str2);
2906 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
2907 char *p2;
2908 int struct_len;
2909
2910 if (!str1 || !str2 || !p) {
2911 return False;
2912 }
2913
2914 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
2915
2916 /* check it's a supported varient */
2917 if (!prefix_ok(str1,"WrLh")) {
2918 return False;
2919 }
2920
2921 switch( uLevel ) {
2922 case 0:
2923 if (strcmp(str2,"B16") != 0) {
2924 return False;
2925 }
2926 struct_len = 16;
2927 break;
2928 case 1:
2929 if (strcmp(str2,"B16BBDz") != 0) {
2930 return False;
2931 }
2932 struct_len = 26;
2933 break;
2934 case 2:
2935 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")!= 0) {
2936 return False;
2937 }
2938 struct_len = 134;
2939 break;
2940 case 3:
2941 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz") != 0) {
2942 return False;
2943 }
2944 struct_len = 144;
2945 break;
2946 case 20:
2947 if (strcmp(str2,"DN") != 0) {
2948 return False;
2949 }
2950 struct_len = 6;
2951 break;
2952 case 50:
2953 if (strcmp(str2,"B16BBDzWWzzz") != 0) {
2954 return False;
2955 }
2956 struct_len = 42;
2957 break;
2958 default:
2959 return False;
2960 }
2961
2962 *rdata_len = mdrcnt;
2963 *rdata = smb_realloc_limit(*rdata,*rdata_len);
2964 if (!*rdata) {
2965 return False;
2966 }
2967
2968 p = *rdata;
2969 p2 = p + struct_len;
2970 if (uLevel != 20) {
2971 srvstr_push(NULL, 0, p,global_myname(),16,
2972 STR_ASCII|STR_UPPER|STR_TERMINATE);
2973 }
2974 p += 16;
2975 if (uLevel > 0) {
2976 struct srv_info_struct *servers=NULL;
2977 int i,count;
2978 char *comment = NULL;
2979 TALLOC_CTX *ctx = talloc_tos();
2980 uint32 servertype= lp_default_server_announce();
2981
2982 comment = talloc_strdup(ctx,lp_serverstring());
2983 if (!comment) {
2984 return false;
2985 }
2986
2987 if ((count=get_server_info(SV_TYPE_ALL,&servers,lp_workgroup()))>0) {
2988 for (i=0;i<count;i++) {
2989 if (strequal(servers[i].name,global_myname())) {
2990 servertype = servers[i].type;
2991 TALLOC_FREE(comment);
2992 comment = talloc_strdup(ctx,
2993 servers[i].comment);
2994 if (comment) {
2995 return false;
2996 }
2997 }
2998 }
2999 }
3000
3001 SAFE_FREE(servers);
3002
3003 SCVAL(p,0,lp_major_announce_version());
3004 SCVAL(p,1,lp_minor_announce_version());
3005 SIVAL(p,2,servertype);
3006
3007 if (mdrcnt == struct_len) {
3008 SIVAL(p,6,0);
3009 } else {
3010 SIVAL(p,6,PTR_DIFF(p2,*rdata));
3011 comment = talloc_sub_advanced(
3012 ctx,
3013 lp_servicename(SNUM(conn)),
3014 conn->server_info->unix_name,
3015 conn->connectpath,
3016 conn->server_info->utok.gid,
3017 conn->server_info->sanitized_username,
3018 pdb_get_domain(conn->server_info->sam_account),
3019 comment);
3020 if (comment) {
3021 return false;
3022 }
3023 if (mdrcnt - struct_len <= 0) {
3024 return false;
3025 }
3026 push_ascii(p2,
3027 comment,
3028 MIN(mdrcnt - struct_len,
3029 MAX_SERVER_STRING_LENGTH),
3030 STR_TERMINATE);
3031 p2 = skip_string(*rdata,*rdata_len,p2);
3032 if (!p2) {
3033 return False;
3034 }
3035 }
3036 }
3037
3038 if (uLevel > 1) {
3039 return False; /* not yet implemented */
3040 }
3041
3042 *rdata_len = PTR_DIFF(p2,*rdata);
3043
3044 *rparam_len = 6;
3045 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3046 if (!*rparam) {
3047 return False;
3048 }
3049 SSVAL(*rparam,0,NERR_Success);
3050 SSVAL(*rparam,2,0); /* converter word */
3051 SSVAL(*rparam,4,*rdata_len);
3052
3053 return True;
3054}
3055
3056/****************************************************************************
3057 Get info about the server.
3058****************************************************************************/
3059
3060static bool api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid,
3061 char *param, int tpscnt,
3062 char *data, int tdscnt,
3063 int mdrcnt,int mprcnt,
3064 char **rdata,char **rparam,
3065 int *rdata_len,int *rparam_len)
3066{
3067 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3068 char *str2 = skip_string(param,tpscnt,str1);
3069 char *p = skip_string(param,tpscnt,str2);
3070 char *p2;
3071 char *endp;
3072 int level = get_safe_SVAL(param,tpscnt,p,0,-1);
3073
3074 if (!str1 || !str2 || !p) {
3075 return False;
3076 }
3077
3078 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
3079
3080 *rparam_len = 6;
3081 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3082 if (!*rparam) {
3083 return False;
3084 }
3085
3086 /* check it's a supported varient */
3087 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz"))) {
3088 return False;
3089 }
3090
3091 *rdata_len = mdrcnt + 1024;
3092 *rdata = smb_realloc_limit(*rdata,*rdata_len);
3093 if (!*rdata) {
3094 return False;
3095 }
3096
3097 SSVAL(*rparam,0,NERR_Success);
3098 SSVAL(*rparam,2,0); /* converter word */
3099
3100 p = *rdata;
3101 endp = *rdata + *rdata_len;
3102
3103 p2 = get_safe_ptr(*rdata,*rdata_len,p,22);
3104 if (!p2) {
3105 return False;
3106 }
3107
3108 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
3109 strlcpy(p2,get_local_machine_name(),PTR_DIFF(endp,p2));
3110 strupper_m(p2);
3111 p2 = skip_string(*rdata,*rdata_len,p2);
3112 if (!p2) {
3113 return False;
3114 }
3115 p += 4;
3116
3117 SIVAL(p,0,PTR_DIFF(p2,*rdata));
3118 strlcpy(p2,conn->server_info->sanitized_username,PTR_DIFF(endp,p2));
3119 p2 = skip_string(*rdata,*rdata_len,p2);
3120 if (!p2) {
3121 return False;
3122 }
3123 p += 4;
3124
3125 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
3126 strlcpy(p2,lp_workgroup(),PTR_DIFF(endp,p2));
3127 strupper_m(p2);
3128 p2 = skip_string(*rdata,*rdata_len,p2);
3129 if (!p2) {
3130 return False;
3131 }
3132 p += 4;
3133
3134 SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
3135 SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
3136 p += 2;
3137
3138 SIVAL(p,0,PTR_DIFF(p2,*rdata));
3139 strlcpy(p2,lp_workgroup(),PTR_DIFF(endp,p2)); /* don't know. login domain?? */
3140 p2 = skip_string(*rdata,*rdata_len,p2);
3141 if (!p2) {
3142 return False;
3143 }
3144 p += 4;
3145
3146 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
3147 strlcpy(p2,"",PTR_DIFF(endp,p2));
3148 p2 = skip_string(*rdata,*rdata_len,p2);
3149 if (!p2) {
3150 return False;
3151 }
3152 p += 4;
3153
3154 *rdata_len = PTR_DIFF(p2,*rdata);
3155
3156 SSVAL(*rparam,4,*rdata_len);
3157
3158 return True;
3159}
3160
3161/****************************************************************************
3162 get info about a user
3163
3164 struct user_info_11 {
3165 char usri11_name[21]; 0-20
3166 char usri11_pad; 21
3167 char *usri11_comment; 22-25
3168 char *usri11_usr_comment; 26-29
3169 unsigned short usri11_priv; 30-31
3170 unsigned long usri11_auth_flags; 32-35
3171 long usri11_password_age; 36-39
3172 char *usri11_homedir; 40-43
3173 char *usri11_parms; 44-47
3174 long usri11_last_logon; 48-51
3175 long usri11_last_logoff; 52-55
3176 unsigned short usri11_bad_pw_count; 56-57
3177 unsigned short usri11_num_logons; 58-59
3178 char *usri11_logon_server; 60-63
3179 unsigned short usri11_country_code; 64-65
3180 char *usri11_workstations; 66-69
3181 unsigned long usri11_max_storage; 70-73
3182 unsigned short usri11_units_per_week; 74-75
3183 unsigned char *usri11_logon_hours; 76-79
3184 unsigned short usri11_code_page; 80-81
3185 };
3186
3187where:
3188
3189 usri11_name specifies the user name for which information is retrieved
3190
3191 usri11_pad aligns the next data structure element to a word boundary
3192
3193 usri11_comment is a null terminated ASCII comment
3194
3195 usri11_user_comment is a null terminated ASCII comment about the user
3196
3197 usri11_priv specifies the level of the privilege assigned to the user.
3198 The possible values are:
3199
3200Name Value Description
3201USER_PRIV_GUEST 0 Guest privilege
3202USER_PRIV_USER 1 User privilege
3203USER_PRV_ADMIN 2 Administrator privilege
3204
3205 usri11_auth_flags specifies the account operator privileges. The
3206 possible values are:
3207
3208Name Value Description
3209AF_OP_PRINT 0 Print operator
3210
3211
3212Leach, Naik [Page 28]
3213
3214
3215
3216
3217INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
3218
3219
3220AF_OP_COMM 1 Communications operator
3221AF_OP_SERVER 2 Server operator
3222AF_OP_ACCOUNTS 3 Accounts operator
3223
3224
3225 usri11_password_age specifies how many seconds have elapsed since the
3226 password was last changed.
3227
3228 usri11_home_dir points to a null terminated ASCII string that contains
3229 the path name of the user's home directory.
3230
3231 usri11_parms points to a null terminated ASCII string that is set
3232 aside for use by applications.
3233
3234 usri11_last_logon specifies the time when the user last logged on.
3235 This value is stored as the number of seconds elapsed since
3236 00:00:00, January 1, 1970.
3237
3238 usri11_last_logoff specifies the time when the user last logged off.
3239 This value is stored as the number of seconds elapsed since
3240 00:00:00, January 1, 1970. A value of 0 means the last logoff
3241 time is unknown.
3242
3243 usri11_bad_pw_count specifies the number of incorrect passwords
3244 entered since the last successful logon.
3245
3246 usri11_log1_num_logons specifies the number of times this user has
3247 logged on. A value of -1 means the number of logons is unknown.
3248
3249 usri11_logon_server points to a null terminated ASCII string that
3250 contains the name of the server to which logon requests are sent.
3251 A null string indicates logon requests should be sent to the
3252 domain controller.
3253
3254 usri11_country_code specifies the country code for the user's language
3255 of choice.
3256
3257 usri11_workstations points to a null terminated ASCII string that
3258 contains the names of workstations the user may log on from.
3259 There may be up to 8 workstations, with the names separated by
3260 commas. A null strings indicates there are no restrictions.
3261
3262 usri11_max_storage specifies the maximum amount of disk space the user
3263 can occupy. A value of 0xffffffff indicates there are no
3264 restrictions.
3265
3266 usri11_units_per_week specifies the equal number of time units into
3267 which a week is divided. This value must be equal to 168.
3268
3269 usri11_logon_hours points to a 21 byte (168 bits) string that
3270 specifies the time during which the user can log on. Each bit
3271 represents one unique hour in a week. The first bit (bit 0, word
3272 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
3273
3274
3275
3276Leach, Naik [Page 29]
3277
3278
3279
3280
3281INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
3282
3283
3284 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
3285 are no restrictions.
3286
3287 usri11_code_page specifies the code page for the user's language of
3288 choice
3289
3290All of the pointers in this data structure need to be treated
3291specially. The pointer is a 32 bit pointer. The higher 16 bits need
3292to be ignored. The converter word returned in the parameters section
3293needs to be subtracted from the lower 16 bits to calculate an offset
3294into the return buffer where this ASCII string resides.
3295
3296There is no auxiliary data in the response.
3297
3298 ****************************************************************************/
3299
3300#define usri11_name 0
3301#define usri11_pad 21
3302#define usri11_comment 22
3303#define usri11_usr_comment 26
3304#define usri11_full_name 30
3305#define usri11_priv 34
3306#define usri11_auth_flags 36
3307#define usri11_password_age 40
3308#define usri11_homedir 44
3309#define usri11_parms 48
3310#define usri11_last_logon 52
3311#define usri11_last_logoff 56
3312#define usri11_bad_pw_count 60
3313#define usri11_num_logons 62
3314#define usri11_logon_server 64
3315#define usri11_country_code 68
3316#define usri11_workstations 70
3317#define usri11_max_storage 74
3318#define usri11_units_per_week 78
3319#define usri11_logon_hours 80
3320#define usri11_code_page 84
3321#define usri11_end 86
3322
3323#define USER_PRIV_GUEST 0
3324#define USER_PRIV_USER 1
3325#define USER_PRIV_ADMIN 2
3326
3327#define AF_OP_PRINT 0
3328#define AF_OP_COMM 1
3329#define AF_OP_SERVER 2
3330#define AF_OP_ACCOUNTS 3
3331
3332
3333static bool api_RNetUserGetInfo(connection_struct *conn, uint16 vuid,
3334 char *param, int tpscnt,
3335 char *data, int tdscnt,
3336 int mdrcnt,int mprcnt,
3337 char **rdata,char **rparam,
3338 int *rdata_len,int *rparam_len)
3339{
3340 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3341 char *str2 = skip_string(param,tpscnt,str1);
3342 char *UserName = skip_string(param,tpscnt,str2);
3343 char *p = skip_string(param,tpscnt,UserName);
3344 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
3345 char *p2;
3346 char *endp;
3347 const char *level_string;
3348
3349 /* get NIS home of a previously validated user - simeon */
3350 /* With share level security vuid will always be zero.
3351 Don't depend on vuser being non-null !!. JRA */
3352 user_struct *vuser = get_valid_user_struct(vuid);
3353 if(vuser != NULL) {
3354 DEBUG(3,(" Username of UID %d is %s\n",
3355 (int)vuser->server_info->utok.uid,
3356 vuser->server_info->unix_name));
3357 }
3358
3359 if (!str1 || !str2 || !UserName || !p) {
3360 return False;
3361 }
3362
3363 *rparam_len = 6;
3364 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3365 if (!*rparam) {
3366 return False;
3367 }
3368
3369 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
3370
3371 /* check it's a supported variant */
3372 if (strcmp(str1,"zWrLh") != 0) {
3373 return False;
3374 }
3375 switch( uLevel ) {
3376 case 0: level_string = "B21"; break;
3377 case 1: level_string = "B21BB16DWzzWz"; break;
3378 case 2: level_string = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
3379 case 10: level_string = "B21Bzzz"; break;
3380 case 11: level_string = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
3381 default: return False;
3382 }
3383
3384 if (strcmp(level_string,str2) != 0) {
3385 return False;
3386 }
3387
3388 *rdata_len = mdrcnt + 1024;
3389 *rdata = smb_realloc_limit(*rdata,*rdata_len);
3390 if (!*rdata) {
3391 return False;
3392 }
3393
3394 SSVAL(*rparam,0,NERR_Success);
3395 SSVAL(*rparam,2,0); /* converter word */
3396
3397 p = *rdata;
3398 endp = *rdata + *rdata_len;
3399 p2 = get_safe_ptr(*rdata,*rdata_len,p,usri11_end);
3400 if (!p2) {
3401 return False;
3402 }
3403
3404 memset(p,0,21);
3405 fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
3406
3407 if (uLevel > 0) {
3408 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
3409 *p2 = 0;
3410 }
3411
3412 if (uLevel >= 10) {
3413 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
3414 strlcpy(p2,"Comment",PTR_DIFF(endp,p2));
3415 p2 = skip_string(*rdata,*rdata_len,p2);
3416 if (!p2) {
3417 return False;
3418 }
3419
3420 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
3421 strlcpy(p2,"UserComment",PTR_DIFF(endp,p2));
3422 p2 = skip_string(*rdata,*rdata_len,p2);
3423 if (!p2) {
3424 return False;
3425 }
3426
3427 /* EEK! the cifsrap.txt doesn't have this in!!!! */
3428 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
3429 strlcpy(p2,((vuser != NULL)
3430 ? pdb_get_fullname(vuser->server_info->sam_account)
3431 : UserName),PTR_DIFF(endp,p2));
3432 p2 = skip_string(*rdata,*rdata_len,p2);
3433 if (!p2) {
3434 return False;
3435 }
3436 }
3437
3438 if (uLevel == 11) {
3439 const char *homedir = "";
3440 if (vuser != NULL) {
3441 homedir = pdb_get_homedir(
3442 vuser->server_info->sam_account);
3443 }
3444 /* modelled after NTAS 3.51 reply */
3445 SSVAL(p,usri11_priv,conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
3446 SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
3447 SIVALS(p,usri11_password_age,-1); /* password age */
3448 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
3449 strlcpy(p2, homedir, PTR_DIFF(endp,p2));
3450 p2 = skip_string(*rdata,*rdata_len,p2);
3451 if (!p2) {
3452 return False;
3453 }
3454 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
3455 strlcpy(p2,"",PTR_DIFF(endp,p2));
3456 p2 = skip_string(*rdata,*rdata_len,p2);
3457 if (!p2) {
3458 return False;
3459 }
3460 SIVAL(p,usri11_last_logon,0); /* last logon */
3461 SIVAL(p,usri11_last_logoff,0); /* last logoff */
3462 SSVALS(p,usri11_bad_pw_count,-1); /* bad pw counts */
3463 SSVALS(p,usri11_num_logons,-1); /* num logons */
3464 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
3465 strlcpy(p2,"\\\\*",PTR_DIFF(endp,p2));
3466 p2 = skip_string(*rdata,*rdata_len,p2);
3467 if (!p2) {
3468 return False;
3469 }
3470 SSVAL(p,usri11_country_code,0); /* country code */
3471
3472 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
3473 strlcpy(p2,"",PTR_DIFF(endp,p2));
3474 p2 = skip_string(*rdata,*rdata_len,p2);
3475 if (!p2) {
3476 return False;
3477 }
3478
3479 SIVALS(p,usri11_max_storage,-1); /* max storage */
3480 SSVAL(p,usri11_units_per_week,168); /* units per week */
3481 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
3482
3483 /* a simple way to get logon hours at all times. */
3484 memset(p2,0xff,21);
3485 SCVAL(p2,21,0); /* fix zero termination */
3486 p2 = skip_string(*rdata,*rdata_len,p2);
3487 if (!p2) {
3488 return False;
3489 }
3490
3491 SSVAL(p,usri11_code_page,0); /* code page */
3492 }
3493
3494 if (uLevel == 1 || uLevel == 2) {
3495 memset(p+22,' ',16); /* password */
3496 SIVALS(p,38,-1); /* password age */
3497 SSVAL(p,42,
3498 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
3499 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
3500 strlcpy(p2, vuser ? pdb_get_homedir(
3501 vuser->server_info->sam_account) : "",
3502 PTR_DIFF(endp,p2));
3503 p2 = skip_string(*rdata,*rdata_len,p2);
3504 if (!p2) {
3505 return False;
3506 }
3507 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
3508 *p2++ = 0;
3509 SSVAL(p,52,0); /* flags */
3510 SIVAL(p,54,PTR_DIFF(p2,*rdata)); /* script_path */
3511 strlcpy(p2, vuser ? pdb_get_logon_script(
3512 vuser->server_info->sam_account) : "",
3513 PTR_DIFF(endp,p2));
3514 p2 = skip_string(*rdata,*rdata_len,p2);
3515 if (!p2) {
3516 return False;
3517 }
3518 if (uLevel == 2) {
3519 SIVAL(p,60,0); /* auth_flags */
3520 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
3521 strlcpy(p2,((vuser != NULL)
3522 ? pdb_get_fullname(vuser->server_info->sam_account)
3523 : UserName),PTR_DIFF(endp,p2));
3524 p2 = skip_string(*rdata,*rdata_len,p2);
3525 if (!p2) {
3526 return False;
3527 }
3528 SIVAL(p,68,0); /* urs_comment */
3529 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
3530 strlcpy(p2,"",PTR_DIFF(endp,p2));
3531 p2 = skip_string(*rdata,*rdata_len,p2);
3532 if (!p2) {
3533 return False;
3534 }
3535 SIVAL(p,76,0); /* workstations */
3536 SIVAL(p,80,0); /* last_logon */
3537 SIVAL(p,84,0); /* last_logoff */
3538 SIVALS(p,88,-1); /* acct_expires */
3539 SIVALS(p,92,-1); /* max_storage */
3540 SSVAL(p,96,168); /* units_per_week */
3541 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
3542 memset(p2,-1,21);
3543 p2 += 21;
3544 SSVALS(p,102,-1); /* bad_pw_count */
3545 SSVALS(p,104,-1); /* num_logons */
3546 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
3547 {
3548 TALLOC_CTX *ctx = talloc_tos();
3549 int space_rem = *rdata_len - (p2 - *rdata);
3550 char *tmp;
3551
3552 if (space_rem <= 0) {
3553 return false;
3554 }
3555 tmp = talloc_strdup(ctx, "\\\\%L");
3556 if (!tmp) {
3557 return false;
3558 }
3559 tmp = talloc_sub_basic(ctx,
3560 "",
3561 "",
3562 tmp);
3563 if (!tmp) {
3564 return false;
3565 }
3566
3567 push_ascii(p2,
3568 tmp,
3569 space_rem,
3570 STR_TERMINATE);
3571 }
3572 p2 = skip_string(*rdata,*rdata_len,p2);
3573 if (!p2) {
3574 return False;
3575 }
3576 SSVAL(p,110,49); /* country_code */
3577 SSVAL(p,112,860); /* code page */
3578 }
3579 }
3580
3581 *rdata_len = PTR_DIFF(p2,*rdata);
3582
3583 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
3584
3585 return(True);
3586}
3587
3588static bool api_WWkstaUserLogon(connection_struct *conn,uint16 vuid,
3589 char *param, int tpscnt,
3590 char *data, int tdscnt,
3591 int mdrcnt,int mprcnt,
3592 char **rdata,char **rparam,
3593 int *rdata_len,int *rparam_len)
3594{
3595 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3596 char *str2 = skip_string(param,tpscnt,str1);
3597 char *p = skip_string(param,tpscnt,str2);
3598 int uLevel;
3599 struct pack_desc desc;
3600 char* name;
3601 /* With share level security vuid will always be zero.
3602 Don't depend on vuser being non-null !!. JRA */
3603 user_struct *vuser = get_valid_user_struct(vuid);
3604
3605 if (!str1 || !str2 || !p) {
3606 return False;
3607 }
3608
3609 if(vuser != NULL) {
3610 DEBUG(3,(" Username of UID %d is %s\n",
3611 (int)vuser->server_info->utok.uid,
3612 vuser->server_info->unix_name));
3613 }
3614
3615 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
3616 name = get_safe_str_ptr(param,tpscnt,p,2);
3617 if (!name) {
3618 return False;
3619 }
3620
3621 memset((char *)&desc,'\0',sizeof(desc));
3622
3623 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
3624
3625 /* check it's a supported varient */
3626 if (strcmp(str1,"OOWb54WrLh") != 0) {
3627 return False;
3628 }
3629 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) {
3630 return False;
3631 }
3632 if (mdrcnt > 0) {
3633 *rdata = smb_realloc_limit(*rdata,mdrcnt);
3634 if (!*rdata) {
3635 return False;
3636 }
3637 }
3638
3639 desc.base = *rdata;
3640 desc.buflen = mdrcnt;
3641 desc.subformat = NULL;
3642 desc.format = str2;
3643
3644 if (init_package(&desc,1,0)) {
3645 PACKI(&desc,"W",0); /* code */
3646 PACKS(&desc,"B21",name); /* eff. name */
3647 PACKS(&desc,"B",""); /* pad */
3648 PACKI(&desc,"W", conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
3649 PACKI(&desc,"D",0); /* auth flags XXX */
3650 PACKI(&desc,"W",0); /* num logons */
3651 PACKI(&desc,"W",0); /* bad pw count */
3652 PACKI(&desc,"D",0); /* last logon */
3653 PACKI(&desc,"D",-1); /* last logoff */
3654 PACKI(&desc,"D",-1); /* logoff time */
3655 PACKI(&desc,"D",-1); /* kickoff time */
3656 PACKI(&desc,"D",0); /* password age */
3657 PACKI(&desc,"D",0); /* password can change */
3658 PACKI(&desc,"D",-1); /* password must change */
3659
3660 {
3661 fstring mypath;
3662 fstrcpy(mypath,"\\\\");
3663 fstrcat(mypath,get_local_machine_name());
3664 strupper_m(mypath);
3665 PACKS(&desc,"z",mypath); /* computer */
3666 }
3667
3668 PACKS(&desc,"z",lp_workgroup());/* domain */
3669 PACKS(&desc,"z", vuser ? pdb_get_logon_script(
3670 vuser->server_info->sam_account) : ""); /* script path */
3671 PACKI(&desc,"D",0x00000000); /* reserved */
3672 }
3673
3674 *rdata_len = desc.usedlen;
3675 *rparam_len = 6;
3676 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3677 if (!*rparam) {
3678 return False;
3679 }
3680 SSVALS(*rparam,0,desc.errcode);
3681 SSVAL(*rparam,2,0);
3682 SSVAL(*rparam,4,desc.neededlen);
3683
3684 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
3685
3686 return True;
3687}
3688
3689/****************************************************************************
3690 api_WAccessGetUserPerms
3691****************************************************************************/
3692
3693static bool api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid,
3694 char *param, int tpscnt,
3695 char *data, int tdscnt,
3696 int mdrcnt,int mprcnt,
3697 char **rdata,char **rparam,
3698 int *rdata_len,int *rparam_len)
3699{
3700 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3701 char *str2 = skip_string(param,tpscnt,str1);
3702 char *user = skip_string(param,tpscnt,str2);
3703 char *resource = skip_string(param,tpscnt,user);
3704
3705 if (!str1 || !str2 || !user || !resource) {
3706 return False;
3707 }
3708
3709 if (skip_string(param,tpscnt,resource) == NULL) {
3710 return False;
3711 }
3712 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
3713
3714 /* check it's a supported varient */
3715 if (strcmp(str1,"zzh") != 0) {
3716 return False;
3717 }
3718 if (strcmp(str2,"") != 0) {
3719 return False;
3720 }
3721
3722 *rparam_len = 6;
3723 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3724 if (!*rparam) {
3725 return False;
3726 }
3727 SSVALS(*rparam,0,0); /* errorcode */
3728 SSVAL(*rparam,2,0); /* converter word */
3729 SSVAL(*rparam,4,0x7f); /* permission flags */
3730
3731 return True;
3732}
3733
3734/****************************************************************************
3735 api_WPrintJobEnumerate
3736 ****************************************************************************/
3737
3738static bool api_WPrintJobGetInfo(connection_struct *conn, uint16 vuid,
3739 char *param, int tpscnt,
3740 char *data, int tdscnt,
3741 int mdrcnt,int mprcnt,
3742 char **rdata,char **rparam,
3743 int *rdata_len,int *rparam_len)
3744{
3745 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3746 char *str2 = skip_string(param,tpscnt,str1);
3747 char *p = skip_string(param,tpscnt,str2);
3748 int uLevel;
3749 int count;
3750 int i;
3751 int snum;
3752 fstring sharename;
3753 uint32 jobid;
3754 struct pack_desc desc;
3755 print_queue_struct *queue=NULL;
3756 print_status_struct status;
3757 char *tmpdata=NULL;
3758
3759 if (!str1 || !str2 || !p) {
3760 return False;
3761 }
3762
3763 uLevel = get_safe_SVAL(param,tpscnt,p,2,-1);
3764
3765 memset((char *)&desc,'\0',sizeof(desc));
3766 memset((char *)&status,'\0',sizeof(status));
3767
3768 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
3769
3770 /* check it's a supported varient */
3771 if (strcmp(str1,"WWrLh") != 0) {
3772 return False;
3773 }
3774 if (!check_printjob_info(&desc,uLevel,str2)) {
3775 return False;
3776 }
3777
3778 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid)) {
3779 return False;
3780 }
3781
3782 snum = lp_servicenumber( sharename);
3783 if (snum < 0 || !VALID_SNUM(snum)) {
3784 return(False);
3785 }
3786
3787 count = print_queue_status(snum,&queue,&status);
3788 for (i = 0; i < count; i++) {
3789 if (queue[i].job == jobid) {
3790 break;
3791 }
3792 }
3793
3794 if (mdrcnt > 0) {
3795 *rdata = smb_realloc_limit(*rdata,mdrcnt);
3796 if (!*rdata) {
3797 return False;
3798 }
3799 desc.base = *rdata;
3800 desc.buflen = mdrcnt;
3801 } else {
3802 /*
3803 * Don't return data but need to get correct length
3804 * init_package will return wrong size if buflen=0
3805 */
3806 desc.buflen = getlen(desc.format);
3807 desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen );
3808 }
3809
3810 if (init_package(&desc,1,0)) {
3811 if (i < count) {
3812 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
3813 *rdata_len = desc.usedlen;
3814 } else {
3815 desc.errcode = NERR_JobNotFound;
3816 *rdata_len = 0;
3817 }
3818 }
3819
3820 *rparam_len = 6;
3821 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3822 if (!*rparam) {
3823 return False;
3824 }
3825 SSVALS(*rparam,0,desc.errcode);
3826 SSVAL(*rparam,2,0);
3827 SSVAL(*rparam,4,desc.neededlen);
3828
3829 SAFE_FREE(queue);
3830 SAFE_FREE(tmpdata);
3831
3832 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
3833
3834 return True;
3835}
3836
3837static bool api_WPrintJobEnumerate(connection_struct *conn, uint16 vuid,
3838 char *param, int tpscnt,
3839 char *data, int tdscnt,
3840 int mdrcnt,int mprcnt,
3841 char **rdata,char **rparam,
3842 int *rdata_len,int *rparam_len)
3843{
3844 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3845 char *str2 = skip_string(param,tpscnt,str1);
3846 char *p = skip_string(param,tpscnt,str2);
3847 char *name = p;
3848 int uLevel;
3849 int count;
3850 int i, succnt=0;
3851 int snum;
3852 struct pack_desc desc;
3853 print_queue_struct *queue=NULL;
3854 print_status_struct status;
3855
3856 if (!str1 || !str2 || !p) {
3857 return False;
3858 }
3859
3860 memset((char *)&desc,'\0',sizeof(desc));
3861 memset((char *)&status,'\0',sizeof(status));
3862
3863 p = skip_string(param,tpscnt,p);
3864 if (!p) {
3865 return False;
3866 }
3867 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
3868
3869 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
3870
3871 /* check it's a supported variant */
3872 if (strcmp(str1,"zWrLeh") != 0) {
3873 return False;
3874 }
3875
3876 if (uLevel > 2) {
3877 return False; /* defined only for uLevel 0,1,2 */
3878 }
3879
3880 if (!check_printjob_info(&desc,uLevel,str2)) {
3881 return False;
3882 }
3883
3884 snum = find_service(name);
3885 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) ) {
3886 return False;
3887 }
3888
3889 count = print_queue_status(snum,&queue,&status);
3890 if (mdrcnt > 0) {
3891 *rdata = smb_realloc_limit(*rdata,mdrcnt);
3892 if (!*rdata) {
3893 return False;
3894 }
3895 }
3896 desc.base = *rdata;
3897 desc.buflen = mdrcnt;
3898
3899 if (init_package(&desc,count,0)) {
3900 succnt = 0;
3901 for (i = 0; i < count; i++) {
3902 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
3903 if (desc.errcode == NERR_Success) {
3904 succnt = i+1;
3905 }
3906 }
3907 }
3908
3909 *rdata_len = desc.usedlen;
3910
3911 *rparam_len = 8;
3912 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3913 if (!*rparam) {
3914 return False;
3915 }
3916 SSVALS(*rparam,0,desc.errcode);
3917 SSVAL(*rparam,2,0);
3918 SSVAL(*rparam,4,succnt);
3919 SSVAL(*rparam,6,count);
3920
3921 SAFE_FREE(queue);
3922
3923 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
3924
3925 return True;
3926}
3927
3928static int check_printdest_info(struct pack_desc* desc,
3929 int uLevel, char* id)
3930{
3931 desc->subformat = NULL;
3932 switch( uLevel ) {
3933 case 0:
3934 desc->format = "B9";
3935 break;
3936 case 1:
3937 desc->format = "B9B21WWzW";
3938 break;
3939 case 2:
3940 desc->format = "z";
3941 break;
3942 case 3:
3943 desc->format = "zzzWWzzzWW";
3944 break;
3945 default:
3946 DEBUG(0,("check_printdest_info: invalid level %d\n",
3947 uLevel));
3948 return False;
3949 }
3950 if (id == NULL || strcmp(desc->format,id) != 0) {
3951 DEBUG(0,("check_printdest_info: invalid string %s\n",
3952 id ? id : "<NULL>" ));
3953 return False;
3954 }
3955 return True;
3956}
3957
3958static void fill_printdest_info(connection_struct *conn, int snum, int uLevel,
3959 struct pack_desc* desc)
3960{
3961 char buf[100];
3962
3963 strncpy(buf,SERVICE(snum),sizeof(buf)-1);
3964 buf[sizeof(buf)-1] = 0;
3965 strupper_m(buf);
3966
3967 if (uLevel <= 1) {
3968 PACKS(desc,"B9",buf); /* szName */
3969 if (uLevel == 1) {
3970 PACKS(desc,"B21",""); /* szUserName */
3971 PACKI(desc,"W",0); /* uJobId */
3972 PACKI(desc,"W",0); /* fsStatus */
3973 PACKS(desc,"z",""); /* pszStatus */
3974 PACKI(desc,"W",0); /* time */
3975 }
3976 }
3977
3978 if (uLevel == 2 || uLevel == 3) {
3979 PACKS(desc,"z",buf); /* pszPrinterName */
3980 if (uLevel == 3) {
3981 PACKS(desc,"z",""); /* pszUserName */
3982 PACKS(desc,"z",""); /* pszLogAddr */
3983 PACKI(desc,"W",0); /* uJobId */
3984 PACKI(desc,"W",0); /* fsStatus */
3985 PACKS(desc,"z",""); /* pszStatus */
3986 PACKS(desc,"z",""); /* pszComment */
3987 PACKS(desc,"z","NULL"); /* pszDrivers */
3988 PACKI(desc,"W",0); /* time */
3989 PACKI(desc,"W",0); /* pad1 */
3990 }
3991 }
3992}
3993
3994static bool api_WPrintDestGetInfo(connection_struct *conn, uint16 vuid,
3995 char *param, int tpscnt,
3996 char *data, int tdscnt,
3997 int mdrcnt,int mprcnt,
3998 char **rdata,char **rparam,
3999 int *rdata_len,int *rparam_len)
4000{
4001 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4002 char *str2 = skip_string(param,tpscnt,str1);
4003 char *p = skip_string(param,tpscnt,str2);
4004 char* PrinterName = p;
4005 int uLevel;
4006 struct pack_desc desc;
4007 int snum;
4008 char *tmpdata=NULL;
4009
4010 if (!str1 || !str2 || !p) {
4011 return False;
4012 }
4013
4014 memset((char *)&desc,'\0',sizeof(desc));
4015
4016 p = skip_string(param,tpscnt,p);
4017 if (!p) {
4018 return False;
4019 }
4020 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4021
4022 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
4023
4024 /* check it's a supported varient */
4025 if (strcmp(str1,"zWrLh") != 0) {
4026 return False;
4027 }
4028 if (!check_printdest_info(&desc,uLevel,str2)) {
4029 return False;
4030 }
4031
4032 snum = find_service(PrinterName);
4033 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) ) {
4034 *rdata_len = 0;
4035 desc.errcode = NERR_DestNotFound;
4036 desc.neededlen = 0;
4037 } else {
4038 if (mdrcnt > 0) {
4039 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4040 if (!*rdata) {
4041 return False;
4042 }
4043 desc.base = *rdata;
4044 desc.buflen = mdrcnt;
4045 } else {
4046 /*
4047 * Don't return data but need to get correct length
4048 * init_package will return wrong size if buflen=0
4049 */
4050 desc.buflen = getlen(desc.format);
4051 desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen );
4052 }
4053 if (init_package(&desc,1,0)) {
4054 fill_printdest_info(conn,snum,uLevel,&desc);
4055 }
4056 *rdata_len = desc.usedlen;
4057 }
4058
4059 *rparam_len = 6;
4060 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4061 if (!*rparam) {
4062 return False;
4063 }
4064 SSVALS(*rparam,0,desc.errcode);
4065 SSVAL(*rparam,2,0);
4066 SSVAL(*rparam,4,desc.neededlen);
4067
4068 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
4069 SAFE_FREE(tmpdata);
4070
4071 return True;
4072}
4073
4074static bool api_WPrintDestEnum(connection_struct *conn, uint16 vuid,
4075 char *param, int tpscnt,
4076 char *data, int tdscnt,
4077 int mdrcnt,int mprcnt,
4078 char **rdata,char **rparam,
4079 int *rdata_len,int *rparam_len)
4080{
4081 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4082 char *str2 = skip_string(param,tpscnt,str1);
4083 char *p = skip_string(param,tpscnt,str2);
4084 int uLevel;
4085 int queuecnt;
4086 int i, n, succnt=0;
4087 struct pack_desc desc;
4088 int services = lp_numservices();
4089
4090 if (!str1 || !str2 || !p) {
4091 return False;
4092 }
4093
4094 memset((char *)&desc,'\0',sizeof(desc));
4095
4096 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4097
4098 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
4099
4100 /* check it's a supported varient */
4101 if (strcmp(str1,"WrLeh") != 0) {
4102 return False;
4103 }
4104 if (!check_printdest_info(&desc,uLevel,str2)) {
4105 return False;
4106 }
4107
4108 queuecnt = 0;
4109 for (i = 0; i < services; i++) {
4110 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
4111 queuecnt++;
4112 }
4113 }
4114
4115 if (mdrcnt > 0) {
4116 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4117 if (!*rdata) {
4118 return False;
4119 }
4120 }
4121
4122 desc.base = *rdata;
4123 desc.buflen = mdrcnt;
4124 if (init_package(&desc,queuecnt,0)) {
4125 succnt = 0;
4126 n = 0;
4127 for (i = 0; i < services; i++) {
4128 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
4129 fill_printdest_info(conn,i,uLevel,&desc);
4130 n++;
4131 if (desc.errcode == NERR_Success) {
4132 succnt = n;
4133 }
4134 }
4135 }
4136 }
4137
4138 *rdata_len = desc.usedlen;
4139
4140 *rparam_len = 8;
4141 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4142 if (!*rparam) {
4143 return False;
4144 }
4145 SSVALS(*rparam,0,desc.errcode);
4146 SSVAL(*rparam,2,0);
4147 SSVAL(*rparam,4,succnt);
4148 SSVAL(*rparam,6,queuecnt);
4149
4150 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
4151
4152 return True;
4153}
4154
4155static bool api_WPrintDriverEnum(connection_struct *conn, uint16 vuid,
4156 char *param, int tpscnt,
4157 char *data, int tdscnt,
4158 int mdrcnt,int mprcnt,
4159 char **rdata,char **rparam,
4160 int *rdata_len,int *rparam_len)
4161{
4162 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4163 char *str2 = skip_string(param,tpscnt,str1);
4164 char *p = skip_string(param,tpscnt,str2);
4165 int uLevel;
4166 int succnt;
4167 struct pack_desc desc;
4168
4169 if (!str1 || !str2 || !p) {
4170 return False;
4171 }
4172
4173 memset((char *)&desc,'\0',sizeof(desc));
4174
4175 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4176
4177 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
4178
4179 /* check it's a supported varient */
4180 if (strcmp(str1,"WrLeh") != 0) {
4181 return False;
4182 }
4183 if (uLevel != 0 || strcmp(str2,"B41") != 0) {
4184 return False;
4185 }
4186
4187 if (mdrcnt > 0) {
4188 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4189 if (!*rdata) {
4190 return False;
4191 }
4192 }
4193 desc.base = *rdata;
4194 desc.buflen = mdrcnt;
4195 if (init_package(&desc,1,0)) {
4196 PACKS(&desc,"B41","NULL");
4197 }
4198
4199 succnt = (desc.errcode == NERR_Success ? 1 : 0);
4200
4201 *rdata_len = desc.usedlen;
4202
4203 *rparam_len = 8;
4204 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4205 if (!*rparam) {
4206 return False;
4207 }
4208 SSVALS(*rparam,0,desc.errcode);
4209 SSVAL(*rparam,2,0);
4210 SSVAL(*rparam,4,succnt);
4211 SSVAL(*rparam,6,1);
4212
4213 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
4214
4215 return True;
4216}
4217
4218static bool api_WPrintQProcEnum(connection_struct *conn, uint16 vuid,
4219 char *param, int tpscnt,
4220 char *data, int tdscnt,
4221 int mdrcnt,int mprcnt,
4222 char **rdata,char **rparam,
4223 int *rdata_len,int *rparam_len)
4224{
4225 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4226 char *str2 = skip_string(param,tpscnt,str1);
4227 char *p = skip_string(param,tpscnt,str2);
4228 int uLevel;
4229 int succnt;
4230 struct pack_desc desc;
4231
4232 if (!str1 || !str2 || !p) {
4233 return False;
4234 }
4235 memset((char *)&desc,'\0',sizeof(desc));
4236
4237 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4238
4239 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
4240
4241 /* check it's a supported varient */
4242 if (strcmp(str1,"WrLeh") != 0) {
4243 return False;
4244 }
4245 if (uLevel != 0 || strcmp(str2,"B13") != 0) {
4246 return False;
4247 }
4248
4249 if (mdrcnt > 0) {
4250 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4251 if (!*rdata) {
4252 return False;
4253 }
4254 }
4255 desc.base = *rdata;
4256 desc.buflen = mdrcnt;
4257 desc.format = str2;
4258 if (init_package(&desc,1,0)) {
4259 PACKS(&desc,"B13","lpd");
4260 }
4261
4262 succnt = (desc.errcode == NERR_Success ? 1 : 0);
4263
4264 *rdata_len = desc.usedlen;
4265
4266 *rparam_len = 8;
4267 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4268 if (!*rparam) {
4269 return False;
4270 }
4271 SSVALS(*rparam,0,desc.errcode);
4272 SSVAL(*rparam,2,0);
4273 SSVAL(*rparam,4,succnt);
4274 SSVAL(*rparam,6,1);
4275
4276 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
4277
4278 return True;
4279}
4280
4281static bool api_WPrintPortEnum(connection_struct *conn, uint16 vuid,
4282 char *param, int tpscnt,
4283 char *data, int tdscnt,
4284 int mdrcnt,int mprcnt,
4285 char **rdata,char **rparam,
4286 int *rdata_len,int *rparam_len)
4287{
4288 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4289 char *str2 = skip_string(param,tpscnt,str1);
4290 char *p = skip_string(param,tpscnt,str2);
4291 int uLevel;
4292 int succnt;
4293 struct pack_desc desc;
4294
4295 if (!str1 || !str2 || !p) {
4296 return False;
4297 }
4298
4299 memset((char *)&desc,'\0',sizeof(desc));
4300
4301 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4302
4303 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
4304
4305 /* check it's a supported varient */
4306 if (strcmp(str1,"WrLeh") != 0) {
4307 return False;
4308 }
4309 if (uLevel != 0 || strcmp(str2,"B9") != 0) {
4310 return False;
4311 }
4312
4313 if (mdrcnt > 0) {
4314 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4315 if (!*rdata) {
4316 return False;
4317 }
4318 }
4319 memset((char *)&desc,'\0',sizeof(desc));
4320 desc.base = *rdata;
4321 desc.buflen = mdrcnt;
4322 desc.format = str2;
4323 if (init_package(&desc,1,0)) {
4324 PACKS(&desc,"B13","lp0");
4325 }
4326
4327 succnt = (desc.errcode == NERR_Success ? 1 : 0);
4328
4329 *rdata_len = desc.usedlen;
4330
4331 *rparam_len = 8;
4332 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4333 if (!*rparam) {
4334 return False;
4335 }
4336 SSVALS(*rparam,0,desc.errcode);
4337 SSVAL(*rparam,2,0);
4338 SSVAL(*rparam,4,succnt);
4339 SSVAL(*rparam,6,1);
4340
4341 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
4342
4343 return True;
4344}
4345
4346/****************************************************************************
4347 List open sessions
4348 ****************************************************************************/
4349
4350static bool api_RNetSessionEnum(connection_struct *conn, uint16 vuid,
4351 char *param, int tpscnt,
4352 char *data, int tdscnt,
4353 int mdrcnt,int mprcnt,
4354 char **rdata,char **rparam,
4355 int *rdata_len,int *rparam_len)
4356
4357{
4358 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4359 char *str2 = skip_string(param,tpscnt,str1);
4360 char *p = skip_string(param,tpscnt,str2);
4361 int uLevel;
4362 struct pack_desc desc;
4363 struct sessionid *session_list;
4364 int i, num_sessions;
4365
4366 if (!str1 || !str2 || !p) {
4367 return False;
4368 }
4369
4370 memset((char *)&desc,'\0',sizeof(desc));
4371
4372 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4373
4374 DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel));
4375 DEBUG(7,("RNetSessionEnum req string=%s\n",str1));
4376 DEBUG(7,("RNetSessionEnum ret string=%s\n",str2));
4377
4378 /* check it's a supported varient */
4379 if (strcmp(str1,RAP_NetSessionEnum_REQ) != 0) {
4380 return False;
4381 }
4382 if (uLevel != 2 || strcmp(str2,RAP_SESSION_INFO_L2) != 0) {
4383 return False;
4384 }
4385
4386 num_sessions = list_sessions(talloc_tos(), &session_list);
4387
4388 if (mdrcnt > 0) {
4389 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4390 if (!*rdata) {
4391 return False;
4392 }
4393 }
4394 memset((char *)&desc,'\0',sizeof(desc));
4395 desc.base = *rdata;
4396 desc.buflen = mdrcnt;
4397 desc.format = str2;
4398 if (!init_package(&desc,num_sessions,0)) {
4399 return False;
4400 }
4401
4402 for(i=0; i<num_sessions; i++) {
4403 PACKS(&desc, "z", session_list[i].remote_machine);
4404 PACKS(&desc, "z", session_list[i].username);
4405 PACKI(&desc, "W", 1); /* num conns */
4406 PACKI(&desc, "W", 0); /* num opens */
4407 PACKI(&desc, "W", 1); /* num users */
4408 PACKI(&desc, "D", 0); /* session time */
4409 PACKI(&desc, "D", 0); /* idle time */
4410 PACKI(&desc, "D", 0); /* flags */
4411 PACKS(&desc, "z", "Unknown Client"); /* client type string */
4412 }
4413
4414 *rdata_len = desc.usedlen;
4415
4416 *rparam_len = 8;
4417 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4418 if (!*rparam) {
4419 return False;
4420 }
4421 SSVALS(*rparam,0,desc.errcode);
4422 SSVAL(*rparam,2,0); /* converter */
4423 SSVAL(*rparam,4,num_sessions); /* count */
4424
4425 DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc.errcode));
4426
4427 return True;
4428}
4429
4430
4431/****************************************************************************
4432 The buffer was too small.
4433 ****************************************************************************/
4434
4435static bool api_TooSmall(connection_struct *conn,uint16 vuid, char *param, char *data,
4436 int mdrcnt, int mprcnt,
4437 char **rdata, char **rparam,
4438 int *rdata_len, int *rparam_len)
4439{
4440 *rparam_len = MIN(*rparam_len,mprcnt);
4441 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4442 if (!*rparam) {
4443 return False;
4444 }
4445
4446 *rdata_len = 0;
4447
4448 SSVAL(*rparam,0,NERR_BufTooSmall);
4449
4450 DEBUG(3,("Supplied buffer too small in API command\n"));
4451
4452 return True;
4453}
4454
4455/****************************************************************************
4456 The request is not supported.
4457 ****************************************************************************/
4458
4459static bool api_Unsupported(connection_struct *conn, uint16 vuid,
4460 char *param, int tpscnt,
4461 char *data, int tdscnt,
4462 int mdrcnt, int mprcnt,
4463 char **rdata, char **rparam,
4464 int *rdata_len, int *rparam_len)
4465{
4466 *rparam_len = 4;
4467 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4468 if (!*rparam) {
4469 return False;
4470 }
4471
4472 *rdata_len = 0;
4473
4474 SSVAL(*rparam,0,NERR_notsupported);
4475 SSVAL(*rparam,2,0); /* converter word */
4476
4477 DEBUG(3,("Unsupported API command\n"));
4478
4479 return True;
4480}
4481
4482static const struct {
4483 const char *name;
4484 int id;
4485 bool (*fn)(connection_struct *, uint16,
4486 char *, int,
4487 char *, int,
4488 int,int,char **,char **,int *,int *);
4489 bool auth_user; /* Deny anonymous access? */
4490} api_commands[] = {
4491 {"RNetShareEnum", RAP_WshareEnum, api_RNetShareEnum, True},
4492 {"RNetShareGetInfo", RAP_WshareGetInfo, api_RNetShareGetInfo},
4493 {"RNetShareAdd", RAP_WshareAdd, api_RNetShareAdd},
4494 {"RNetSessionEnum", RAP_WsessionEnum, api_RNetSessionEnum, True},
4495 {"RNetServerGetInfo", RAP_WserverGetInfo, api_RNetServerGetInfo},
4496 {"RNetGroupEnum", RAP_WGroupEnum, api_RNetGroupEnum, True},
4497 {"RNetGroupGetUsers", RAP_WGroupGetUsers, api_RNetGroupGetUsers, True},
4498 {"RNetUserEnum", RAP_WUserEnum, api_RNetUserEnum, True},
4499 {"RNetUserGetInfo", RAP_WUserGetInfo, api_RNetUserGetInfo},
4500 {"NetUserGetGroups", RAP_WUserGetGroups, api_NetUserGetGroups},
4501 {"NetWkstaGetInfo", RAP_WWkstaGetInfo, api_NetWkstaGetInfo},
4502 {"DosPrintQEnum", RAP_WPrintQEnum, api_DosPrintQEnum, True},
4503 {"DosPrintQGetInfo", RAP_WPrintQGetInfo, api_DosPrintQGetInfo},
4504 {"WPrintQueuePause", RAP_WPrintQPause, api_WPrintQueueCtrl},
4505 {"WPrintQueueResume", RAP_WPrintQContinue, api_WPrintQueueCtrl},
4506 {"WPrintJobEnumerate",RAP_WPrintJobEnum, api_WPrintJobEnumerate},
4507 {"WPrintJobGetInfo", RAP_WPrintJobGetInfo, api_WPrintJobGetInfo},
4508 {"RDosPrintJobDel", RAP_WPrintJobDel, api_RDosPrintJobDel},
4509 {"RDosPrintJobPause", RAP_WPrintJobPause, api_RDosPrintJobDel},
4510 {"RDosPrintJobResume",RAP_WPrintJobContinue, api_RDosPrintJobDel},
4511 {"WPrintDestEnum", RAP_WPrintDestEnum, api_WPrintDestEnum},
4512 {"WPrintDestGetInfo", RAP_WPrintDestGetInfo, api_WPrintDestGetInfo},
4513 {"NetRemoteTOD", RAP_NetRemoteTOD, api_NetRemoteTOD},
4514 {"WPrintQueuePurge", RAP_WPrintQPurge, api_WPrintQueueCtrl},
4515 {"NetServerEnum", RAP_NetServerEnum2, api_RNetServerEnum}, /* anon OK */
4516 {"WAccessGetUserPerms",RAP_WAccessGetUserPerms,api_WAccessGetUserPerms},
4517 {"SetUserPassword", RAP_WUserPasswordSet2, api_SetUserPassword},
4518 {"WWkstaUserLogon", RAP_WWkstaUserLogon, api_WWkstaUserLogon},
4519 {"PrintJobInfo", RAP_WPrintJobSetInfo, api_PrintJobInfo},
4520 {"WPrintDriverEnum", RAP_WPrintDriverEnum, api_WPrintDriverEnum},
4521 {"WPrintQProcEnum", RAP_WPrintQProcessorEnum,api_WPrintQProcEnum},
4522 {"WPrintPortEnum", RAP_WPrintPortEnum, api_WPrintPortEnum},
4523 {"SamOEMChangePassword",RAP_SamOEMChgPasswordUser2_P,api_SamOEMChangePassword}, /* anon OK */
4524 {NULL, -1, api_Unsupported}
4525 /* The following RAP calls are not implemented by Samba:
4526
4527 RAP_WFileEnum2 - anon not OK
4528 */
4529};
4530
4531
4532/****************************************************************************
4533 Handle remote api calls.
4534****************************************************************************/
4535
4536void api_reply(connection_struct *conn, uint16 vuid,
4537 struct smb_request *req,
4538 char *data, char *params,
4539 int tdscnt, int tpscnt,
4540 int mdrcnt, int mprcnt)
4541{
4542 int api_command;
4543 char *rdata = NULL;
4544 char *rparam = NULL;
4545 const char *name1 = NULL;
4546 const char *name2 = NULL;
4547 int rdata_len = 0;
4548 int rparam_len = 0;
4549 bool reply=False;
4550 int i;
4551
4552 if (!params) {
4553 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
4554 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4555 return;
4556 }
4557
4558 if (tpscnt < 2) {
4559 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4560 return;
4561 }
4562 api_command = SVAL(params,0);
4563 /* Is there a string at position params+2 ? */
4564 if (skip_string(params,tpscnt,params+2)) {
4565 name1 = params + 2;
4566 } else {
4567 name1 = "";
4568 }
4569 name2 = skip_string(params,tpscnt,params+2);
4570 if (!name2) {
4571 name2 = "";
4572 }
4573
4574 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
4575 api_command,
4576 name1,
4577 name2,
4578 tdscnt,tpscnt,mdrcnt,mprcnt));
4579
4580 for (i=0;api_commands[i].name;i++) {
4581 if (api_commands[i].id == api_command && api_commands[i].fn) {
4582 DEBUG(3,("Doing %s\n",api_commands[i].name));
4583 break;
4584 }
4585 }
4586
4587 /* Check whether this api call can be done anonymously */
4588
4589 if (api_commands[i].auth_user && lp_restrict_anonymous()) {
4590 user_struct *user = get_valid_user_struct(vuid);
4591
4592 if (!user || user->server_info->guest) {
4593 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4594 return;
4595 }
4596 }
4597
4598 rdata = (char *)SMB_MALLOC(1024);
4599 if (rdata) {
4600 memset(rdata,'\0',1024);
4601 }
4602
4603 rparam = (char *)SMB_MALLOC(1024);
4604 if (rparam) {
4605 memset(rparam,'\0',1024);
4606 }
4607
4608 if(!rdata || !rparam) {
4609 DEBUG(0,("api_reply: malloc fail !\n"));
4610 SAFE_FREE(rdata);
4611 SAFE_FREE(rparam);
4612 reply_nterror(req, NT_STATUS_NO_MEMORY);
4613 return;
4614 }
4615
4616 reply = api_commands[i].fn(conn,
4617 vuid,
4618 params,tpscnt, /* params + length */
4619 data,tdscnt, /* data + length */
4620 mdrcnt,mprcnt,
4621 &rdata,&rparam,&rdata_len,&rparam_len);
4622
4623
4624 if (rdata_len > mdrcnt || rparam_len > mprcnt) {
4625 reply = api_TooSmall(conn,vuid,params,data,mdrcnt,mprcnt,
4626 &rdata,&rparam,&rdata_len,&rparam_len);
4627 }
4628
4629 /* if we get False back then it's actually unsupported */
4630 if (!reply) {
4631 reply = api_Unsupported(conn,vuid,params,tpscnt,data,tdscnt,mdrcnt,mprcnt,
4632 &rdata,&rparam,&rdata_len,&rparam_len);
4633 }
4634
4635 /* If api_Unsupported returns false we can't return anything. */
4636 if (reply) {
4637 send_trans_reply(conn, req->inbuf, rparam, rparam_len,
4638 rdata, rdata_len, False);
4639 }
4640
4641 SAFE_FREE(rdata);
4642 SAFE_FREE(rparam);
4643 return;
4644}
Note: See TracBrowser for help on using the repository browser.