source: branches/samba-3.5.x/source3/smbd/lanman.c@ 1075

Last change on this file since 1075 was 773, checked in by Herwig Bauernfeind, 12 years ago

Samba Server 3.5: Update branch to 3.5.20

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