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

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

Samba 3.5.0: Initial import

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