r4348: syncing up for 3.0.11pre1
[Samba.git] / source / smbd / lanman.c
blob4af11da78440917ceec5cfe311c5637a45bda69b
1 /*
2 Unix SMB/CIFS implementation.
3 Inter-process communication and named pipe handling
4 Copyright (C) Andrew Tridgell 1992-1998
6 SMB Version handling
7 Copyright (C) John H Terpstra 1995-1998
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 This file handles the named pipe and mailslot calls
25 in the SMBtrans protocol
28 #include "includes.h"
30 #ifdef CHECK_TYPES
31 #undef CHECK_TYPES
32 #endif
33 #define CHECK_TYPES 0
35 extern fstring local_machine;
37 #define NERR_Success 0
38 #define NERR_badpass 86
39 #define NERR_notsupported 50
41 #define NERR_BASE (2100)
42 #define NERR_BufTooSmall (NERR_BASE+23)
43 #define NERR_JobNotFound (NERR_BASE+51)
44 #define NERR_DestNotFound (NERR_BASE+52)
46 #define ACCESS_READ 0x01
47 #define ACCESS_WRITE 0x02
48 #define ACCESS_CREATE 0x04
50 #define SHPWLEN 8 /* share password length */
52 static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param,char *data,
53 int mdrcnt,int mprcnt,
54 char **rdata,char **rparam,
55 int *rdata_len,int *rparam_len);
56 static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param,char *data,
57 int mdrcnt,int mprcnt,
58 char **rdata,char **rparam,
59 int *rdata_len,int *rparam_len);
62 static int CopyExpanded(connection_struct *conn,
63 int snum, char** dst, char* src, int* n)
65 pstring buf;
66 int l;
68 if (!src || !dst || !n || !(*dst)) return(0);
70 StrnCpy(buf,src,sizeof(buf)/2);
71 pstring_sub(buf,"%S",lp_servicename(snum));
72 standard_sub_conn(conn,buf,sizeof(buf));
73 l = push_ascii(*dst,buf,*n, STR_TERMINATE);
74 (*dst) += l;
75 (*n) -= l;
76 return l;
79 static int CopyAndAdvance(char** dst, char* src, int* n)
81 int l;
82 if (!src || !dst || !n || !(*dst)) return(0);
83 l = push_ascii(*dst,src,*n, STR_TERMINATE);
84 (*dst) += l;
85 (*n) -= l;
86 return l;
89 static int StrlenExpanded(connection_struct *conn, int snum, char* s)
91 pstring buf;
92 if (!s) return(0);
93 StrnCpy(buf,s,sizeof(buf)/2);
94 pstring_sub(buf,"%S",lp_servicename(snum));
95 standard_sub_conn(conn,buf,sizeof(buf));
96 return strlen(buf) + 1;
99 static char* Expand(connection_struct *conn, int snum, char* s)
101 static pstring buf;
102 if (!s) return(NULL);
103 StrnCpy(buf,s,sizeof(buf)/2);
104 pstring_sub(buf,"%S",lp_servicename(snum));
105 standard_sub_conn(conn,buf,sizeof(buf));
106 return &buf[0];
109 /*******************************************************************
110 check a API string for validity when we only need to check the prefix
111 ******************************************************************/
112 static BOOL prefix_ok(const char *str, const char *prefix)
114 return(strncmp(str,prefix,strlen(prefix)) == 0);
117 struct pack_desc {
118 const char* format; /* formatstring for structure */
119 const char* subformat; /* subformat for structure */
120 char* base; /* baseaddress of buffer */
121 int buflen; /* remaining size for fixed part; on init: length of base */
122 int subcount; /* count of substructures */
123 char* structbuf; /* pointer into buffer for remaining fixed part */
124 int stringlen; /* remaining size for variable part */
125 char* stringbuf; /* pointer into buffer for remaining variable part */
126 int neededlen; /* total needed size */
127 int usedlen; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
128 const char* curpos; /* current position; pointer into format or subformat */
129 int errcode;
132 static int get_counter(const char** p)
134 int i, n;
135 if (!p || !(*p)) return(1);
136 if (!isdigit((int)**p)) return 1;
137 for (n = 0;;) {
138 i = **p;
139 if (isdigit(i))
140 n = 10 * n + (i - '0');
141 else
142 return n;
143 (*p)++;
147 static int getlen(const char* p)
149 int n = 0;
150 if (!p) return(0);
151 while (*p) {
152 switch( *p++ ) {
153 case 'W': /* word (2 byte) */
154 n += 2;
155 break;
156 case 'K': /* status word? (2 byte) */
157 n += 2;
158 break;
159 case 'N': /* count of substructures (word) at end */
160 n += 2;
161 break;
162 case 'D': /* double word (4 byte) */
163 case 'z': /* offset to zero terminated string (4 byte) */
164 case 'l': /* offset to user data (4 byte) */
165 n += 4;
166 break;
167 case 'b': /* offset to data (with counter) (4 byte) */
168 n += 4;
169 get_counter(&p);
170 break;
171 case 'B': /* byte (with optional counter) */
172 n += get_counter(&p);
173 break;
176 return n;
179 static BOOL init_package(struct pack_desc* p, int count, int subcount)
181 int n = p->buflen;
182 int i;
184 if (!p->format || !p->base) return(False);
186 i = count * getlen(p->format);
187 if (p->subformat) i += subcount * getlen(p->subformat);
188 p->structbuf = p->base;
189 p->neededlen = 0;
190 p->usedlen = 0;
191 p->subcount = 0;
192 p->curpos = p->format;
193 if (i > n) {
194 p->neededlen = i;
195 i = n = 0;
196 #if 0
198 * This is the old error code we used. Aparently
199 * WinNT/2k systems return ERRbuftoosmall (2123) and
200 * OS/2 needs this. I'm leaving this here so we can revert
201 * if needed. JRA.
203 p->errcode = ERRmoredata;
204 #else
205 p->errcode = ERRbuftoosmall;
206 #endif
208 else
209 p->errcode = NERR_Success;
210 p->buflen = i;
211 n -= i;
212 p->stringbuf = p->base + i;
213 p->stringlen = n;
214 return(p->errcode == NERR_Success);
217 static int package(struct pack_desc* p, ...)
219 va_list args;
220 int needed=0, stringneeded;
221 const char* str=NULL;
222 int is_string=0, stringused;
223 int32 temp;
225 va_start(args,p);
227 if (!*p->curpos) {
228 if (!p->subcount)
229 p->curpos = p->format;
230 else {
231 p->curpos = p->subformat;
232 p->subcount--;
235 #if CHECK_TYPES
236 str = va_arg(args,char*);
237 SMB_ASSERT(strncmp(str,p->curpos,strlen(str)) == 0);
238 #endif
239 stringneeded = -1;
241 if (!p->curpos) {
242 va_end(args);
243 return(0);
246 switch( *p->curpos++ ) {
247 case 'W': /* word (2 byte) */
248 needed = 2;
249 temp = va_arg(args,int);
250 if (p->buflen >= needed) SSVAL(p->structbuf,0,temp);
251 break;
252 case 'K': /* status word? (2 byte) */
253 needed = 2;
254 temp = va_arg(args,int);
255 if (p->buflen >= needed) SSVAL(p->structbuf,0,temp);
256 break;
257 case 'N': /* count of substructures (word) at end */
258 needed = 2;
259 p->subcount = va_arg(args,int);
260 if (p->buflen >= needed) SSVAL(p->structbuf,0,p->subcount);
261 break;
262 case 'D': /* double word (4 byte) */
263 needed = 4;
264 temp = va_arg(args,int);
265 if (p->buflen >= needed) SIVAL(p->structbuf,0,temp);
266 break;
267 case 'B': /* byte (with optional counter) */
268 needed = get_counter(&p->curpos);
270 char *s = va_arg(args,char*);
271 if (p->buflen >= needed) StrnCpy(p->structbuf,s?s:"",needed-1);
273 break;
274 case 'z': /* offset to zero terminated string (4 byte) */
275 str = va_arg(args,char*);
276 stringneeded = (str ? strlen(str)+1 : 0);
277 is_string = 1;
278 break;
279 case 'l': /* offset to user data (4 byte) */
280 str = va_arg(args,char*);
281 stringneeded = va_arg(args,int);
282 is_string = 0;
283 break;
284 case 'b': /* offset to data (with counter) (4 byte) */
285 str = va_arg(args,char*);
286 stringneeded = get_counter(&p->curpos);
287 is_string = 0;
288 break;
290 va_end(args);
291 if (stringneeded >= 0) {
292 needed = 4;
293 if (p->buflen >= needed) {
294 stringused = stringneeded;
295 if (stringused > p->stringlen) {
296 stringused = (is_string ? p->stringlen : 0);
297 if (p->errcode == NERR_Success) p->errcode = ERRmoredata;
299 if (!stringused)
300 SIVAL(p->structbuf,0,0);
301 else {
302 SIVAL(p->structbuf,0,PTR_DIFF(p->stringbuf,p->base));
303 memcpy(p->stringbuf,str?str:"",stringused);
304 if (is_string) p->stringbuf[stringused-1] = '\0';
305 p->stringbuf += stringused;
306 p->stringlen -= stringused;
307 p->usedlen += stringused;
310 p->neededlen += stringneeded;
312 p->neededlen += needed;
313 if (p->buflen >= needed) {
314 p->structbuf += needed;
315 p->buflen -= needed;
316 p->usedlen += needed;
318 else {
319 if (p->errcode == NERR_Success) p->errcode = ERRmoredata;
321 return 1;
324 #if CHECK_TYPES
325 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
326 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
327 #else
328 #define PACK(desc,t,v) package(desc,v)
329 #define PACKl(desc,t,v,l) package(desc,v,l)
330 #endif
332 static void PACKI(struct pack_desc* desc, const char *t,int v)
334 PACK(desc,t,v);
337 static void PACKS(struct pack_desc* desc,const char *t,const char *v)
339 PACK(desc,t,v);
343 /****************************************************************************
344 get a print queue
345 ****************************************************************************/
346 static void PackDriverData(struct pack_desc* desc)
348 char drivdata[4+4+32];
349 SIVAL(drivdata,0,sizeof drivdata); /* cb */
350 SIVAL(drivdata,4,1000); /* lVersion */
351 memset(drivdata+8,0,32); /* szDeviceName */
352 push_ascii(drivdata+8,"NULL",-1, STR_TERMINATE);
353 PACKl(desc,"l",drivdata,sizeof drivdata); /* pDriverData */
356 static int check_printq_info(struct pack_desc* desc,
357 int uLevel, char *id1, char *id2)
359 desc->subformat = NULL;
360 switch( uLevel ) {
361 case 0:
362 desc->format = "B13";
363 break;
364 case 1:
365 desc->format = "B13BWWWzzzzzWW";
366 break;
367 case 2:
368 desc->format = "B13BWWWzzzzzWN";
369 desc->subformat = "WB21BB16B10zWWzDDz";
370 break;
371 case 3:
372 desc->format = "zWWWWzzzzWWzzl";
373 break;
374 case 4:
375 desc->format = "zWWWWzzzzWNzzl";
376 desc->subformat = "WWzWWDDzz";
377 break;
378 case 5:
379 desc->format = "z";
380 break;
381 case 51:
382 desc->format = "K";
383 break;
384 case 52:
385 desc->format = "WzzzzzzzzN";
386 desc->subformat = "z";
387 break;
388 default: return False;
390 if (strcmp(desc->format,id1) != 0) return False;
391 if (desc->subformat && strcmp(desc->subformat,id2) != 0) return False;
392 return True;
396 #define RAP_JOB_STATUS_QUEUED 0
397 #define RAP_JOB_STATUS_PAUSED 1
398 #define RAP_JOB_STATUS_SPOOLING 2
399 #define RAP_JOB_STATUS_PRINTING 3
400 #define RAP_JOB_STATUS_PRINTED 4
402 #define RAP_QUEUE_STATUS_PAUSED 1
403 #define RAP_QUEUE_STATUS_ERROR 2
405 /* turn a print job status into a on the wire status
407 static int printj_status(int v)
409 switch (v) {
410 case LPQ_QUEUED:
411 return RAP_JOB_STATUS_QUEUED;
412 case LPQ_PAUSED:
413 return RAP_JOB_STATUS_PAUSED;
414 case LPQ_SPOOLING:
415 return RAP_JOB_STATUS_SPOOLING;
416 case LPQ_PRINTING:
417 return RAP_JOB_STATUS_PRINTING;
419 return 0;
422 /* turn a print queue status into a on the wire status
424 static int printq_status(int v)
426 switch (v) {
427 case LPQ_QUEUED:
428 return 0;
429 case LPQ_PAUSED:
430 return RAP_QUEUE_STATUS_PAUSED;
432 return RAP_QUEUE_STATUS_ERROR;
435 static void fill_printjob_info(connection_struct *conn, int snum, int uLevel,
436 struct pack_desc* desc,
437 print_queue_struct* queue, int n)
439 time_t t = queue->time;
441 /* the client expects localtime */
442 t -= TimeDiff(t);
444 PACKI(desc,"W",pjobid_to_rap(lp_const_servicename(snum),queue->job)); /* uJobId */
445 if (uLevel == 1) {
446 PACKS(desc,"B21",queue->fs_user); /* szUserName */
447 PACKS(desc,"B",""); /* pad */
448 PACKS(desc,"B16",""); /* szNotifyName */
449 PACKS(desc,"B10","PM_Q_RAW"); /* szDataType */
450 PACKS(desc,"z",""); /* pszParms */
451 PACKI(desc,"W",n+1); /* uPosition */
452 PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */
453 PACKS(desc,"z",""); /* pszStatus */
454 PACKI(desc,"D",t); /* ulSubmitted */
455 PACKI(desc,"D",queue->size); /* ulSize */
456 PACKS(desc,"z",queue->fs_file); /* pszComment */
458 if (uLevel == 2 || uLevel == 3 || uLevel == 4) {
459 PACKI(desc,"W",queue->priority); /* uPriority */
460 PACKS(desc,"z",queue->fs_user); /* pszUserName */
461 PACKI(desc,"W",n+1); /* uPosition */
462 PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */
463 PACKI(desc,"D",t); /* ulSubmitted */
464 PACKI(desc,"D",queue->size); /* ulSize */
465 PACKS(desc,"z","Samba"); /* pszComment */
466 PACKS(desc,"z",queue->fs_file); /* pszDocument */
467 if (uLevel == 3) {
468 PACKS(desc,"z",""); /* pszNotifyName */
469 PACKS(desc,"z","PM_Q_RAW"); /* pszDataType */
470 PACKS(desc,"z",""); /* pszParms */
471 PACKS(desc,"z",""); /* pszStatus */
472 PACKS(desc,"z",SERVICE(snum)); /* pszQueue */
473 PACKS(desc,"z","lpd"); /* pszQProcName */
474 PACKS(desc,"z",""); /* pszQProcParms */
475 PACKS(desc,"z","NULL"); /* pszDriverName */
476 PackDriverData(desc); /* pDriverData */
477 PACKS(desc,"z",""); /* pszPrinterName */
478 } else if (uLevel == 4) { /* OS2 */
479 PACKS(desc,"z",""); /* pszSpoolFileName */
480 PACKS(desc,"z",""); /* pszPortName */
481 PACKS(desc,"z",""); /* pszStatus */
482 PACKI(desc,"D",0); /* ulPagesSpooled */
483 PACKI(desc,"D",0); /* ulPagesSent */
484 PACKI(desc,"D",0); /* ulPagesPrinted */
485 PACKI(desc,"D",0); /* ulTimePrinted */
486 PACKI(desc,"D",0); /* ulExtendJobStatus */
487 PACKI(desc,"D",0); /* ulStartPage */
488 PACKI(desc,"D",0); /* ulEndPage */
493 /********************************************************************
494 Return a driver name given an snum.
495 Returns True if from tdb, False otherwise.
496 ********************************************************************/
498 static BOOL get_driver_name(int snum, pstring drivername)
500 NT_PRINTER_INFO_LEVEL *info = NULL;
501 BOOL in_tdb = False;
503 get_a_printer (NULL, &info, 2, lp_servicename(snum));
504 if (info != NULL) {
505 pstrcpy( drivername, info->info_2->drivername);
506 in_tdb = True;
507 free_a_printer(&info, 2);
510 return in_tdb;
513 /********************************************************************
514 Respond to the DosPrintQInfo command with a level of 52
515 This is used to get printer driver information for Win9x clients
516 ********************************************************************/
517 static void fill_printq_info_52(connection_struct *conn, int snum,
518 struct pack_desc* desc, int count )
520 int i;
521 fstring location;
522 NT_PRINTER_DRIVER_INFO_LEVEL driver;
523 NT_PRINTER_INFO_LEVEL *printer = NULL;
525 ZERO_STRUCT(driver);
527 if ( !W_ERROR_IS_OK(get_a_printer( NULL, &printer, 2, lp_servicename(snum))) ) {
528 DEBUG(3,("fill_printq_info_52: Failed to lookup printer [%s]\n",
529 lp_servicename(snum)));
530 goto err;
533 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername,
534 "Windows 4.0", 0)) )
536 DEBUG(3,("fill_printq_info_52: Failed to lookup driver [%s]\n",
537 printer->info_2->drivername));
538 goto err;
541 trim_string(driver.info_3->driverpath, "\\print$\\WIN40\\0\\", 0);
542 trim_string(driver.info_3->datafile, "\\print$\\WIN40\\0\\", 0);
543 trim_string(driver.info_3->helpfile, "\\print$\\WIN40\\0\\", 0);
545 PACKI(desc, "W", 0x0400); /* don't know */
546 PACKS(desc, "z", driver.info_3->name); /* long printer name */
547 PACKS(desc, "z", driver.info_3->driverpath); /* Driverfile Name */
548 PACKS(desc, "z", driver.info_3->datafile); /* Datafile name */
549 PACKS(desc, "z", driver.info_3->monitorname); /* language monitor */
551 fstrcpy(location, "\\\\%L\\print$\\WIN40\\0");
552 standard_sub_basic( "", location, sizeof(location)-1 );
553 PACKS(desc,"z", location); /* share to retrieve files */
555 PACKS(desc,"z", driver.info_3->defaultdatatype); /* default data type */
556 PACKS(desc,"z", driver.info_3->helpfile); /* helpfile name */
557 PACKS(desc,"z", driver.info_3->driverpath); /* driver name */
559 DEBUG(3,("Printer Driver Name: %s:\n",driver.info_3->name));
560 DEBUG(3,("Driver: %s:\n",driver.info_3->driverpath));
561 DEBUG(3,("Data File: %s:\n",driver.info_3->datafile));
562 DEBUG(3,("Language Monitor: %s:\n",driver.info_3->monitorname));
563 DEBUG(3,("Driver Location: %s:\n",location));
564 DEBUG(3,("Data Type: %s:\n",driver.info_3->defaultdatatype));
565 DEBUG(3,("Help File: %s:\n",driver.info_3->helpfile));
566 PACKI(desc,"N",count); /* number of files to copy */
568 for ( i=0; i<count && driver.info_3->dependentfiles && *driver.info_3->dependentfiles[i]; i++)
570 trim_string(driver.info_3->dependentfiles[i], "\\print$\\WIN40\\0\\", 0);
571 PACKS(desc,"z",driver.info_3->dependentfiles[i]); /* driver files to copy */
572 DEBUG(3,("Dependent File: %s:\n",driver.info_3->dependentfiles[i]));
575 /* sanity check */
576 if ( i != count )
577 DEBUG(3,("fill_printq_info_52: file count specified by client [%d] != number of dependent files [%i]\n",
578 count, i));
580 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n", SERVICE(snum),i));
582 desc->errcode=NERR_Success;
583 goto done;
585 err:
586 DEBUG(3,("fill_printq_info: Can't supply driver files\n"));
587 desc->errcode=NERR_notsupported;
589 done:
590 if ( printer )
591 free_a_printer( &printer, 2 );
593 if ( driver.info_3 )
594 free_a_printer_driver( driver, 3 );
598 static void fill_printq_info(connection_struct *conn, int snum, int uLevel,
599 struct pack_desc* desc,
600 int count, print_queue_struct* queue,
601 print_status_struct* status)
603 switch (uLevel) {
604 case 1:
605 case 2:
606 PACKS(desc,"B13",SERVICE(snum));
607 break;
608 case 3:
609 case 4:
610 case 5:
611 PACKS(desc,"z",Expand(conn,snum,SERVICE(snum)));
612 break;
613 case 51:
614 PACKI(desc,"K",printq_status(status->status));
615 break;
618 if (uLevel == 1 || uLevel == 2) {
619 PACKS(desc,"B",""); /* alignment */
620 PACKI(desc,"W",5); /* priority */
621 PACKI(desc,"W",0); /* start time */
622 PACKI(desc,"W",0); /* until time */
623 PACKS(desc,"z",""); /* pSepFile */
624 PACKS(desc,"z","lpd"); /* pPrProc */
625 PACKS(desc,"z",SERVICE(snum)); /* pDestinations */
626 PACKS(desc,"z",""); /* pParms */
627 if (snum < 0) {
628 PACKS(desc,"z","UNKNOWN PRINTER");
629 PACKI(desc,"W",LPSTAT_ERROR);
631 else if (!status || !status->message[0]) {
632 PACKS(desc,"z",Expand(conn,snum,lp_comment(snum)));
633 PACKI(desc,"W",LPSTAT_OK); /* status */
634 } else {
635 PACKS(desc,"z",status->message);
636 PACKI(desc,"W",printq_status(status->status)); /* status */
638 PACKI(desc,(uLevel == 1 ? "W" : "N"),count);
641 if (uLevel == 3 || uLevel == 4) {
642 pstring drivername;
644 PACKI(desc,"W",5); /* uPriority */
645 PACKI(desc,"W",0); /* uStarttime */
646 PACKI(desc,"W",0); /* uUntiltime */
647 PACKI(desc,"W",5); /* pad1 */
648 PACKS(desc,"z",""); /* pszSepFile */
649 PACKS(desc,"z","WinPrint"); /* pszPrProc */
650 PACKS(desc,"z",NULL); /* pszParms */
651 PACKS(desc,"z",NULL); /* pszComment - don't ask.... JRA */
652 /* "don't ask" that it's done this way to fix corrupted
653 Win9X/ME printer comments. */
654 if (!status) {
655 PACKI(desc,"W",LPSTAT_OK); /* fsStatus */
656 } else {
657 PACKI(desc,"W",printq_status(status->status)); /* fsStatus */
659 PACKI(desc,(uLevel == 3 ? "W" : "N"),count); /* cJobs */
660 PACKS(desc,"z",SERVICE(snum)); /* pszPrinters */
661 get_driver_name(snum,drivername);
662 PACKS(desc,"z",drivername); /* pszDriverName */
663 PackDriverData(desc); /* pDriverData */
666 if (uLevel == 2 || uLevel == 4) {
667 int i;
668 for (i=0;i<count;i++)
669 fill_printjob_info(conn,snum,uLevel == 2 ? 1 : 2,desc,&queue[i],i);
672 if (uLevel==52)
673 fill_printq_info_52( conn, snum, desc, count );
676 /* This function returns the number of files for a given driver */
677 static int get_printerdrivernumber(int snum)
679 int result = 0;
680 NT_PRINTER_DRIVER_INFO_LEVEL driver;
681 NT_PRINTER_INFO_LEVEL *printer = NULL;
683 ZERO_STRUCT(driver);
685 if ( !W_ERROR_IS_OK(get_a_printer( NULL, &printer, 2, lp_servicename(snum))) ) {
686 DEBUG(3,("get_printerdrivernumber: Failed to lookup printer [%s]\n",
687 lp_servicename(snum)));
688 goto done;
691 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername,
692 "Windows 4.0", 0)) )
694 DEBUG(3,("get_printerdrivernumber: Failed to lookup driver [%s]\n",
695 printer->info_2->drivername));
696 goto done;
699 /* count the number of files */
700 while ( driver.info_3->dependentfiles && *driver.info_3->dependentfiles[result] )
701 result++;
703 done:
704 if ( printer )
705 free_a_printer( &printer, 2 );
707 if ( driver.info_3 )
708 free_a_printer_driver( driver, 3 );
710 return result;
713 static BOOL api_DosPrintQGetInfo(connection_struct *conn,
714 uint16 vuid, char *param,char *data,
715 int mdrcnt,int mprcnt,
716 char **rdata,char **rparam,
717 int *rdata_len,int *rparam_len)
719 char *str1 = param+2;
720 char *str2 = skip_string(str1,1);
721 char *p = skip_string(str2,1);
722 char *QueueName = p;
723 int uLevel;
724 int count=0;
725 int snum;
726 char* str3;
727 struct pack_desc desc;
728 print_queue_struct *queue=NULL;
729 print_status_struct status;
730 char* tmpdata=NULL;
732 memset((char *)&status,'\0',sizeof(status));
733 memset((char *)&desc,'\0',sizeof(desc));
735 p = skip_string(p,1);
736 uLevel = SVAL(p,0);
737 str3 = p + 4;
739 /* remove any trailing username */
740 if ((p = strchr_m(QueueName,'%')))
741 *p = 0;
743 DEBUG(3,("api_DosPrintQGetInfo uLevel=%d name=%s\n",uLevel,QueueName));
745 /* check it's a supported varient */
746 if (!prefix_ok(str1,"zWrLh"))
747 return False;
748 if (!check_printq_info(&desc,uLevel,str2,str3)) {
750 * Patch from Scott Moomaw <scott@bridgewater.edu>
751 * to return the 'invalid info level' error if an
752 * unknown level was requested.
754 *rdata_len = 0;
755 *rparam_len = 6;
756 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
757 SSVALS(*rparam,0,ERRunknownlevel);
758 SSVAL(*rparam,2,0);
759 SSVAL(*rparam,4,0);
760 return(True);
763 snum = find_service(QueueName);
764 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
765 return False;
767 if (uLevel==52) {
768 count = get_printerdrivernumber(snum);
769 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count));
770 } else {
771 count = print_queue_status(snum, &queue,&status);
774 if (mdrcnt > 0) {
775 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
776 desc.base = *rdata;
777 desc.buflen = mdrcnt;
778 } else {
780 * Don't return data but need to get correct length
781 * init_package will return wrong size if buflen=0
783 desc.buflen = getlen(desc.format);
784 desc.base = tmpdata = (char *) SMB_MALLOC (desc.buflen);
787 if (init_package(&desc,1,count)) {
788 desc.subcount = count;
789 fill_printq_info(conn,snum,uLevel,&desc,count,queue,&status);
792 *rdata_len = desc.usedlen;
795 * We must set the return code to ERRbuftoosmall
796 * in order to support lanman style printing with Win NT/2k
797 * clients --jerry
799 if (!mdrcnt && lp_disable_spoolss())
800 desc.errcode = ERRbuftoosmall;
802 *rdata_len = desc.usedlen;
803 *rparam_len = 6;
804 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
805 SSVALS(*rparam,0,desc.errcode);
806 SSVAL(*rparam,2,0);
807 SSVAL(*rparam,4,desc.neededlen);
809 DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode));
811 SAFE_FREE(queue);
812 SAFE_FREE(tmpdata);
814 return(True);
817 /****************************************************************************
818 View list of all print jobs on all queues.
819 ****************************************************************************/
821 static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid, char* param, char* data,
822 int mdrcnt, int mprcnt,
823 char **rdata, char** rparam,
824 int *rdata_len, int *rparam_len)
826 char *param_format = param+2;
827 char *output_format1 = skip_string(param_format,1);
828 char *p = skip_string(output_format1,1);
829 int uLevel = SVAL(p,0);
830 char *output_format2 = p + 4;
831 int services = lp_numservices();
832 int i, n;
833 struct pack_desc desc;
834 print_queue_struct **queue = NULL;
835 print_status_struct *status = NULL;
836 int* subcntarr = NULL;
837 int queuecnt, subcnt=0, succnt=0;
839 memset((char *)&desc,'\0',sizeof(desc));
841 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
843 if (!prefix_ok(param_format,"WrLeh")) return False;
844 if (!check_printq_info(&desc,uLevel,output_format1,output_format2)) {
846 * Patch from Scott Moomaw <scott@bridgewater.edu>
847 * to return the 'invalid info level' error if an
848 * unknown level was requested.
850 *rdata_len = 0;
851 *rparam_len = 6;
852 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
853 SSVALS(*rparam,0,ERRunknownlevel);
854 SSVAL(*rparam,2,0);
855 SSVAL(*rparam,4,0);
856 return(True);
859 queuecnt = 0;
860 for (i = 0; i < services; i++)
861 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
862 queuecnt++;
863 if (uLevel > 0) {
864 if((queue = SMB_MALLOC_ARRAY(print_queue_struct*, queuecnt)) == NULL) {
865 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
866 return False;
868 memset(queue,0,queuecnt*sizeof(print_queue_struct*));
869 if((status = SMB_MALLOC_ARRAY(print_status_struct,queuecnt)) == NULL) {
870 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
871 return False;
873 memset(status,0,queuecnt*sizeof(print_status_struct));
874 if((subcntarr = SMB_MALLOC_ARRAY(int,queuecnt)) == NULL) {
875 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
876 return False;
878 subcnt = 0;
879 n = 0;
880 for (i = 0; i < services; i++)
881 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
882 subcntarr[n] = print_queue_status(i, &queue[n],&status[n]);
883 subcnt += subcntarr[n];
884 n++;
887 if (mdrcnt > 0) *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
888 desc.base = *rdata;
889 desc.buflen = mdrcnt;
891 if (init_package(&desc,queuecnt,subcnt)) {
892 n = 0;
893 succnt = 0;
894 for (i = 0; i < services; i++)
895 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
896 fill_printq_info(conn,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]);
897 n++;
898 if (desc.errcode == NERR_Success) succnt = n;
902 SAFE_FREE(subcntarr);
904 *rdata_len = desc.usedlen;
905 *rparam_len = 8;
906 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
907 SSVALS(*rparam,0,desc.errcode);
908 SSVAL(*rparam,2,0);
909 SSVAL(*rparam,4,succnt);
910 SSVAL(*rparam,6,queuecnt);
912 for (i = 0; i < queuecnt; i++) {
913 if (queue) SAFE_FREE(queue[i]);
916 SAFE_FREE(queue);
917 SAFE_FREE(status);
919 return True;
922 /****************************************************************************
923 get info level for a server list query
924 ****************************************************************************/
925 static BOOL check_server_info(int uLevel, char* id)
927 switch( uLevel ) {
928 case 0:
929 if (strcmp(id,"B16") != 0) return False;
930 break;
931 case 1:
932 if (strcmp(id,"B16BBDz") != 0) return False;
933 break;
934 default:
935 return False;
937 return True;
940 struct srv_info_struct
942 fstring name;
943 uint32 type;
944 fstring comment;
945 fstring domain;
946 BOOL server_added;
950 /*******************************************************************
951 get server info lists from the files saved by nmbd. Return the
952 number of entries
953 ******************************************************************/
954 static int get_server_info(uint32 servertype,
955 struct srv_info_struct **servers,
956 const char *domain)
958 int count=0;
959 int alloced=0;
960 char **lines;
961 BOOL local_list_only;
962 int i;
964 lines = file_lines_load(lock_path(SERVER_LIST), NULL);
965 if (!lines) {
966 DEBUG(4,("Can't open %s - %s\n",lock_path(SERVER_LIST),strerror(errno)));
967 return(0);
970 /* request for everything is code for request all servers */
971 if (servertype == SV_TYPE_ALL)
972 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
974 local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY);
976 DEBUG(4,("Servertype search: %8x\n",servertype));
978 for (i=0;lines[i];i++) {
979 fstring stype;
980 struct srv_info_struct *s;
981 const char *ptr = lines[i];
982 BOOL ok = True;
984 if (!*ptr) continue;
986 if (count == alloced) {
987 struct srv_info_struct *ts;
989 alloced += 10;
990 ts = SMB_REALLOC_ARRAY(*servers,struct srv_info_struct, alloced);
991 if (!ts) {
992 DEBUG(0,("get_server_info: failed to enlarge servers info struct!\n"));
993 return(0);
995 else *servers = ts;
996 memset((char *)((*servers)+count),'\0',sizeof(**servers)*(alloced-count));
998 s = &(*servers)[count];
1000 if (!next_token(&ptr,s->name , NULL, sizeof(s->name))) continue;
1001 if (!next_token(&ptr,stype , NULL, sizeof(stype))) continue;
1002 if (!next_token(&ptr,s->comment, NULL, sizeof(s->comment))) continue;
1003 if (!next_token(&ptr,s->domain , NULL, sizeof(s->domain))) {
1004 /* this allows us to cope with an old nmbd */
1005 fstrcpy(s->domain,lp_workgroup());
1008 if (sscanf(stype,"%X",&s->type) != 1) {
1009 DEBUG(4,("r:host file "));
1010 ok = False;
1013 /* Filter the servers/domains we return based on what was asked for. */
1015 /* Check to see if we are being asked for a local list only. */
1016 if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) {
1017 DEBUG(4,("r: local list only"));
1018 ok = False;
1021 /* doesn't match up: don't want it */
1022 if (!(servertype & s->type)) {
1023 DEBUG(4,("r:serv type "));
1024 ok = False;
1027 if ((servertype & SV_TYPE_DOMAIN_ENUM) !=
1028 (s->type & SV_TYPE_DOMAIN_ENUM))
1030 DEBUG(4,("s: dom mismatch "));
1031 ok = False;
1034 if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM))
1036 ok = False;
1039 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1040 s->type &= ~SV_TYPE_LOCAL_LIST_ONLY;
1042 if (ok)
1044 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1045 s->name, s->type, s->comment, s->domain));
1047 s->server_added = True;
1048 count++;
1050 else
1052 DEBUG(4,("%20s %8x %25s %15s\n",
1053 s->name, s->type, s->comment, s->domain));
1057 file_lines_free(lines);
1058 return(count);
1062 /*******************************************************************
1063 fill in a server info structure
1064 ******************************************************************/
1065 static int fill_srv_info(struct srv_info_struct *service,
1066 int uLevel, char **buf, int *buflen,
1067 char **stringbuf, int *stringspace, char *baseaddr)
1069 int struct_len;
1070 char* p;
1071 char* p2;
1072 int l2;
1073 int len;
1075 switch (uLevel) {
1076 case 0: struct_len = 16; break;
1077 case 1: struct_len = 26; break;
1078 default: return -1;
1081 if (!buf)
1083 len = 0;
1084 switch (uLevel)
1086 case 1:
1087 len = strlen(service->comment)+1;
1088 break;
1091 if (buflen) *buflen = struct_len;
1092 if (stringspace) *stringspace = len;
1093 return struct_len + len;
1096 len = struct_len;
1097 p = *buf;
1098 if (*buflen < struct_len) return -1;
1099 if (stringbuf)
1101 p2 = *stringbuf;
1102 l2 = *stringspace;
1104 else
1106 p2 = p + struct_len;
1107 l2 = *buflen - struct_len;
1109 if (!baseaddr) baseaddr = p;
1111 switch (uLevel)
1113 case 0:
1114 push_ascii(p,service->name, MAX_NETBIOSNAME_LEN, STR_TERMINATE);
1115 break;
1117 case 1:
1118 push_ascii(p,service->name,MAX_NETBIOSNAME_LEN, STR_TERMINATE);
1119 SIVAL(p,18,service->type);
1120 SIVAL(p,22,PTR_DIFF(p2,baseaddr));
1121 len += CopyAndAdvance(&p2,service->comment,&l2);
1122 break;
1125 if (stringbuf)
1127 *buf = p + struct_len;
1128 *buflen -= struct_len;
1129 *stringbuf = p2;
1130 *stringspace = l2;
1132 else
1134 *buf = p2;
1135 *buflen -= len;
1137 return len;
1141 static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
1143 return(strcmp(s1->name,s2->name));
1146 /****************************************************************************
1147 view list of servers available (or possibly domains). The info is
1148 extracted from lists saved by nmbd on the local host
1149 ****************************************************************************/
1150 static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid, char *param, char *data,
1151 int mdrcnt, int mprcnt, char **rdata,
1152 char **rparam, int *rdata_len, int *rparam_len)
1154 char *str1 = param+2;
1155 char *str2 = skip_string(str1,1);
1156 char *p = skip_string(str2,1);
1157 int uLevel = SVAL(p,0);
1158 int buf_len = SVAL(p,2);
1159 uint32 servertype = IVAL(p,4);
1160 char *p2;
1161 int data_len, fixed_len, string_len;
1162 int f_len = 0, s_len = 0;
1163 struct srv_info_struct *servers=NULL;
1164 int counted=0,total=0;
1165 int i,missed;
1166 fstring domain;
1167 BOOL domain_request;
1168 BOOL local_request;
1170 /* If someone sets all the bits they don't really mean to set
1171 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1172 known servers. */
1174 if (servertype == SV_TYPE_ALL)
1175 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1177 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1178 any other bit (they may just set this bit on it's own) they
1179 want all the locally seen servers. However this bit can be
1180 set on its own so set the requested servers to be
1181 ALL - DOMAIN_ENUM. */
1183 if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM))
1184 servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
1186 domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
1187 local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
1189 p += 8;
1191 if (!prefix_ok(str1,"WrLehD")) return False;
1192 if (!check_server_info(uLevel,str2)) return False;
1194 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1195 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1196 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1198 if (strcmp(str1, "WrLehDz") == 0) {
1199 pull_ascii_fstring(domain, p);
1200 } else {
1201 fstrcpy(domain, lp_workgroup());
1204 if (lp_browse_list())
1205 total = get_server_info(servertype,&servers,domain);
1207 data_len = fixed_len = string_len = 0;
1208 missed = 0;
1210 if (total > 0)
1211 qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
1214 char *lastname=NULL;
1216 for (i=0;i<total;i++)
1218 struct srv_info_struct *s = &servers[i];
1219 if (lastname && strequal(lastname,s->name)) continue;
1220 lastname = s->name;
1221 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1222 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1223 s->name, s->type, s->comment, s->domain));
1225 if (data_len <= buf_len) {
1226 counted++;
1227 fixed_len += f_len;
1228 string_len += s_len;
1229 } else {
1230 missed++;
1235 *rdata_len = fixed_len + string_len;
1236 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
1237 memset(*rdata,'\0',*rdata_len);
1239 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1240 p = *rdata;
1241 f_len = fixed_len;
1242 s_len = string_len;
1245 char *lastname=NULL;
1246 int count2 = counted;
1247 for (i = 0; i < total && count2;i++)
1249 struct srv_info_struct *s = &servers[i];
1250 if (lastname && strequal(lastname,s->name)) continue;
1251 lastname = s->name;
1252 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1253 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1254 s->name, s->type, s->comment, s->domain));
1255 count2--;
1259 *rparam_len = 8;
1260 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1261 SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata));
1262 SSVAL(*rparam,2,0);
1263 SSVAL(*rparam,4,counted);
1264 SSVAL(*rparam,6,counted+missed);
1266 SAFE_FREE(servers);
1268 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1269 domain,uLevel,counted,counted+missed));
1271 return(True);
1274 /****************************************************************************
1275 command 0x34 - suspected of being a "Lookup Names" stub api
1276 ****************************************************************************/
1277 static BOOL api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid, char *param, char *data,
1278 int mdrcnt, int mprcnt, char **rdata,
1279 char **rparam, int *rdata_len, int *rparam_len)
1281 char *str1 = param+2;
1282 char *str2 = skip_string(str1,1);
1283 char *p = skip_string(str2,1);
1284 int uLevel = SVAL(p,0);
1285 int buf_len = SVAL(p,2);
1286 int counted=0;
1287 int missed=0;
1289 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1290 str1, str2, p, uLevel, buf_len));
1292 if (!prefix_ok(str1,"zWrLeh")) return False;
1294 *rdata_len = 0;
1296 *rparam_len = 8;
1297 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1299 SSVAL(*rparam,0,0x08AC); /* informational warning message */
1300 SSVAL(*rparam,2,0);
1301 SSVAL(*rparam,4,counted);
1302 SSVAL(*rparam,6,counted+missed);
1304 return(True);
1307 /****************************************************************************
1308 get info about a share
1309 ****************************************************************************/
1310 static BOOL check_share_info(int uLevel, char* id)
1312 switch( uLevel ) {
1313 case 0:
1314 if (strcmp(id,"B13") != 0) return False;
1315 break;
1316 case 1:
1317 if (strcmp(id,"B13BWz") != 0) return False;
1318 break;
1319 case 2:
1320 if (strcmp(id,"B13BWzWWWzB9B") != 0) return False;
1321 break;
1322 case 91:
1323 if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) return False;
1324 break;
1325 default: return False;
1327 return True;
1330 static int fill_share_info(connection_struct *conn, int snum, int uLevel,
1331 char** buf, int* buflen,
1332 char** stringbuf, int* stringspace, char* baseaddr)
1334 int struct_len;
1335 char* p;
1336 char* p2;
1337 int l2;
1338 int len;
1340 switch( uLevel ) {
1341 case 0: struct_len = 13; break;
1342 case 1: struct_len = 20; break;
1343 case 2: struct_len = 40; break;
1344 case 91: struct_len = 68; break;
1345 default: return -1;
1349 if (!buf)
1351 len = 0;
1352 if (uLevel > 0) len += StrlenExpanded(conn,snum,lp_comment(snum));
1353 if (uLevel > 1) len += strlen(lp_pathname(snum)) + 1;
1354 if (buflen) *buflen = struct_len;
1355 if (stringspace) *stringspace = len;
1356 return struct_len + len;
1359 len = struct_len;
1360 p = *buf;
1361 if ((*buflen) < struct_len) return -1;
1362 if (stringbuf)
1364 p2 = *stringbuf;
1365 l2 = *stringspace;
1367 else
1369 p2 = p + struct_len;
1370 l2 = (*buflen) - struct_len;
1372 if (!baseaddr) baseaddr = p;
1374 push_ascii(p,lp_servicename(snum),13, STR_TERMINATE);
1376 if (uLevel > 0)
1378 int type;
1379 SCVAL(p,13,0);
1380 type = STYPE_DISKTREE;
1381 if (lp_print_ok(snum)) type = STYPE_PRINTQ;
1382 if (strequal("IPC",lp_fstype(snum))) type = STYPE_IPC;
1383 SSVAL(p,14,type); /* device type */
1384 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1385 len += CopyExpanded(conn,snum,&p2,lp_comment(snum),&l2);
1388 if (uLevel > 1)
1390 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1391 SSVALS(p,22,-1); /* max uses */
1392 SSVAL(p,24,1); /* current uses */
1393 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1394 len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1395 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1398 if (uLevel > 2)
1400 memset(p+40,0,SHPWLEN+2);
1401 SSVAL(p,50,0);
1402 SIVAL(p,52,0);
1403 SSVAL(p,56,0);
1404 SSVAL(p,58,0);
1405 SIVAL(p,60,0);
1406 SSVAL(p,64,0);
1407 SSVAL(p,66,0);
1410 if (stringbuf)
1412 (*buf) = p + struct_len;
1413 (*buflen) -= struct_len;
1414 (*stringbuf) = p2;
1415 (*stringspace) = l2;
1417 else
1419 (*buf) = p2;
1420 (*buflen) -= len;
1422 return len;
1425 static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
1426 int mdrcnt,int mprcnt,
1427 char **rdata,char **rparam,
1428 int *rdata_len,int *rparam_len)
1430 char *str1 = param+2;
1431 char *str2 = skip_string(str1,1);
1432 char *netname = skip_string(str2,1);
1433 char *p = skip_string(netname,1);
1434 int uLevel = SVAL(p,0);
1435 int snum = find_service(netname);
1437 if (snum < 0) return False;
1439 /* check it's a supported varient */
1440 if (!prefix_ok(str1,"zWrLh")) return False;
1441 if (!check_share_info(uLevel,str2)) return False;
1443 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
1444 p = *rdata;
1445 *rdata_len = fill_share_info(conn,snum,uLevel,&p,&mdrcnt,0,0,0);
1446 if (*rdata_len < 0) return False;
1448 *rparam_len = 6;
1449 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1450 SSVAL(*rparam,0,NERR_Success);
1451 SSVAL(*rparam,2,0); /* converter word */
1452 SSVAL(*rparam,4,*rdata_len);
1454 return(True);
1457 /****************************************************************************
1458 View the list of available shares.
1460 This function is the server side of the NetShareEnum() RAP call.
1461 It fills the return buffer with share names and share comments.
1462 Note that the return buffer normally (in all known cases) allows only
1463 twelve byte strings for share names (plus one for a nul terminator).
1464 Share names longer than 12 bytes must be skipped.
1465 ****************************************************************************/
1466 static BOOL api_RNetShareEnum( connection_struct *conn,
1467 uint16 vuid,
1468 char *param,
1469 char *data,
1470 int mdrcnt,
1471 int mprcnt,
1472 char **rdata,
1473 char **rparam,
1474 int *rdata_len,
1475 int *rparam_len )
1477 char *str1 = param+2;
1478 char *str2 = skip_string(str1,1);
1479 char *p = skip_string(str2,1);
1480 int uLevel = SVAL(p,0);
1481 int buf_len = SVAL(p,2);
1482 char *p2;
1483 int count=lp_numservices();
1484 int total=0,counted=0;
1485 BOOL missed = False;
1486 int i;
1487 int data_len, fixed_len, string_len;
1488 int f_len = 0, s_len = 0;
1490 if (!prefix_ok(str1,"WrLeh")) return False;
1491 if (!check_share_info(uLevel,str2)) return False;
1493 data_len = fixed_len = string_len = 0;
1494 for (i=0;i<count;i++) {
1495 fstring servicename_dos;
1496 if (!(lp_browseable(i) && lp_snum_ok(i)))
1497 continue;
1498 push_ascii_fstring(servicename_dos, lp_servicename(i));
1499 if( lp_browseable( i )
1500 && lp_snum_ok( i )
1501 && (strlen(servicename_dos) < 13) ) /* Maximum name length. */
1503 total++;
1504 data_len += fill_share_info(conn,i,uLevel,0,&f_len,0,&s_len,0);
1505 if (data_len <= buf_len)
1507 counted++;
1508 fixed_len += f_len;
1509 string_len += s_len;
1511 else
1512 missed = True;
1515 *rdata_len = fixed_len + string_len;
1516 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
1517 memset(*rdata,0,*rdata_len);
1519 p2 = (*rdata) + fixed_len; /* auxiliary data (strings) will go here */
1520 p = *rdata;
1521 f_len = fixed_len;
1522 s_len = string_len;
1523 for( i = 0; i < count; i++ )
1525 fstring servicename_dos;
1526 if (!(lp_browseable(i) && lp_snum_ok(i)))
1527 continue;
1528 push_ascii_fstring(servicename_dos, lp_servicename(i));
1529 if( lp_browseable( i )
1530 && lp_snum_ok( i )
1531 && (strlen(servicename_dos) < 13) )
1533 if( fill_share_info( conn,i,uLevel,&p,&f_len,&p2,&s_len,*rdata ) < 0 )
1534 break;
1538 *rparam_len = 8;
1539 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1540 SSVAL(*rparam,0,missed ? ERRmoredata : NERR_Success);
1541 SSVAL(*rparam,2,0);
1542 SSVAL(*rparam,4,counted);
1543 SSVAL(*rparam,6,total);
1545 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1546 counted,total,uLevel,
1547 buf_len,*rdata_len,mdrcnt));
1548 return(True);
1549 } /* api_RNetShareEnum */
1551 /****************************************************************************
1552 Add a share
1553 ****************************************************************************/
1554 static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid, char *param,char *data,
1555 int mdrcnt,int mprcnt,
1556 char **rdata,char **rparam,
1557 int *rdata_len,int *rparam_len)
1559 char *str1 = param+2;
1560 char *str2 = skip_string(str1,1);
1561 char *p = skip_string(str2,1);
1562 int uLevel = SVAL(p,0);
1563 fstring sharename;
1564 fstring comment;
1565 pstring pathname;
1566 char *command, *cmdname;
1567 unsigned int offset;
1568 int snum;
1569 int res = ERRunsup;
1571 /* check it's a supported varient */
1572 if (!prefix_ok(str1,RAP_WShareAdd_REQ)) return False;
1573 if (!check_share_info(uLevel,str2)) return False;
1574 if (uLevel != 2) return False;
1576 pull_ascii_fstring(sharename,data);
1577 snum = find_service(sharename);
1578 if (snum >= 0) { /* already exists */
1579 res = ERRfilexists;
1580 goto error_exit;
1583 /* only support disk share adds */
1584 if (SVAL(data,14)!=STYPE_DISKTREE) return False;
1586 offset = IVAL(data, 16);
1587 if (offset >= mdrcnt) {
1588 res = ERRinvalidparam;
1589 goto error_exit;
1591 pull_ascii_fstring(comment, offset? (data+offset) : "");
1593 offset = IVAL(data, 26);
1594 if (offset >= mdrcnt) {
1595 res = ERRinvalidparam;
1596 goto error_exit;
1598 pull_ascii_pstring(pathname, offset? (data+offset) : "");
1600 string_replace(sharename, '"', ' ');
1601 string_replace(pathname, '"', ' ');
1602 string_replace(comment, '"', ' ');
1604 cmdname = lp_add_share_cmd();
1606 if (!cmdname || *cmdname == '\0') return False;
1608 asprintf(&command, "%s \"%s\" \"%s\" \"%s\" \"%s\"",
1609 lp_add_share_cmd(), dyn_CONFIGFILE, sharename, pathname, comment);
1611 if (command) {
1612 DEBUG(10,("api_RNetShareAdd: Running [%s]\n", command ));
1613 if ((res = smbrun(command, NULL)) != 0) {
1614 DEBUG(1,("api_RNetShareAdd: Running [%s] returned (%d)\n", command, res ));
1615 SAFE_FREE(command);
1616 res = ERRnoaccess;
1617 goto error_exit;
1618 } else {
1619 SAFE_FREE(command);
1620 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
1622 } else return False;
1624 *rparam_len = 6;
1625 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1626 SSVAL(*rparam,0,NERR_Success);
1627 SSVAL(*rparam,2,0); /* converter word */
1628 SSVAL(*rparam,4,*rdata_len);
1629 *rdata_len = 0;
1631 return True;
1633 error_exit:
1634 *rparam_len = 4;
1635 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1636 *rdata_len = 0;
1637 SSVAL(*rparam,0,res);
1638 SSVAL(*rparam,2,0);
1639 return True;
1643 /****************************************************************************
1644 view list of groups available
1645 ****************************************************************************/
1646 static BOOL api_RNetGroupEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
1647 int mdrcnt,int mprcnt,
1648 char **rdata,char **rparam,
1649 int *rdata_len,int *rparam_len)
1651 int i;
1652 int errflags=0;
1653 int resume_context, cli_buf_size;
1654 char *str1 = param+2;
1655 char *str2 = skip_string(str1,1);
1656 char *p = skip_string(str2,1);
1657 BOOL ret;
1659 GROUP_MAP *group_list;
1660 int num_entries;
1662 if (strcmp(str1,"WrLeh") != 0)
1663 return False;
1665 /* parameters
1666 * W-> resume context (number of users to skip)
1667 * r -> return parameter pointer to receive buffer
1668 * L -> length of receive buffer
1669 * e -> return parameter number of entries
1670 * h -> return parameter total number of users
1672 if (strcmp("B21",str2) != 0)
1673 return False;
1675 /* get list of domain groups SID_DOMAIN_GRP=2 */
1676 become_root();
1677 ret = pdb_enum_group_mapping(SID_NAME_DOM_GRP , &group_list, &num_entries, False);
1678 unbecome_root();
1680 if( !ret ) {
1681 DEBUG(3,("api_RNetGroupEnum:failed to get group list"));
1682 return False;
1685 resume_context = SVAL(p,0);
1686 cli_buf_size=SVAL(p+2,0);
1687 DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: %d\n", resume_context, cli_buf_size));
1689 *rdata_len = cli_buf_size;
1690 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
1692 p = *rdata;
1694 for(i=resume_context; i<num_entries; i++) {
1695 char* name=group_list[i].nt_name;
1696 if( ((PTR_DIFF(p,*rdata)+21) <= *rdata_len) ) {
1697 /* truncate the name at 21 chars. */
1698 memcpy(p, name, 21);
1699 DEBUG(10,("adding entry %d group %s\n", i, p));
1700 p += 21;
1701 } else {
1702 /* set overflow error */
1703 DEBUG(3,("overflow on entry %d group %s\n", i, name));
1704 errflags=234;
1705 break;
1709 *rdata_len = PTR_DIFF(p,*rdata);
1711 *rparam_len = 8;
1712 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1714 SSVAL(*rparam, 0, errflags);
1715 SSVAL(*rparam, 2, 0); /* converter word */
1716 SSVAL(*rparam, 4, i-resume_context); /* is this right?? */
1717 SSVAL(*rparam, 6, num_entries); /* is this right?? */
1719 return(True);
1722 /*******************************************************************
1723 get groups that a user is a member of
1724 ******************************************************************/
1725 static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *param,char *data,
1726 int mdrcnt,int mprcnt,
1727 char **rdata,char **rparam,
1728 int *rdata_len,int *rparam_len)
1730 char *str1 = param+2;
1731 char *str2 = skip_string(str1,1);
1732 char *UserName = skip_string(str2,1);
1733 char *p = skip_string(UserName,1);
1734 int uLevel = SVAL(p,0);
1735 const char *level_string;
1736 int count=0;
1737 SAM_ACCOUNT *sampw = NULL;
1738 BOOL ret = False;
1739 DOM_SID *sids;
1740 gid_t *gids;
1741 int num_groups;
1742 int i;
1743 fstring grp_domain;
1744 fstring grp_name;
1745 enum SID_NAME_USE grp_type;
1746 struct passwd *passwd;
1747 NTSTATUS result;
1749 *rparam_len = 8;
1750 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1752 /* check it's a supported varient */
1754 if ( strcmp(str1,"zWrLeh") != 0 )
1755 return False;
1757 switch( uLevel ) {
1758 case 0:
1759 level_string = "B21";
1760 break;
1761 default:
1762 return False;
1765 if (strcmp(level_string,str2) != 0)
1766 return False;
1768 *rdata_len = mdrcnt + 1024;
1769 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
1771 SSVAL(*rparam,0,NERR_Success);
1772 SSVAL(*rparam,2,0); /* converter word */
1774 p = *rdata;
1776 /* Lookup the user information; This should only be one of
1777 our accounts (not remote domains) */
1779 passwd = getpwnam_alloc(UserName);
1781 if (passwd == NULL)
1782 return False;
1784 pdb_init_sam( &sampw );
1786 become_root(); /* ROOT BLOCK */
1788 if ( !pdb_getsampwnam(sampw, UserName) )
1789 goto out;
1791 sids = NULL;
1792 num_groups = 0;
1794 result = pdb_enum_group_memberships(pdb_get_username(sampw),
1795 passwd->pw_gid,
1796 &sids, &gids, &num_groups);
1798 if (!NT_STATUS_IS_OK(result))
1799 goto out;
1801 for (i=0; i<num_groups; i++) {
1803 if ( lookup_sid(&sids[i], grp_domain, grp_name, &grp_type) ) {
1804 pstrcpy(p, grp_name);
1805 p += 21;
1806 count++;
1810 SAFE_FREE(sids);
1812 *rdata_len = PTR_DIFF(p,*rdata);
1814 SSVAL(*rparam,4,count); /* is this right?? */
1815 SSVAL(*rparam,6,count); /* is this right?? */
1817 ret = True;
1819 out:
1820 unbecome_root(); /* END ROOT BLOCK */
1822 pdb_free_sam( &sampw );
1823 passwd_free(&passwd);
1825 return ret;
1828 /*******************************************************************
1829 get all users
1830 ******************************************************************/
1831 static BOOL api_RNetUserEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
1832 int mdrcnt,int mprcnt,
1833 char **rdata,char **rparam,
1834 int *rdata_len,int *rparam_len)
1836 SAM_ACCOUNT *pwd=NULL;
1837 int count_sent=0;
1838 int count_total=0;
1839 int errflags=0;
1840 int resume_context, cli_buf_size;
1842 char *str1 = param+2;
1843 char *str2 = skip_string(str1,1);
1844 char *p = skip_string(str2,1);
1846 if (strcmp(str1,"WrLeh") != 0)
1847 return False;
1848 /* parameters
1849 * W-> resume context (number of users to skip)
1850 * r -> return parameter pointer to receive buffer
1851 * L -> length of receive buffer
1852 * e -> return parameter number of entries
1853 * h -> return parameter total number of users
1856 resume_context = SVAL(p,0);
1857 cli_buf_size=SVAL(p+2,0);
1858 DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n", resume_context, cli_buf_size));
1860 *rparam_len = 8;
1861 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1863 /* check it's a supported varient */
1864 if (strcmp("B21",str2) != 0)
1865 return False;
1867 *rdata_len = cli_buf_size;
1868 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
1870 p = *rdata;
1872 /* to get user list enumerations for NetUserEnum in B21 format */
1873 pdb_init_sam(&pwd);
1875 /* Open the passgrp file - not for update. */
1876 become_root();
1877 if(!pdb_setsampwent(False)) {
1878 DEBUG(0, ("api_RNetUserEnum:unable to open sam database.\n"));
1879 unbecome_root();
1880 return False;
1882 errflags=NERR_Success;
1884 while ( pdb_getsampwent(pwd) ) {
1885 const char *name=pdb_get_username(pwd);
1886 if ((name) && (*(name+strlen(name)-1)!='$')) {
1887 count_total++;
1888 if(count_total>=resume_context) {
1889 if( ((PTR_DIFF(p,*rdata)+21)<=*rdata_len)&&(strlen(name)<=21) ) {
1890 pstrcpy(p,name);
1891 DEBUG(10,("api_RNetUserEnum:adding entry %d username %s\n",count_sent,p));
1892 p += 21;
1893 count_sent++;
1894 } else {
1895 /* set overflow error */
1896 DEBUG(10,("api_RNetUserEnum:overflow on entry %d username %s\n",count_sent,name));
1897 errflags=234;
1898 break;
1904 pdb_endsampwent();
1905 unbecome_root();
1907 pdb_free_sam(&pwd);
1909 *rdata_len = PTR_DIFF(p,*rdata);
1911 SSVAL(*rparam,0,errflags);
1912 SSVAL(*rparam,2,0); /* converter word */
1913 SSVAL(*rparam,4,count_sent); /* is this right?? */
1914 SSVAL(*rparam,6,count_total); /* is this right?? */
1916 return True;
1921 /****************************************************************************
1922 get the time of day info
1923 ****************************************************************************/
1924 static BOOL api_NetRemoteTOD(connection_struct *conn,uint16 vuid, char *param,char *data,
1925 int mdrcnt,int mprcnt,
1926 char **rdata,char **rparam,
1927 int *rdata_len,int *rparam_len)
1929 char *p;
1930 *rparam_len = 4;
1931 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1933 *rdata_len = 21;
1934 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
1936 SSVAL(*rparam,0,NERR_Success);
1937 SSVAL(*rparam,2,0); /* converter word */
1939 p = *rdata;
1942 struct tm *t;
1943 time_t unixdate = time(NULL);
1945 put_dos_date3(p,0,unixdate); /* this is the time that is looked at
1946 by NT in a "net time" operation,
1947 it seems to ignore the one below */
1949 /* the client expects to get localtime, not GMT, in this bit
1950 (I think, this needs testing) */
1951 t = LocalTime(&unixdate);
1953 SIVAL(p,4,0); /* msecs ? */
1954 SCVAL(p,8,t->tm_hour);
1955 SCVAL(p,9,t->tm_min);
1956 SCVAL(p,10,t->tm_sec);
1957 SCVAL(p,11,0); /* hundredths of seconds */
1958 SSVALS(p,12,TimeDiff(unixdate)/60); /* timezone in minutes from GMT */
1959 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
1960 SCVAL(p,16,t->tm_mday);
1961 SCVAL(p,17,t->tm_mon + 1);
1962 SSVAL(p,18,1900+t->tm_year);
1963 SCVAL(p,20,t->tm_wday);
1967 return(True);
1970 /****************************************************************************
1971 Set the user password.
1972 *****************************************************************************/
1974 static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param,char *data,
1975 int mdrcnt,int mprcnt,
1976 char **rdata,char **rparam,
1977 int *rdata_len,int *rparam_len)
1979 char *p = skip_string(param+2,2);
1980 fstring user;
1981 fstring pass1,pass2;
1983 pull_ascii_fstring(user,p);
1985 p = skip_string(p,1);
1987 memset(pass1,'\0',sizeof(pass1));
1988 memset(pass2,'\0',sizeof(pass2));
1989 memcpy(pass1,p,16);
1990 memcpy(pass2,p+16,16);
1992 *rparam_len = 4;
1993 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1995 *rdata_len = 0;
1997 SSVAL(*rparam,0,NERR_badpass);
1998 SSVAL(*rparam,2,0); /* converter word */
2000 DEBUG(3,("Set password for <%s>\n",user));
2003 * Attempt to verify the old password against smbpasswd entries
2004 * Win98 clients send old and new password in plaintext for this call.
2008 auth_serversupplied_info *server_info = NULL;
2009 DATA_BLOB password = data_blob(pass1, strlen(pass1)+1);
2011 if (NT_STATUS_IS_OK(check_plaintext_password(user,password,&server_info))) {
2013 become_root();
2014 if (NT_STATUS_IS_OK(change_oem_password(server_info->sam_account, pass1, pass2, False))) {
2015 SSVAL(*rparam,0,NERR_Success);
2017 unbecome_root();
2019 free_server_info(&server_info);
2021 data_blob_clear_free(&password);
2025 * If the plaintext change failed, attempt
2026 * the old encrypted method. NT will generate this
2027 * after trying the samr method. Note that this
2028 * method is done as a last resort as this
2029 * password change method loses the NT password hash
2030 * and cannot change the UNIX password as no plaintext
2031 * is received.
2034 if(SVAL(*rparam,0) != NERR_Success) {
2035 SAM_ACCOUNT *hnd = NULL;
2037 if (check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &hnd)) {
2038 become_root();
2039 if (change_lanman_password(hnd,(uchar *)pass2)) {
2040 SSVAL(*rparam,0,NERR_Success);
2042 unbecome_root();
2043 pdb_free_sam(&hnd);
2047 memset((char *)pass1,'\0',sizeof(fstring));
2048 memset((char *)pass2,'\0',sizeof(fstring));
2050 return(True);
2053 /****************************************************************************
2054 Set the user password (SamOEM version - gets plaintext).
2055 ****************************************************************************/
2057 static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char *param,char *data,
2058 int mdrcnt,int mprcnt,
2059 char **rdata,char **rparam,
2060 int *rdata_len,int *rparam_len)
2062 fstring user;
2063 char *p = param + 2;
2064 *rparam_len = 2;
2065 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2067 *rdata_len = 0;
2069 SSVAL(*rparam,0,NERR_badpass);
2072 * Check the parameter definition is correct.
2075 if(!strequal(param + 2, "zsT")) {
2076 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", param + 2));
2077 return False;
2079 p = skip_string(p, 1);
2081 if(!strequal(p, "B516B16")) {
2082 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p));
2083 return False;
2085 p = skip_string(p,1);
2086 p += pull_ascii_fstring(user,p);
2088 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user));
2091 * Pass the user through the NT -> unix user mapping
2092 * function.
2095 (void)map_username(user);
2097 if (NT_STATUS_IS_OK(pass_oem_change(user, (uchar*) data, (uchar *)&data[516], NULL, NULL))) {
2098 SSVAL(*rparam,0,NERR_Success);
2101 return(True);
2104 /****************************************************************************
2105 delete a print job
2106 Form: <W> <>
2107 ****************************************************************************/
2108 static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char *param,char *data,
2109 int mdrcnt,int mprcnt,
2110 char **rdata,char **rparam,
2111 int *rdata_len,int *rparam_len)
2113 int function = SVAL(param,0);
2114 char *str1 = param+2;
2115 char *str2 = skip_string(str1,1);
2116 char *p = skip_string(str2,1);
2117 uint32 jobid;
2118 int snum;
2119 fstring sharename;
2120 int errcode;
2121 extern struct current_user current_user;
2122 WERROR werr = WERR_OK;
2124 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
2125 return False;
2127 /* check it's a supported varient */
2128 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
2129 return(False);
2131 *rparam_len = 4;
2132 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2133 *rdata_len = 0;
2135 if (!print_job_exists(sharename, jobid)) {
2136 errcode = NERR_JobNotFound;
2137 goto out;
2140 snum = lp_servicenumber( sharename);
2141 if (snum == -1) {
2142 errcode = NERR_DestNotFound;
2143 goto out;
2146 errcode = NERR_notsupported;
2148 switch (function) {
2149 case 81: /* delete */
2150 if (print_job_delete(&current_user, snum, jobid, &werr))
2151 errcode = NERR_Success;
2152 break;
2153 case 82: /* pause */
2154 if (print_job_pause(&current_user, snum, jobid, &werr))
2155 errcode = NERR_Success;
2156 break;
2157 case 83: /* resume */
2158 if (print_job_resume(&current_user, snum, jobid, &werr))
2159 errcode = NERR_Success;
2160 break;
2163 if (!W_ERROR_IS_OK(werr))
2164 errcode = W_ERROR_V(werr);
2166 out:
2167 SSVAL(*rparam,0,errcode);
2168 SSVAL(*rparam,2,0); /* converter word */
2170 return(True);
2173 /****************************************************************************
2174 Purge a print queue - or pause or resume it.
2175 ****************************************************************************/
2176 static BOOL api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid, char *param,char *data,
2177 int mdrcnt,int mprcnt,
2178 char **rdata,char **rparam,
2179 int *rdata_len,int *rparam_len)
2181 int function = SVAL(param,0);
2182 char *str1 = param+2;
2183 char *str2 = skip_string(str1,1);
2184 char *QueueName = skip_string(str2,1);
2185 int errcode = NERR_notsupported;
2186 int snum;
2187 WERROR werr = WERR_OK;
2188 extern struct current_user current_user;
2190 /* check it's a supported varient */
2191 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
2192 return(False);
2194 *rparam_len = 4;
2195 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2196 *rdata_len = 0;
2198 snum = print_queue_snum(QueueName);
2200 if (snum == -1) {
2201 errcode = NERR_JobNotFound;
2202 goto out;
2205 switch (function) {
2206 case 74: /* Pause queue */
2207 if (print_queue_pause(&current_user, snum, &werr)) errcode = NERR_Success;
2208 break;
2209 case 75: /* Resume queue */
2210 if (print_queue_resume(&current_user, snum, &werr)) errcode = NERR_Success;
2211 break;
2212 case 103: /* Purge */
2213 if (print_queue_purge(&current_user, snum, &werr)) errcode = NERR_Success;
2214 break;
2217 if (!W_ERROR_IS_OK(werr)) errcode = W_ERROR_V(werr);
2219 out:
2220 SSVAL(*rparam,0,errcode);
2221 SSVAL(*rparam,2,0); /* converter word */
2223 return(True);
2227 /****************************************************************************
2228 set the property of a print job (undocumented?)
2229 ? function = 0xb -> set name of print job
2230 ? function = 0x6 -> move print job up/down
2231 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
2232 or <WWsTP> <WB21BB16B10zWWzDDz>
2233 ****************************************************************************/
2234 static int check_printjob_info(struct pack_desc* desc,
2235 int uLevel, char* id)
2237 desc->subformat = NULL;
2238 switch( uLevel ) {
2239 case 0: desc->format = "W"; break;
2240 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
2241 case 2: desc->format = "WWzWWDDzz"; break;
2242 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
2243 case 4: desc->format = "WWzWWDDzzzzzDDDDDDD"; break;
2244 default: return False;
2246 if (strcmp(desc->format,id) != 0) return False;
2247 return True;
2250 static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,char *data,
2251 int mdrcnt,int mprcnt,
2252 char **rdata,char **rparam,
2253 int *rdata_len,int *rparam_len)
2255 struct pack_desc desc;
2256 char *str1 = param+2;
2257 char *str2 = skip_string(str1,1);
2258 char *p = skip_string(str2,1);
2259 uint32 jobid;
2260 int snum;
2261 fstring sharename;
2262 int uLevel = SVAL(p,2);
2263 int function = SVAL(p,4);
2264 int place, errcode;
2266 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
2267 return False;
2268 *rparam_len = 4;
2269 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2271 if ( (snum = lp_servicenumber(sharename)) == -1 ) {
2272 DEBUG(0,("api_PrintJobInfo: unable to get service number from sharename [%s]\n",
2273 sharename));
2274 return False;
2277 *rdata_len = 0;
2279 /* check it's a supported varient */
2280 if ((strcmp(str1,"WWsTP")) ||
2281 (!check_printjob_info(&desc,uLevel,str2)))
2282 return(False);
2284 if (!print_job_exists(sharename, jobid)) {
2285 errcode=NERR_JobNotFound;
2286 goto out;
2289 errcode = NERR_notsupported;
2291 switch (function) {
2292 case 0x6:
2293 /* change job place in the queue,
2294 data gives the new place */
2295 place = SVAL(data,0);
2296 if (print_job_set_place(snum, jobid, place)) {
2297 errcode=NERR_Success;
2299 break;
2301 case 0xb:
2302 /* change print job name, data gives the name */
2303 if (print_job_set_name(snum, jobid, data)) {
2304 errcode=NERR_Success;
2306 break;
2308 default:
2309 return False;
2312 out:
2313 SSVALS(*rparam,0,errcode);
2314 SSVAL(*rparam,2,0); /* converter word */
2316 return(True);
2320 /****************************************************************************
2321 get info about the server
2322 ****************************************************************************/
2323 static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2324 int mdrcnt,int mprcnt,
2325 char **rdata,char **rparam,
2326 int *rdata_len,int *rparam_len)
2328 char *str1 = param+2;
2329 char *str2 = skip_string(str1,1);
2330 char *p = skip_string(str2,1);
2331 int uLevel = SVAL(p,0);
2332 char *p2;
2333 int struct_len;
2335 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
2337 /* check it's a supported varient */
2338 if (!prefix_ok(str1,"WrLh")) return False;
2339 switch( uLevel ) {
2340 case 0:
2341 if (strcmp(str2,"B16") != 0) return False;
2342 struct_len = 16;
2343 break;
2344 case 1:
2345 if (strcmp(str2,"B16BBDz") != 0) return False;
2346 struct_len = 26;
2347 break;
2348 case 2:
2349 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")
2350 != 0) return False;
2351 struct_len = 134;
2352 break;
2353 case 3:
2354 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz")
2355 != 0) return False;
2356 struct_len = 144;
2357 break;
2358 case 20:
2359 if (strcmp(str2,"DN") != 0) return False;
2360 struct_len = 6;
2361 break;
2362 case 50:
2363 if (strcmp(str2,"B16BBDzWWzzz") != 0) return False;
2364 struct_len = 42;
2365 break;
2366 default: return False;
2369 *rdata_len = mdrcnt;
2370 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
2372 p = *rdata;
2373 p2 = p + struct_len;
2374 if (uLevel != 20) {
2375 srvstr_push(NULL, p,local_machine,16,
2376 STR_ASCII|STR_UPPER|STR_TERMINATE);
2378 p += 16;
2379 if (uLevel > 0)
2381 struct srv_info_struct *servers=NULL;
2382 int i,count;
2383 pstring comment;
2384 uint32 servertype= lp_default_server_announce();
2386 push_ascii(comment,lp_serverstring(), MAX_SERVER_STRING_LENGTH,STR_TERMINATE);
2388 if ((count=get_server_info(SV_TYPE_ALL,&servers,lp_workgroup()))>0) {
2389 for (i=0;i<count;i++) {
2390 if (strequal(servers[i].name,local_machine)) {
2391 servertype = servers[i].type;
2392 push_ascii(comment,servers[i].comment,sizeof(pstring),STR_TERMINATE);
2396 SAFE_FREE(servers);
2398 SCVAL(p,0,lp_major_announce_version());
2399 SCVAL(p,1,lp_minor_announce_version());
2400 SIVAL(p,2,servertype);
2402 if (mdrcnt == struct_len) {
2403 SIVAL(p,6,0);
2404 } else {
2405 SIVAL(p,6,PTR_DIFF(p2,*rdata));
2406 standard_sub_conn(conn,comment,sizeof(comment));
2407 StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
2408 p2 = skip_string(p2,1);
2411 if (uLevel > 1)
2413 return False; /* not yet implemented */
2416 *rdata_len = PTR_DIFF(p2,*rdata);
2418 *rparam_len = 6;
2419 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2420 SSVAL(*rparam,0,NERR_Success);
2421 SSVAL(*rparam,2,0); /* converter word */
2422 SSVAL(*rparam,4,*rdata_len);
2424 return(True);
2428 /****************************************************************************
2429 get info about the server
2430 ****************************************************************************/
2431 static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2432 int mdrcnt,int mprcnt,
2433 char **rdata,char **rparam,
2434 int *rdata_len,int *rparam_len)
2436 char *str1 = param+2;
2437 char *str2 = skip_string(str1,1);
2438 char *p = skip_string(str2,1);
2439 char *p2;
2440 extern userdom_struct current_user_info;
2441 int level = SVAL(p,0);
2443 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
2445 *rparam_len = 6;
2446 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2448 /* check it's a supported varient */
2449 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz")))
2450 return(False);
2452 *rdata_len = mdrcnt + 1024;
2453 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
2455 SSVAL(*rparam,0,NERR_Success);
2456 SSVAL(*rparam,2,0); /* converter word */
2458 p = *rdata;
2459 p2 = p + 22;
2462 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
2463 pstrcpy(p2,local_machine);
2464 strupper_m(p2);
2465 p2 = skip_string(p2,1);
2466 p += 4;
2468 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2469 pstrcpy(p2,current_user_info.smb_name);
2470 p2 = skip_string(p2,1);
2471 p += 4;
2473 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
2474 pstrcpy(p2,lp_workgroup());
2475 strupper_m(p2);
2476 p2 = skip_string(p2,1);
2477 p += 4;
2479 SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
2480 SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
2481 p += 2;
2483 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2484 pstrcpy(p2,lp_workgroup()); /* don't know. login domain?? */
2485 p2 = skip_string(p2,1);
2486 p += 4;
2488 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
2489 pstrcpy(p2,"");
2490 p2 = skip_string(p2,1);
2491 p += 4;
2493 *rdata_len = PTR_DIFF(p2,*rdata);
2495 SSVAL(*rparam,4,*rdata_len);
2497 return(True);
2500 /****************************************************************************
2501 get info about a user
2503 struct user_info_11 {
2504 char usri11_name[21]; 0-20
2505 char usri11_pad; 21
2506 char *usri11_comment; 22-25
2507 char *usri11_usr_comment; 26-29
2508 unsigned short usri11_priv; 30-31
2509 unsigned long usri11_auth_flags; 32-35
2510 long usri11_password_age; 36-39
2511 char *usri11_homedir; 40-43
2512 char *usri11_parms; 44-47
2513 long usri11_last_logon; 48-51
2514 long usri11_last_logoff; 52-55
2515 unsigned short usri11_bad_pw_count; 56-57
2516 unsigned short usri11_num_logons; 58-59
2517 char *usri11_logon_server; 60-63
2518 unsigned short usri11_country_code; 64-65
2519 char *usri11_workstations; 66-69
2520 unsigned long usri11_max_storage; 70-73
2521 unsigned short usri11_units_per_week; 74-75
2522 unsigned char *usri11_logon_hours; 76-79
2523 unsigned short usri11_code_page; 80-81
2526 where:
2528 usri11_name specifies the user name for which information is retireved
2530 usri11_pad aligns the next data structure element to a word boundary
2532 usri11_comment is a null terminated ASCII comment
2534 usri11_user_comment is a null terminated ASCII comment about the user
2536 usri11_priv specifies the level of the privilege assigned to the user.
2537 The possible values are:
2539 Name Value Description
2540 USER_PRIV_GUEST 0 Guest privilege
2541 USER_PRIV_USER 1 User privilege
2542 USER_PRV_ADMIN 2 Administrator privilege
2544 usri11_auth_flags specifies the account operator privileges. The
2545 possible values are:
2547 Name Value Description
2548 AF_OP_PRINT 0 Print operator
2551 Leach, Naik [Page 28]
2555 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2558 AF_OP_COMM 1 Communications operator
2559 AF_OP_SERVER 2 Server operator
2560 AF_OP_ACCOUNTS 3 Accounts operator
2563 usri11_password_age specifies how many seconds have elapsed since the
2564 password was last changed.
2566 usri11_home_dir points to a null terminated ASCII string that contains
2567 the path name of the user's home directory.
2569 usri11_parms points to a null terminated ASCII string that is set
2570 aside for use by applications.
2572 usri11_last_logon specifies the time when the user last logged on.
2573 This value is stored as the number of seconds elapsed since
2574 00:00:00, January 1, 1970.
2576 usri11_last_logoff specifies the time when the user last logged off.
2577 This value is stored as the number of seconds elapsed since
2578 00:00:00, January 1, 1970. A value of 0 means the last logoff
2579 time is unknown.
2581 usri11_bad_pw_count specifies the number of incorrect passwords
2582 entered since the last successful logon.
2584 usri11_log1_num_logons specifies the number of times this user has
2585 logged on. A value of -1 means the number of logons is unknown.
2587 usri11_logon_server points to a null terminated ASCII string that
2588 contains the name of the server to which logon requests are sent.
2589 A null string indicates logon requests should be sent to the
2590 domain controller.
2592 usri11_country_code specifies the country code for the user's language
2593 of choice.
2595 usri11_workstations points to a null terminated ASCII string that
2596 contains the names of workstations the user may log on from.
2597 There may be up to 8 workstations, with the names separated by
2598 commas. A null strings indicates there are no restrictions.
2600 usri11_max_storage specifies the maximum amount of disk space the user
2601 can occupy. A value of 0xffffffff indicates there are no
2602 restrictions.
2604 usri11_units_per_week specifies the equal number of time units into
2605 which a week is divided. This value must be equal to 168.
2607 usri11_logon_hours points to a 21 byte (168 bits) string that
2608 specifies the time during which the user can log on. Each bit
2609 represents one unique hour in a week. The first bit (bit 0, word
2610 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
2614 Leach, Naik [Page 29]
2618 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2621 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
2622 are no restrictions.
2624 usri11_code_page specifies the code page for the user's language of
2625 choice
2627 All of the pointers in this data structure need to be treated
2628 specially. The pointer is a 32 bit pointer. The higher 16 bits need
2629 to be ignored. The converter word returned in the parameters section
2630 needs to be subtracted from the lower 16 bits to calculate an offset
2631 into the return buffer where this ASCII string resides.
2633 There is no auxiliary data in the response.
2635 ****************************************************************************/
2637 #define usri11_name 0
2638 #define usri11_pad 21
2639 #define usri11_comment 22
2640 #define usri11_usr_comment 26
2641 #define usri11_full_name 30
2642 #define usri11_priv 34
2643 #define usri11_auth_flags 36
2644 #define usri11_password_age 40
2645 #define usri11_homedir 44
2646 #define usri11_parms 48
2647 #define usri11_last_logon 52
2648 #define usri11_last_logoff 56
2649 #define usri11_bad_pw_count 60
2650 #define usri11_num_logons 62
2651 #define usri11_logon_server 64
2652 #define usri11_country_code 68
2653 #define usri11_workstations 70
2654 #define usri11_max_storage 74
2655 #define usri11_units_per_week 78
2656 #define usri11_logon_hours 80
2657 #define usri11_code_page 84
2658 #define usri11_end 86
2660 #define USER_PRIV_GUEST 0
2661 #define USER_PRIV_USER 1
2662 #define USER_PRIV_ADMIN 2
2664 #define AF_OP_PRINT 0
2665 #define AF_OP_COMM 1
2666 #define AF_OP_SERVER 2
2667 #define AF_OP_ACCOUNTS 3
2670 static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2671 int mdrcnt,int mprcnt,
2672 char **rdata,char **rparam,
2673 int *rdata_len,int *rparam_len)
2675 char *str1 = param+2;
2676 char *str2 = skip_string(str1,1);
2677 char *UserName = skip_string(str2,1);
2678 char *p = skip_string(UserName,1);
2679 int uLevel = SVAL(p,0);
2680 char *p2;
2681 const char *level_string;
2683 /* get NIS home of a previously validated user - simeon */
2684 /* With share level security vuid will always be zero.
2685 Don't depend on vuser being non-null !!. JRA */
2686 user_struct *vuser = get_valid_user_struct(vuid);
2687 if(vuser != NULL)
2688 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid,
2689 vuser->user.unix_name));
2691 *rparam_len = 6;
2692 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2694 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
2696 /* check it's a supported variant */
2697 if (strcmp(str1,"zWrLh") != 0) return False;
2698 switch( uLevel )
2700 case 0: level_string = "B21"; break;
2701 case 1: level_string = "B21BB16DWzzWz"; break;
2702 case 2: level_string = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
2703 case 10: level_string = "B21Bzzz"; break;
2704 case 11: level_string = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
2705 default: return False;
2708 if (strcmp(level_string,str2) != 0) return False;
2710 *rdata_len = mdrcnt + 1024;
2711 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
2713 SSVAL(*rparam,0,NERR_Success);
2714 SSVAL(*rparam,2,0); /* converter word */
2716 p = *rdata;
2717 p2 = p + usri11_end;
2719 memset(p,0,21);
2720 fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
2722 if (uLevel > 0)
2724 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
2725 *p2 = 0;
2727 if (uLevel >= 10)
2729 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
2730 pstrcpy(p2,"Comment");
2731 p2 = skip_string(p2,1);
2733 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
2734 pstrcpy(p2,"UserComment");
2735 p2 = skip_string(p2,1);
2737 /* EEK! the cifsrap.txt doesn't have this in!!!! */
2738 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
2739 pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName));
2740 p2 = skip_string(p2,1);
2743 if (uLevel == 11) /* modelled after NTAS 3.51 reply */
2745 SSVAL(p,usri11_priv,conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2746 SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
2747 SIVALS(p,usri11_password_age,-1); /* password age */
2748 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
2749 pstrcpy(p2, vuser && vuser->homedir ? vuser->homedir : "");
2750 p2 = skip_string(p2,1);
2751 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
2752 pstrcpy(p2,"");
2753 p2 = skip_string(p2,1);
2754 SIVAL(p,usri11_last_logon,0); /* last logon */
2755 SIVAL(p,usri11_last_logoff,0); /* last logoff */
2756 SSVALS(p,usri11_bad_pw_count,-1); /* bad pw counts */
2757 SSVALS(p,usri11_num_logons,-1); /* num logons */
2758 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
2759 pstrcpy(p2,"\\\\*");
2760 p2 = skip_string(p2,1);
2761 SSVAL(p,usri11_country_code,0); /* country code */
2763 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
2764 pstrcpy(p2,"");
2765 p2 = skip_string(p2,1);
2767 SIVALS(p,usri11_max_storage,-1); /* max storage */
2768 SSVAL(p,usri11_units_per_week,168); /* units per week */
2769 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
2771 /* a simple way to get logon hours at all times. */
2772 memset(p2,0xff,21);
2773 SCVAL(p2,21,0); /* fix zero termination */
2774 p2 = skip_string(p2,1);
2776 SSVAL(p,usri11_code_page,0); /* code page */
2778 if (uLevel == 1 || uLevel == 2)
2780 memset(p+22,' ',16); /* password */
2781 SIVALS(p,38,-1); /* password age */
2782 SSVAL(p,42,
2783 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2784 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
2785 pstrcpy(p2, vuser && vuser->homedir ? vuser->homedir : "");
2786 p2 = skip_string(p2,1);
2787 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
2788 *p2++ = 0;
2789 SSVAL(p,52,0); /* flags */
2790 SIVAL(p,54,PTR_DIFF(p2,*rdata)); /* script_path */
2791 pstrcpy(p2,vuser && vuser->logon_script ? vuser->logon_script : "");
2792 p2 = skip_string(p2,1);
2793 if (uLevel == 2)
2795 SIVAL(p,60,0); /* auth_flags */
2796 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
2797 pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName));
2798 p2 = skip_string(p2,1);
2799 SIVAL(p,68,0); /* urs_comment */
2800 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
2801 pstrcpy(p2,"");
2802 p2 = skip_string(p2,1);
2803 SIVAL(p,76,0); /* workstations */
2804 SIVAL(p,80,0); /* last_logon */
2805 SIVAL(p,84,0); /* last_logoff */
2806 SIVALS(p,88,-1); /* acct_expires */
2807 SIVALS(p,92,-1); /* max_storage */
2808 SSVAL(p,96,168); /* units_per_week */
2809 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
2810 memset(p2,-1,21);
2811 p2 += 21;
2812 SSVALS(p,102,-1); /* bad_pw_count */
2813 SSVALS(p,104,-1); /* num_logons */
2814 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
2815 pstrcpy(p2,"\\\\%L");
2816 standard_sub_conn(conn, p2,0);
2817 p2 = skip_string(p2,1);
2818 SSVAL(p,110,49); /* country_code */
2819 SSVAL(p,112,860); /* code page */
2823 *rdata_len = PTR_DIFF(p2,*rdata);
2825 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
2827 return(True);
2830 static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param,char *data,
2831 int mdrcnt,int mprcnt,
2832 char **rdata,char **rparam,
2833 int *rdata_len,int *rparam_len)
2835 char *str1 = param+2;
2836 char *str2 = skip_string(str1,1);
2837 char *p = skip_string(str2,1);
2838 int uLevel;
2839 struct pack_desc desc;
2840 char* name;
2841 /* With share level security vuid will always be zero.
2842 Don't depend on vuser being non-null !!. JRA */
2843 user_struct *vuser = get_valid_user_struct(vuid);
2844 if(vuser != NULL)
2845 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid,
2846 vuser->user.unix_name));
2848 uLevel = SVAL(p,0);
2849 name = p + 2;
2851 memset((char *)&desc,'\0',sizeof(desc));
2853 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
2855 /* check it's a supported varient */
2856 if (strcmp(str1,"OOWb54WrLh") != 0) return False;
2857 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) return False;
2858 if (mdrcnt > 0) *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
2859 desc.base = *rdata;
2860 desc.buflen = mdrcnt;
2861 desc.subformat = NULL;
2862 desc.format = str2;
2864 if (init_package(&desc,1,0))
2866 PACKI(&desc,"W",0); /* code */
2867 PACKS(&desc,"B21",name); /* eff. name */
2868 PACKS(&desc,"B",""); /* pad */
2869 PACKI(&desc,"W",
2870 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2871 PACKI(&desc,"D",0); /* auth flags XXX */
2872 PACKI(&desc,"W",0); /* num logons */
2873 PACKI(&desc,"W",0); /* bad pw count */
2874 PACKI(&desc,"D",0); /* last logon */
2875 PACKI(&desc,"D",-1); /* last logoff */
2876 PACKI(&desc,"D",-1); /* logoff time */
2877 PACKI(&desc,"D",-1); /* kickoff time */
2878 PACKI(&desc,"D",0); /* password age */
2879 PACKI(&desc,"D",0); /* password can change */
2880 PACKI(&desc,"D",-1); /* password must change */
2882 fstring mypath;
2883 fstrcpy(mypath,"\\\\");
2884 fstrcat(mypath,local_machine);
2885 strupper_m(mypath);
2886 PACKS(&desc,"z",mypath); /* computer */
2888 PACKS(&desc,"z",lp_workgroup());/* domain */
2890 PACKS(&desc,"z", vuser && vuser->logon_script ? vuser->logon_script :""); /* script path */
2892 PACKI(&desc,"D",0x00000000); /* reserved */
2895 *rdata_len = desc.usedlen;
2896 *rparam_len = 6;
2897 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2898 SSVALS(*rparam,0,desc.errcode);
2899 SSVAL(*rparam,2,0);
2900 SSVAL(*rparam,4,desc.neededlen);
2902 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
2903 return(True);
2907 /****************************************************************************
2908 api_WAccessGetUserPerms
2909 ****************************************************************************/
2910 static BOOL api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid, char *param,char *data,
2911 int mdrcnt,int mprcnt,
2912 char **rdata,char **rparam,
2913 int *rdata_len,int *rparam_len)
2915 char *str1 = param+2;
2916 char *str2 = skip_string(str1,1);
2917 char *user = skip_string(str2,1);
2918 char *resource = skip_string(user,1);
2920 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
2922 /* check it's a supported varient */
2923 if (strcmp(str1,"zzh") != 0) return False;
2924 if (strcmp(str2,"") != 0) return False;
2926 *rparam_len = 6;
2927 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2928 SSVALS(*rparam,0,0); /* errorcode */
2929 SSVAL(*rparam,2,0); /* converter word */
2930 SSVAL(*rparam,4,0x7f); /* permission flags */
2932 return(True);
2935 /****************************************************************************
2936 api_WPrintJobEnumerate
2937 ****************************************************************************/
2938 static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2939 int mdrcnt,int mprcnt,
2940 char **rdata,char **rparam,
2941 int *rdata_len,int *rparam_len)
2943 char *str1 = param+2;
2944 char *str2 = skip_string(str1,1);
2945 char *p = skip_string(str2,1);
2946 int uLevel;
2947 int count;
2948 int i;
2949 int snum;
2950 fstring sharename;
2951 uint32 jobid;
2952 struct pack_desc desc;
2953 print_queue_struct *queue=NULL;
2954 print_status_struct status;
2955 char *tmpdata=NULL;
2957 uLevel = SVAL(p,2);
2959 memset((char *)&desc,'\0',sizeof(desc));
2960 memset((char *)&status,'\0',sizeof(status));
2962 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
2964 /* check it's a supported varient */
2965 if (strcmp(str1,"WWrLh") != 0) return False;
2966 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2968 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
2969 return False;
2971 snum = lp_servicenumber( sharename);
2972 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2974 count = print_queue_status(snum,&queue,&status);
2975 for (i = 0; i < count; i++) {
2976 if (queue[i].job == jobid) break;
2979 if (mdrcnt > 0) {
2980 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
2981 desc.base = *rdata;
2982 desc.buflen = mdrcnt;
2983 } else {
2985 * Don't return data but need to get correct length
2986 * init_package will return wrong size if buflen=0
2988 desc.buflen = getlen(desc.format);
2989 desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen );
2992 if (init_package(&desc,1,0)) {
2993 if (i < count) {
2994 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
2995 *rdata_len = desc.usedlen;
2997 else {
2998 desc.errcode = NERR_JobNotFound;
2999 *rdata_len = 0;
3003 *rparam_len = 6;
3004 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3005 SSVALS(*rparam,0,desc.errcode);
3006 SSVAL(*rparam,2,0);
3007 SSVAL(*rparam,4,desc.neededlen);
3009 SAFE_FREE(queue);
3010 SAFE_FREE(tmpdata);
3012 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
3013 return(True);
3016 static BOOL api_WPrintJobEnumerate(connection_struct *conn,uint16 vuid, char *param,char *data,
3017 int mdrcnt,int mprcnt,
3018 char **rdata,char **rparam,
3019 int *rdata_len,int *rparam_len)
3021 char *str1 = param+2;
3022 char *str2 = skip_string(str1,1);
3023 char *p = skip_string(str2,1);
3024 char* name = p;
3025 int uLevel;
3026 int count;
3027 int i, succnt=0;
3028 int snum;
3029 struct pack_desc desc;
3030 print_queue_struct *queue=NULL;
3031 print_status_struct status;
3033 memset((char *)&desc,'\0',sizeof(desc));
3034 memset((char *)&status,'\0',sizeof(status));
3036 p = skip_string(p,1);
3037 uLevel = SVAL(p,0);
3039 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
3041 /* check it's a supported variant */
3042 if (strcmp(str1,"zWrLeh") != 0)
3043 return False;
3045 if (uLevel > 2)
3046 return False; /* defined only for uLevel 0,1,2 */
3048 if (!check_printjob_info(&desc,uLevel,str2))
3049 return False;
3051 snum = find_service(name);
3052 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
3053 return False;
3055 count = print_queue_status(snum,&queue,&status);
3056 if (mdrcnt > 0) *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3057 desc.base = *rdata;
3058 desc.buflen = mdrcnt;
3060 if (init_package(&desc,count,0)) {
3061 succnt = 0;
3062 for (i = 0; i < count; i++) {
3063 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
3064 if (desc.errcode == NERR_Success) succnt = i+1;
3068 *rdata_len = desc.usedlen;
3070 *rparam_len = 8;
3071 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3072 SSVALS(*rparam,0,desc.errcode);
3073 SSVAL(*rparam,2,0);
3074 SSVAL(*rparam,4,succnt);
3075 SSVAL(*rparam,6,count);
3077 SAFE_FREE(queue);
3079 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
3080 return(True);
3083 static int check_printdest_info(struct pack_desc* desc,
3084 int uLevel, char* id)
3086 desc->subformat = NULL;
3087 switch( uLevel ) {
3088 case 0: desc->format = "B9"; break;
3089 case 1: desc->format = "B9B21WWzW"; break;
3090 case 2: desc->format = "z"; break;
3091 case 3: desc->format = "zzzWWzzzWW"; break;
3092 default: return False;
3094 if (strcmp(desc->format,id) != 0) return False;
3095 return True;
3098 static void fill_printdest_info(connection_struct *conn, int snum, int uLevel,
3099 struct pack_desc* desc)
3101 char buf[100];
3102 strncpy(buf,SERVICE(snum),sizeof(buf)-1);
3103 buf[sizeof(buf)-1] = 0;
3104 strupper_m(buf);
3105 if (uLevel <= 1) {
3106 PACKS(desc,"B9",buf); /* szName */
3107 if (uLevel == 1) {
3108 PACKS(desc,"B21",""); /* szUserName */
3109 PACKI(desc,"W",0); /* uJobId */
3110 PACKI(desc,"W",0); /* fsStatus */
3111 PACKS(desc,"z",""); /* pszStatus */
3112 PACKI(desc,"W",0); /* time */
3115 if (uLevel == 2 || uLevel == 3) {
3116 PACKS(desc,"z",buf); /* pszPrinterName */
3117 if (uLevel == 3) {
3118 PACKS(desc,"z",""); /* pszUserName */
3119 PACKS(desc,"z",""); /* pszLogAddr */
3120 PACKI(desc,"W",0); /* uJobId */
3121 PACKI(desc,"W",0); /* fsStatus */
3122 PACKS(desc,"z",""); /* pszStatus */
3123 PACKS(desc,"z",""); /* pszComment */
3124 PACKS(desc,"z","NULL"); /* pszDrivers */
3125 PACKI(desc,"W",0); /* time */
3126 PACKI(desc,"W",0); /* pad1 */
3131 static BOOL api_WPrintDestGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
3132 int mdrcnt,int mprcnt,
3133 char **rdata,char **rparam,
3134 int *rdata_len,int *rparam_len)
3136 char *str1 = param+2;
3137 char *str2 = skip_string(str1,1);
3138 char *p = skip_string(str2,1);
3139 char* PrinterName = p;
3140 int uLevel;
3141 struct pack_desc desc;
3142 int snum;
3143 char *tmpdata=NULL;
3145 memset((char *)&desc,'\0',sizeof(desc));
3147 p = skip_string(p,1);
3148 uLevel = SVAL(p,0);
3150 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
3152 /* check it's a supported varient */
3153 if (strcmp(str1,"zWrLh") != 0) return False;
3154 if (!check_printdest_info(&desc,uLevel,str2)) return False;
3156 snum = find_service(PrinterName);
3157 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) ) {
3158 *rdata_len = 0;
3159 desc.errcode = NERR_DestNotFound;
3160 desc.neededlen = 0;
3162 else {
3163 if (mdrcnt > 0) {
3164 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3165 desc.base = *rdata;
3166 desc.buflen = mdrcnt;
3167 } else {
3169 * Don't return data but need to get correct length
3170 * init_package will return wrong size if buflen=0
3172 desc.buflen = getlen(desc.format);
3173 desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen );
3175 if (init_package(&desc,1,0)) {
3176 fill_printdest_info(conn,snum,uLevel,&desc);
3178 *rdata_len = desc.usedlen;
3181 *rparam_len = 6;
3182 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3183 SSVALS(*rparam,0,desc.errcode);
3184 SSVAL(*rparam,2,0);
3185 SSVAL(*rparam,4,desc.neededlen);
3187 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
3188 SAFE_FREE(tmpdata);
3189 return(True);
3192 static BOOL api_WPrintDestEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3193 int mdrcnt,int mprcnt,
3194 char **rdata,char **rparam,
3195 int *rdata_len,int *rparam_len)
3197 char *str1 = param+2;
3198 char *str2 = skip_string(str1,1);
3199 char *p = skip_string(str2,1);
3200 int uLevel;
3201 int queuecnt;
3202 int i, n, succnt=0;
3203 struct pack_desc desc;
3204 int services = lp_numservices();
3206 memset((char *)&desc,'\0',sizeof(desc));
3208 uLevel = SVAL(p,0);
3210 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
3212 /* check it's a supported varient */
3213 if (strcmp(str1,"WrLeh") != 0) return False;
3214 if (!check_printdest_info(&desc,uLevel,str2)) return False;
3216 queuecnt = 0;
3217 for (i = 0; i < services; i++)
3218 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
3219 queuecnt++;
3221 if (mdrcnt > 0) *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3222 desc.base = *rdata;
3223 desc.buflen = mdrcnt;
3224 if (init_package(&desc,queuecnt,0)) {
3225 succnt = 0;
3226 n = 0;
3227 for (i = 0; i < services; i++) {
3228 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
3229 fill_printdest_info(conn,i,uLevel,&desc);
3230 n++;
3231 if (desc.errcode == NERR_Success) succnt = n;
3236 *rdata_len = desc.usedlen;
3238 *rparam_len = 8;
3239 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3240 SSVALS(*rparam,0,desc.errcode);
3241 SSVAL(*rparam,2,0);
3242 SSVAL(*rparam,4,succnt);
3243 SSVAL(*rparam,6,queuecnt);
3245 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
3246 return(True);
3249 static BOOL api_WPrintDriverEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3250 int mdrcnt,int mprcnt,
3251 char **rdata,char **rparam,
3252 int *rdata_len,int *rparam_len)
3254 char *str1 = param+2;
3255 char *str2 = skip_string(str1,1);
3256 char *p = skip_string(str2,1);
3257 int uLevel;
3258 int succnt;
3259 struct pack_desc desc;
3261 memset((char *)&desc,'\0',sizeof(desc));
3263 uLevel = SVAL(p,0);
3265 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
3267 /* check it's a supported varient */
3268 if (strcmp(str1,"WrLeh") != 0) return False;
3269 if (uLevel != 0 || strcmp(str2,"B41") != 0) return False;
3271 if (mdrcnt > 0) *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3272 desc.base = *rdata;
3273 desc.buflen = mdrcnt;
3274 if (init_package(&desc,1,0)) {
3275 PACKS(&desc,"B41","NULL");
3278 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3280 *rdata_len = desc.usedlen;
3282 *rparam_len = 8;
3283 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3284 SSVALS(*rparam,0,desc.errcode);
3285 SSVAL(*rparam,2,0);
3286 SSVAL(*rparam,4,succnt);
3287 SSVAL(*rparam,6,1);
3289 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
3290 return(True);
3293 static BOOL api_WPrintQProcEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3294 int mdrcnt,int mprcnt,
3295 char **rdata,char **rparam,
3296 int *rdata_len,int *rparam_len)
3298 char *str1 = param+2;
3299 char *str2 = skip_string(str1,1);
3300 char *p = skip_string(str2,1);
3301 int uLevel;
3302 int succnt;
3303 struct pack_desc desc;
3305 memset((char *)&desc,'\0',sizeof(desc));
3307 uLevel = SVAL(p,0);
3309 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
3311 /* check it's a supported varient */
3312 if (strcmp(str1,"WrLeh") != 0) return False;
3313 if (uLevel != 0 || strcmp(str2,"B13") != 0) return False;
3315 if (mdrcnt > 0) *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3316 desc.base = *rdata;
3317 desc.buflen = mdrcnt;
3318 desc.format = str2;
3319 if (init_package(&desc,1,0)) {
3320 PACKS(&desc,"B13","lpd");
3323 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3325 *rdata_len = desc.usedlen;
3327 *rparam_len = 8;
3328 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3329 SSVALS(*rparam,0,desc.errcode);
3330 SSVAL(*rparam,2,0);
3331 SSVAL(*rparam,4,succnt);
3332 SSVAL(*rparam,6,1);
3334 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
3335 return(True);
3338 static BOOL api_WPrintPortEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3339 int mdrcnt,int mprcnt,
3340 char **rdata,char **rparam,
3341 int *rdata_len,int *rparam_len)
3343 char *str1 = param+2;
3344 char *str2 = skip_string(str1,1);
3345 char *p = skip_string(str2,1);
3346 int uLevel;
3347 int succnt;
3348 struct pack_desc desc;
3350 memset((char *)&desc,'\0',sizeof(desc));
3352 uLevel = SVAL(p,0);
3354 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
3356 /* check it's a supported varient */
3357 if (strcmp(str1,"WrLeh") != 0) return False;
3358 if (uLevel != 0 || strcmp(str2,"B9") != 0) return False;
3360 if (mdrcnt > 0) *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3361 memset((char *)&desc,'\0',sizeof(desc));
3362 desc.base = *rdata;
3363 desc.buflen = mdrcnt;
3364 desc.format = str2;
3365 if (init_package(&desc,1,0)) {
3366 PACKS(&desc,"B13","lp0");
3369 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3371 *rdata_len = desc.usedlen;
3373 *rparam_len = 8;
3374 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3375 SSVALS(*rparam,0,desc.errcode);
3376 SSVAL(*rparam,2,0);
3377 SSVAL(*rparam,4,succnt);
3378 SSVAL(*rparam,6,1);
3380 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
3381 return(True);
3385 /****************************************************************************
3386 List open sessions
3387 ****************************************************************************/
3388 static BOOL api_RNetSessionEnum(connection_struct *conn,uint16 vuid, char *param, char *data,
3389 int mdrcnt,int mprcnt,
3390 char **rdata,char **rparam,
3391 int *rdata_len,int *rparam_len)
3394 char *str1 = param+2;
3395 char *str2 = skip_string(str1,1);
3396 char *p = skip_string(str2,1);
3397 int uLevel;
3398 struct pack_desc desc;
3399 struct sessionid *session_list;
3400 int i, num_sessions;
3402 memset((char *)&desc,'\0',sizeof(desc));
3404 uLevel = SVAL(p,0);
3406 DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel));
3407 DEBUG(7,("RNetSessionEnum req string=%s\n",str1));
3408 DEBUG(7,("RNetSessionEnum ret string=%s\n",str2));
3410 /* check it's a supported varient */
3411 if (strcmp(str1,RAP_NetSessionEnum_REQ) != 0) return False;
3412 if (uLevel != 2 || strcmp(str2,RAP_SESSION_INFO_L2) != 0) return False;
3414 num_sessions = list_sessions(&session_list);
3416 if (mdrcnt > 0) *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3417 memset((char *)&desc,'\0',sizeof(desc));
3418 desc.base = *rdata;
3419 desc.buflen = mdrcnt;
3420 desc.format = str2;
3421 if (!init_package(&desc,num_sessions,0)) {
3422 return False;
3425 for(i=0; i<num_sessions; i++) {
3426 PACKS(&desc, "z", session_list[i].remote_machine);
3427 PACKS(&desc, "z", session_list[i].username);
3428 PACKI(&desc, "W", 1); /* num conns */
3429 PACKI(&desc, "W", 0); /* num opens */
3430 PACKI(&desc, "W", 1); /* num users */
3431 PACKI(&desc, "D", 0); /* session time */
3432 PACKI(&desc, "D", 0); /* idle time */
3433 PACKI(&desc, "D", 0); /* flags */
3434 PACKS(&desc, "z", "Unknown Client"); /* client type string */
3437 *rdata_len = desc.usedlen;
3439 *rparam_len = 8;
3440 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3441 SSVALS(*rparam,0,desc.errcode);
3442 SSVAL(*rparam,2,0); /* converter */
3443 SSVAL(*rparam,4,num_sessions); /* count */
3445 DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc.errcode));
3446 return True;
3450 /****************************************************************************
3451 The buffer was too small
3452 ****************************************************************************/
3454 static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param,char *data,
3455 int mdrcnt,int mprcnt,
3456 char **rdata,char **rparam,
3457 int *rdata_len,int *rparam_len)
3459 *rparam_len = MIN(*rparam_len,mprcnt);
3460 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3462 *rdata_len = 0;
3464 SSVAL(*rparam,0,NERR_BufTooSmall);
3466 DEBUG(3,("Supplied buffer too small in API command\n"));
3468 return(True);
3472 /****************************************************************************
3473 The request is not supported
3474 ****************************************************************************/
3476 static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param,char *data,
3477 int mdrcnt,int mprcnt,
3478 char **rdata,char **rparam,
3479 int *rdata_len,int *rparam_len)
3481 *rparam_len = 4;
3482 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3484 *rdata_len = 0;
3486 SSVAL(*rparam,0,NERR_notsupported);
3487 SSVAL(*rparam,2,0); /* converter word */
3489 DEBUG(3,("Unsupported API command\n"));
3491 return(True);
3497 static const struct
3499 const char *name;
3500 int id;
3501 BOOL (*fn)(connection_struct *,uint16,char *,char *,
3502 int,int,char **,char **,int *,int *);
3503 BOOL auth_user; /* Deny anonymous access? */
3504 } api_commands[] = {
3505 {"RNetShareEnum", RAP_WshareEnum, api_RNetShareEnum, True},
3506 {"RNetShareGetInfo", RAP_WshareGetInfo, api_RNetShareGetInfo},
3507 {"RNetShareAdd", RAP_WshareAdd, api_RNetShareAdd},
3508 {"RNetSessionEnum", RAP_WsessionEnum, api_RNetSessionEnum, True},
3509 {"RNetServerGetInfo", RAP_WserverGetInfo, api_RNetServerGetInfo},
3510 {"RNetGroupEnum", RAP_WGroupEnum, api_RNetGroupEnum, True},
3511 {"RNetGroupGetUsers", RAP_WGroupGetUsers, api_RNetGroupGetUsers, True},
3512 {"RNetUserEnum", RAP_WUserEnum, api_RNetUserEnum, True},
3513 {"RNetUserGetInfo", RAP_WUserGetInfo, api_RNetUserGetInfo},
3514 {"NetUserGetGroups", RAP_WUserGetGroups, api_NetUserGetGroups},
3515 {"NetWkstaGetInfo", RAP_WWkstaGetInfo, api_NetWkstaGetInfo},
3516 {"DosPrintQEnum", RAP_WPrintQEnum, api_DosPrintQEnum, True},
3517 {"DosPrintQGetInfo", RAP_WPrintQGetInfo, api_DosPrintQGetInfo},
3518 {"WPrintQueuePause", RAP_WPrintQPause, api_WPrintQueueCtrl},
3519 {"WPrintQueueResume", RAP_WPrintQContinue, api_WPrintQueueCtrl},
3520 {"WPrintJobEnumerate",RAP_WPrintJobEnum, api_WPrintJobEnumerate},
3521 {"WPrintJobGetInfo", RAP_WPrintJobGetInfo, api_WPrintJobGetInfo},
3522 {"RDosPrintJobDel", RAP_WPrintJobDel, api_RDosPrintJobDel},
3523 {"RDosPrintJobPause", RAP_WPrintJobPause, api_RDosPrintJobDel},
3524 {"RDosPrintJobResume",RAP_WPrintJobContinue, api_RDosPrintJobDel},
3525 {"WPrintDestEnum", RAP_WPrintDestEnum, api_WPrintDestEnum},
3526 {"WPrintDestGetInfo", RAP_WPrintDestGetInfo, api_WPrintDestGetInfo},
3527 {"NetRemoteTOD", RAP_NetRemoteTOD, api_NetRemoteTOD},
3528 {"WPrintQueuePurge", RAP_WPrintQPurge, api_WPrintQueueCtrl},
3529 {"NetServerEnum", RAP_NetServerEnum2, api_RNetServerEnum}, /* anon OK */
3530 {"WAccessGetUserPerms",RAP_WAccessGetUserPerms,api_WAccessGetUserPerms},
3531 {"SetUserPassword", RAP_WUserPasswordSet2, api_SetUserPassword},
3532 {"WWkstaUserLogon", RAP_WWkstaUserLogon, api_WWkstaUserLogon},
3533 {"PrintJobInfo", RAP_WPrintJobSetInfo, api_PrintJobInfo},
3534 {"WPrintDriverEnum", RAP_WPrintDriverEnum, api_WPrintDriverEnum},
3535 {"WPrintQProcEnum", RAP_WPrintQProcessorEnum,api_WPrintQProcEnum},
3536 {"WPrintPortEnum", RAP_WPrintPortEnum, api_WPrintPortEnum},
3537 {"SamOEMChangePassword",RAP_SamOEMChgPasswordUser2_P,api_SamOEMChangePassword}, /* anon OK */
3538 {NULL, -1, api_Unsupported}};
3540 /* The following RAP calls are not implemented by Samba:
3542 RAP_WFileEnum2 - anon not OK
3545 /****************************************************************************
3546 Handle remote api calls
3547 ****************************************************************************/
3549 int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data,char *params,
3550 int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
3552 int api_command;
3553 char *rdata = NULL;
3554 char *rparam = NULL;
3555 int rdata_len = 0;
3556 int rparam_len = 0;
3557 BOOL reply=False;
3558 int i;
3560 if (!params) {
3561 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
3562 return 0;
3565 api_command = SVAL(params,0);
3567 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
3568 api_command,
3569 params+2,
3570 skip_string(params+2,1),
3571 tdscnt,tpscnt,mdrcnt,mprcnt));
3573 for (i=0;api_commands[i].name;i++) {
3574 if (api_commands[i].id == api_command && api_commands[i].fn) {
3575 DEBUG(3,("Doing %s\n",api_commands[i].name));
3576 break;
3580 /* Check whether this api call can be done anonymously */
3582 if (api_commands[i].auth_user && lp_restrict_anonymous()) {
3583 user_struct *user = get_valid_user_struct(vuid);
3585 if (!user || user->guest)
3586 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
3589 rdata = (char *)SMB_MALLOC(1024);
3590 if (rdata)
3591 memset(rdata,'\0',1024);
3593 rparam = (char *)SMB_MALLOC(1024);
3594 if (rparam)
3595 memset(rparam,'\0',1024);
3597 if(!rdata || !rparam) {
3598 DEBUG(0,("api_reply: malloc fail !\n"));
3599 return -1;
3602 reply = api_commands[i].fn(conn,vuid,params,data,mdrcnt,mprcnt,
3603 &rdata,&rparam,&rdata_len,&rparam_len);
3606 if (rdata_len > mdrcnt ||
3607 rparam_len > mprcnt) {
3608 reply = api_TooSmall(conn,vuid,params,data,mdrcnt,mprcnt,
3609 &rdata,&rparam,&rdata_len,&rparam_len);
3612 /* if we get False back then it's actually unsupported */
3613 if (!reply)
3614 api_Unsupported(conn,vuid,params,data,mdrcnt,mprcnt,
3615 &rdata,&rparam,&rdata_len,&rparam_len);
3617 send_trans_reply(outbuf, rparam, rparam_len, rdata, rdata_len, False);
3619 SAFE_FREE(rdata);
3620 SAFE_FREE(rparam);
3622 return -1;