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

Last change on this file since 285 was 136, checked in by Paul Smedley, 17 years ago

Update trunk to 3.2.0rc1

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