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

Last change on this file since 411 was 411, checked in by Herwig Bauernfeind, 15 years ago

Update Samba 3.3.x to 3.3.11

File size: 117.6 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 string_truncate(s->comment, MAX_SERVER_STRING_LENGTH);
1218
1219 s->domain[0] = '\0';
1220 if (!next_token_talloc(frame,&ptr,&p, NULL)) {
1221 /* this allows us to cope with an old nmbd */
1222 fstrcpy(s->domain,lp_workgroup());
1223 } else {
1224 fstrcpy(s->domain, p);
1225 }
1226 TALLOC_FREE(frame);
1227
1228 if (sscanf(stype,"%X",&s->type) != 1) {
1229 DEBUG(4,("r:host file "));
1230 ok = False;
1231 }
1232
1233 /* Filter the servers/domains we return based on what was asked for. */
1234
1235 /* Check to see if we are being asked for a local list only. */
1236 if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) {
1237 DEBUG(4,("r: local list only"));
1238 ok = False;
1239 }
1240
1241 /* doesn't match up: don't want it */
1242 if (!(servertype & s->type)) {
1243 DEBUG(4,("r:serv type "));
1244 ok = False;
1245 }
1246
1247 if ((servertype & SV_TYPE_DOMAIN_ENUM) !=
1248 (s->type & SV_TYPE_DOMAIN_ENUM)) {
1249 DEBUG(4,("s: dom mismatch "));
1250 ok = False;
1251 }
1252
1253 if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM)) {
1254 ok = False;
1255 }
1256
1257 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1258 s->type &= ~SV_TYPE_LOCAL_LIST_ONLY;
1259
1260 if (ok) {
1261 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1262 s->name, s->type, s->comment, s->domain));
1263 s->server_added = True;
1264 count++;
1265 } else {
1266 DEBUG(4,("%20s %8x %25s %15s\n",
1267 s->name, s->type, s->comment, s->domain));
1268 }
1269 }
1270
1271 file_lines_free(lines);
1272 return count;
1273}
1274
1275/*******************************************************************
1276 Fill in a server info structure.
1277******************************************************************/
1278
1279static int fill_srv_info(struct srv_info_struct *service,
1280 int uLevel, char **buf, int *buflen,
1281 char **stringbuf, int *stringspace, char *baseaddr)
1282{
1283 int struct_len;
1284 char* p;
1285 char* p2;
1286 int l2;
1287 int len;
1288
1289 switch (uLevel) {
1290 case 0:
1291 struct_len = 16;
1292 break;
1293 case 1:
1294 struct_len = 26;
1295 break;
1296 default:
1297 return -1;
1298 }
1299
1300 if (!buf) {
1301 len = 0;
1302 switch (uLevel) {
1303 case 1:
1304 len = strlen(service->comment)+1;
1305 break;
1306 }
1307
1308 *buflen = struct_len;
1309 *stringspace = len;
1310 return struct_len + len;
1311 }
1312
1313 len = struct_len;
1314 p = *buf;
1315 if (*buflen < struct_len) {
1316 return -1;
1317 }
1318 if (stringbuf) {
1319 p2 = *stringbuf;
1320 l2 = *stringspace;
1321 } else {
1322 p2 = p + struct_len;
1323 l2 = *buflen - struct_len;
1324 }
1325 if (!baseaddr) {
1326 baseaddr = p;
1327 }
1328
1329 switch (uLevel) {
1330 case 0:
1331 push_ascii(p,service->name, MAX_NETBIOSNAME_LEN, STR_TERMINATE);
1332 break;
1333
1334 case 1:
1335 push_ascii(p,service->name,MAX_NETBIOSNAME_LEN, STR_TERMINATE);
1336 SIVAL(p,18,service->type);
1337 SIVAL(p,22,PTR_DIFF(p2,baseaddr));
1338 len += CopyAndAdvance(&p2,service->comment,&l2);
1339 break;
1340 }
1341
1342 if (stringbuf) {
1343 *buf = p + struct_len;
1344 *buflen -= struct_len;
1345 *stringbuf = p2;
1346 *stringspace = l2;
1347 } else {
1348 *buf = p2;
1349 *buflen -= len;
1350 }
1351 return len;
1352}
1353
1354
1355static int srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
1356{
1357 return(strcmp(s1->name,s2->name));
1358}
1359
1360/****************************************************************************
1361 View list of servers available (or possibly domains). The info is
1362 extracted from lists saved by nmbd on the local host.
1363****************************************************************************/
1364
1365static bool api_RNetServerEnum(connection_struct *conn, uint16 vuid,
1366 char *param, int tpscnt,
1367 char *data, int tdscnt,
1368 int mdrcnt, int mprcnt, char **rdata,
1369 char **rparam, int *rdata_len, int *rparam_len)
1370{
1371 char *str1 = get_safe_str_ptr(param, tpscnt, param, 2);
1372 char *str2 = skip_string(param,tpscnt,str1);
1373 char *p = skip_string(param,tpscnt,str2);
1374 int uLevel = get_safe_SVAL(param, tpscnt, p, 0, -1);
1375 int buf_len = get_safe_SVAL(param,tpscnt, p, 2, 0);
1376 uint32 servertype = get_safe_IVAL(param,tpscnt,p,4, 0);
1377 char *p2;
1378 int data_len, fixed_len, string_len;
1379 int f_len = 0, s_len = 0;
1380 struct srv_info_struct *servers=NULL;
1381 int counted=0,total=0;
1382 int i,missed;
1383 fstring domain;
1384 bool domain_request;
1385 bool local_request;
1386
1387 if (!str1 || !str2 || !p) {
1388 return False;
1389 }
1390
1391 /* If someone sets all the bits they don't really mean to set
1392 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1393 known servers. */
1394
1395 if (servertype == SV_TYPE_ALL) {
1396 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1397 }
1398
1399 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1400 any other bit (they may just set this bit on its own) they
1401 want all the locally seen servers. However this bit can be
1402 set on its own so set the requested servers to be
1403 ALL - DOMAIN_ENUM. */
1404
1405 if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM)) {
1406 servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
1407 }
1408
1409 domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
1410 local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
1411
1412 p += 8;
1413
1414 if (!prefix_ok(str1,"WrLehD")) {
1415 return False;
1416 }
1417 if (!check_server_info(uLevel,str2)) {
1418 return False;
1419 }
1420
1421 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1422 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1423 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1424
1425 if (strcmp(str1, "WrLehDz") == 0) {
1426 if (skip_string(param,tpscnt,p) == NULL) {
1427 return False;
1428 }
1429 pull_ascii_fstring(domain, p);
1430 } else {
1431 fstrcpy(domain, lp_workgroup());
1432 }
1433
1434 if (lp_browse_list()) {
1435 total = get_server_info(servertype,&servers,domain);
1436 }
1437
1438 data_len = fixed_len = string_len = 0;
1439 missed = 0;
1440
1441 if (total > 0) {
1442 qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
1443 }
1444
1445 {
1446 char *lastname=NULL;
1447
1448 for (i=0;i<total;i++) {
1449 struct srv_info_struct *s = &servers[i];
1450
1451 if (lastname && strequal(lastname,s->name)) {
1452 continue;
1453 }
1454 lastname = s->name;
1455 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1456 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1457 s->name, s->type, s->comment, s->domain));
1458
1459 if (data_len < buf_len) {
1460 counted++;
1461 fixed_len += f_len;
1462 string_len += s_len;
1463 } else {
1464 missed++;
1465 }
1466 }
1467 }
1468
1469 *rdata_len = fixed_len + string_len;
1470 *rdata = smb_realloc_limit(*rdata,*rdata_len);
1471 if (!*rdata) {
1472 return False;
1473 }
1474
1475 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1476 p = *rdata;
1477 f_len = fixed_len;
1478 s_len = string_len;
1479
1480 {
1481 char *lastname=NULL;
1482 int count2 = counted;
1483
1484 for (i = 0; i < total && count2;i++) {
1485 struct srv_info_struct *s = &servers[i];
1486
1487 if (lastname && strequal(lastname,s->name)) {
1488 continue;
1489 }
1490 lastname = s->name;
1491 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1492 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1493 s->name, s->type, s->comment, s->domain));
1494 count2--;
1495 }
1496 }
1497
1498 *rparam_len = 8;
1499 *rparam = smb_realloc_limit(*rparam,*rparam_len);
1500 if (!*rparam) {
1501 return False;
1502 }
1503 SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata));
1504 SSVAL(*rparam,2,0);
1505 SSVAL(*rparam,4,counted);
1506 SSVAL(*rparam,6,counted+missed);
1507
1508 SAFE_FREE(servers);
1509
1510 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1511 domain,uLevel,counted,counted+missed));
1512
1513 return True;
1514}
1515
1516/****************************************************************************
1517 command 0x34 - suspected of being a "Lookup Names" stub api
1518 ****************************************************************************/
1519
1520static bool api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid,
1521 char *param, int tpscnt,
1522 char *data, int tdscnt,
1523 int mdrcnt, int mprcnt, char **rdata,
1524 char **rparam, int *rdata_len, int *rparam_len)
1525{
1526 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
1527 char *str2 = skip_string(param,tpscnt,str1);
1528 char *p = skip_string(param,tpscnt,str2);
1529 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
1530 int buf_len = get_safe_SVAL(param,tpscnt,p,2,0);
1531 int counted=0;
1532 int missed=0;
1533
1534 if (!str1 || !str2 || !p) {
1535 return False;
1536 }
1537
1538 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1539 str1, str2, p, uLevel, buf_len));
1540
1541 if (!prefix_ok(str1,"zWrLeh")) {
1542 return False;
1543 }
1544
1545 *rdata_len = 0;
1546
1547 *rparam_len = 8;
1548 *rparam = smb_realloc_limit(*rparam,*rparam_len);
1549 if (!*rparam) {
1550 return False;
1551 }
1552
1553 SSVAL(*rparam,0,0x08AC); /* informational warning message */
1554 SSVAL(*rparam,2,0);
1555 SSVAL(*rparam,4,counted);
1556 SSVAL(*rparam,6,counted+missed);
1557
1558 return True;
1559}
1560
1561/****************************************************************************
1562 get info about a share
1563 ****************************************************************************/
1564
1565static bool check_share_info(int uLevel, char* id)
1566{
1567 switch( uLevel ) {
1568 case 0:
1569 if (strcmp(id,"B13") != 0) {
1570 return False;
1571 }
1572 break;
1573 case 1:
1574 if (strcmp(id,"B13BWz") != 0) {
1575 return False;
1576 }
1577 break;
1578 case 2:
1579 if (strcmp(id,"B13BWzWWWzB9B") != 0) {
1580 return False;
1581 }
1582 break;
1583 case 91:
1584 if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) {
1585 return False;
1586 }
1587 break;
1588 default:
1589 return False;
1590 }
1591 return True;
1592}
1593
1594static int fill_share_info(connection_struct *conn, int snum, int uLevel,
1595 char** buf, int* buflen,
1596 char** stringbuf, int* stringspace, char* baseaddr)
1597{
1598 int struct_len;
1599 char* p;
1600 char* p2;
1601 int l2;
1602 int len;
1603
1604 switch( uLevel ) {
1605 case 0:
1606 struct_len = 13;
1607 break;
1608 case 1:
1609 struct_len = 20;
1610 break;
1611 case 2:
1612 struct_len = 40;
1613 break;
1614 case 91:
1615 struct_len = 68;
1616 break;
1617 default:
1618 return -1;
1619 }
1620
1621
1622 if (!buf) {
1623 len = 0;
1624
1625 if (uLevel > 0) {
1626 len += StrlenExpanded(conn,snum,lp_comment(snum));
1627 }
1628 if (uLevel > 1) {
1629 len += strlen(lp_pathname(snum)) + 1;
1630 }
1631 if (buflen) {
1632 *buflen = struct_len;
1633 }
1634 if (stringspace) {
1635 *stringspace = len;
1636 }
1637 return struct_len + len;
1638 }
1639
1640 len = struct_len;
1641 p = *buf;
1642 if ((*buflen) < struct_len) {
1643 return -1;
1644 }
1645
1646 if (stringbuf) {
1647 p2 = *stringbuf;
1648 l2 = *stringspace;
1649 } else {
1650 p2 = p + struct_len;
1651 l2 = (*buflen) - struct_len;
1652 }
1653
1654 if (!baseaddr) {
1655 baseaddr = p;
1656 }
1657
1658 push_ascii(p,lp_servicename(snum),13, STR_TERMINATE);
1659
1660 if (uLevel > 0) {
1661 int type;
1662
1663 SCVAL(p,13,0);
1664 type = STYPE_DISKTREE;
1665 if (lp_print_ok(snum)) {
1666 type = STYPE_PRINTQ;
1667 }
1668 if (strequal("IPC",lp_fstype(snum))) {
1669 type = STYPE_IPC;
1670 }
1671 SSVAL(p,14,type); /* device type */
1672 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1673 len += CopyExpanded(conn,snum,&p2,lp_comment(snum),&l2);
1674 }
1675
1676 if (uLevel > 1) {
1677 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1678 SSVALS(p,22,-1); /* max uses */
1679 SSVAL(p,24,1); /* current uses */
1680 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1681 len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1682 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1683 }
1684
1685 if (uLevel > 2) {
1686 memset(p+40,0,SHPWLEN+2);
1687 SSVAL(p,50,0);
1688 SIVAL(p,52,0);
1689 SSVAL(p,56,0);
1690 SSVAL(p,58,0);
1691 SIVAL(p,60,0);
1692 SSVAL(p,64,0);
1693 SSVAL(p,66,0);
1694 }
1695
1696 if (stringbuf) {
1697 (*buf) = p + struct_len;
1698 (*buflen) -= struct_len;
1699 (*stringbuf) = p2;
1700 (*stringspace) = l2;
1701 } else {
1702 (*buf) = p2;
1703 (*buflen) -= len;
1704 }
1705
1706 return len;
1707}
1708
1709static bool api_RNetShareGetInfo(connection_struct *conn,uint16 vuid,
1710 char *param, int tpscnt,
1711 char *data, int tdscnt,
1712 int mdrcnt,int mprcnt,
1713 char **rdata,char **rparam,
1714 int *rdata_len,int *rparam_len)
1715{
1716 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
1717 char *str2 = skip_string(param,tpscnt,str1);
1718 char *netname = skip_string(param,tpscnt,str2);
1719 char *p = skip_string(param,tpscnt,netname);
1720 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
1721 int snum;
1722
1723 if (!str1 || !str2 || !netname || !p) {
1724 return False;
1725 }
1726
1727 snum = find_service(netname);
1728 if (snum < 0) {
1729 return False;
1730 }
1731
1732 /* check it's a supported varient */
1733 if (!prefix_ok(str1,"zWrLh")) {
1734 return False;
1735 }
1736 if (!check_share_info(uLevel,str2)) {
1737 return False;
1738 }
1739
1740 *rdata = smb_realloc_limit(*rdata,mdrcnt);
1741 if (!*rdata) {
1742 return False;
1743 }
1744 p = *rdata;
1745 *rdata_len = fill_share_info(conn,snum,uLevel,&p,&mdrcnt,0,0,0);
1746 if (*rdata_len < 0) {
1747 return False;
1748 }
1749
1750 *rparam_len = 6;
1751 *rparam = smb_realloc_limit(*rparam,*rparam_len);
1752 if (!*rparam) {
1753 return False;
1754 }
1755 SSVAL(*rparam,0,NERR_Success);
1756 SSVAL(*rparam,2,0); /* converter word */
1757 SSVAL(*rparam,4,*rdata_len);
1758
1759 return True;
1760}
1761
1762/****************************************************************************
1763 View the list of available shares.
1764
1765 This function is the server side of the NetShareEnum() RAP call.
1766 It fills the return buffer with share names and share comments.
1767 Note that the return buffer normally (in all known cases) allows only
1768 twelve byte strings for share names (plus one for a nul terminator).
1769 Share names longer than 12 bytes must be skipped.
1770 ****************************************************************************/
1771
1772static bool api_RNetShareEnum( connection_struct *conn, uint16 vuid,
1773 char *param, int tpscnt,
1774 char *data, int tdscnt,
1775 int mdrcnt,
1776 int mprcnt,
1777 char **rdata,
1778 char **rparam,
1779 int *rdata_len,
1780 int *rparam_len )
1781{
1782 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
1783 char *str2 = skip_string(param,tpscnt,str1);
1784 char *p = skip_string(param,tpscnt,str2);
1785 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
1786 int buf_len = get_safe_SVAL(param,tpscnt,p,2,0);
1787 char *p2;
1788 int count = 0;
1789 int total=0,counted=0;
1790 bool missed = False;
1791 int i;
1792 int data_len, fixed_len, string_len;
1793 int f_len = 0, s_len = 0;
1794
1795 if (!str1 || !str2 || !p) {
1796 return False;
1797 }
1798
1799 if (!prefix_ok(str1,"WrLeh")) {
1800 return False;
1801 }
1802 if (!check_share_info(uLevel,str2)) {
1803 return False;
1804 }
1805
1806 /* Ensure all the usershares are loaded. */
1807 become_root();
1808 load_registry_shares();
1809 count = load_usershare_shares();
1810 unbecome_root();
1811
1812 data_len = fixed_len = string_len = 0;
1813 for (i=0;i<count;i++) {
1814 fstring servicename_dos;
1815 if (!(lp_browseable(i) && lp_snum_ok(i))) {
1816 continue;
1817 }
1818 push_ascii_fstring(servicename_dos, lp_servicename(i));
1819 /* Maximum name length = 13. */
1820 if( lp_browseable( i ) && lp_snum_ok( i ) && (strlen(servicename_dos) < 13)) {
1821 total++;
1822 data_len += fill_share_info(conn,i,uLevel,0,&f_len,0,&s_len,0);
1823 if (data_len < buf_len) {
1824 counted++;
1825 fixed_len += f_len;
1826 string_len += s_len;
1827 } else {
1828 missed = True;
1829 }
1830 }
1831 }
1832
1833 *rdata_len = fixed_len + string_len;
1834 *rdata = smb_realloc_limit(*rdata,*rdata_len);
1835 if (!*rdata) {
1836 return False;
1837 }
1838
1839 p2 = (*rdata) + fixed_len; /* auxiliary data (strings) will go here */
1840 p = *rdata;
1841 f_len = fixed_len;
1842 s_len = string_len;
1843
1844 for( i = 0; i < count; i++ ) {
1845 fstring servicename_dos;
1846 if (!(lp_browseable(i) && lp_snum_ok(i))) {
1847 continue;
1848 }
1849
1850 push_ascii_fstring(servicename_dos, lp_servicename(i));
1851 if (lp_browseable(i) && lp_snum_ok(i) && (strlen(servicename_dos) < 13)) {
1852 if (fill_share_info( conn,i,uLevel,&p,&f_len,&p2,&s_len,*rdata ) < 0) {
1853 break;
1854 }
1855 }
1856 }
1857
1858 *rparam_len = 8;
1859 *rparam = smb_realloc_limit(*rparam,*rparam_len);
1860 if (!*rparam) {
1861 return False;
1862 }
1863 SSVAL(*rparam,0,missed ? ERRmoredata : NERR_Success);
1864 SSVAL(*rparam,2,0);
1865 SSVAL(*rparam,4,counted);
1866 SSVAL(*rparam,6,total);
1867
1868 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1869 counted,total,uLevel,
1870 buf_len,*rdata_len,mdrcnt));
1871
1872 return True;
1873}
1874
1875/****************************************************************************
1876 Add a share
1877 ****************************************************************************/
1878
1879static bool api_RNetShareAdd(connection_struct *conn,uint16 vuid,
1880 char *param, int tpscnt,
1881 char *data, int tdscnt,
1882 int mdrcnt,int mprcnt,
1883 char **rdata,char **rparam,
1884 int *rdata_len,int *rparam_len)
1885{
1886 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
1887 char *str2 = skip_string(param,tpscnt,str1);
1888 char *p = skip_string(param,tpscnt,str2);
1889 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
1890 fstring sharename;
1891 fstring comment;
1892 char *pathname = NULL;
1893 char *command, *cmdname;
1894 unsigned int offset;
1895 int snum;
1896 int res = ERRunsup;
1897 size_t converted_size;
1898
1899 if (!str1 || !str2 || !p) {
1900 return False;
1901 }
1902
1903 /* check it's a supported varient */
1904 if (!prefix_ok(str1,RAP_WShareAdd_REQ)) {
1905 return False;
1906 }
1907 if (!check_share_info(uLevel,str2)) {
1908 return False;
1909 }
1910 if (uLevel != 2) {
1911 return False;
1912 }
1913
1914 /* Do we have a string ? */
1915 if (skip_string(data,mdrcnt,data) == NULL) {
1916 return False;
1917 }
1918 pull_ascii_fstring(sharename,data);
1919 snum = find_service(sharename);
1920 if (snum >= 0) { /* already exists */
1921 res = ERRfilexists;
1922 goto error_exit;
1923 }
1924
1925 if (mdrcnt < 28) {
1926 return False;
1927 }
1928
1929 /* only support disk share adds */
1930 if (SVAL(data,14)!=STYPE_DISKTREE) {
1931 return False;
1932 }
1933
1934 offset = IVAL(data, 16);
1935 if (offset >= mdrcnt) {
1936 res = ERRinvalidparam;
1937 goto error_exit;
1938 }
1939
1940 /* Do we have a string ? */
1941 if (skip_string(data,mdrcnt,data+offset) == NULL) {
1942 return False;
1943 }
1944 pull_ascii_fstring(comment, offset? (data+offset) : "");
1945
1946 offset = IVAL(data, 26);
1947
1948 if (offset >= mdrcnt) {
1949 res = ERRinvalidparam;
1950 goto error_exit;
1951 }
1952
1953 /* Do we have a string ? */
1954 if (skip_string(data,mdrcnt,data+offset) == NULL) {
1955 return False;
1956 }
1957
1958 if (!pull_ascii_talloc(talloc_tos(), &pathname,
1959 offset ? (data+offset) : "", &converted_size))
1960 {
1961 DEBUG(0,("api_RNetShareAdd: pull_ascii_talloc failed: %s",
1962 strerror(errno)));
1963 }
1964
1965 if (!pathname) {
1966 return false;
1967 }
1968
1969 string_replace(sharename, '"', ' ');
1970 string_replace(pathname, '"', ' ');
1971 string_replace(comment, '"', ' ');
1972
1973 cmdname = lp_add_share_cmd();
1974
1975 if (!cmdname || *cmdname == '\0') {
1976 return False;
1977 }
1978
1979 if (asprintf(&command, "%s \"%s\" \"%s\" \"%s\" \"%s\"",
1980 lp_add_share_cmd(), get_dyn_CONFIGFILE(), sharename,
1981 pathname, comment) == -1) {
1982 return false;
1983 }
1984
1985 DEBUG(10,("api_RNetShareAdd: Running [%s]\n", command ));
1986
1987 if ((res = smbrun(command, NULL)) != 0) {
1988 DEBUG(1,("api_RNetShareAdd: Running [%s] returned (%d)\n",
1989 command, res ));
1990 SAFE_FREE(command);
1991 res = ERRnoaccess;
1992 goto error_exit;
1993 } else {
1994 SAFE_FREE(command);
1995 message_send_all(smbd_messaging_context(),
1996 MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
1997 }
1998
1999 *rparam_len = 6;
2000 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2001 if (!*rparam) {
2002 return False;
2003 }
2004 SSVAL(*rparam,0,NERR_Success);
2005 SSVAL(*rparam,2,0); /* converter word */
2006 SSVAL(*rparam,4,*rdata_len);
2007 *rdata_len = 0;
2008
2009 return True;
2010
2011 error_exit:
2012
2013 *rparam_len = 4;
2014 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2015 if (!*rparam) {
2016 return False;
2017 }
2018 *rdata_len = 0;
2019 SSVAL(*rparam,0,res);
2020 SSVAL(*rparam,2,0);
2021 return True;
2022}
2023
2024/****************************************************************************
2025 view list of groups available
2026 ****************************************************************************/
2027
2028static bool api_RNetGroupEnum(connection_struct *conn,uint16 vuid,
2029 char *param, int tpscnt,
2030 char *data, int tdscnt,
2031 int mdrcnt,int mprcnt,
2032 char **rdata,char **rparam,
2033 int *rdata_len,int *rparam_len)
2034{
2035 int i;
2036 int errflags=0;
2037 int resume_context, cli_buf_size;
2038 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2039 char *str2 = skip_string(param,tpscnt,str1);
2040 char *p = skip_string(param,tpscnt,str2);
2041
2042 struct pdb_search *search;
2043 struct samr_displayentry *entries;
2044
2045 int num_entries;
2046
2047 if (!str1 || !str2 || !p) {
2048 return False;
2049 }
2050
2051 if (strcmp(str1,"WrLeh") != 0) {
2052 return False;
2053 }
2054
2055 /* parameters
2056 * W-> resume context (number of users to skip)
2057 * r -> return parameter pointer to receive buffer
2058 * L -> length of receive buffer
2059 * e -> return parameter number of entries
2060 * h -> return parameter total number of users
2061 */
2062
2063 if (strcmp("B21",str2) != 0) {
2064 return False;
2065 }
2066
2067 /* get list of domain groups SID_DOMAIN_GRP=2 */
2068 become_root();
2069 search = pdb_search_groups();
2070 unbecome_root();
2071
2072 if (search == NULL) {
2073 DEBUG(3,("api_RNetGroupEnum:failed to get group list"));
2074 return False;
2075 }
2076
2077 resume_context = get_safe_SVAL(param,tpscnt,p,0,-1);
2078 cli_buf_size= get_safe_SVAL(param,tpscnt,p,2,0);
2079 DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: "
2080 "%d\n", resume_context, cli_buf_size));
2081
2082 become_root();
2083 num_entries = pdb_search_entries(search, resume_context, 0xffffffff,
2084 &entries);
2085 unbecome_root();
2086
2087 *rdata_len = cli_buf_size;
2088 *rdata = smb_realloc_limit(*rdata,*rdata_len);
2089 if (!*rdata) {
2090 return False;
2091 }
2092
2093 p = *rdata;
2094
2095 for(i=0; i<num_entries; i++) {
2096 fstring name;
2097 fstrcpy(name, entries[i].account_name);
2098 if( ((PTR_DIFF(p,*rdata)+21) <= *rdata_len) ) {
2099 /* truncate the name at 21 chars. */
2100 memcpy(p, name, 21);
2101 DEBUG(10,("adding entry %d group %s\n", i, p));
2102 p += 21;
2103 p += 5; /* Both NT4 and W2k3SP1 do padding here.
2104 No idea why... */
2105 } else {
2106 /* set overflow error */
2107 DEBUG(3,("overflow on entry %d group %s\n", i, name));
2108 errflags=234;
2109 break;
2110 }
2111 }
2112
2113 pdb_search_destroy(search);
2114
2115 *rdata_len = PTR_DIFF(p,*rdata);
2116
2117 *rparam_len = 8;
2118 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2119 if (!*rparam) {
2120 return False;
2121 }
2122 SSVAL(*rparam, 0, errflags);
2123 SSVAL(*rparam, 2, 0); /* converter word */
2124 SSVAL(*rparam, 4, i); /* is this right?? */
2125 SSVAL(*rparam, 6, resume_context+num_entries); /* is this right?? */
2126
2127 return(True);
2128}
2129
2130/*******************************************************************
2131 Get groups that a user is a member of.
2132******************************************************************/
2133
2134static bool api_NetUserGetGroups(connection_struct *conn,uint16 vuid,
2135 char *param, int tpscnt,
2136 char *data, int tdscnt,
2137 int mdrcnt,int mprcnt,
2138 char **rdata,char **rparam,
2139 int *rdata_len,int *rparam_len)
2140{
2141 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2142 char *str2 = skip_string(param,tpscnt,str1);
2143 char *UserName = skip_string(param,tpscnt,str2);
2144 char *p = skip_string(param,tpscnt,UserName);
2145 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
2146 const char *level_string;
2147 int count=0;
2148 struct samu *sampw = NULL;
2149 bool ret = False;
2150 DOM_SID *sids;
2151 gid_t *gids;
2152 size_t num_groups;
2153 size_t i;
2154 NTSTATUS result;
2155 DOM_SID user_sid;
2156 enum lsa_SidType type;
2157 char *endp = NULL;
2158 TALLOC_CTX *mem_ctx;
2159
2160 if (!str1 || !str2 || !UserName || !p) {
2161 return False;
2162 }
2163
2164 *rparam_len = 8;
2165 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2166 if (!*rparam) {
2167 return False;
2168 }
2169
2170 /* check it's a supported varient */
2171
2172 if ( strcmp(str1,"zWrLeh") != 0 )
2173 return False;
2174
2175 switch( uLevel ) {
2176 case 0:
2177 level_string = "B21";
2178 break;
2179 default:
2180 return False;
2181 }
2182
2183 if (strcmp(level_string,str2) != 0)
2184 return False;
2185
2186 *rdata_len = mdrcnt + 1024;
2187 *rdata = smb_realloc_limit(*rdata,*rdata_len);
2188 if (!*rdata) {
2189 return False;
2190 }
2191
2192 SSVAL(*rparam,0,NERR_Success);
2193 SSVAL(*rparam,2,0); /* converter word */
2194
2195 p = *rdata;
2196 endp = *rdata + *rdata_len;
2197
2198 mem_ctx = talloc_new(NULL);
2199 if (mem_ctx == NULL) {
2200 DEBUG(0, ("talloc_new failed\n"));
2201 return False;
2202 }
2203
2204 if ( !(sampw = samu_new(mem_ctx)) ) {
2205 DEBUG(0, ("samu_new() failed!\n"));
2206 TALLOC_FREE(mem_ctx);
2207 return False;
2208 }
2209
2210 /* Lookup the user information; This should only be one of
2211 our accounts (not remote domains) */
2212
2213 become_root(); /* ROOT BLOCK */
2214
2215 if (!lookup_name(mem_ctx, UserName, LOOKUP_NAME_ALL,
2216 NULL, NULL, &user_sid, &type)) {
2217 DEBUG(10, ("lookup_name(%s) failed\n", UserName));
2218 goto done;
2219 }
2220
2221 if (type != SID_NAME_USER) {
2222 DEBUG(10, ("%s is a %s, not a user\n", UserName,
2223 sid_type_lookup(type)));
2224 goto done;
2225 }
2226
2227 if ( !pdb_getsampwsid(sampw, &user_sid) ) {
2228 DEBUG(10, ("pdb_getsampwsid(%s) failed for user %s\n",
2229 sid_string_dbg(&user_sid), UserName));
2230 goto done;
2231 }
2232
2233 gids = NULL;
2234 sids = NULL;
2235 num_groups = 0;
2236
2237 result = pdb_enum_group_memberships(mem_ctx, sampw,
2238 &sids, &gids, &num_groups);
2239
2240 if (!NT_STATUS_IS_OK(result)) {
2241 DEBUG(10, ("pdb_enum_group_memberships failed for %s\n",
2242 UserName));
2243 goto done;
2244 }
2245
2246 for (i=0; i<num_groups; i++) {
2247 const char *grp_name;
2248
2249 if ( lookup_sid(mem_ctx, &sids[i], NULL, &grp_name, NULL) ) {
2250 strlcpy(p, grp_name, PTR_DIFF(endp,p));
2251 p += 21;
2252 count++;
2253 }
2254 }
2255
2256 *rdata_len = PTR_DIFF(p,*rdata);
2257
2258 SSVAL(*rparam,4,count); /* is this right?? */
2259 SSVAL(*rparam,6,count); /* is this right?? */
2260
2261 ret = True;
2262
2263done:
2264 unbecome_root(); /* END ROOT BLOCK */
2265
2266 TALLOC_FREE(mem_ctx);
2267
2268 return ret;
2269}
2270
2271/*******************************************************************
2272 Get all users.
2273******************************************************************/
2274
2275static bool api_RNetUserEnum(connection_struct *conn, uint16 vuid,
2276 char *param, int tpscnt,
2277 char *data, int tdscnt,
2278 int mdrcnt,int mprcnt,
2279 char **rdata,char **rparam,
2280 int *rdata_len,int *rparam_len)
2281{
2282 int count_sent=0;
2283 int num_users=0;
2284 int errflags=0;
2285 int i, resume_context, cli_buf_size;
2286 struct pdb_search *search;
2287 struct samr_displayentry *users;
2288
2289 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2290 char *str2 = skip_string(param,tpscnt,str1);
2291 char *p = skip_string(param,tpscnt,str2);
2292 char *endp = NULL;
2293
2294 if (!str1 || !str2 || !p) {
2295 return False;
2296 }
2297
2298 if (strcmp(str1,"WrLeh") != 0)
2299 return False;
2300 /* parameters
2301 * W-> resume context (number of users to skip)
2302 * r -> return parameter pointer to receive buffer
2303 * L -> length of receive buffer
2304 * e -> return parameter number of entries
2305 * h -> return parameter total number of users
2306 */
2307
2308 resume_context = get_safe_SVAL(param,tpscnt,p,0,-1);
2309 cli_buf_size= get_safe_SVAL(param,tpscnt,p,2,0);
2310 DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n",
2311 resume_context, cli_buf_size));
2312
2313 *rparam_len = 8;
2314 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2315 if (!*rparam) {
2316 return False;
2317 }
2318
2319 /* check it's a supported varient */
2320 if (strcmp("B21",str2) != 0)
2321 return False;
2322
2323 *rdata_len = cli_buf_size;
2324 *rdata = smb_realloc_limit(*rdata,*rdata_len);
2325 if (!*rdata) {
2326 return False;
2327 }
2328
2329 p = *rdata;
2330 endp = *rdata + *rdata_len;
2331
2332 become_root();
2333 search = pdb_search_users(ACB_NORMAL);
2334 unbecome_root();
2335 if (search == NULL) {
2336 DEBUG(0, ("api_RNetUserEnum:unable to open sam database.\n"));
2337 return False;
2338 }
2339
2340 become_root();
2341 num_users = pdb_search_entries(search, resume_context, 0xffffffff,
2342 &users);
2343 unbecome_root();
2344
2345 errflags=NERR_Success;
2346
2347 for (i=0; i<num_users; i++) {
2348 const char *name = users[i].account_name;
2349
2350 if(((PTR_DIFF(p,*rdata)+21)<=*rdata_len)&&(strlen(name)<=21)) {
2351 strlcpy(p,name,PTR_DIFF(endp,p));
2352 DEBUG(10,("api_RNetUserEnum:adding entry %d username "
2353 "%s\n",count_sent,p));
2354 p += 21;
2355 count_sent++;
2356 } else {
2357 /* set overflow error */
2358 DEBUG(10,("api_RNetUserEnum:overflow on entry %d "
2359 "username %s\n",count_sent,name));
2360 errflags=234;
2361 break;
2362 }
2363 }
2364
2365 pdb_search_destroy(search);
2366
2367 *rdata_len = PTR_DIFF(p,*rdata);
2368
2369 SSVAL(*rparam,0,errflags);
2370 SSVAL(*rparam,2,0); /* converter word */
2371 SSVAL(*rparam,4,count_sent); /* is this right?? */
2372 SSVAL(*rparam,6,num_users); /* is this right?? */
2373
2374 return True;
2375}
2376
2377/****************************************************************************
2378 Get the time of day info.
2379****************************************************************************/
2380
2381static bool api_NetRemoteTOD(connection_struct *conn,uint16 vuid,
2382 char *param, int tpscnt,
2383 char *data, int tdscnt,
2384 int mdrcnt,int mprcnt,
2385 char **rdata,char **rparam,
2386 int *rdata_len,int *rparam_len)
2387{
2388 struct tm *t;
2389 time_t unixdate = time(NULL);
2390 char *p;
2391
2392 *rparam_len = 4;
2393 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2394 if (!*rparam) {
2395 return False;
2396 }
2397
2398 *rdata_len = 21;
2399 *rdata = smb_realloc_limit(*rdata,*rdata_len);
2400 if (!*rdata) {
2401 return False;
2402 }
2403
2404 SSVAL(*rparam,0,NERR_Success);
2405 SSVAL(*rparam,2,0); /* converter word */
2406
2407 p = *rdata;
2408
2409 srv_put_dos_date3(p,0,unixdate); /* this is the time that is looked at
2410 by NT in a "net time" operation,
2411 it seems to ignore the one below */
2412
2413 /* the client expects to get localtime, not GMT, in this bit
2414 (I think, this needs testing) */
2415 t = localtime(&unixdate);
2416 if (!t) {
2417 return False;
2418 }
2419
2420 SIVAL(p,4,0); /* msecs ? */
2421 SCVAL(p,8,t->tm_hour);
2422 SCVAL(p,9,t->tm_min);
2423 SCVAL(p,10,t->tm_sec);
2424 SCVAL(p,11,0); /* hundredths of seconds */
2425 SSVALS(p,12,get_time_zone(unixdate)/60); /* timezone in minutes from GMT */
2426 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
2427 SCVAL(p,16,t->tm_mday);
2428 SCVAL(p,17,t->tm_mon + 1);
2429 SSVAL(p,18,1900+t->tm_year);
2430 SCVAL(p,20,t->tm_wday);
2431
2432 return True;
2433}
2434
2435/****************************************************************************
2436 Set the user password.
2437*****************************************************************************/
2438
2439static bool api_SetUserPassword(connection_struct *conn,uint16 vuid,
2440 char *param, int tpscnt,
2441 char *data, int tdscnt,
2442 int mdrcnt,int mprcnt,
2443 char **rdata,char **rparam,
2444 int *rdata_len,int *rparam_len)
2445{
2446 char *np = get_safe_str_ptr(param,tpscnt,param,2);
2447 char *p = NULL;
2448 fstring user;
2449 fstring pass1,pass2;
2450
2451 /* Skip 2 strings. */
2452 p = skip_string(param,tpscnt,np);
2453 p = skip_string(param,tpscnt,p);
2454
2455 if (!np || !p) {
2456 return False;
2457 }
2458
2459 /* Do we have a string ? */
2460 if (skip_string(param,tpscnt,p) == NULL) {
2461 return False;
2462 }
2463 pull_ascii_fstring(user,p);
2464
2465 p = skip_string(param,tpscnt,p);
2466 if (!p) {
2467 return False;
2468 }
2469
2470 memset(pass1,'\0',sizeof(pass1));
2471 memset(pass2,'\0',sizeof(pass2));
2472 /*
2473 * We use 31 here not 32 as we're checking
2474 * the last byte we want to access is safe.
2475 */
2476 if (!is_offset_safe(param,tpscnt,p,31)) {
2477 return False;
2478 }
2479 memcpy(pass1,p,16);
2480 memcpy(pass2,p+16,16);
2481
2482 *rparam_len = 4;
2483 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2484 if (!*rparam) {
2485 return False;
2486 }
2487
2488 *rdata_len = 0;
2489
2490 SSVAL(*rparam,0,NERR_badpass);
2491 SSVAL(*rparam,2,0); /* converter word */
2492
2493 DEBUG(3,("Set password for <%s>\n",user));
2494
2495 /*
2496 * Attempt to verify the old password against smbpasswd entries
2497 * Win98 clients send old and new password in plaintext for this call.
2498 */
2499
2500 {
2501 auth_serversupplied_info *server_info = NULL;
2502 DATA_BLOB password = data_blob(pass1, strlen(pass1)+1);
2503
2504 if (NT_STATUS_IS_OK(check_plaintext_password(user,password,&server_info))) {
2505
2506 become_root();
2507 if (NT_STATUS_IS_OK(change_oem_password(server_info->sam_account, pass1, pass2, False, NULL))) {
2508 SSVAL(*rparam,0,NERR_Success);
2509 }
2510 unbecome_root();
2511
2512 TALLOC_FREE(server_info);
2513 }
2514 data_blob_clear_free(&password);
2515 }
2516
2517 /*
2518 * If the plaintext change failed, attempt
2519 * the old encrypted method. NT will generate this
2520 * after trying the samr method. Note that this
2521 * method is done as a last resort as this
2522 * password change method loses the NT password hash
2523 * and cannot change the UNIX password as no plaintext
2524 * is received.
2525 */
2526
2527 if(SVAL(*rparam,0) != NERR_Success) {
2528 struct samu *hnd = NULL;
2529
2530 if (check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &hnd)) {
2531 become_root();
2532 if (change_lanman_password(hnd,(uchar *)pass2)) {
2533 SSVAL(*rparam,0,NERR_Success);
2534 }
2535 unbecome_root();
2536 TALLOC_FREE(hnd);
2537 }
2538 }
2539
2540 memset((char *)pass1,'\0',sizeof(fstring));
2541 memset((char *)pass2,'\0',sizeof(fstring));
2542
2543 return(True);
2544}
2545
2546/****************************************************************************
2547 Set the user password (SamOEM version - gets plaintext).
2548****************************************************************************/
2549
2550static bool api_SamOEMChangePassword(connection_struct *conn,uint16 vuid,
2551 char *param, int tpscnt,
2552 char *data, int tdscnt,
2553 int mdrcnt,int mprcnt,
2554 char **rdata,char **rparam,
2555 int *rdata_len,int *rparam_len)
2556{
2557 fstring user;
2558 char *p = get_safe_str_ptr(param,tpscnt,param,2);
2559 *rparam_len = 2;
2560 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2561 if (!*rparam) {
2562 return False;
2563 }
2564
2565 if (!p) {
2566 return False;
2567 }
2568 *rdata_len = 0;
2569
2570 SSVAL(*rparam,0,NERR_badpass);
2571
2572 /*
2573 * Check the parameter definition is correct.
2574 */
2575
2576 /* Do we have a string ? */
2577 if (skip_string(param,tpscnt,p) == 0) {
2578 return False;
2579 }
2580 if(!strequal(p, "zsT")) {
2581 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", p));
2582 return False;
2583 }
2584 p = skip_string(param, tpscnt, p);
2585 if (!p) {
2586 return False;
2587 }
2588
2589 /* Do we have a string ? */
2590 if (skip_string(param,tpscnt,p) == 0) {
2591 return False;
2592 }
2593 if(!strequal(p, "B516B16")) {
2594 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p));
2595 return False;
2596 }
2597 p = skip_string(param,tpscnt,p);
2598 if (!p) {
2599 return False;
2600 }
2601 /* Do we have a string ? */
2602 if (skip_string(param,tpscnt,p) == 0) {
2603 return False;
2604 }
2605 p += pull_ascii_fstring(user,p);
2606
2607 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user));
2608
2609 /*
2610 * Pass the user through the NT -> unix user mapping
2611 * function.
2612 */
2613
2614 (void)map_username(user);
2615
2616 if (NT_STATUS_IS_OK(pass_oem_change(user, (uchar*) data, (uchar *)&data[516], NULL, NULL, NULL))) {
2617 SSVAL(*rparam,0,NERR_Success);
2618 }
2619
2620 return(True);
2621}
2622
2623/****************************************************************************
2624 delete a print job
2625 Form: <W> <>
2626 ****************************************************************************/
2627
2628static bool api_RDosPrintJobDel(connection_struct *conn,uint16 vuid,
2629 char *param, int tpscnt,
2630 char *data, int tdscnt,
2631 int mdrcnt,int mprcnt,
2632 char **rdata,char **rparam,
2633 int *rdata_len,int *rparam_len)
2634{
2635 int function = get_safe_SVAL(param,tpscnt,param,0,0);
2636 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2637 char *str2 = skip_string(param,tpscnt,str1);
2638 char *p = skip_string(param,tpscnt,str2);
2639 uint32 jobid;
2640 int snum;
2641 fstring sharename;
2642 int errcode;
2643 WERROR werr = WERR_OK;
2644
2645 if (!str1 || !str2 || !p) {
2646 return False;
2647 }
2648 /*
2649 * We use 1 here not 2 as we're checking
2650 * the last byte we want to access is safe.
2651 */
2652 if (!is_offset_safe(param,tpscnt,p,1)) {
2653 return False;
2654 }
2655 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
2656 return False;
2657
2658 /* check it's a supported varient */
2659 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
2660 return(False);
2661
2662 *rparam_len = 4;
2663 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2664 if (!*rparam) {
2665 return False;
2666 }
2667 *rdata_len = 0;
2668
2669 if (!print_job_exists(sharename, jobid)) {
2670 errcode = NERR_JobNotFound;
2671 goto out;
2672 }
2673
2674 snum = lp_servicenumber( sharename);
2675 if (snum == -1) {
2676 errcode = NERR_DestNotFound;
2677 goto out;
2678 }
2679
2680 errcode = NERR_notsupported;
2681
2682 switch (function) {
2683 case 81: /* delete */
2684 if (print_job_delete(conn->server_info, snum, jobid, &werr))
2685 errcode = NERR_Success;
2686 break;
2687 case 82: /* pause */
2688 if (print_job_pause(conn->server_info, snum, jobid, &werr))
2689 errcode = NERR_Success;
2690 break;
2691 case 83: /* resume */
2692 if (print_job_resume(conn->server_info, snum, jobid, &werr))
2693 errcode = NERR_Success;
2694 break;
2695 }
2696
2697 if (!W_ERROR_IS_OK(werr))
2698 errcode = W_ERROR_V(werr);
2699
2700 out:
2701 SSVAL(*rparam,0,errcode);
2702 SSVAL(*rparam,2,0); /* converter word */
2703
2704 return(True);
2705}
2706
2707/****************************************************************************
2708 Purge a print queue - or pause or resume it.
2709 ****************************************************************************/
2710
2711static bool api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid,
2712 char *param, int tpscnt,
2713 char *data, int tdscnt,
2714 int mdrcnt,int mprcnt,
2715 char **rdata,char **rparam,
2716 int *rdata_len,int *rparam_len)
2717{
2718 int function = get_safe_SVAL(param,tpscnt,param,0,0);
2719 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2720 char *str2 = skip_string(param,tpscnt,str1);
2721 char *QueueName = skip_string(param,tpscnt,str2);
2722 int errcode = NERR_notsupported;
2723 int snum;
2724 WERROR werr = WERR_OK;
2725
2726 if (!str1 || !str2 || !QueueName) {
2727 return False;
2728 }
2729
2730 /* check it's a supported varient */
2731 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
2732 return(False);
2733
2734 *rparam_len = 4;
2735 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2736 if (!*rparam) {
2737 return False;
2738 }
2739 *rdata_len = 0;
2740
2741 if (skip_string(param,tpscnt,QueueName) == NULL) {
2742 return False;
2743 }
2744 snum = print_queue_snum(QueueName);
2745
2746 if (snum == -1) {
2747 errcode = NERR_JobNotFound;
2748 goto out;
2749 }
2750
2751 switch (function) {
2752 case 74: /* Pause queue */
2753 if (print_queue_pause(conn->server_info, snum, &werr)) {
2754 errcode = NERR_Success;
2755 }
2756 break;
2757 case 75: /* Resume queue */
2758 if (print_queue_resume(conn->server_info, snum, &werr)) {
2759 errcode = NERR_Success;
2760 }
2761 break;
2762 case 103: /* Purge */
2763 if (print_queue_purge(conn->server_info, snum, &werr)) {
2764 errcode = NERR_Success;
2765 }
2766 break;
2767 }
2768
2769 if (!W_ERROR_IS_OK(werr)) errcode = W_ERROR_V(werr);
2770
2771 out:
2772 SSVAL(*rparam,0,errcode);
2773 SSVAL(*rparam,2,0); /* converter word */
2774
2775 return(True);
2776}
2777
2778/****************************************************************************
2779 set the property of a print job (undocumented?)
2780 ? function = 0xb -> set name of print job
2781 ? function = 0x6 -> move print job up/down
2782 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
2783 or <WWsTP> <WB21BB16B10zWWzDDz>
2784****************************************************************************/
2785
2786static int check_printjob_info(struct pack_desc* desc,
2787 int uLevel, char* id)
2788{
2789 desc->subformat = NULL;
2790 switch( uLevel ) {
2791 case 0: desc->format = "W"; break;
2792 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
2793 case 2: desc->format = "WWzWWDDzz"; break;
2794 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
2795 case 4: desc->format = "WWzWWDDzzzzzDDDDDDD"; break;
2796 default:
2797 DEBUG(0,("check_printjob_info: invalid level %d\n",
2798 uLevel ));
2799 return False;
2800 }
2801 if (id == NULL || strcmp(desc->format,id) != 0) {
2802 DEBUG(0,("check_printjob_info: invalid format %s\n",
2803 id ? id : "<NULL>" ));
2804 return False;
2805 }
2806 return True;
2807}
2808
2809static bool api_PrintJobInfo(connection_struct *conn, uint16 vuid,
2810 char *param, int tpscnt,
2811 char *data, int tdscnt,
2812 int mdrcnt,int mprcnt,
2813 char **rdata,char **rparam,
2814 int *rdata_len,int *rparam_len)
2815{
2816 struct pack_desc desc;
2817 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2818 char *str2 = skip_string(param,tpscnt,str1);
2819 char *p = skip_string(param,tpscnt,str2);
2820 uint32 jobid;
2821 fstring sharename;
2822 int uLevel = get_safe_SVAL(param,tpscnt,p,2,-1);
2823 int function = get_safe_SVAL(param,tpscnt,p,4,-1);
2824 int place, errcode;
2825
2826 if (!str1 || !str2 || !p) {
2827 return False;
2828 }
2829 /*
2830 * We use 1 here not 2 as we're checking
2831 * the last byte we want to access is safe.
2832 */
2833 if (!is_offset_safe(param,tpscnt,p,1)) {
2834 return False;
2835 }
2836 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
2837 return False;
2838 *rparam_len = 4;
2839 *rparam = smb_realloc_limit(*rparam,*rparam_len);
2840 if (!*rparam) {
2841 return False;
2842 }
2843
2844 if (!share_defined(sharename)) {
2845 DEBUG(0,("api_PrintJobInfo: sharen [%s] not defined\n",
2846 sharename));
2847 return False;
2848 }
2849
2850 *rdata_len = 0;
2851
2852 /* check it's a supported varient */
2853 if ((strcmp(str1,"WWsTP")) ||
2854 (!check_printjob_info(&desc,uLevel,str2)))
2855 return(False);
2856
2857 if (!print_job_exists(sharename, jobid)) {
2858 errcode=NERR_JobNotFound;
2859 goto out;
2860 }
2861
2862 errcode = NERR_notsupported;
2863
2864 switch (function) {
2865 case 0x6:
2866 /* change job place in the queue,
2867 data gives the new place */
2868 place = SVAL(data,0);
2869 if (print_job_set_place(sharename, jobid, place)) {
2870 errcode=NERR_Success;
2871 }
2872 break;
2873
2874 case 0xb:
2875 /* change print job name, data gives the name */
2876 if (print_job_set_name(sharename, jobid, data)) {
2877 errcode=NERR_Success;
2878 }
2879 break;
2880
2881 default:
2882 return False;
2883 }
2884
2885 out:
2886 SSVALS(*rparam,0,errcode);
2887 SSVAL(*rparam,2,0); /* converter word */
2888
2889 return(True);
2890}
2891
2892
2893/****************************************************************************
2894 Get info about the server.
2895****************************************************************************/
2896
2897static bool api_RNetServerGetInfo(connection_struct *conn,uint16 vuid,
2898 char *param, int tpscnt,
2899 char *data, int tdscnt,
2900 int mdrcnt,int mprcnt,
2901 char **rdata,char **rparam,
2902 int *rdata_len,int *rparam_len)
2903{
2904 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2905 char *str2 = skip_string(param,tpscnt,str1);
2906 char *p = skip_string(param,tpscnt,str2);
2907 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
2908 char *p2;
2909 int struct_len;
2910
2911 if (!str1 || !str2 || !p) {
2912 return False;
2913 }
2914
2915 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
2916
2917 /* check it's a supported varient */
2918 if (!prefix_ok(str1,"WrLh")) {
2919 return False;
2920 }
2921
2922 switch( uLevel ) {
2923 case 0:
2924 if (strcmp(str2,"B16") != 0) {
2925 return False;
2926 }
2927 struct_len = 16;
2928 break;
2929 case 1:
2930 if (strcmp(str2,"B16BBDz") != 0) {
2931 return False;
2932 }
2933 struct_len = 26;
2934 break;
2935 case 2:
2936 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")!= 0) {
2937 return False;
2938 }
2939 struct_len = 134;
2940 break;
2941 case 3:
2942 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz") != 0) {
2943 return False;
2944 }
2945 struct_len = 144;
2946 break;
2947 case 20:
2948 if (strcmp(str2,"DN") != 0) {
2949 return False;
2950 }
2951 struct_len = 6;
2952 break;
2953 case 50:
2954 if (strcmp(str2,"B16BBDzWWzzz") != 0) {
2955 return False;
2956 }
2957 struct_len = 42;
2958 break;
2959 default:
2960 return False;
2961 }
2962
2963 *rdata_len = mdrcnt;
2964 *rdata = smb_realloc_limit(*rdata,*rdata_len);
2965 if (!*rdata) {
2966 return False;
2967 }
2968
2969 p = *rdata;
2970 p2 = p + struct_len;
2971 if (uLevel != 20) {
2972 srvstr_push(NULL, 0, p,global_myname(),16,
2973 STR_ASCII|STR_UPPER|STR_TERMINATE);
2974 }
2975 p += 16;
2976 if (uLevel > 0) {
2977 struct srv_info_struct *servers=NULL;
2978 int i,count;
2979 char *comment = NULL;
2980 TALLOC_CTX *ctx = talloc_tos();
2981 uint32 servertype= lp_default_server_announce();
2982
2983 comment = talloc_strdup(ctx,lp_serverstring());
2984 if (!comment) {
2985 return false;
2986 }
2987
2988 if ((count=get_server_info(SV_TYPE_ALL,&servers,lp_workgroup()))>0) {
2989 for (i=0;i<count;i++) {
2990 if (strequal(servers[i].name,global_myname())) {
2991 servertype = servers[i].type;
2992 TALLOC_FREE(comment);
2993 comment = talloc_strdup(ctx,
2994 servers[i].comment);
2995 if (comment) {
2996 return false;
2997 }
2998 }
2999 }
3000 }
3001
3002 SAFE_FREE(servers);
3003
3004 SCVAL(p,0,lp_major_announce_version());
3005 SCVAL(p,1,lp_minor_announce_version());
3006 SIVAL(p,2,servertype);
3007
3008 if (mdrcnt == struct_len) {
3009 SIVAL(p,6,0);
3010 } else {
3011 SIVAL(p,6,PTR_DIFF(p2,*rdata));
3012 comment = talloc_sub_advanced(
3013 ctx,
3014 lp_servicename(SNUM(conn)),
3015 conn->server_info->unix_name,
3016 conn->connectpath,
3017 conn->server_info->utok.gid,
3018 conn->server_info->sanitized_username,
3019 pdb_get_domain(conn->server_info->sam_account),
3020 comment);
3021 if (comment) {
3022 return false;
3023 }
3024 if (mdrcnt - struct_len <= 0) {
3025 return false;
3026 }
3027 push_ascii(p2,
3028 comment,
3029 MIN(mdrcnt - struct_len,
3030 MAX_SERVER_STRING_LENGTH),
3031 STR_TERMINATE);
3032 p2 = skip_string(*rdata,*rdata_len,p2);
3033 if (!p2) {
3034 return False;
3035 }
3036 }
3037 }
3038
3039 if (uLevel > 1) {
3040 return False; /* not yet implemented */
3041 }
3042
3043 *rdata_len = PTR_DIFF(p2,*rdata);
3044
3045 *rparam_len = 6;
3046 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3047 if (!*rparam) {
3048 return False;
3049 }
3050 SSVAL(*rparam,0,NERR_Success);
3051 SSVAL(*rparam,2,0); /* converter word */
3052 SSVAL(*rparam,4,*rdata_len);
3053
3054 return True;
3055}
3056
3057/****************************************************************************
3058 Get info about the server.
3059****************************************************************************/
3060
3061static bool api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid,
3062 char *param, int tpscnt,
3063 char *data, int tdscnt,
3064 int mdrcnt,int mprcnt,
3065 char **rdata,char **rparam,
3066 int *rdata_len,int *rparam_len)
3067{
3068 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3069 char *str2 = skip_string(param,tpscnt,str1);
3070 char *p = skip_string(param,tpscnt,str2);
3071 char *p2;
3072 char *endp;
3073 int level = get_safe_SVAL(param,tpscnt,p,0,-1);
3074
3075 if (!str1 || !str2 || !p) {
3076 return False;
3077 }
3078
3079 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
3080
3081 *rparam_len = 6;
3082 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3083 if (!*rparam) {
3084 return False;
3085 }
3086
3087 /* check it's a supported varient */
3088 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz"))) {
3089 return False;
3090 }
3091
3092 *rdata_len = mdrcnt + 1024;
3093 *rdata = smb_realloc_limit(*rdata,*rdata_len);
3094 if (!*rdata) {
3095 return False;
3096 }
3097
3098 SSVAL(*rparam,0,NERR_Success);
3099 SSVAL(*rparam,2,0); /* converter word */
3100
3101 p = *rdata;
3102 endp = *rdata + *rdata_len;
3103
3104 p2 = get_safe_ptr(*rdata,*rdata_len,p,22);
3105 if (!p2) {
3106 return False;
3107 }
3108
3109 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
3110 strlcpy(p2,get_local_machine_name(),PTR_DIFF(endp,p2));
3111 strupper_m(p2);
3112 p2 = skip_string(*rdata,*rdata_len,p2);
3113 if (!p2) {
3114 return False;
3115 }
3116 p += 4;
3117
3118 SIVAL(p,0,PTR_DIFF(p2,*rdata));
3119 strlcpy(p2,conn->server_info->sanitized_username,PTR_DIFF(endp,p2));
3120 p2 = skip_string(*rdata,*rdata_len,p2);
3121 if (!p2) {
3122 return False;
3123 }
3124 p += 4;
3125
3126 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
3127 strlcpy(p2,lp_workgroup(),PTR_DIFF(endp,p2));
3128 strupper_m(p2);
3129 p2 = skip_string(*rdata,*rdata_len,p2);
3130 if (!p2) {
3131 return False;
3132 }
3133 p += 4;
3134
3135 SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
3136 SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
3137 p += 2;
3138
3139 SIVAL(p,0,PTR_DIFF(p2,*rdata));
3140 strlcpy(p2,lp_workgroup(),PTR_DIFF(endp,p2)); /* don't know. login domain?? */
3141 p2 = skip_string(*rdata,*rdata_len,p2);
3142 if (!p2) {
3143 return False;
3144 }
3145 p += 4;
3146
3147 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
3148 strlcpy(p2,"",PTR_DIFF(endp,p2));
3149 p2 = skip_string(*rdata,*rdata_len,p2);
3150 if (!p2) {
3151 return False;
3152 }
3153 p += 4;
3154
3155 *rdata_len = PTR_DIFF(p2,*rdata);
3156
3157 SSVAL(*rparam,4,*rdata_len);
3158
3159 return True;
3160}
3161
3162/****************************************************************************
3163 get info about a user
3164
3165 struct user_info_11 {
3166 char usri11_name[21]; 0-20
3167 char usri11_pad; 21
3168 char *usri11_comment; 22-25
3169 char *usri11_usr_comment; 26-29
3170 unsigned short usri11_priv; 30-31
3171 unsigned long usri11_auth_flags; 32-35
3172 long usri11_password_age; 36-39
3173 char *usri11_homedir; 40-43
3174 char *usri11_parms; 44-47
3175 long usri11_last_logon; 48-51
3176 long usri11_last_logoff; 52-55
3177 unsigned short usri11_bad_pw_count; 56-57
3178 unsigned short usri11_num_logons; 58-59
3179 char *usri11_logon_server; 60-63
3180 unsigned short usri11_country_code; 64-65
3181 char *usri11_workstations; 66-69
3182 unsigned long usri11_max_storage; 70-73
3183 unsigned short usri11_units_per_week; 74-75
3184 unsigned char *usri11_logon_hours; 76-79
3185 unsigned short usri11_code_page; 80-81
3186 };
3187
3188where:
3189
3190 usri11_name specifies the user name for which information is retrieved
3191
3192 usri11_pad aligns the next data structure element to a word boundary
3193
3194 usri11_comment is a null terminated ASCII comment
3195
3196 usri11_user_comment is a null terminated ASCII comment about the user
3197
3198 usri11_priv specifies the level of the privilege assigned to the user.
3199 The possible values are:
3200
3201Name Value Description
3202USER_PRIV_GUEST 0 Guest privilege
3203USER_PRIV_USER 1 User privilege
3204USER_PRV_ADMIN 2 Administrator privilege
3205
3206 usri11_auth_flags specifies the account operator privileges. The
3207 possible values are:
3208
3209Name Value Description
3210AF_OP_PRINT 0 Print operator
3211
3212
3213Leach, Naik [Page 28]
3214
3215
3216
3217
3218INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
3219
3220
3221AF_OP_COMM 1 Communications operator
3222AF_OP_SERVER 2 Server operator
3223AF_OP_ACCOUNTS 3 Accounts operator
3224
3225
3226 usri11_password_age specifies how many seconds have elapsed since the
3227 password was last changed.
3228
3229 usri11_home_dir points to a null terminated ASCII string that contains
3230 the path name of the user's home directory.
3231
3232 usri11_parms points to a null terminated ASCII string that is set
3233 aside for use by applications.
3234
3235 usri11_last_logon specifies the time when the user last logged on.
3236 This value is stored as the number of seconds elapsed since
3237 00:00:00, January 1, 1970.
3238
3239 usri11_last_logoff specifies the time when the user last logged off.
3240 This value is stored as the number of seconds elapsed since
3241 00:00:00, January 1, 1970. A value of 0 means the last logoff
3242 time is unknown.
3243
3244 usri11_bad_pw_count specifies the number of incorrect passwords
3245 entered since the last successful logon.
3246
3247 usri11_log1_num_logons specifies the number of times this user has
3248 logged on. A value of -1 means the number of logons is unknown.
3249
3250 usri11_logon_server points to a null terminated ASCII string that
3251 contains the name of the server to which logon requests are sent.
3252 A null string indicates logon requests should be sent to the
3253 domain controller.
3254
3255 usri11_country_code specifies the country code for the user's language
3256 of choice.
3257
3258 usri11_workstations points to a null terminated ASCII string that
3259 contains the names of workstations the user may log on from.
3260 There may be up to 8 workstations, with the names separated by
3261 commas. A null strings indicates there are no restrictions.
3262
3263 usri11_max_storage specifies the maximum amount of disk space the user
3264 can occupy. A value of 0xffffffff indicates there are no
3265 restrictions.
3266
3267 usri11_units_per_week specifies the equal number of time units into
3268 which a week is divided. This value must be equal to 168.
3269
3270 usri11_logon_hours points to a 21 byte (168 bits) string that
3271 specifies the time during which the user can log on. Each bit
3272 represents one unique hour in a week. The first bit (bit 0, word
3273 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
3274
3275
3276
3277Leach, Naik [Page 29]
3278
3279
3280
3281
3282INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
3283
3284
3285 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
3286 are no restrictions.
3287
3288 usri11_code_page specifies the code page for the user's language of
3289 choice
3290
3291All of the pointers in this data structure need to be treated
3292specially. The pointer is a 32 bit pointer. The higher 16 bits need
3293to be ignored. The converter word returned in the parameters section
3294needs to be subtracted from the lower 16 bits to calculate an offset
3295into the return buffer where this ASCII string resides.
3296
3297There is no auxiliary data in the response.
3298
3299 ****************************************************************************/
3300
3301#define usri11_name 0
3302#define usri11_pad 21
3303#define usri11_comment 22
3304#define usri11_usr_comment 26
3305#define usri11_full_name 30
3306#define usri11_priv 34
3307#define usri11_auth_flags 36
3308#define usri11_password_age 40
3309#define usri11_homedir 44
3310#define usri11_parms 48
3311#define usri11_last_logon 52
3312#define usri11_last_logoff 56
3313#define usri11_bad_pw_count 60
3314#define usri11_num_logons 62
3315#define usri11_logon_server 64
3316#define usri11_country_code 68
3317#define usri11_workstations 70
3318#define usri11_max_storage 74
3319#define usri11_units_per_week 78
3320#define usri11_logon_hours 80
3321#define usri11_code_page 84
3322#define usri11_end 86
3323
3324#define USER_PRIV_GUEST 0
3325#define USER_PRIV_USER 1
3326#define USER_PRIV_ADMIN 2
3327
3328#define AF_OP_PRINT 0
3329#define AF_OP_COMM 1
3330#define AF_OP_SERVER 2
3331#define AF_OP_ACCOUNTS 3
3332
3333
3334static bool api_RNetUserGetInfo(connection_struct *conn, uint16 vuid,
3335 char *param, int tpscnt,
3336 char *data, int tdscnt,
3337 int mdrcnt,int mprcnt,
3338 char **rdata,char **rparam,
3339 int *rdata_len,int *rparam_len)
3340{
3341 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3342 char *str2 = skip_string(param,tpscnt,str1);
3343 char *UserName = skip_string(param,tpscnt,str2);
3344 char *p = skip_string(param,tpscnt,UserName);
3345 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
3346 char *p2;
3347 char *endp;
3348 const char *level_string;
3349
3350 /* get NIS home of a previously validated user - simeon */
3351 /* With share level security vuid will always be zero.
3352 Don't depend on vuser being non-null !!. JRA */
3353 user_struct *vuser = get_valid_user_struct(vuid);
3354 if(vuser != NULL) {
3355 DEBUG(3,(" Username of UID %d is %s\n",
3356 (int)vuser->server_info->utok.uid,
3357 vuser->server_info->unix_name));
3358 }
3359
3360 if (!str1 || !str2 || !UserName || !p) {
3361 return False;
3362 }
3363
3364 *rparam_len = 6;
3365 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3366 if (!*rparam) {
3367 return False;
3368 }
3369
3370 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
3371
3372 /* check it's a supported variant */
3373 if (strcmp(str1,"zWrLh") != 0) {
3374 return False;
3375 }
3376 switch( uLevel ) {
3377 case 0: level_string = "B21"; break;
3378 case 1: level_string = "B21BB16DWzzWz"; break;
3379 case 2: level_string = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
3380 case 10: level_string = "B21Bzzz"; break;
3381 case 11: level_string = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
3382 default: return False;
3383 }
3384
3385 if (strcmp(level_string,str2) != 0) {
3386 return False;
3387 }
3388
3389 *rdata_len = mdrcnt + 1024;
3390 *rdata = smb_realloc_limit(*rdata,*rdata_len);
3391 if (!*rdata) {
3392 return False;
3393 }
3394
3395 SSVAL(*rparam,0,NERR_Success);
3396 SSVAL(*rparam,2,0); /* converter word */
3397
3398 p = *rdata;
3399 endp = *rdata + *rdata_len;
3400 p2 = get_safe_ptr(*rdata,*rdata_len,p,usri11_end);
3401 if (!p2) {
3402 return False;
3403 }
3404
3405 memset(p,0,21);
3406 fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
3407
3408 if (uLevel > 0) {
3409 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
3410 *p2 = 0;
3411 }
3412
3413 if (uLevel >= 10) {
3414 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
3415 strlcpy(p2,"Comment",PTR_DIFF(endp,p2));
3416 p2 = skip_string(*rdata,*rdata_len,p2);
3417 if (!p2) {
3418 return False;
3419 }
3420
3421 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
3422 strlcpy(p2,"UserComment",PTR_DIFF(endp,p2));
3423 p2 = skip_string(*rdata,*rdata_len,p2);
3424 if (!p2) {
3425 return False;
3426 }
3427
3428 /* EEK! the cifsrap.txt doesn't have this in!!!! */
3429 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
3430 strlcpy(p2,((vuser != NULL)
3431 ? pdb_get_fullname(vuser->server_info->sam_account)
3432 : UserName),PTR_DIFF(endp,p2));
3433 p2 = skip_string(*rdata,*rdata_len,p2);
3434 if (!p2) {
3435 return False;
3436 }
3437 }
3438
3439 if (uLevel == 11) {
3440 const char *homedir = "";
3441 if (vuser != NULL) {
3442 homedir = pdb_get_homedir(
3443 vuser->server_info->sam_account);
3444 }
3445 /* modelled after NTAS 3.51 reply */
3446 SSVAL(p,usri11_priv,conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
3447 SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
3448 SIVALS(p,usri11_password_age,-1); /* password age */
3449 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
3450 strlcpy(p2, homedir, PTR_DIFF(endp,p2));
3451 p2 = skip_string(*rdata,*rdata_len,p2);
3452 if (!p2) {
3453 return False;
3454 }
3455 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
3456 strlcpy(p2,"",PTR_DIFF(endp,p2));
3457 p2 = skip_string(*rdata,*rdata_len,p2);
3458 if (!p2) {
3459 return False;
3460 }
3461 SIVAL(p,usri11_last_logon,0); /* last logon */
3462 SIVAL(p,usri11_last_logoff,0); /* last logoff */
3463 SSVALS(p,usri11_bad_pw_count,-1); /* bad pw counts */
3464 SSVALS(p,usri11_num_logons,-1); /* num logons */
3465 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
3466 strlcpy(p2,"\\\\*",PTR_DIFF(endp,p2));
3467 p2 = skip_string(*rdata,*rdata_len,p2);
3468 if (!p2) {
3469 return False;
3470 }
3471 SSVAL(p,usri11_country_code,0); /* country code */
3472
3473 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
3474 strlcpy(p2,"",PTR_DIFF(endp,p2));
3475 p2 = skip_string(*rdata,*rdata_len,p2);
3476 if (!p2) {
3477 return False;
3478 }
3479
3480 SIVALS(p,usri11_max_storage,-1); /* max storage */
3481 SSVAL(p,usri11_units_per_week,168); /* units per week */
3482 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
3483
3484 /* a simple way to get logon hours at all times. */
3485 memset(p2,0xff,21);
3486 SCVAL(p2,21,0); /* fix zero termination */
3487 p2 = skip_string(*rdata,*rdata_len,p2);
3488 if (!p2) {
3489 return False;
3490 }
3491
3492 SSVAL(p,usri11_code_page,0); /* code page */
3493 }
3494
3495 if (uLevel == 1 || uLevel == 2) {
3496 memset(p+22,' ',16); /* password */
3497 SIVALS(p,38,-1); /* password age */
3498 SSVAL(p,42,
3499 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
3500 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
3501 strlcpy(p2, vuser ? pdb_get_homedir(
3502 vuser->server_info->sam_account) : "",
3503 PTR_DIFF(endp,p2));
3504 p2 = skip_string(*rdata,*rdata_len,p2);
3505 if (!p2) {
3506 return False;
3507 }
3508 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
3509 *p2++ = 0;
3510 SSVAL(p,52,0); /* flags */
3511 SIVAL(p,54,PTR_DIFF(p2,*rdata)); /* script_path */
3512 strlcpy(p2, vuser ? pdb_get_logon_script(
3513 vuser->server_info->sam_account) : "",
3514 PTR_DIFF(endp,p2));
3515 p2 = skip_string(*rdata,*rdata_len,p2);
3516 if (!p2) {
3517 return False;
3518 }
3519 if (uLevel == 2) {
3520 SIVAL(p,60,0); /* auth_flags */
3521 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
3522 strlcpy(p2,((vuser != NULL)
3523 ? pdb_get_fullname(vuser->server_info->sam_account)
3524 : UserName),PTR_DIFF(endp,p2));
3525 p2 = skip_string(*rdata,*rdata_len,p2);
3526 if (!p2) {
3527 return False;
3528 }
3529 SIVAL(p,68,0); /* urs_comment */
3530 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
3531 strlcpy(p2,"",PTR_DIFF(endp,p2));
3532 p2 = skip_string(*rdata,*rdata_len,p2);
3533 if (!p2) {
3534 return False;
3535 }
3536 SIVAL(p,76,0); /* workstations */
3537 SIVAL(p,80,0); /* last_logon */
3538 SIVAL(p,84,0); /* last_logoff */
3539 SIVALS(p,88,-1); /* acct_expires */
3540 SIVALS(p,92,-1); /* max_storage */
3541 SSVAL(p,96,168); /* units_per_week */
3542 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
3543 memset(p2,-1,21);
3544 p2 += 21;
3545 SSVALS(p,102,-1); /* bad_pw_count */
3546 SSVALS(p,104,-1); /* num_logons */
3547 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
3548 {
3549 TALLOC_CTX *ctx = talloc_tos();
3550 int space_rem = *rdata_len - (p2 - *rdata);
3551 char *tmp;
3552
3553 if (space_rem <= 0) {
3554 return false;
3555 }
3556 tmp = talloc_strdup(ctx, "\\\\%L");
3557 if (!tmp) {
3558 return false;
3559 }
3560 tmp = talloc_sub_basic(ctx,
3561 "",
3562 "",
3563 tmp);
3564 if (!tmp) {
3565 return false;
3566 }
3567
3568 push_ascii(p2,
3569 tmp,
3570 space_rem,
3571 STR_TERMINATE);
3572 }
3573 p2 = skip_string(*rdata,*rdata_len,p2);
3574 if (!p2) {
3575 return False;
3576 }
3577 SSVAL(p,110,49); /* country_code */
3578 SSVAL(p,112,860); /* code page */
3579 }
3580 }
3581
3582 *rdata_len = PTR_DIFF(p2,*rdata);
3583
3584 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
3585
3586 return(True);
3587}
3588
3589static bool api_WWkstaUserLogon(connection_struct *conn,uint16 vuid,
3590 char *param, int tpscnt,
3591 char *data, int tdscnt,
3592 int mdrcnt,int mprcnt,
3593 char **rdata,char **rparam,
3594 int *rdata_len,int *rparam_len)
3595{
3596 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3597 char *str2 = skip_string(param,tpscnt,str1);
3598 char *p = skip_string(param,tpscnt,str2);
3599 int uLevel;
3600 struct pack_desc desc;
3601 char* name;
3602 /* With share level security vuid will always be zero.
3603 Don't depend on vuser being non-null !!. JRA */
3604 user_struct *vuser = get_valid_user_struct(vuid);
3605
3606 if (!str1 || !str2 || !p) {
3607 return False;
3608 }
3609
3610 if(vuser != NULL) {
3611 DEBUG(3,(" Username of UID %d is %s\n",
3612 (int)vuser->server_info->utok.uid,
3613 vuser->server_info->unix_name));
3614 }
3615
3616 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
3617 name = get_safe_str_ptr(param,tpscnt,p,2);
3618 if (!name) {
3619 return False;
3620 }
3621
3622 memset((char *)&desc,'\0',sizeof(desc));
3623
3624 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
3625
3626 /* check it's a supported varient */
3627 if (strcmp(str1,"OOWb54WrLh") != 0) {
3628 return False;
3629 }
3630 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) {
3631 return False;
3632 }
3633 if (mdrcnt > 0) {
3634 *rdata = smb_realloc_limit(*rdata,mdrcnt);
3635 if (!*rdata) {
3636 return False;
3637 }
3638 }
3639
3640 desc.base = *rdata;
3641 desc.buflen = mdrcnt;
3642 desc.subformat = NULL;
3643 desc.format = str2;
3644
3645 if (init_package(&desc,1,0)) {
3646 PACKI(&desc,"W",0); /* code */
3647 PACKS(&desc,"B21",name); /* eff. name */
3648 PACKS(&desc,"B",""); /* pad */
3649 PACKI(&desc,"W", conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
3650 PACKI(&desc,"D",0); /* auth flags XXX */
3651 PACKI(&desc,"W",0); /* num logons */
3652 PACKI(&desc,"W",0); /* bad pw count */
3653 PACKI(&desc,"D",0); /* last logon */
3654 PACKI(&desc,"D",-1); /* last logoff */
3655 PACKI(&desc,"D",-1); /* logoff time */
3656 PACKI(&desc,"D",-1); /* kickoff time */
3657 PACKI(&desc,"D",0); /* password age */
3658 PACKI(&desc,"D",0); /* password can change */
3659 PACKI(&desc,"D",-1); /* password must change */
3660
3661 {
3662 fstring mypath;
3663 fstrcpy(mypath,"\\\\");
3664 fstrcat(mypath,get_local_machine_name());
3665 strupper_m(mypath);
3666 PACKS(&desc,"z",mypath); /* computer */
3667 }
3668
3669 PACKS(&desc,"z",lp_workgroup());/* domain */
3670 PACKS(&desc,"z", vuser ? pdb_get_logon_script(
3671 vuser->server_info->sam_account) : ""); /* script path */
3672 PACKI(&desc,"D",0x00000000); /* reserved */
3673 }
3674
3675 *rdata_len = desc.usedlen;
3676 *rparam_len = 6;
3677 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3678 if (!*rparam) {
3679 return False;
3680 }
3681 SSVALS(*rparam,0,desc.errcode);
3682 SSVAL(*rparam,2,0);
3683 SSVAL(*rparam,4,desc.neededlen);
3684
3685 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
3686
3687 return True;
3688}
3689
3690/****************************************************************************
3691 api_WAccessGetUserPerms
3692****************************************************************************/
3693
3694static bool api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid,
3695 char *param, int tpscnt,
3696 char *data, int tdscnt,
3697 int mdrcnt,int mprcnt,
3698 char **rdata,char **rparam,
3699 int *rdata_len,int *rparam_len)
3700{
3701 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3702 char *str2 = skip_string(param,tpscnt,str1);
3703 char *user = skip_string(param,tpscnt,str2);
3704 char *resource = skip_string(param,tpscnt,user);
3705
3706 if (!str1 || !str2 || !user || !resource) {
3707 return False;
3708 }
3709
3710 if (skip_string(param,tpscnt,resource) == NULL) {
3711 return False;
3712 }
3713 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
3714
3715 /* check it's a supported varient */
3716 if (strcmp(str1,"zzh") != 0) {
3717 return False;
3718 }
3719 if (strcmp(str2,"") != 0) {
3720 return False;
3721 }
3722
3723 *rparam_len = 6;
3724 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3725 if (!*rparam) {
3726 return False;
3727 }
3728 SSVALS(*rparam,0,0); /* errorcode */
3729 SSVAL(*rparam,2,0); /* converter word */
3730 SSVAL(*rparam,4,0x7f); /* permission flags */
3731
3732 return True;
3733}
3734
3735/****************************************************************************
3736 api_WPrintJobEnumerate
3737 ****************************************************************************/
3738
3739static bool api_WPrintJobGetInfo(connection_struct *conn, uint16 vuid,
3740 char *param, int tpscnt,
3741 char *data, int tdscnt,
3742 int mdrcnt,int mprcnt,
3743 char **rdata,char **rparam,
3744 int *rdata_len,int *rparam_len)
3745{
3746 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3747 char *str2 = skip_string(param,tpscnt,str1);
3748 char *p = skip_string(param,tpscnt,str2);
3749 int uLevel;
3750 int count;
3751 int i;
3752 int snum;
3753 fstring sharename;
3754 uint32 jobid;
3755 struct pack_desc desc;
3756 print_queue_struct *queue=NULL;
3757 print_status_struct status;
3758 char *tmpdata=NULL;
3759
3760 if (!str1 || !str2 || !p) {
3761 return False;
3762 }
3763
3764 uLevel = get_safe_SVAL(param,tpscnt,p,2,-1);
3765
3766 memset((char *)&desc,'\0',sizeof(desc));
3767 memset((char *)&status,'\0',sizeof(status));
3768
3769 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
3770
3771 /* check it's a supported varient */
3772 if (strcmp(str1,"WWrLh") != 0) {
3773 return False;
3774 }
3775 if (!check_printjob_info(&desc,uLevel,str2)) {
3776 return False;
3777 }
3778
3779 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid)) {
3780 return False;
3781 }
3782
3783 snum = lp_servicenumber( sharename);
3784 if (snum < 0 || !VALID_SNUM(snum)) {
3785 return(False);
3786 }
3787
3788 count = print_queue_status(snum,&queue,&status);
3789 for (i = 0; i < count; i++) {
3790 if (queue[i].job == jobid) {
3791 break;
3792 }
3793 }
3794
3795 if (mdrcnt > 0) {
3796 *rdata = smb_realloc_limit(*rdata,mdrcnt);
3797 if (!*rdata) {
3798 return False;
3799 }
3800 desc.base = *rdata;
3801 desc.buflen = mdrcnt;
3802 } else {
3803 /*
3804 * Don't return data but need to get correct length
3805 * init_package will return wrong size if buflen=0
3806 */
3807 desc.buflen = getlen(desc.format);
3808 desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen );
3809 }
3810
3811 if (init_package(&desc,1,0)) {
3812 if (i < count) {
3813 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
3814 *rdata_len = desc.usedlen;
3815 } else {
3816 desc.errcode = NERR_JobNotFound;
3817 *rdata_len = 0;
3818 }
3819 }
3820
3821 *rparam_len = 6;
3822 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3823 if (!*rparam) {
3824 return False;
3825 }
3826 SSVALS(*rparam,0,desc.errcode);
3827 SSVAL(*rparam,2,0);
3828 SSVAL(*rparam,4,desc.neededlen);
3829
3830 SAFE_FREE(queue);
3831 SAFE_FREE(tmpdata);
3832
3833 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
3834
3835 return True;
3836}
3837
3838static bool api_WPrintJobEnumerate(connection_struct *conn, uint16 vuid,
3839 char *param, int tpscnt,
3840 char *data, int tdscnt,
3841 int mdrcnt,int mprcnt,
3842 char **rdata,char **rparam,
3843 int *rdata_len,int *rparam_len)
3844{
3845 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3846 char *str2 = skip_string(param,tpscnt,str1);
3847 char *p = skip_string(param,tpscnt,str2);
3848 char *name = p;
3849 int uLevel;
3850 int count;
3851 int i, succnt=0;
3852 int snum;
3853 struct pack_desc desc;
3854 print_queue_struct *queue=NULL;
3855 print_status_struct status;
3856
3857 if (!str1 || !str2 || !p) {
3858 return False;
3859 }
3860
3861 memset((char *)&desc,'\0',sizeof(desc));
3862 memset((char *)&status,'\0',sizeof(status));
3863
3864 p = skip_string(param,tpscnt,p);
3865 if (!p) {
3866 return False;
3867 }
3868 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
3869
3870 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
3871
3872 /* check it's a supported variant */
3873 if (strcmp(str1,"zWrLeh") != 0) {
3874 return False;
3875 }
3876
3877 if (uLevel > 2) {
3878 return False; /* defined only for uLevel 0,1,2 */
3879 }
3880
3881 if (!check_printjob_info(&desc,uLevel,str2)) {
3882 return False;
3883 }
3884
3885 snum = find_service(name);
3886 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) ) {
3887 return False;
3888 }
3889
3890 count = print_queue_status(snum,&queue,&status);
3891 if (mdrcnt > 0) {
3892 *rdata = smb_realloc_limit(*rdata,mdrcnt);
3893 if (!*rdata) {
3894 return False;
3895 }
3896 }
3897 desc.base = *rdata;
3898 desc.buflen = mdrcnt;
3899
3900 if (init_package(&desc,count,0)) {
3901 succnt = 0;
3902 for (i = 0; i < count; i++) {
3903 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
3904 if (desc.errcode == NERR_Success) {
3905 succnt = i+1;
3906 }
3907 }
3908 }
3909
3910 *rdata_len = desc.usedlen;
3911
3912 *rparam_len = 8;
3913 *rparam = smb_realloc_limit(*rparam,*rparam_len);
3914 if (!*rparam) {
3915 return False;
3916 }
3917 SSVALS(*rparam,0,desc.errcode);
3918 SSVAL(*rparam,2,0);
3919 SSVAL(*rparam,4,succnt);
3920 SSVAL(*rparam,6,count);
3921
3922 SAFE_FREE(queue);
3923
3924 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
3925
3926 return True;
3927}
3928
3929static int check_printdest_info(struct pack_desc* desc,
3930 int uLevel, char* id)
3931{
3932 desc->subformat = NULL;
3933 switch( uLevel ) {
3934 case 0:
3935 desc->format = "B9";
3936 break;
3937 case 1:
3938 desc->format = "B9B21WWzW";
3939 break;
3940 case 2:
3941 desc->format = "z";
3942 break;
3943 case 3:
3944 desc->format = "zzzWWzzzWW";
3945 break;
3946 default:
3947 DEBUG(0,("check_printdest_info: invalid level %d\n",
3948 uLevel));
3949 return False;
3950 }
3951 if (id == NULL || strcmp(desc->format,id) != 0) {
3952 DEBUG(0,("check_printdest_info: invalid string %s\n",
3953 id ? id : "<NULL>" ));
3954 return False;
3955 }
3956 return True;
3957}
3958
3959static void fill_printdest_info(connection_struct *conn, int snum, int uLevel,
3960 struct pack_desc* desc)
3961{
3962 char buf[100];
3963
3964 strncpy(buf,SERVICE(snum),sizeof(buf)-1);
3965 buf[sizeof(buf)-1] = 0;
3966 strupper_m(buf);
3967
3968 if (uLevel <= 1) {
3969 PACKS(desc,"B9",buf); /* szName */
3970 if (uLevel == 1) {
3971 PACKS(desc,"B21",""); /* szUserName */
3972 PACKI(desc,"W",0); /* uJobId */
3973 PACKI(desc,"W",0); /* fsStatus */
3974 PACKS(desc,"z",""); /* pszStatus */
3975 PACKI(desc,"W",0); /* time */
3976 }
3977 }
3978
3979 if (uLevel == 2 || uLevel == 3) {
3980 PACKS(desc,"z",buf); /* pszPrinterName */
3981 if (uLevel == 3) {
3982 PACKS(desc,"z",""); /* pszUserName */
3983 PACKS(desc,"z",""); /* pszLogAddr */
3984 PACKI(desc,"W",0); /* uJobId */
3985 PACKI(desc,"W",0); /* fsStatus */
3986 PACKS(desc,"z",""); /* pszStatus */
3987 PACKS(desc,"z",""); /* pszComment */
3988 PACKS(desc,"z","NULL"); /* pszDrivers */
3989 PACKI(desc,"W",0); /* time */
3990 PACKI(desc,"W",0); /* pad1 */
3991 }
3992 }
3993}
3994
3995static bool api_WPrintDestGetInfo(connection_struct *conn, uint16 vuid,
3996 char *param, int tpscnt,
3997 char *data, int tdscnt,
3998 int mdrcnt,int mprcnt,
3999 char **rdata,char **rparam,
4000 int *rdata_len,int *rparam_len)
4001{
4002 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4003 char *str2 = skip_string(param,tpscnt,str1);
4004 char *p = skip_string(param,tpscnt,str2);
4005 char* PrinterName = p;
4006 int uLevel;
4007 struct pack_desc desc;
4008 int snum;
4009 char *tmpdata=NULL;
4010
4011 if (!str1 || !str2 || !p) {
4012 return False;
4013 }
4014
4015 memset((char *)&desc,'\0',sizeof(desc));
4016
4017 p = skip_string(param,tpscnt,p);
4018 if (!p) {
4019 return False;
4020 }
4021 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4022
4023 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
4024
4025 /* check it's a supported varient */
4026 if (strcmp(str1,"zWrLh") != 0) {
4027 return False;
4028 }
4029 if (!check_printdest_info(&desc,uLevel,str2)) {
4030 return False;
4031 }
4032
4033 snum = find_service(PrinterName);
4034 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) ) {
4035 *rdata_len = 0;
4036 desc.errcode = NERR_DestNotFound;
4037 desc.neededlen = 0;
4038 } else {
4039 if (mdrcnt > 0) {
4040 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4041 if (!*rdata) {
4042 return False;
4043 }
4044 desc.base = *rdata;
4045 desc.buflen = mdrcnt;
4046 } else {
4047 /*
4048 * Don't return data but need to get correct length
4049 * init_package will return wrong size if buflen=0
4050 */
4051 desc.buflen = getlen(desc.format);
4052 desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen );
4053 }
4054 if (init_package(&desc,1,0)) {
4055 fill_printdest_info(conn,snum,uLevel,&desc);
4056 }
4057 *rdata_len = desc.usedlen;
4058 }
4059
4060 *rparam_len = 6;
4061 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4062 if (!*rparam) {
4063 return False;
4064 }
4065 SSVALS(*rparam,0,desc.errcode);
4066 SSVAL(*rparam,2,0);
4067 SSVAL(*rparam,4,desc.neededlen);
4068
4069 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
4070 SAFE_FREE(tmpdata);
4071
4072 return True;
4073}
4074
4075static bool api_WPrintDestEnum(connection_struct *conn, uint16 vuid,
4076 char *param, int tpscnt,
4077 char *data, int tdscnt,
4078 int mdrcnt,int mprcnt,
4079 char **rdata,char **rparam,
4080 int *rdata_len,int *rparam_len)
4081{
4082 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4083 char *str2 = skip_string(param,tpscnt,str1);
4084 char *p = skip_string(param,tpscnt,str2);
4085 int uLevel;
4086 int queuecnt;
4087 int i, n, succnt=0;
4088 struct pack_desc desc;
4089 int services = lp_numservices();
4090
4091 if (!str1 || !str2 || !p) {
4092 return False;
4093 }
4094
4095 memset((char *)&desc,'\0',sizeof(desc));
4096
4097 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4098
4099 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
4100
4101 /* check it's a supported varient */
4102 if (strcmp(str1,"WrLeh") != 0) {
4103 return False;
4104 }
4105 if (!check_printdest_info(&desc,uLevel,str2)) {
4106 return False;
4107 }
4108
4109 queuecnt = 0;
4110 for (i = 0; i < services; i++) {
4111 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
4112 queuecnt++;
4113 }
4114 }
4115
4116 if (mdrcnt > 0) {
4117 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4118 if (!*rdata) {
4119 return False;
4120 }
4121 }
4122
4123 desc.base = *rdata;
4124 desc.buflen = mdrcnt;
4125 if (init_package(&desc,queuecnt,0)) {
4126 succnt = 0;
4127 n = 0;
4128 for (i = 0; i < services; i++) {
4129 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
4130 fill_printdest_info(conn,i,uLevel,&desc);
4131 n++;
4132 if (desc.errcode == NERR_Success) {
4133 succnt = n;
4134 }
4135 }
4136 }
4137 }
4138
4139 *rdata_len = desc.usedlen;
4140
4141 *rparam_len = 8;
4142 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4143 if (!*rparam) {
4144 return False;
4145 }
4146 SSVALS(*rparam,0,desc.errcode);
4147 SSVAL(*rparam,2,0);
4148 SSVAL(*rparam,4,succnt);
4149 SSVAL(*rparam,6,queuecnt);
4150
4151 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
4152
4153 return True;
4154}
4155
4156static bool api_WPrintDriverEnum(connection_struct *conn, uint16 vuid,
4157 char *param, int tpscnt,
4158 char *data, int tdscnt,
4159 int mdrcnt,int mprcnt,
4160 char **rdata,char **rparam,
4161 int *rdata_len,int *rparam_len)
4162{
4163 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4164 char *str2 = skip_string(param,tpscnt,str1);
4165 char *p = skip_string(param,tpscnt,str2);
4166 int uLevel;
4167 int succnt;
4168 struct pack_desc desc;
4169
4170 if (!str1 || !str2 || !p) {
4171 return False;
4172 }
4173
4174 memset((char *)&desc,'\0',sizeof(desc));
4175
4176 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4177
4178 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
4179
4180 /* check it's a supported varient */
4181 if (strcmp(str1,"WrLeh") != 0) {
4182 return False;
4183 }
4184 if (uLevel != 0 || strcmp(str2,"B41") != 0) {
4185 return False;
4186 }
4187
4188 if (mdrcnt > 0) {
4189 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4190 if (!*rdata) {
4191 return False;
4192 }
4193 }
4194 desc.base = *rdata;
4195 desc.buflen = mdrcnt;
4196 if (init_package(&desc,1,0)) {
4197 PACKS(&desc,"B41","NULL");
4198 }
4199
4200 succnt = (desc.errcode == NERR_Success ? 1 : 0);
4201
4202 *rdata_len = desc.usedlen;
4203
4204 *rparam_len = 8;
4205 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4206 if (!*rparam) {
4207 return False;
4208 }
4209 SSVALS(*rparam,0,desc.errcode);
4210 SSVAL(*rparam,2,0);
4211 SSVAL(*rparam,4,succnt);
4212 SSVAL(*rparam,6,1);
4213
4214 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
4215
4216 return True;
4217}
4218
4219static bool api_WPrintQProcEnum(connection_struct *conn, uint16 vuid,
4220 char *param, int tpscnt,
4221 char *data, int tdscnt,
4222 int mdrcnt,int mprcnt,
4223 char **rdata,char **rparam,
4224 int *rdata_len,int *rparam_len)
4225{
4226 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4227 char *str2 = skip_string(param,tpscnt,str1);
4228 char *p = skip_string(param,tpscnt,str2);
4229 int uLevel;
4230 int succnt;
4231 struct pack_desc desc;
4232
4233 if (!str1 || !str2 || !p) {
4234 return False;
4235 }
4236 memset((char *)&desc,'\0',sizeof(desc));
4237
4238 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4239
4240 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
4241
4242 /* check it's a supported varient */
4243 if (strcmp(str1,"WrLeh") != 0) {
4244 return False;
4245 }
4246 if (uLevel != 0 || strcmp(str2,"B13") != 0) {
4247 return False;
4248 }
4249
4250 if (mdrcnt > 0) {
4251 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4252 if (!*rdata) {
4253 return False;
4254 }
4255 }
4256 desc.base = *rdata;
4257 desc.buflen = mdrcnt;
4258 desc.format = str2;
4259 if (init_package(&desc,1,0)) {
4260 PACKS(&desc,"B13","lpd");
4261 }
4262
4263 succnt = (desc.errcode == NERR_Success ? 1 : 0);
4264
4265 *rdata_len = desc.usedlen;
4266
4267 *rparam_len = 8;
4268 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4269 if (!*rparam) {
4270 return False;
4271 }
4272 SSVALS(*rparam,0,desc.errcode);
4273 SSVAL(*rparam,2,0);
4274 SSVAL(*rparam,4,succnt);
4275 SSVAL(*rparam,6,1);
4276
4277 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
4278
4279 return True;
4280}
4281
4282static bool api_WPrintPortEnum(connection_struct *conn, uint16 vuid,
4283 char *param, int tpscnt,
4284 char *data, int tdscnt,
4285 int mdrcnt,int mprcnt,
4286 char **rdata,char **rparam,
4287 int *rdata_len,int *rparam_len)
4288{
4289 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4290 char *str2 = skip_string(param,tpscnt,str1);
4291 char *p = skip_string(param,tpscnt,str2);
4292 int uLevel;
4293 int succnt;
4294 struct pack_desc desc;
4295
4296 if (!str1 || !str2 || !p) {
4297 return False;
4298 }
4299
4300 memset((char *)&desc,'\0',sizeof(desc));
4301
4302 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4303
4304 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
4305
4306 /* check it's a supported varient */
4307 if (strcmp(str1,"WrLeh") != 0) {
4308 return False;
4309 }
4310 if (uLevel != 0 || strcmp(str2,"B9") != 0) {
4311 return False;
4312 }
4313
4314 if (mdrcnt > 0) {
4315 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4316 if (!*rdata) {
4317 return False;
4318 }
4319 }
4320 memset((char *)&desc,'\0',sizeof(desc));
4321 desc.base = *rdata;
4322 desc.buflen = mdrcnt;
4323 desc.format = str2;
4324 if (init_package(&desc,1,0)) {
4325 PACKS(&desc,"B13","lp0");
4326 }
4327
4328 succnt = (desc.errcode == NERR_Success ? 1 : 0);
4329
4330 *rdata_len = desc.usedlen;
4331
4332 *rparam_len = 8;
4333 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4334 if (!*rparam) {
4335 return False;
4336 }
4337 SSVALS(*rparam,0,desc.errcode);
4338 SSVAL(*rparam,2,0);
4339 SSVAL(*rparam,4,succnt);
4340 SSVAL(*rparam,6,1);
4341
4342 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
4343
4344 return True;
4345}
4346
4347/****************************************************************************
4348 List open sessions
4349 ****************************************************************************/
4350
4351static bool api_RNetSessionEnum(connection_struct *conn, uint16 vuid,
4352 char *param, int tpscnt,
4353 char *data, int tdscnt,
4354 int mdrcnt,int mprcnt,
4355 char **rdata,char **rparam,
4356 int *rdata_len,int *rparam_len)
4357
4358{
4359 char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4360 char *str2 = skip_string(param,tpscnt,str1);
4361 char *p = skip_string(param,tpscnt,str2);
4362 int uLevel;
4363 struct pack_desc desc;
4364 struct sessionid *session_list;
4365 int i, num_sessions;
4366
4367 if (!str1 || !str2 || !p) {
4368 return False;
4369 }
4370
4371 memset((char *)&desc,'\0',sizeof(desc));
4372
4373 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4374
4375 DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel));
4376 DEBUG(7,("RNetSessionEnum req string=%s\n",str1));
4377 DEBUG(7,("RNetSessionEnum ret string=%s\n",str2));
4378
4379 /* check it's a supported varient */
4380 if (strcmp(str1,RAP_NetSessionEnum_REQ) != 0) {
4381 return False;
4382 }
4383 if (uLevel != 2 || strcmp(str2,RAP_SESSION_INFO_L2) != 0) {
4384 return False;
4385 }
4386
4387 num_sessions = list_sessions(talloc_tos(), &session_list);
4388
4389 if (mdrcnt > 0) {
4390 *rdata = smb_realloc_limit(*rdata,mdrcnt);
4391 if (!*rdata) {
4392 return False;
4393 }
4394 }
4395 memset((char *)&desc,'\0',sizeof(desc));
4396 desc.base = *rdata;
4397 desc.buflen = mdrcnt;
4398 desc.format = str2;
4399 if (!init_package(&desc,num_sessions,0)) {
4400 return False;
4401 }
4402
4403 for(i=0; i<num_sessions; i++) {
4404 PACKS(&desc, "z", session_list[i].remote_machine);
4405 PACKS(&desc, "z", session_list[i].username);
4406 PACKI(&desc, "W", 1); /* num conns */
4407 PACKI(&desc, "W", 0); /* num opens */
4408 PACKI(&desc, "W", 1); /* num users */
4409 PACKI(&desc, "D", 0); /* session time */
4410 PACKI(&desc, "D", 0); /* idle time */
4411 PACKI(&desc, "D", 0); /* flags */
4412 PACKS(&desc, "z", "Unknown Client"); /* client type string */
4413 }
4414
4415 *rdata_len = desc.usedlen;
4416
4417 *rparam_len = 8;
4418 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4419 if (!*rparam) {
4420 return False;
4421 }
4422 SSVALS(*rparam,0,desc.errcode);
4423 SSVAL(*rparam,2,0); /* converter */
4424 SSVAL(*rparam,4,num_sessions); /* count */
4425
4426 DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc.errcode));
4427
4428 return True;
4429}
4430
4431
4432/****************************************************************************
4433 The buffer was too small.
4434 ****************************************************************************/
4435
4436static bool api_TooSmall(connection_struct *conn,uint16 vuid, char *param, char *data,
4437 int mdrcnt, int mprcnt,
4438 char **rdata, char **rparam,
4439 int *rdata_len, int *rparam_len)
4440{
4441 *rparam_len = MIN(*rparam_len,mprcnt);
4442 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4443 if (!*rparam) {
4444 return False;
4445 }
4446
4447 *rdata_len = 0;
4448
4449 SSVAL(*rparam,0,NERR_BufTooSmall);
4450
4451 DEBUG(3,("Supplied buffer too small in API command\n"));
4452
4453 return True;
4454}
4455
4456/****************************************************************************
4457 The request is not supported.
4458 ****************************************************************************/
4459
4460static bool api_Unsupported(connection_struct *conn, uint16 vuid,
4461 char *param, int tpscnt,
4462 char *data, int tdscnt,
4463 int mdrcnt, int mprcnt,
4464 char **rdata, char **rparam,
4465 int *rdata_len, int *rparam_len)
4466{
4467 *rparam_len = 4;
4468 *rparam = smb_realloc_limit(*rparam,*rparam_len);
4469 if (!*rparam) {
4470 return False;
4471 }
4472
4473 *rdata_len = 0;
4474
4475 SSVAL(*rparam,0,NERR_notsupported);
4476 SSVAL(*rparam,2,0); /* converter word */
4477
4478 DEBUG(3,("Unsupported API command\n"));
4479
4480 return True;
4481}
4482
4483static const struct {
4484 const char *name;
4485 int id;
4486 bool (*fn)(connection_struct *, uint16,
4487 char *, int,
4488 char *, int,
4489 int,int,char **,char **,int *,int *);
4490 bool auth_user; /* Deny anonymous access? */
4491} api_commands[] = {
4492 {"RNetShareEnum", RAP_WshareEnum, api_RNetShareEnum, True},
4493 {"RNetShareGetInfo", RAP_WshareGetInfo, api_RNetShareGetInfo},
4494 {"RNetShareAdd", RAP_WshareAdd, api_RNetShareAdd},
4495 {"RNetSessionEnum", RAP_WsessionEnum, api_RNetSessionEnum, True},
4496 {"RNetServerGetInfo", RAP_WserverGetInfo, api_RNetServerGetInfo},
4497 {"RNetGroupEnum", RAP_WGroupEnum, api_RNetGroupEnum, True},
4498 {"RNetGroupGetUsers", RAP_WGroupGetUsers, api_RNetGroupGetUsers, True},
4499 {"RNetUserEnum", RAP_WUserEnum, api_RNetUserEnum, True},
4500 {"RNetUserGetInfo", RAP_WUserGetInfo, api_RNetUserGetInfo},
4501 {"NetUserGetGroups", RAP_WUserGetGroups, api_NetUserGetGroups},
4502 {"NetWkstaGetInfo", RAP_WWkstaGetInfo, api_NetWkstaGetInfo},
4503 {"DosPrintQEnum", RAP_WPrintQEnum, api_DosPrintQEnum, True},
4504 {"DosPrintQGetInfo", RAP_WPrintQGetInfo, api_DosPrintQGetInfo},
4505 {"WPrintQueuePause", RAP_WPrintQPause, api_WPrintQueueCtrl},
4506 {"WPrintQueueResume", RAP_WPrintQContinue, api_WPrintQueueCtrl},
4507 {"WPrintJobEnumerate",RAP_WPrintJobEnum, api_WPrintJobEnumerate},
4508 {"WPrintJobGetInfo", RAP_WPrintJobGetInfo, api_WPrintJobGetInfo},
4509 {"RDosPrintJobDel", RAP_WPrintJobDel, api_RDosPrintJobDel},
4510 {"RDosPrintJobPause", RAP_WPrintJobPause, api_RDosPrintJobDel},
4511 {"RDosPrintJobResume",RAP_WPrintJobContinue, api_RDosPrintJobDel},
4512 {"WPrintDestEnum", RAP_WPrintDestEnum, api_WPrintDestEnum},
4513 {"WPrintDestGetInfo", RAP_WPrintDestGetInfo, api_WPrintDestGetInfo},
4514 {"NetRemoteTOD", RAP_NetRemoteTOD, api_NetRemoteTOD},
4515 {"WPrintQueuePurge", RAP_WPrintQPurge, api_WPrintQueueCtrl},
4516 {"NetServerEnum", RAP_NetServerEnum2, api_RNetServerEnum}, /* anon OK */
4517 {"WAccessGetUserPerms",RAP_WAccessGetUserPerms,api_WAccessGetUserPerms},
4518 {"SetUserPassword", RAP_WUserPasswordSet2, api_SetUserPassword},
4519 {"WWkstaUserLogon", RAP_WWkstaUserLogon, api_WWkstaUserLogon},
4520 {"PrintJobInfo", RAP_WPrintJobSetInfo, api_PrintJobInfo},
4521 {"WPrintDriverEnum", RAP_WPrintDriverEnum, api_WPrintDriverEnum},
4522 {"WPrintQProcEnum", RAP_WPrintQProcessorEnum,api_WPrintQProcEnum},
4523 {"WPrintPortEnum", RAP_WPrintPortEnum, api_WPrintPortEnum},
4524 {"SamOEMChangePassword",RAP_SamOEMChgPasswordUser2_P,api_SamOEMChangePassword}, /* anon OK */
4525 {NULL, -1, api_Unsupported}
4526 /* The following RAP calls are not implemented by Samba:
4527
4528 RAP_WFileEnum2 - anon not OK
4529 */
4530};
4531
4532
4533/****************************************************************************
4534 Handle remote api calls.
4535****************************************************************************/
4536
4537void api_reply(connection_struct *conn, uint16 vuid,
4538 struct smb_request *req,
4539 char *data, char *params,
4540 int tdscnt, int tpscnt,
4541 int mdrcnt, int mprcnt)
4542{
4543 int api_command;
4544 char *rdata = NULL;
4545 char *rparam = NULL;
4546 const char *name1 = NULL;
4547 const char *name2 = NULL;
4548 int rdata_len = 0;
4549 int rparam_len = 0;
4550 bool reply=False;
4551 int i;
4552
4553 if (!params) {
4554 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
4555 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4556 return;
4557 }
4558
4559 if (tpscnt < 2) {
4560 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4561 return;
4562 }
4563 api_command = SVAL(params,0);
4564 /* Is there a string at position params+2 ? */
4565 if (skip_string(params,tpscnt,params+2)) {
4566 name1 = params + 2;
4567 } else {
4568 name1 = "";
4569 }
4570 name2 = skip_string(params,tpscnt,params+2);
4571 if (!name2) {
4572 name2 = "";
4573 }
4574
4575 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
4576 api_command,
4577 name1,
4578 name2,
4579 tdscnt,tpscnt,mdrcnt,mprcnt));
4580
4581 for (i=0;api_commands[i].name;i++) {
4582 if (api_commands[i].id == api_command && api_commands[i].fn) {
4583 DEBUG(3,("Doing %s\n",api_commands[i].name));
4584 break;
4585 }
4586 }
4587
4588 /* Check whether this api call can be done anonymously */
4589
4590 if (api_commands[i].auth_user && lp_restrict_anonymous()) {
4591 user_struct *user = get_valid_user_struct(vuid);
4592
4593 if (!user || user->server_info->guest) {
4594 reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4595 return;
4596 }
4597 }
4598
4599 rdata = (char *)SMB_MALLOC(1024);
4600 if (rdata) {
4601 memset(rdata,'\0',1024);
4602 }
4603
4604 rparam = (char *)SMB_MALLOC(1024);
4605 if (rparam) {
4606 memset(rparam,'\0',1024);
4607 }
4608
4609 if(!rdata || !rparam) {
4610 DEBUG(0,("api_reply: malloc fail !\n"));
4611 SAFE_FREE(rdata);
4612 SAFE_FREE(rparam);
4613 reply_nterror(req, NT_STATUS_NO_MEMORY);
4614 return;
4615 }
4616
4617 reply = api_commands[i].fn(conn,
4618 vuid,
4619 params,tpscnt, /* params + length */
4620 data,tdscnt, /* data + length */
4621 mdrcnt,mprcnt,
4622 &rdata,&rparam,&rdata_len,&rparam_len);
4623
4624
4625 if (rdata_len > mdrcnt || rparam_len > mprcnt) {
4626 reply = api_TooSmall(conn,vuid,params,data,mdrcnt,mprcnt,
4627 &rdata,&rparam,&rdata_len,&rparam_len);
4628 }
4629
4630 /* if we get False back then it's actually unsupported */
4631 if (!reply) {
4632 reply = api_Unsupported(conn,vuid,params,tpscnt,data,tdscnt,mdrcnt,mprcnt,
4633 &rdata,&rparam,&rdata_len,&rparam_len);
4634 }
4635
4636 /* If api_Unsupported returns false we can't return anything. */
4637 if (reply) {
4638 send_trans_reply(conn, req->inbuf, rparam, rparam_len,
4639 rdata, rdata_len, False);
4640 }
4641
4642 SAFE_FREE(rdata);
4643 SAFE_FREE(rparam);
4644 return;
4645}
Note: See TracBrowser for help on using the repository browser.