source: branches/samba-3.2.x/source/smbd/lanman.c@ 814

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

Update 3.2 to 3.2.14 (final)

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