r11137: Compile with only 2 warnings (I'm still working on that code) on a gcc4
[Samba.git] / source / smbd / lanman.c
blob3e1174b22fd5dbdbc29e92d1b3f3b2b618e092c0
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 extern struct current_user current_user;
31 extern userdom_struct current_user_info;
33 #ifdef CHECK_TYPES
34 #undef CHECK_TYPES
35 #endif
36 #define CHECK_TYPES 0
38 #define NERR_Success 0
39 #define NERR_badpass 86
40 #define NERR_notsupported 50
42 #define NERR_BASE (2100)
43 #define NERR_BufTooSmall (NERR_BASE+23)
44 #define NERR_JobNotFound (NERR_BASE+51)
45 #define NERR_DestNotFound (NERR_BASE+52)
47 #define ACCESS_READ 0x01
48 #define ACCESS_WRITE 0x02
49 #define ACCESS_CREATE 0x04
51 #define SHPWLEN 8 /* share password length */
53 static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param,char *data,
54 int mdrcnt,int mprcnt,
55 char **rdata,char **rparam,
56 int *rdata_len,int *rparam_len);
57 static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param,char *data,
58 int mdrcnt,int mprcnt,
59 char **rdata,char **rparam,
60 int *rdata_len,int *rparam_len);
63 static int CopyExpanded(connection_struct *conn,
64 int snum, char** dst, char* src, int* n)
66 pstring buf;
67 int l;
69 if (!src || !dst || !n || !(*dst)) return(0);
71 StrnCpy(buf,src,sizeof(buf)/2);
72 pstring_sub(buf,"%S",lp_servicename(snum));
73 standard_sub_conn(conn,buf,sizeof(buf));
74 l = push_ascii(*dst,buf,*n, STR_TERMINATE);
75 (*dst) += l;
76 (*n) -= l;
77 return l;
80 static int CopyAndAdvance(char** dst, char* src, int* n)
82 int l;
83 if (!src || !dst || !n || !(*dst)) return(0);
84 l = push_ascii(*dst,src,*n, STR_TERMINATE);
85 (*dst) += l;
86 (*n) -= l;
87 return l;
90 static int StrlenExpanded(connection_struct *conn, int snum, char* s)
92 pstring buf;
93 if (!s) return(0);
94 StrnCpy(buf,s,sizeof(buf)/2);
95 pstring_sub(buf,"%S",lp_servicename(snum));
96 standard_sub_conn(conn,buf,sizeof(buf));
97 return strlen(buf) + 1;
100 static char* Expand(connection_struct *conn, int snum, char* s)
102 static pstring buf;
103 if (!s) return(NULL);
104 StrnCpy(buf,s,sizeof(buf)/2);
105 pstring_sub(buf,"%S",lp_servicename(snum));
106 standard_sub_conn(conn,buf,sizeof(buf));
107 return &buf[0];
110 /*******************************************************************
111 check a API string for validity when we only need to check the prefix
112 ******************************************************************/
113 static BOOL prefix_ok(const char *str, const char *prefix)
115 return(strncmp(str,prefix,strlen(prefix)) == 0);
118 struct pack_desc {
119 const char* format; /* formatstring for structure */
120 const char* subformat; /* subformat for structure */
121 char* base; /* baseaddress of buffer */
122 int buflen; /* remaining size for fixed part; on init: length of base */
123 int subcount; /* count of substructures */
124 char* structbuf; /* pointer into buffer for remaining fixed part */
125 int stringlen; /* remaining size for variable part */
126 char* stringbuf; /* pointer into buffer for remaining variable part */
127 int neededlen; /* total needed size */
128 int usedlen; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
129 const char* curpos; /* current position; pointer into format or subformat */
130 int errcode;
133 static int get_counter(const char** p)
135 int i, n;
136 if (!p || !(*p)) return(1);
137 if (!isdigit((int)**p)) return 1;
138 for (n = 0;;) {
139 i = **p;
140 if (isdigit(i))
141 n = 10 * n + (i - '0');
142 else
143 return n;
144 (*p)++;
148 static int getlen(const char* p)
150 int n = 0;
151 if (!p) return(0);
152 while (*p) {
153 switch( *p++ ) {
154 case 'W': /* word (2 byte) */
155 n += 2;
156 break;
157 case 'K': /* status word? (2 byte) */
158 n += 2;
159 break;
160 case 'N': /* count of substructures (word) at end */
161 n += 2;
162 break;
163 case 'D': /* double word (4 byte) */
164 case 'z': /* offset to zero terminated string (4 byte) */
165 case 'l': /* offset to user data (4 byte) */
166 n += 4;
167 break;
168 case 'b': /* offset to data (with counter) (4 byte) */
169 n += 4;
170 get_counter(&p);
171 break;
172 case 'B': /* byte (with optional counter) */
173 n += get_counter(&p);
174 break;
177 return n;
180 static BOOL init_package(struct pack_desc* p, int count, int subcount)
182 int n = p->buflen;
183 int i;
185 if (!p->format || !p->base) return(False);
187 i = count * getlen(p->format);
188 if (p->subformat) i += subcount * getlen(p->subformat);
189 p->structbuf = p->base;
190 p->neededlen = 0;
191 p->usedlen = 0;
192 p->subcount = 0;
193 p->curpos = p->format;
194 if (i > n) {
195 p->neededlen = i;
196 i = n = 0;
197 #if 0
199 * This is the old error code we used. Aparently
200 * WinNT/2k systems return ERRbuftoosmall (2123) and
201 * OS/2 needs this. I'm leaving this here so we can revert
202 * if needed. JRA.
204 p->errcode = ERRmoredata;
205 #else
206 p->errcode = ERRbuftoosmall;
207 #endif
209 else
210 p->errcode = NERR_Success;
211 p->buflen = i;
212 n -= i;
213 p->stringbuf = p->base + i;
214 p->stringlen = n;
215 return(p->errcode == NERR_Success);
218 static int package(struct pack_desc* p, ...)
220 va_list args;
221 int needed=0, stringneeded;
222 const char* str=NULL;
223 int is_string=0, stringused;
224 int32 temp;
226 va_start(args,p);
228 if (!*p->curpos) {
229 if (!p->subcount)
230 p->curpos = p->format;
231 else {
232 p->curpos = p->subformat;
233 p->subcount--;
236 #if CHECK_TYPES
237 str = va_arg(args,char*);
238 SMB_ASSERT(strncmp(str,p->curpos,strlen(str)) == 0);
239 #endif
240 stringneeded = -1;
242 if (!p->curpos) {
243 va_end(args);
244 return(0);
247 switch( *p->curpos++ ) {
248 case 'W': /* word (2 byte) */
249 needed = 2;
250 temp = va_arg(args,int);
251 if (p->buflen >= needed) SSVAL(p->structbuf,0,temp);
252 break;
253 case 'K': /* status word? (2 byte) */
254 needed = 2;
255 temp = va_arg(args,int);
256 if (p->buflen >= needed) SSVAL(p->structbuf,0,temp);
257 break;
258 case 'N': /* count of substructures (word) at end */
259 needed = 2;
260 p->subcount = va_arg(args,int);
261 if (p->buflen >= needed) SSVAL(p->structbuf,0,p->subcount);
262 break;
263 case 'D': /* double word (4 byte) */
264 needed = 4;
265 temp = va_arg(args,int);
266 if (p->buflen >= needed) SIVAL(p->structbuf,0,temp);
267 break;
268 case 'B': /* byte (with optional counter) */
269 needed = get_counter(&p->curpos);
271 char *s = va_arg(args,char*);
272 if (p->buflen >= needed) StrnCpy(p->structbuf,s?s:"",needed-1);
274 break;
275 case 'z': /* offset to zero terminated string (4 byte) */
276 str = va_arg(args,char*);
277 stringneeded = (str ? strlen(str)+1 : 0);
278 is_string = 1;
279 break;
280 case 'l': /* offset to user data (4 byte) */
281 str = va_arg(args,char*);
282 stringneeded = va_arg(args,int);
283 is_string = 0;
284 break;
285 case 'b': /* offset to data (with counter) (4 byte) */
286 str = va_arg(args,char*);
287 stringneeded = get_counter(&p->curpos);
288 is_string = 0;
289 break;
291 va_end(args);
292 if (stringneeded >= 0) {
293 needed = 4;
294 if (p->buflen >= needed) {
295 stringused = stringneeded;
296 if (stringused > p->stringlen) {
297 stringused = (is_string ? p->stringlen : 0);
298 if (p->errcode == NERR_Success) p->errcode = ERRmoredata;
300 if (!stringused)
301 SIVAL(p->structbuf,0,0);
302 else {
303 SIVAL(p->structbuf,0,PTR_DIFF(p->stringbuf,p->base));
304 memcpy(p->stringbuf,str?str:"",stringused);
305 if (is_string) p->stringbuf[stringused-1] = '\0';
306 p->stringbuf += stringused;
307 p->stringlen -= stringused;
308 p->usedlen += stringused;
311 p->neededlen += stringneeded;
313 p->neededlen += needed;
314 if (p->buflen >= needed) {
315 p->structbuf += needed;
316 p->buflen -= needed;
317 p->usedlen += needed;
319 else {
320 if (p->errcode == NERR_Success) p->errcode = ERRmoredata;
322 return 1;
325 #if CHECK_TYPES
326 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
327 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
328 #else
329 #define PACK(desc,t,v) package(desc,v)
330 #define PACKl(desc,t,v,l) package(desc,v,l)
331 #endif
333 static void PACKI(struct pack_desc* desc, const char *t,int v)
335 PACK(desc,t,v);
338 static void PACKS(struct pack_desc* desc,const char *t,const char *v)
340 PACK(desc,t,v);
344 /****************************************************************************
345 get a print queue
346 ****************************************************************************/
347 static void PackDriverData(struct pack_desc* desc)
349 char drivdata[4+4+32];
350 SIVAL(drivdata,0,sizeof drivdata); /* cb */
351 SIVAL(drivdata,4,1000); /* lVersion */
352 memset(drivdata+8,0,32); /* szDeviceName */
353 push_ascii(drivdata+8,"NULL",-1, STR_TERMINATE);
354 PACKl(desc,"l",drivdata,sizeof drivdata); /* pDriverData */
357 static int check_printq_info(struct pack_desc* desc,
358 unsigned int uLevel, char *id1, char *id2)
360 desc->subformat = NULL;
361 switch( uLevel ) {
362 case 0:
363 desc->format = "B13";
364 break;
365 case 1:
366 desc->format = "B13BWWWzzzzzWW";
367 break;
368 case 2:
369 desc->format = "B13BWWWzzzzzWN";
370 desc->subformat = "WB21BB16B10zWWzDDz";
371 break;
372 case 3:
373 desc->format = "zWWWWzzzzWWzzl";
374 break;
375 case 4:
376 desc->format = "zWWWWzzzzWNzzl";
377 desc->subformat = "WWzWWDDzz";
378 break;
379 case 5:
380 desc->format = "z";
381 break;
382 case 51:
383 desc->format = "K";
384 break;
385 case 52:
386 desc->format = "WzzzzzzzzN";
387 desc->subformat = "z";
388 break;
389 default:
390 return False;
392 if (strcmp(desc->format,id1) != 0) {
393 return False;
395 if (desc->subformat && strcmp(desc->subformat,id2) != 0) {
396 return False;
398 return True;
402 #define RAP_JOB_STATUS_QUEUED 0
403 #define RAP_JOB_STATUS_PAUSED 1
404 #define RAP_JOB_STATUS_SPOOLING 2
405 #define RAP_JOB_STATUS_PRINTING 3
406 #define RAP_JOB_STATUS_PRINTED 4
408 #define RAP_QUEUE_STATUS_PAUSED 1
409 #define RAP_QUEUE_STATUS_ERROR 2
411 /* turn a print job status into a on the wire status
413 static int printj_status(int v)
415 switch (v) {
416 case LPQ_QUEUED:
417 return RAP_JOB_STATUS_QUEUED;
418 case LPQ_PAUSED:
419 return RAP_JOB_STATUS_PAUSED;
420 case LPQ_SPOOLING:
421 return RAP_JOB_STATUS_SPOOLING;
422 case LPQ_PRINTING:
423 return RAP_JOB_STATUS_PRINTING;
425 return 0;
428 /* turn a print queue status into a on the wire status
430 static int printq_status(int v)
432 switch (v) {
433 case LPQ_QUEUED:
434 return 0;
435 case LPQ_PAUSED:
436 return RAP_QUEUE_STATUS_PAUSED;
438 return RAP_QUEUE_STATUS_ERROR;
441 static void fill_printjob_info(connection_struct *conn, int snum, int uLevel,
442 struct pack_desc* desc,
443 print_queue_struct* queue, int n)
445 time_t t = queue->time;
447 /* the client expects localtime */
448 t -= TimeDiff(t);
450 PACKI(desc,"W",pjobid_to_rap(lp_const_servicename(snum),queue->job)); /* uJobId */
451 if (uLevel == 1) {
452 PACKS(desc,"B21",queue->fs_user); /* szUserName */
453 PACKS(desc,"B",""); /* pad */
454 PACKS(desc,"B16",""); /* szNotifyName */
455 PACKS(desc,"B10","PM_Q_RAW"); /* szDataType */
456 PACKS(desc,"z",""); /* pszParms */
457 PACKI(desc,"W",n+1); /* uPosition */
458 PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */
459 PACKS(desc,"z",""); /* pszStatus */
460 PACKI(desc,"D",t); /* ulSubmitted */
461 PACKI(desc,"D",queue->size); /* ulSize */
462 PACKS(desc,"z",queue->fs_file); /* pszComment */
464 if (uLevel == 2 || uLevel == 3 || uLevel == 4) {
465 PACKI(desc,"W",queue->priority); /* uPriority */
466 PACKS(desc,"z",queue->fs_user); /* pszUserName */
467 PACKI(desc,"W",n+1); /* uPosition */
468 PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */
469 PACKI(desc,"D",t); /* ulSubmitted */
470 PACKI(desc,"D",queue->size); /* ulSize */
471 PACKS(desc,"z","Samba"); /* pszComment */
472 PACKS(desc,"z",queue->fs_file); /* pszDocument */
473 if (uLevel == 3) {
474 PACKS(desc,"z",""); /* pszNotifyName */
475 PACKS(desc,"z","PM_Q_RAW"); /* pszDataType */
476 PACKS(desc,"z",""); /* pszParms */
477 PACKS(desc,"z",""); /* pszStatus */
478 PACKS(desc,"z",SERVICE(snum)); /* pszQueue */
479 PACKS(desc,"z","lpd"); /* pszQProcName */
480 PACKS(desc,"z",""); /* pszQProcParms */
481 PACKS(desc,"z","NULL"); /* pszDriverName */
482 PackDriverData(desc); /* pDriverData */
483 PACKS(desc,"z",""); /* pszPrinterName */
484 } else if (uLevel == 4) { /* OS2 */
485 PACKS(desc,"z",""); /* pszSpoolFileName */
486 PACKS(desc,"z",""); /* pszPortName */
487 PACKS(desc,"z",""); /* pszStatus */
488 PACKI(desc,"D",0); /* ulPagesSpooled */
489 PACKI(desc,"D",0); /* ulPagesSent */
490 PACKI(desc,"D",0); /* ulPagesPrinted */
491 PACKI(desc,"D",0); /* ulTimePrinted */
492 PACKI(desc,"D",0); /* ulExtendJobStatus */
493 PACKI(desc,"D",0); /* ulStartPage */
494 PACKI(desc,"D",0); /* ulEndPage */
499 /********************************************************************
500 Return a driver name given an snum.
501 Returns True if from tdb, False otherwise.
502 ********************************************************************/
504 static BOOL get_driver_name(int snum, pstring drivername)
506 NT_PRINTER_INFO_LEVEL *info = NULL;
507 BOOL in_tdb = False;
509 get_a_printer (NULL, &info, 2, lp_servicename(snum));
510 if (info != NULL) {
511 pstrcpy( drivername, info->info_2->drivername);
512 in_tdb = True;
513 free_a_printer(&info, 2);
516 return in_tdb;
519 /********************************************************************
520 Respond to the DosPrintQInfo command with a level of 52
521 This is used to get printer driver information for Win9x clients
522 ********************************************************************/
523 static void fill_printq_info_52(connection_struct *conn, int snum,
524 struct pack_desc* desc, int count )
526 int i;
527 fstring location;
528 NT_PRINTER_DRIVER_INFO_LEVEL driver;
529 NT_PRINTER_INFO_LEVEL *printer = NULL;
531 ZERO_STRUCT(driver);
533 if ( !W_ERROR_IS_OK(get_a_printer( NULL, &printer, 2, lp_servicename(snum))) ) {
534 DEBUG(3,("fill_printq_info_52: Failed to lookup printer [%s]\n",
535 lp_servicename(snum)));
536 goto err;
539 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername,
540 "Windows 4.0", 0)) )
542 DEBUG(3,("fill_printq_info_52: Failed to lookup driver [%s]\n",
543 printer->info_2->drivername));
544 goto err;
547 trim_string(driver.info_3->driverpath, "\\print$\\WIN40\\0\\", 0);
548 trim_string(driver.info_3->datafile, "\\print$\\WIN40\\0\\", 0);
549 trim_string(driver.info_3->helpfile, "\\print$\\WIN40\\0\\", 0);
551 PACKI(desc, "W", 0x0400); /* don't know */
552 PACKS(desc, "z", driver.info_3->name); /* long printer name */
553 PACKS(desc, "z", driver.info_3->driverpath); /* Driverfile Name */
554 PACKS(desc, "z", driver.info_3->datafile); /* Datafile name */
555 PACKS(desc, "z", driver.info_3->monitorname); /* language monitor */
557 fstrcpy(location, "\\\\%L\\print$\\WIN40\\0");
558 standard_sub_basic( "", location, sizeof(location)-1 );
559 PACKS(desc,"z", location); /* share to retrieve files */
561 PACKS(desc,"z", driver.info_3->defaultdatatype); /* default data type */
562 PACKS(desc,"z", driver.info_3->helpfile); /* helpfile name */
563 PACKS(desc,"z", driver.info_3->driverpath); /* driver name */
565 DEBUG(3,("Printer Driver Name: %s:\n",driver.info_3->name));
566 DEBUG(3,("Driver: %s:\n",driver.info_3->driverpath));
567 DEBUG(3,("Data File: %s:\n",driver.info_3->datafile));
568 DEBUG(3,("Language Monitor: %s:\n",driver.info_3->monitorname));
569 DEBUG(3,("Driver Location: %s:\n",location));
570 DEBUG(3,("Data Type: %s:\n",driver.info_3->defaultdatatype));
571 DEBUG(3,("Help File: %s:\n",driver.info_3->helpfile));
572 PACKI(desc,"N",count); /* number of files to copy */
574 for ( i=0; i<count && driver.info_3->dependentfiles && *driver.info_3->dependentfiles[i]; i++)
576 trim_string(driver.info_3->dependentfiles[i], "\\print$\\WIN40\\0\\", 0);
577 PACKS(desc,"z",driver.info_3->dependentfiles[i]); /* driver files to copy */
578 DEBUG(3,("Dependent File: %s:\n",driver.info_3->dependentfiles[i]));
581 /* sanity check */
582 if ( i != count )
583 DEBUG(3,("fill_printq_info_52: file count specified by client [%d] != number of dependent files [%i]\n",
584 count, i));
586 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n", SERVICE(snum),i));
588 desc->errcode=NERR_Success;
589 goto done;
591 err:
592 DEBUG(3,("fill_printq_info: Can't supply driver files\n"));
593 desc->errcode=NERR_notsupported;
595 done:
596 if ( printer )
597 free_a_printer( &printer, 2 );
599 if ( driver.info_3 )
600 free_a_printer_driver( driver, 3 );
604 static void fill_printq_info(connection_struct *conn, int snum, int uLevel,
605 struct pack_desc* desc,
606 int count, print_queue_struct* queue,
607 print_status_struct* status)
609 switch (uLevel) {
610 case 1:
611 case 2:
612 PACKS(desc,"B13",SERVICE(snum));
613 break;
614 case 3:
615 case 4:
616 case 5:
617 PACKS(desc,"z",Expand(conn,snum,SERVICE(snum)));
618 break;
619 case 51:
620 PACKI(desc,"K",printq_status(status->status));
621 break;
624 if (uLevel == 1 || uLevel == 2) {
625 PACKS(desc,"B",""); /* alignment */
626 PACKI(desc,"W",5); /* priority */
627 PACKI(desc,"W",0); /* start time */
628 PACKI(desc,"W",0); /* until time */
629 PACKS(desc,"z",""); /* pSepFile */
630 PACKS(desc,"z","lpd"); /* pPrProc */
631 PACKS(desc,"z",SERVICE(snum)); /* pDestinations */
632 PACKS(desc,"z",""); /* pParms */
633 if (snum < 0) {
634 PACKS(desc,"z","UNKNOWN PRINTER");
635 PACKI(desc,"W",LPSTAT_ERROR);
637 else if (!status || !status->message[0]) {
638 PACKS(desc,"z",Expand(conn,snum,lp_comment(snum)));
639 PACKI(desc,"W",LPSTAT_OK); /* status */
640 } else {
641 PACKS(desc,"z",status->message);
642 PACKI(desc,"W",printq_status(status->status)); /* status */
644 PACKI(desc,(uLevel == 1 ? "W" : "N"),count);
647 if (uLevel == 3 || uLevel == 4) {
648 pstring drivername;
650 PACKI(desc,"W",5); /* uPriority */
651 PACKI(desc,"W",0); /* uStarttime */
652 PACKI(desc,"W",0); /* uUntiltime */
653 PACKI(desc,"W",5); /* pad1 */
654 PACKS(desc,"z",""); /* pszSepFile */
655 PACKS(desc,"z","WinPrint"); /* pszPrProc */
656 PACKS(desc,"z",NULL); /* pszParms */
657 PACKS(desc,"z",NULL); /* pszComment - don't ask.... JRA */
658 /* "don't ask" that it's done this way to fix corrupted
659 Win9X/ME printer comments. */
660 if (!status) {
661 PACKI(desc,"W",LPSTAT_OK); /* fsStatus */
662 } else {
663 PACKI(desc,"W",printq_status(status->status)); /* fsStatus */
665 PACKI(desc,(uLevel == 3 ? "W" : "N"),count); /* cJobs */
666 PACKS(desc,"z",SERVICE(snum)); /* pszPrinters */
667 get_driver_name(snum,drivername);
668 PACKS(desc,"z",drivername); /* pszDriverName */
669 PackDriverData(desc); /* pDriverData */
672 if (uLevel == 2 || uLevel == 4) {
673 int i;
674 for (i=0;i<count;i++)
675 fill_printjob_info(conn,snum,uLevel == 2 ? 1 : 2,desc,&queue[i],i);
678 if (uLevel==52)
679 fill_printq_info_52( conn, snum, desc, count );
682 /* This function returns the number of files for a given driver */
683 static int get_printerdrivernumber(int snum)
685 int result = 0;
686 NT_PRINTER_DRIVER_INFO_LEVEL driver;
687 NT_PRINTER_INFO_LEVEL *printer = NULL;
689 ZERO_STRUCT(driver);
691 if ( !W_ERROR_IS_OK(get_a_printer( NULL, &printer, 2, lp_servicename(snum))) ) {
692 DEBUG(3,("get_printerdrivernumber: Failed to lookup printer [%s]\n",
693 lp_servicename(snum)));
694 goto done;
697 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername,
698 "Windows 4.0", 0)) )
700 DEBUG(3,("get_printerdrivernumber: Failed to lookup driver [%s]\n",
701 printer->info_2->drivername));
702 goto done;
705 /* count the number of files */
706 while ( driver.info_3->dependentfiles && *driver.info_3->dependentfiles[result] )
707 result++;
709 done:
710 if ( printer )
711 free_a_printer( &printer, 2 );
713 if ( driver.info_3 )
714 free_a_printer_driver( driver, 3 );
716 return result;
719 static BOOL api_DosPrintQGetInfo(connection_struct *conn,
720 uint16 vuid, char *param,char *data,
721 int mdrcnt,int mprcnt,
722 char **rdata,char **rparam,
723 int *rdata_len,int *rparam_len)
725 char *str1 = param+2;
726 char *str2 = skip_string(str1,1);
727 char *p = skip_string(str2,1);
728 char *QueueName = p;
729 unsigned int uLevel;
730 int count=0;
731 int snum;
732 char* str3;
733 struct pack_desc desc;
734 print_queue_struct *queue=NULL;
735 print_status_struct status;
736 char* tmpdata=NULL;
738 memset((char *)&status,'\0',sizeof(status));
739 memset((char *)&desc,'\0',sizeof(desc));
741 p = skip_string(p,1);
742 uLevel = SVAL(p,0);
743 str3 = p + 4;
745 /* remove any trailing username */
746 if ((p = strchr_m(QueueName,'%')))
747 *p = 0;
749 DEBUG(3,("api_DosPrintQGetInfo uLevel=%d name=%s\n",uLevel,QueueName));
751 /* check it's a supported varient */
752 if (!prefix_ok(str1,"zWrLh"))
753 return False;
754 if (!check_printq_info(&desc,uLevel,str2,str3)) {
756 * Patch from Scott Moomaw <scott@bridgewater.edu>
757 * to return the 'invalid info level' error if an
758 * unknown level was requested.
760 *rdata_len = 0;
761 *rparam_len = 6;
762 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
763 SSVALS(*rparam,0,ERRunknownlevel);
764 SSVAL(*rparam,2,0);
765 SSVAL(*rparam,4,0);
766 return(True);
769 snum = find_service(QueueName);
770 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
771 return False;
773 if (uLevel==52) {
774 count = get_printerdrivernumber(snum);
775 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count));
776 } else {
777 count = print_queue_status(snum, &queue,&status);
780 if (mdrcnt > 0) {
781 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
782 desc.base = *rdata;
783 desc.buflen = mdrcnt;
784 } else {
786 * Don't return data but need to get correct length
787 * init_package will return wrong size if buflen=0
789 desc.buflen = getlen(desc.format);
790 desc.base = tmpdata = (char *) SMB_MALLOC (desc.buflen);
793 if (init_package(&desc,1,count)) {
794 desc.subcount = count;
795 fill_printq_info(conn,snum,uLevel,&desc,count,queue,&status);
798 *rdata_len = desc.usedlen;
801 * We must set the return code to ERRbuftoosmall
802 * in order to support lanman style printing with Win NT/2k
803 * clients --jerry
805 if (!mdrcnt && lp_disable_spoolss())
806 desc.errcode = ERRbuftoosmall;
808 *rdata_len = desc.usedlen;
809 *rparam_len = 6;
810 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
811 SSVALS(*rparam,0,desc.errcode);
812 SSVAL(*rparam,2,0);
813 SSVAL(*rparam,4,desc.neededlen);
815 DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode));
817 SAFE_FREE(queue);
818 SAFE_FREE(tmpdata);
820 return(True);
823 /****************************************************************************
824 View list of all print jobs on all queues.
825 ****************************************************************************/
827 static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid, char* param, char* data,
828 int mdrcnt, int mprcnt,
829 char **rdata, char** rparam,
830 int *rdata_len, int *rparam_len)
832 char *param_format = param+2;
833 char *output_format1 = skip_string(param_format,1);
834 char *p = skip_string(output_format1,1);
835 unsigned int uLevel = SVAL(p,0);
836 char *output_format2 = p + 4;
837 int services = lp_numservices();
838 int i, n;
839 struct pack_desc desc;
840 print_queue_struct **queue = NULL;
841 print_status_struct *status = NULL;
842 int *subcntarr = NULL;
843 int queuecnt = 0, subcnt = 0, succnt = 0;
845 memset((char *)&desc,'\0',sizeof(desc));
847 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
849 if (!prefix_ok(param_format,"WrLeh")) {
850 return False;
852 if (!check_printq_info(&desc,uLevel,output_format1,output_format2)) {
854 * Patch from Scott Moomaw <scott@bridgewater.edu>
855 * to return the 'invalid info level' error if an
856 * unknown level was requested.
858 *rdata_len = 0;
859 *rparam_len = 6;
860 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
861 SSVALS(*rparam,0,ERRunknownlevel);
862 SSVAL(*rparam,2,0);
863 SSVAL(*rparam,4,0);
864 return(True);
867 for (i = 0; i < services; i++) {
868 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
869 queuecnt++;
873 if((queue = SMB_MALLOC_ARRAY(print_queue_struct*, queuecnt)) == NULL) {
874 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
875 goto err;
877 memset(queue,0,queuecnt*sizeof(print_queue_struct*));
878 if((status = SMB_MALLOC_ARRAY(print_status_struct,queuecnt)) == NULL) {
879 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
880 goto err;
882 memset(status,0,queuecnt*sizeof(print_status_struct));
883 if((subcntarr = SMB_MALLOC_ARRAY(int,queuecnt)) == NULL) {
884 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
885 goto err;
888 subcnt = 0;
889 n = 0;
890 for (i = 0; i < services; i++) {
891 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
892 subcntarr[n] = print_queue_status(i, &queue[n],&status[n]);
893 subcnt += subcntarr[n];
894 n++;
898 if (mdrcnt > 0) {
899 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
900 if (!*rdata) {
901 goto err;
904 desc.base = *rdata;
905 desc.buflen = mdrcnt;
907 if (init_package(&desc,queuecnt,subcnt)) {
908 n = 0;
909 succnt = 0;
910 for (i = 0; i < services; i++) {
911 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
912 fill_printq_info(conn,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]);
913 n++;
914 if (desc.errcode == NERR_Success) {
915 succnt = n;
921 SAFE_FREE(subcntarr);
923 *rdata_len = desc.usedlen;
924 *rparam_len = 8;
925 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
926 if (!*rparam) {
927 goto err;
929 SSVALS(*rparam,0,desc.errcode);
930 SSVAL(*rparam,2,0);
931 SSVAL(*rparam,4,succnt);
932 SSVAL(*rparam,6,queuecnt);
934 for (i = 0; i < queuecnt; i++) {
935 if (queue) {
936 SAFE_FREE(queue[i]);
940 SAFE_FREE(queue);
941 SAFE_FREE(status);
943 return True;
945 err:
947 SAFE_FREE(subcntarr);
948 for (i = 0; i < queuecnt; i++) {
949 if (queue) {
950 SAFE_FREE(queue[i]);
953 SAFE_FREE(queue);
954 SAFE_FREE(status);
956 return False;
959 /****************************************************************************
960 Get info level for a server list query.
961 ****************************************************************************/
963 static BOOL check_server_info(int uLevel, char* id)
965 switch( uLevel ) {
966 case 0:
967 if (strcmp(id,"B16") != 0) {
968 return False;
970 break;
971 case 1:
972 if (strcmp(id,"B16BBDz") != 0) {
973 return False;
975 break;
976 default:
977 return False;
979 return True;
982 struct srv_info_struct {
983 fstring name;
984 uint32 type;
985 fstring comment;
986 fstring domain;
987 BOOL server_added;
990 /*******************************************************************
991 Get server info lists from the files saved by nmbd. Return the
992 number of entries.
993 ******************************************************************/
995 static int get_server_info(uint32 servertype,
996 struct srv_info_struct **servers,
997 const char *domain)
999 int count=0;
1000 int alloced=0;
1001 char **lines;
1002 BOOL local_list_only;
1003 int i;
1005 lines = file_lines_load(lock_path(SERVER_LIST), NULL);
1006 if (!lines) {
1007 DEBUG(4,("Can't open %s - %s\n",lock_path(SERVER_LIST),strerror(errno)));
1008 return(0);
1011 /* request for everything is code for request all servers */
1012 if (servertype == SV_TYPE_ALL)
1013 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1015 local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY);
1017 DEBUG(4,("Servertype search: %8x\n",servertype));
1019 for (i=0;lines[i];i++) {
1020 fstring stype;
1021 struct srv_info_struct *s;
1022 const char *ptr = lines[i];
1023 BOOL ok = True;
1025 if (!*ptr) continue;
1027 if (count == alloced) {
1028 struct srv_info_struct *ts;
1030 alloced += 10;
1031 ts = SMB_REALLOC_ARRAY(*servers,struct srv_info_struct, alloced);
1032 if (!ts) {
1033 DEBUG(0,("get_server_info: failed to enlarge servers info struct!\n"));
1034 return(0);
1036 else *servers = ts;
1037 memset((char *)((*servers)+count),'\0',sizeof(**servers)*(alloced-count));
1039 s = &(*servers)[count];
1041 if (!next_token(&ptr,s->name , NULL, sizeof(s->name))) continue;
1042 if (!next_token(&ptr,stype , NULL, sizeof(stype))) continue;
1043 if (!next_token(&ptr,s->comment, NULL, sizeof(s->comment))) continue;
1044 if (!next_token(&ptr,s->domain , NULL, sizeof(s->domain))) {
1045 /* this allows us to cope with an old nmbd */
1046 fstrcpy(s->domain,lp_workgroup());
1049 if (sscanf(stype,"%X",&s->type) != 1) {
1050 DEBUG(4,("r:host file "));
1051 ok = False;
1054 /* Filter the servers/domains we return based on what was asked for. */
1056 /* Check to see if we are being asked for a local list only. */
1057 if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) {
1058 DEBUG(4,("r: local list only"));
1059 ok = False;
1062 /* doesn't match up: don't want it */
1063 if (!(servertype & s->type)) {
1064 DEBUG(4,("r:serv type "));
1065 ok = False;
1068 if ((servertype & SV_TYPE_DOMAIN_ENUM) !=
1069 (s->type & SV_TYPE_DOMAIN_ENUM))
1071 DEBUG(4,("s: dom mismatch "));
1072 ok = False;
1075 if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM))
1077 ok = False;
1080 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1081 s->type &= ~SV_TYPE_LOCAL_LIST_ONLY;
1083 if (ok)
1085 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1086 s->name, s->type, s->comment, s->domain));
1088 s->server_added = True;
1089 count++;
1091 else
1093 DEBUG(4,("%20s %8x %25s %15s\n",
1094 s->name, s->type, s->comment, s->domain));
1098 file_lines_free(lines);
1099 return(count);
1102 /*******************************************************************
1103 Fill in a server info structure.
1104 ******************************************************************/
1106 static int fill_srv_info(struct srv_info_struct *service,
1107 int uLevel, char **buf, int *buflen,
1108 char **stringbuf, int *stringspace, char *baseaddr)
1110 int struct_len;
1111 char* p;
1112 char* p2;
1113 int l2;
1114 int len;
1116 switch (uLevel) {
1117 case 0: struct_len = 16; break;
1118 case 1: struct_len = 26; break;
1119 default: return -1;
1122 if (!buf)
1124 len = 0;
1125 switch (uLevel)
1127 case 1:
1128 len = strlen(service->comment)+1;
1129 break;
1132 if (buflen) *buflen = struct_len;
1133 if (stringspace) *stringspace = len;
1134 return struct_len + len;
1137 len = struct_len;
1138 p = *buf;
1139 if (*buflen < struct_len) return -1;
1140 if (stringbuf)
1142 p2 = *stringbuf;
1143 l2 = *stringspace;
1145 else
1147 p2 = p + struct_len;
1148 l2 = *buflen - struct_len;
1150 if (!baseaddr) baseaddr = p;
1152 switch (uLevel)
1154 case 0:
1155 push_ascii(p,service->name, MAX_NETBIOSNAME_LEN, STR_TERMINATE);
1156 break;
1158 case 1:
1159 push_ascii(p,service->name,MAX_NETBIOSNAME_LEN, STR_TERMINATE);
1160 SIVAL(p,18,service->type);
1161 SIVAL(p,22,PTR_DIFF(p2,baseaddr));
1162 len += CopyAndAdvance(&p2,service->comment,&l2);
1163 break;
1166 if (stringbuf)
1168 *buf = p + struct_len;
1169 *buflen -= struct_len;
1170 *stringbuf = p2;
1171 *stringspace = l2;
1173 else
1175 *buf = p2;
1176 *buflen -= len;
1178 return len;
1182 static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
1184 return(strcmp(s1->name,s2->name));
1187 /****************************************************************************
1188 View list of servers available (or possibly domains). The info is
1189 extracted from lists saved by nmbd on the local host.
1190 ****************************************************************************/
1192 static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid, char *param, char *data,
1193 int mdrcnt, int mprcnt, char **rdata,
1194 char **rparam, int *rdata_len, int *rparam_len)
1196 char *str1 = param+2;
1197 char *str2 = skip_string(str1,1);
1198 char *p = skip_string(str2,1);
1199 int uLevel = SVAL(p,0);
1200 int buf_len = SVAL(p,2);
1201 uint32 servertype = IVAL(p,4);
1202 char *p2;
1203 int data_len, fixed_len, string_len;
1204 int f_len = 0, s_len = 0;
1205 struct srv_info_struct *servers=NULL;
1206 int counted=0,total=0;
1207 int i,missed;
1208 fstring domain;
1209 BOOL domain_request;
1210 BOOL local_request;
1212 /* If someone sets all the bits they don't really mean to set
1213 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1214 known servers. */
1216 if (servertype == SV_TYPE_ALL)
1217 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1219 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1220 any other bit (they may just set this bit on it's own) they
1221 want all the locally seen servers. However this bit can be
1222 set on its own so set the requested servers to be
1223 ALL - DOMAIN_ENUM. */
1225 if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM))
1226 servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
1228 domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
1229 local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
1231 p += 8;
1233 if (!prefix_ok(str1,"WrLehD")) return False;
1234 if (!check_server_info(uLevel,str2)) return False;
1236 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1237 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1238 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1240 if (strcmp(str1, "WrLehDz") == 0) {
1241 pull_ascii_fstring(domain, p);
1242 } else {
1243 fstrcpy(domain, lp_workgroup());
1246 if (lp_browse_list())
1247 total = get_server_info(servertype,&servers,domain);
1249 data_len = fixed_len = string_len = 0;
1250 missed = 0;
1252 if (total > 0)
1253 qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
1256 char *lastname=NULL;
1258 for (i=0;i<total;i++)
1260 struct srv_info_struct *s = &servers[i];
1261 if (lastname && strequal(lastname,s->name)) continue;
1262 lastname = s->name;
1263 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1264 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1265 s->name, s->type, s->comment, s->domain));
1267 if (data_len <= buf_len) {
1268 counted++;
1269 fixed_len += f_len;
1270 string_len += s_len;
1271 } else {
1272 missed++;
1277 *rdata_len = fixed_len + string_len;
1278 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
1279 memset(*rdata,'\0',*rdata_len);
1281 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1282 p = *rdata;
1283 f_len = fixed_len;
1284 s_len = string_len;
1287 char *lastname=NULL;
1288 int count2 = counted;
1289 for (i = 0; i < total && count2;i++)
1291 struct srv_info_struct *s = &servers[i];
1292 if (lastname && strequal(lastname,s->name)) continue;
1293 lastname = s->name;
1294 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1295 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1296 s->name, s->type, s->comment, s->domain));
1297 count2--;
1301 *rparam_len = 8;
1302 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1303 SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata));
1304 SSVAL(*rparam,2,0);
1305 SSVAL(*rparam,4,counted);
1306 SSVAL(*rparam,6,counted+missed);
1308 SAFE_FREE(servers);
1310 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1311 domain,uLevel,counted,counted+missed));
1313 return(True);
1316 /****************************************************************************
1317 command 0x34 - suspected of being a "Lookup Names" stub api
1318 ****************************************************************************/
1320 static BOOL api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid, char *param, char *data,
1321 int mdrcnt, int mprcnt, char **rdata,
1322 char **rparam, int *rdata_len, int *rparam_len)
1324 char *str1 = param+2;
1325 char *str2 = skip_string(str1,1);
1326 char *p = skip_string(str2,1);
1327 int uLevel = SVAL(p,0);
1328 int buf_len = SVAL(p,2);
1329 int counted=0;
1330 int missed=0;
1332 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1333 str1, str2, p, uLevel, buf_len));
1335 if (!prefix_ok(str1,"zWrLeh")) return False;
1337 *rdata_len = 0;
1339 *rparam_len = 8;
1340 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1342 SSVAL(*rparam,0,0x08AC); /* informational warning message */
1343 SSVAL(*rparam,2,0);
1344 SSVAL(*rparam,4,counted);
1345 SSVAL(*rparam,6,counted+missed);
1347 return(True);
1350 /****************************************************************************
1351 get info about a share
1352 ****************************************************************************/
1354 static BOOL check_share_info(int uLevel, char* id)
1356 switch( uLevel ) {
1357 case 0:
1358 if (strcmp(id,"B13") != 0) return False;
1359 break;
1360 case 1:
1361 if (strcmp(id,"B13BWz") != 0) return False;
1362 break;
1363 case 2:
1364 if (strcmp(id,"B13BWzWWWzB9B") != 0) return False;
1365 break;
1366 case 91:
1367 if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) return False;
1368 break;
1369 default: return False;
1371 return True;
1374 static int fill_share_info(connection_struct *conn, int snum, int uLevel,
1375 char** buf, int* buflen,
1376 char** stringbuf, int* stringspace, char* baseaddr)
1378 int struct_len;
1379 char* p;
1380 char* p2;
1381 int l2;
1382 int len;
1384 switch( uLevel ) {
1385 case 0: struct_len = 13; break;
1386 case 1: struct_len = 20; break;
1387 case 2: struct_len = 40; break;
1388 case 91: struct_len = 68; break;
1389 default: return -1;
1393 if (!buf)
1395 len = 0;
1396 if (uLevel > 0) len += StrlenExpanded(conn,snum,lp_comment(snum));
1397 if (uLevel > 1) len += strlen(lp_pathname(snum)) + 1;
1398 if (buflen) *buflen = struct_len;
1399 if (stringspace) *stringspace = len;
1400 return struct_len + len;
1403 len = struct_len;
1404 p = *buf;
1405 if ((*buflen) < struct_len) return -1;
1406 if (stringbuf)
1408 p2 = *stringbuf;
1409 l2 = *stringspace;
1411 else
1413 p2 = p + struct_len;
1414 l2 = (*buflen) - struct_len;
1416 if (!baseaddr) baseaddr = p;
1418 push_ascii(p,lp_servicename(snum),13, STR_TERMINATE);
1420 if (uLevel > 0)
1422 int type;
1423 SCVAL(p,13,0);
1424 type = STYPE_DISKTREE;
1425 if (lp_print_ok(snum)) type = STYPE_PRINTQ;
1426 if (strequal("IPC",lp_fstype(snum))) type = STYPE_IPC;
1427 SSVAL(p,14,type); /* device type */
1428 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1429 len += CopyExpanded(conn,snum,&p2,lp_comment(snum),&l2);
1432 if (uLevel > 1)
1434 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1435 SSVALS(p,22,-1); /* max uses */
1436 SSVAL(p,24,1); /* current uses */
1437 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1438 len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1439 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1442 if (uLevel > 2)
1444 memset(p+40,0,SHPWLEN+2);
1445 SSVAL(p,50,0);
1446 SIVAL(p,52,0);
1447 SSVAL(p,56,0);
1448 SSVAL(p,58,0);
1449 SIVAL(p,60,0);
1450 SSVAL(p,64,0);
1451 SSVAL(p,66,0);
1454 if (stringbuf)
1456 (*buf) = p + struct_len;
1457 (*buflen) -= struct_len;
1458 (*stringbuf) = p2;
1459 (*stringspace) = l2;
1461 else
1463 (*buf) = p2;
1464 (*buflen) -= len;
1466 return len;
1469 static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
1470 int mdrcnt,int mprcnt,
1471 char **rdata,char **rparam,
1472 int *rdata_len,int *rparam_len)
1474 char *str1 = param+2;
1475 char *str2 = skip_string(str1,1);
1476 char *netname = skip_string(str2,1);
1477 char *p = skip_string(netname,1);
1478 int uLevel = SVAL(p,0);
1479 int snum = find_service(netname);
1481 if (snum < 0) return False;
1483 /* check it's a supported varient */
1484 if (!prefix_ok(str1,"zWrLh")) return False;
1485 if (!check_share_info(uLevel,str2)) return False;
1487 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
1488 p = *rdata;
1489 *rdata_len = fill_share_info(conn,snum,uLevel,&p,&mdrcnt,0,0,0);
1490 if (*rdata_len < 0) return False;
1492 *rparam_len = 6;
1493 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1494 SSVAL(*rparam,0,NERR_Success);
1495 SSVAL(*rparam,2,0); /* converter word */
1496 SSVAL(*rparam,4,*rdata_len);
1498 return(True);
1501 /****************************************************************************
1502 View the list of available shares.
1504 This function is the server side of the NetShareEnum() RAP call.
1505 It fills the return buffer with share names and share comments.
1506 Note that the return buffer normally (in all known cases) allows only
1507 twelve byte strings for share names (plus one for a nul terminator).
1508 Share names longer than 12 bytes must be skipped.
1509 ****************************************************************************/
1511 static BOOL api_RNetShareEnum( connection_struct *conn,
1512 uint16 vuid,
1513 char *param,
1514 char *data,
1515 int mdrcnt,
1516 int mprcnt,
1517 char **rdata,
1518 char **rparam,
1519 int *rdata_len,
1520 int *rparam_len )
1522 char *str1 = param+2;
1523 char *str2 = skip_string(str1,1);
1524 char *p = skip_string(str2,1);
1525 int uLevel = SVAL(p,0);
1526 int buf_len = SVAL(p,2);
1527 char *p2;
1528 int count=lp_numservices();
1529 int total=0,counted=0;
1530 BOOL missed = False;
1531 int i;
1532 int data_len, fixed_len, string_len;
1533 int f_len = 0, s_len = 0;
1535 if (!prefix_ok(str1,"WrLeh")) return False;
1536 if (!check_share_info(uLevel,str2)) return False;
1538 data_len = fixed_len = string_len = 0;
1539 for (i=0;i<count;i++) {
1540 fstring servicename_dos;
1541 if (!(lp_browseable(i) && lp_snum_ok(i)))
1542 continue;
1543 push_ascii_fstring(servicename_dos, lp_servicename(i));
1544 if( lp_browseable( i )
1545 && lp_snum_ok( i )
1546 && (strlen(servicename_dos) < 13) ) /* Maximum name length. */
1548 total++;
1549 data_len += fill_share_info(conn,i,uLevel,0,&f_len,0,&s_len,0);
1550 if (data_len <= buf_len)
1552 counted++;
1553 fixed_len += f_len;
1554 string_len += s_len;
1556 else
1557 missed = True;
1560 *rdata_len = fixed_len + string_len;
1561 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
1562 memset(*rdata,0,*rdata_len);
1564 p2 = (*rdata) + fixed_len; /* auxiliary data (strings) will go here */
1565 p = *rdata;
1566 f_len = fixed_len;
1567 s_len = string_len;
1568 for( i = 0; i < count; i++ )
1570 fstring servicename_dos;
1571 if (!(lp_browseable(i) && lp_snum_ok(i)))
1572 continue;
1573 push_ascii_fstring(servicename_dos, lp_servicename(i));
1574 if( lp_browseable( i )
1575 && lp_snum_ok( i )
1576 && (strlen(servicename_dos) < 13) )
1578 if( fill_share_info( conn,i,uLevel,&p,&f_len,&p2,&s_len,*rdata ) < 0 )
1579 break;
1583 *rparam_len = 8;
1584 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1585 SSVAL(*rparam,0,missed ? ERRmoredata : NERR_Success);
1586 SSVAL(*rparam,2,0);
1587 SSVAL(*rparam,4,counted);
1588 SSVAL(*rparam,6,total);
1590 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1591 counted,total,uLevel,
1592 buf_len,*rdata_len,mdrcnt));
1593 return(True);
1596 /****************************************************************************
1597 Add a share
1598 ****************************************************************************/
1600 static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid, char *param,char *data,
1601 int mdrcnt,int mprcnt,
1602 char **rdata,char **rparam,
1603 int *rdata_len,int *rparam_len)
1605 char *str1 = param+2;
1606 char *str2 = skip_string(str1,1);
1607 char *p = skip_string(str2,1);
1608 int uLevel = SVAL(p,0);
1609 fstring sharename;
1610 fstring comment;
1611 pstring pathname;
1612 char *command, *cmdname;
1613 unsigned int offset;
1614 int snum;
1615 int res = ERRunsup;
1617 /* check it's a supported varient */
1618 if (!prefix_ok(str1,RAP_WShareAdd_REQ)) return False;
1619 if (!check_share_info(uLevel,str2)) return False;
1620 if (uLevel != 2) return False;
1622 pull_ascii_fstring(sharename,data);
1623 snum = find_service(sharename);
1624 if (snum >= 0) { /* already exists */
1625 res = ERRfilexists;
1626 goto error_exit;
1629 /* only support disk share adds */
1630 if (SVAL(data,14)!=STYPE_DISKTREE) return False;
1632 offset = IVAL(data, 16);
1633 if (offset >= mdrcnt) {
1634 res = ERRinvalidparam;
1635 goto error_exit;
1637 pull_ascii_fstring(comment, offset? (data+offset) : "");
1639 offset = IVAL(data, 26);
1640 if (offset >= mdrcnt) {
1641 res = ERRinvalidparam;
1642 goto error_exit;
1644 pull_ascii_pstring(pathname, offset? (data+offset) : "");
1646 string_replace(sharename, '"', ' ');
1647 string_replace(pathname, '"', ' ');
1648 string_replace(comment, '"', ' ');
1650 cmdname = lp_add_share_cmd();
1652 if (!cmdname || *cmdname == '\0') return False;
1654 asprintf(&command, "%s \"%s\" \"%s\" \"%s\" \"%s\"",
1655 lp_add_share_cmd(), dyn_CONFIGFILE, sharename, pathname, comment);
1657 if (command) {
1658 DEBUG(10,("api_RNetShareAdd: Running [%s]\n", command ));
1659 if ((res = smbrun(command, NULL)) != 0) {
1660 DEBUG(1,("api_RNetShareAdd: Running [%s] returned (%d)\n", command, res ));
1661 SAFE_FREE(command);
1662 res = ERRnoaccess;
1663 goto error_exit;
1664 } else {
1665 SAFE_FREE(command);
1666 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
1668 } else return False;
1670 *rparam_len = 6;
1671 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1672 SSVAL(*rparam,0,NERR_Success);
1673 SSVAL(*rparam,2,0); /* converter word */
1674 SSVAL(*rparam,4,*rdata_len);
1675 *rdata_len = 0;
1677 return True;
1679 error_exit:
1680 *rparam_len = 4;
1681 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1682 *rdata_len = 0;
1683 SSVAL(*rparam,0,res);
1684 SSVAL(*rparam,2,0);
1685 return True;
1688 /****************************************************************************
1689 view list of groups available
1690 ****************************************************************************/
1692 static BOOL api_RNetGroupEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
1693 int mdrcnt,int mprcnt,
1694 char **rdata,char **rparam,
1695 int *rdata_len,int *rparam_len)
1697 int i;
1698 int errflags=0;
1699 int resume_context, cli_buf_size;
1700 char *str1 = param+2;
1701 char *str2 = skip_string(str1,1);
1702 char *p = skip_string(str2,1);
1704 struct pdb_search *search;
1705 struct samr_displayentry *entries;
1707 int num_entries;
1709 if (strcmp(str1,"WrLeh") != 0)
1710 return False;
1712 /* parameters
1713 * W-> resume context (number of users to skip)
1714 * r -> return parameter pointer to receive buffer
1715 * L -> length of receive buffer
1716 * e -> return parameter number of entries
1717 * h -> return parameter total number of users
1719 if (strcmp("B21",str2) != 0)
1720 return False;
1722 /* get list of domain groups SID_DOMAIN_GRP=2 */
1723 become_root();
1724 search = pdb_search_groups();
1725 unbecome_root();
1727 if (search == NULL) {
1728 DEBUG(3,("api_RNetGroupEnum:failed to get group list"));
1729 return False;
1732 resume_context = SVAL(p,0);
1733 cli_buf_size=SVAL(p+2,0);
1734 DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: "
1735 "%d\n", resume_context, cli_buf_size));
1737 become_root();
1738 num_entries = pdb_search_entries(search, resume_context, 0xffffffff,
1739 &entries);
1740 unbecome_root();
1742 *rdata_len = cli_buf_size;
1743 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
1745 p = *rdata;
1747 for(i=0; i<num_entries; i++) {
1748 fstring name;
1749 fstrcpy(name, entries[i].account_name);
1750 if( ((PTR_DIFF(p,*rdata)+21) <= *rdata_len) ) {
1751 /* truncate the name at 21 chars. */
1752 memcpy(p, name, 21);
1753 DEBUG(10,("adding entry %d group %s\n", i, p));
1754 p += 21;
1755 p += 5; /* Both NT4 and W2k3SP1 do padding here.
1756 No idea why... */
1757 } else {
1758 /* set overflow error */
1759 DEBUG(3,("overflow on entry %d group %s\n", i, name));
1760 errflags=234;
1761 break;
1765 pdb_search_destroy(search);
1767 *rdata_len = PTR_DIFF(p,*rdata);
1769 *rparam_len = 8;
1770 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1772 SSVAL(*rparam, 0, errflags);
1773 SSVAL(*rparam, 2, 0); /* converter word */
1774 SSVAL(*rparam, 4, i); /* is this right?? */
1775 SSVAL(*rparam, 6, resume_context+num_entries); /* is this right?? */
1777 return(True);
1780 /*******************************************************************
1781 Get groups that a user is a member of.
1782 ******************************************************************/
1784 static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *param,char *data,
1785 int mdrcnt,int mprcnt,
1786 char **rdata,char **rparam,
1787 int *rdata_len,int *rparam_len)
1789 char *str1 = param+2;
1790 char *str2 = skip_string(str1,1);
1791 char *UserName = skip_string(str2,1);
1792 char *p = skip_string(UserName,1);
1793 int uLevel = SVAL(p,0);
1794 const char *level_string;
1795 int count=0;
1796 SAM_ACCOUNT *sampw = NULL;
1797 BOOL ret = False;
1798 DOM_SID *sids;
1799 gid_t *gids;
1800 size_t num_groups;
1801 size_t i;
1802 fstring grp_domain;
1803 fstring grp_name;
1804 enum SID_NAME_USE grp_type;
1805 struct passwd *passwd;
1806 NTSTATUS result;
1808 *rparam_len = 8;
1809 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1811 /* check it's a supported varient */
1813 if ( strcmp(str1,"zWrLeh") != 0 )
1814 return False;
1816 switch( uLevel ) {
1817 case 0:
1818 level_string = "B21";
1819 break;
1820 default:
1821 return False;
1824 if (strcmp(level_string,str2) != 0)
1825 return False;
1827 *rdata_len = mdrcnt + 1024;
1828 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
1830 SSVAL(*rparam,0,NERR_Success);
1831 SSVAL(*rparam,2,0); /* converter word */
1833 p = *rdata;
1835 /* Lookup the user information; This should only be one of
1836 our accounts (not remote domains) */
1838 passwd = getpwnam_alloc(UserName);
1840 if (passwd == NULL)
1841 return False;
1843 pdb_init_sam( &sampw );
1845 become_root(); /* ROOT BLOCK */
1847 if ( !pdb_getsampwnam(sampw, UserName) )
1848 goto out;
1850 sids = NULL;
1851 num_groups = 0;
1853 result = pdb_enum_group_memberships(pdb_get_username(sampw),
1854 passwd->pw_gid,
1855 &sids, &gids, &num_groups);
1857 if (!NT_STATUS_IS_OK(result))
1858 goto out;
1860 for (i=0; i<num_groups; i++) {
1862 if ( lookup_sid(&sids[i], grp_domain, grp_name, &grp_type) ) {
1863 pstrcpy(p, grp_name);
1864 p += 21;
1865 count++;
1869 SAFE_FREE(sids);
1871 *rdata_len = PTR_DIFF(p,*rdata);
1873 SSVAL(*rparam,4,count); /* is this right?? */
1874 SSVAL(*rparam,6,count); /* is this right?? */
1876 ret = True;
1878 out:
1879 unbecome_root(); /* END ROOT BLOCK */
1881 pdb_free_sam( &sampw );
1882 passwd_free(&passwd);
1884 return ret;
1887 /*******************************************************************
1888 Get all users.
1889 ******************************************************************/
1891 static BOOL api_RNetUserEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
1892 int mdrcnt,int mprcnt,
1893 char **rdata,char **rparam,
1894 int *rdata_len,int *rparam_len)
1896 int count_sent=0;
1897 int num_users=0;
1898 int errflags=0;
1899 int i, resume_context, cli_buf_size;
1900 struct pdb_search *search;
1901 struct samr_displayentry *users;
1903 char *str1 = param+2;
1904 char *str2 = skip_string(str1,1);
1905 char *p = skip_string(str2,1);
1907 if (strcmp(str1,"WrLeh") != 0)
1908 return False;
1909 /* parameters
1910 * W-> resume context (number of users to skip)
1911 * r -> return parameter pointer to receive buffer
1912 * L -> length of receive buffer
1913 * e -> return parameter number of entries
1914 * h -> return parameter total number of users
1917 resume_context = SVAL(p,0);
1918 cli_buf_size=SVAL(p+2,0);
1919 DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n",
1920 resume_context, cli_buf_size));
1922 *rparam_len = 8;
1923 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1925 /* check it's a supported varient */
1926 if (strcmp("B21",str2) != 0)
1927 return False;
1929 *rdata_len = cli_buf_size;
1930 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
1932 p = *rdata;
1934 become_root();
1935 search = pdb_search_users(ACB_NORMAL);
1936 unbecome_root();
1937 if (search == NULL) {
1938 DEBUG(0, ("api_RNetUserEnum:unable to open sam database.\n"));
1939 return False;
1942 become_root();
1943 num_users = pdb_search_entries(search, resume_context, 0xffffffff,
1944 &users);
1945 unbecome_root();
1947 errflags=NERR_Success;
1949 for (i=0; i<num_users; i++) {
1950 const char *name = users[i].account_name;
1952 if(((PTR_DIFF(p,*rdata)+21)<=*rdata_len)&&(strlen(name)<=21)) {
1953 pstrcpy(p,name);
1954 DEBUG(10,("api_RNetUserEnum:adding entry %d username "
1955 "%s\n",count_sent,p));
1956 p += 21;
1957 count_sent++;
1958 } else {
1959 /* set overflow error */
1960 DEBUG(10,("api_RNetUserEnum:overflow on entry %d "
1961 "username %s\n",count_sent,name));
1962 errflags=234;
1963 break;
1967 pdb_search_destroy(search);
1969 *rdata_len = PTR_DIFF(p,*rdata);
1971 SSVAL(*rparam,0,errflags);
1972 SSVAL(*rparam,2,0); /* converter word */
1973 SSVAL(*rparam,4,count_sent); /* is this right?? */
1974 SSVAL(*rparam,6,num_users); /* is this right?? */
1976 return True;
1979 /****************************************************************************
1980 Get the time of day info.
1981 ****************************************************************************/
1983 static BOOL api_NetRemoteTOD(connection_struct *conn,uint16 vuid, char *param,char *data,
1984 int mdrcnt,int mprcnt,
1985 char **rdata,char **rparam,
1986 int *rdata_len,int *rparam_len)
1988 char *p;
1989 *rparam_len = 4;
1990 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1992 *rdata_len = 21;
1993 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
1995 SSVAL(*rparam,0,NERR_Success);
1996 SSVAL(*rparam,2,0); /* converter word */
1998 p = *rdata;
2001 struct tm *t;
2002 time_t unixdate = time(NULL);
2004 put_dos_date3(p,0,unixdate); /* this is the time that is looked at
2005 by NT in a "net time" operation,
2006 it seems to ignore the one below */
2008 /* the client expects to get localtime, not GMT, in this bit
2009 (I think, this needs testing) */
2010 t = LocalTime(&unixdate);
2012 SIVAL(p,4,0); /* msecs ? */
2013 SCVAL(p,8,t->tm_hour);
2014 SCVAL(p,9,t->tm_min);
2015 SCVAL(p,10,t->tm_sec);
2016 SCVAL(p,11,0); /* hundredths of seconds */
2017 SSVALS(p,12,TimeDiff(unixdate)/60); /* timezone in minutes from GMT */
2018 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
2019 SCVAL(p,16,t->tm_mday);
2020 SCVAL(p,17,t->tm_mon + 1);
2021 SSVAL(p,18,1900+t->tm_year);
2022 SCVAL(p,20,t->tm_wday);
2024 return(True);
2027 /****************************************************************************
2028 Set the user password.
2029 *****************************************************************************/
2031 static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param,char *data,
2032 int mdrcnt,int mprcnt,
2033 char **rdata,char **rparam,
2034 int *rdata_len,int *rparam_len)
2036 char *p = skip_string(param+2,2);
2037 fstring user;
2038 fstring pass1,pass2;
2040 pull_ascii_fstring(user,p);
2042 p = skip_string(p,1);
2044 memset(pass1,'\0',sizeof(pass1));
2045 memset(pass2,'\0',sizeof(pass2));
2046 memcpy(pass1,p,16);
2047 memcpy(pass2,p+16,16);
2049 *rparam_len = 4;
2050 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2052 *rdata_len = 0;
2054 SSVAL(*rparam,0,NERR_badpass);
2055 SSVAL(*rparam,2,0); /* converter word */
2057 DEBUG(3,("Set password for <%s>\n",user));
2060 * Attempt to verify the old password against smbpasswd entries
2061 * Win98 clients send old and new password in plaintext for this call.
2065 auth_serversupplied_info *server_info = NULL;
2066 DATA_BLOB password = data_blob(pass1, strlen(pass1)+1);
2068 if (NT_STATUS_IS_OK(check_plaintext_password(user,password,&server_info))) {
2070 become_root();
2071 if (NT_STATUS_IS_OK(change_oem_password(server_info->sam_account, pass1, pass2, False))) {
2072 SSVAL(*rparam,0,NERR_Success);
2074 unbecome_root();
2076 free_server_info(&server_info);
2078 data_blob_clear_free(&password);
2082 * If the plaintext change failed, attempt
2083 * the old encrypted method. NT will generate this
2084 * after trying the samr method. Note that this
2085 * method is done as a last resort as this
2086 * password change method loses the NT password hash
2087 * and cannot change the UNIX password as no plaintext
2088 * is received.
2091 if(SVAL(*rparam,0) != NERR_Success) {
2092 SAM_ACCOUNT *hnd = NULL;
2094 if (check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &hnd)) {
2095 become_root();
2096 if (change_lanman_password(hnd,(uchar *)pass2)) {
2097 SSVAL(*rparam,0,NERR_Success);
2099 unbecome_root();
2100 pdb_free_sam(&hnd);
2104 memset((char *)pass1,'\0',sizeof(fstring));
2105 memset((char *)pass2,'\0',sizeof(fstring));
2107 return(True);
2110 /****************************************************************************
2111 Set the user password (SamOEM version - gets plaintext).
2112 ****************************************************************************/
2114 static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char *param,char *data,
2115 int mdrcnt,int mprcnt,
2116 char **rdata,char **rparam,
2117 int *rdata_len,int *rparam_len)
2119 fstring user;
2120 char *p = param + 2;
2121 *rparam_len = 2;
2122 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2124 *rdata_len = 0;
2126 SSVAL(*rparam,0,NERR_badpass);
2129 * Check the parameter definition is correct.
2132 if(!strequal(param + 2, "zsT")) {
2133 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", param + 2));
2134 return False;
2136 p = skip_string(p, 1);
2138 if(!strequal(p, "B516B16")) {
2139 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p));
2140 return False;
2142 p = skip_string(p,1);
2143 p += pull_ascii_fstring(user,p);
2145 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user));
2148 * Pass the user through the NT -> unix user mapping
2149 * function.
2152 (void)map_username(user);
2154 if (NT_STATUS_IS_OK(pass_oem_change(user, (uchar*) data, (uchar *)&data[516], NULL, NULL))) {
2155 SSVAL(*rparam,0,NERR_Success);
2158 return(True);
2161 /****************************************************************************
2162 delete a print job
2163 Form: <W> <>
2164 ****************************************************************************/
2166 static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char *param,char *data,
2167 int mdrcnt,int mprcnt,
2168 char **rdata,char **rparam,
2169 int *rdata_len,int *rparam_len)
2171 int function = SVAL(param,0);
2172 char *str1 = param+2;
2173 char *str2 = skip_string(str1,1);
2174 char *p = skip_string(str2,1);
2175 uint32 jobid;
2176 int snum;
2177 fstring sharename;
2178 int errcode;
2179 WERROR werr = WERR_OK;
2181 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
2182 return False;
2184 /* check it's a supported varient */
2185 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
2186 return(False);
2188 *rparam_len = 4;
2189 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2190 *rdata_len = 0;
2192 if (!print_job_exists(sharename, jobid)) {
2193 errcode = NERR_JobNotFound;
2194 goto out;
2197 snum = lp_servicenumber( sharename);
2198 if (snum == -1) {
2199 errcode = NERR_DestNotFound;
2200 goto out;
2203 errcode = NERR_notsupported;
2205 switch (function) {
2206 case 81: /* delete */
2207 if (print_job_delete(&current_user, snum, jobid, &werr))
2208 errcode = NERR_Success;
2209 break;
2210 case 82: /* pause */
2211 if (print_job_pause(&current_user, snum, jobid, &werr))
2212 errcode = NERR_Success;
2213 break;
2214 case 83: /* resume */
2215 if (print_job_resume(&current_user, snum, jobid, &werr))
2216 errcode = NERR_Success;
2217 break;
2220 if (!W_ERROR_IS_OK(werr))
2221 errcode = W_ERROR_V(werr);
2223 out:
2224 SSVAL(*rparam,0,errcode);
2225 SSVAL(*rparam,2,0); /* converter word */
2227 return(True);
2230 /****************************************************************************
2231 Purge a print queue - or pause or resume it.
2232 ****************************************************************************/
2234 static BOOL api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid, char *param,char *data,
2235 int mdrcnt,int mprcnt,
2236 char **rdata,char **rparam,
2237 int *rdata_len,int *rparam_len)
2239 int function = SVAL(param,0);
2240 char *str1 = param+2;
2241 char *str2 = skip_string(str1,1);
2242 char *QueueName = skip_string(str2,1);
2243 int errcode = NERR_notsupported;
2244 int snum;
2245 WERROR werr = WERR_OK;
2247 /* check it's a supported varient */
2248 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
2249 return(False);
2251 *rparam_len = 4;
2252 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2253 *rdata_len = 0;
2255 snum = print_queue_snum(QueueName);
2257 if (snum == -1) {
2258 errcode = NERR_JobNotFound;
2259 goto out;
2262 switch (function) {
2263 case 74: /* Pause queue */
2264 if (print_queue_pause(&current_user, snum, &werr)) errcode = NERR_Success;
2265 break;
2266 case 75: /* Resume queue */
2267 if (print_queue_resume(&current_user, snum, &werr)) errcode = NERR_Success;
2268 break;
2269 case 103: /* Purge */
2270 if (print_queue_purge(&current_user, snum, &werr)) errcode = NERR_Success;
2271 break;
2274 if (!W_ERROR_IS_OK(werr)) errcode = W_ERROR_V(werr);
2276 out:
2277 SSVAL(*rparam,0,errcode);
2278 SSVAL(*rparam,2,0); /* converter word */
2280 return(True);
2283 /****************************************************************************
2284 set the property of a print job (undocumented?)
2285 ? function = 0xb -> set name of print job
2286 ? function = 0x6 -> move print job up/down
2287 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
2288 or <WWsTP> <WB21BB16B10zWWzDDz>
2289 ****************************************************************************/
2291 static int check_printjob_info(struct pack_desc* desc,
2292 int uLevel, char* id)
2294 desc->subformat = NULL;
2295 switch( uLevel ) {
2296 case 0: desc->format = "W"; break;
2297 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
2298 case 2: desc->format = "WWzWWDDzz"; break;
2299 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
2300 case 4: desc->format = "WWzWWDDzzzzzDDDDDDD"; break;
2301 default: return False;
2303 if (strcmp(desc->format,id) != 0) return False;
2304 return True;
2307 static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,char *data,
2308 int mdrcnt,int mprcnt,
2309 char **rdata,char **rparam,
2310 int *rdata_len,int *rparam_len)
2312 struct pack_desc desc;
2313 char *str1 = param+2;
2314 char *str2 = skip_string(str1,1);
2315 char *p = skip_string(str2,1);
2316 uint32 jobid;
2317 int snum;
2318 fstring sharename;
2319 int uLevel = SVAL(p,2);
2320 int function = SVAL(p,4);
2321 int place, errcode;
2323 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
2324 return False;
2325 *rparam_len = 4;
2326 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2328 if ( (snum = lp_servicenumber(sharename)) == -1 ) {
2329 DEBUG(0,("api_PrintJobInfo: unable to get service number from sharename [%s]\n",
2330 sharename));
2331 return False;
2334 *rdata_len = 0;
2336 /* check it's a supported varient */
2337 if ((strcmp(str1,"WWsTP")) ||
2338 (!check_printjob_info(&desc,uLevel,str2)))
2339 return(False);
2341 if (!print_job_exists(sharename, jobid)) {
2342 errcode=NERR_JobNotFound;
2343 goto out;
2346 errcode = NERR_notsupported;
2348 switch (function) {
2349 case 0x6:
2350 /* change job place in the queue,
2351 data gives the new place */
2352 place = SVAL(data,0);
2353 if (print_job_set_place(snum, jobid, place)) {
2354 errcode=NERR_Success;
2356 break;
2358 case 0xb:
2359 /* change print job name, data gives the name */
2360 if (print_job_set_name(snum, jobid, data)) {
2361 errcode=NERR_Success;
2363 break;
2365 default:
2366 return False;
2369 out:
2370 SSVALS(*rparam,0,errcode);
2371 SSVAL(*rparam,2,0); /* converter word */
2373 return(True);
2377 /****************************************************************************
2378 Get info about the server.
2379 ****************************************************************************/
2381 static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2382 int mdrcnt,int mprcnt,
2383 char **rdata,char **rparam,
2384 int *rdata_len,int *rparam_len)
2386 char *str1 = param+2;
2387 char *str2 = skip_string(str1,1);
2388 char *p = skip_string(str2,1);
2389 int uLevel = SVAL(p,0);
2390 char *p2;
2391 int struct_len;
2393 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
2395 /* check it's a supported varient */
2396 if (!prefix_ok(str1,"WrLh")) return False;
2397 switch( uLevel ) {
2398 case 0:
2399 if (strcmp(str2,"B16") != 0) return False;
2400 struct_len = 16;
2401 break;
2402 case 1:
2403 if (strcmp(str2,"B16BBDz") != 0) return False;
2404 struct_len = 26;
2405 break;
2406 case 2:
2407 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")
2408 != 0) return False;
2409 struct_len = 134;
2410 break;
2411 case 3:
2412 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz")
2413 != 0) return False;
2414 struct_len = 144;
2415 break;
2416 case 20:
2417 if (strcmp(str2,"DN") != 0) return False;
2418 struct_len = 6;
2419 break;
2420 case 50:
2421 if (strcmp(str2,"B16BBDzWWzzz") != 0) return False;
2422 struct_len = 42;
2423 break;
2424 default: return False;
2427 *rdata_len = mdrcnt;
2428 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
2430 p = *rdata;
2431 p2 = p + struct_len;
2432 if (uLevel != 20) {
2433 srvstr_push(NULL, p,get_local_machine_name(),16,
2434 STR_ASCII|STR_UPPER|STR_TERMINATE);
2436 p += 16;
2437 if (uLevel > 0)
2439 struct srv_info_struct *servers=NULL;
2440 int i,count;
2441 pstring comment;
2442 uint32 servertype= lp_default_server_announce();
2444 push_ascii(comment,lp_serverstring(), MAX_SERVER_STRING_LENGTH,STR_TERMINATE);
2446 if ((count=get_server_info(SV_TYPE_ALL,&servers,lp_workgroup()))>0) {
2447 for (i=0;i<count;i++) {
2448 if (strequal(servers[i].name,get_local_machine_name())) {
2449 servertype = servers[i].type;
2450 push_ascii(comment,servers[i].comment,sizeof(pstring),STR_TERMINATE);
2454 SAFE_FREE(servers);
2456 SCVAL(p,0,lp_major_announce_version());
2457 SCVAL(p,1,lp_minor_announce_version());
2458 SIVAL(p,2,servertype);
2460 if (mdrcnt == struct_len) {
2461 SIVAL(p,6,0);
2462 } else {
2463 SIVAL(p,6,PTR_DIFF(p2,*rdata));
2464 standard_sub_conn(conn,comment,sizeof(comment));
2465 StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
2466 p2 = skip_string(p2,1);
2469 if (uLevel > 1)
2471 return False; /* not yet implemented */
2474 *rdata_len = PTR_DIFF(p2,*rdata);
2476 *rparam_len = 6;
2477 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2478 SSVAL(*rparam,0,NERR_Success);
2479 SSVAL(*rparam,2,0); /* converter word */
2480 SSVAL(*rparam,4,*rdata_len);
2482 return(True);
2485 /****************************************************************************
2486 Get info about the server.
2487 ****************************************************************************/
2489 static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2490 int mdrcnt,int mprcnt,
2491 char **rdata,char **rparam,
2492 int *rdata_len,int *rparam_len)
2494 char *str1 = param+2;
2495 char *str2 = skip_string(str1,1);
2496 char *p = skip_string(str2,1);
2497 char *p2;
2498 int level = SVAL(p,0);
2500 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
2502 *rparam_len = 6;
2503 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2505 /* check it's a supported varient */
2506 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz")))
2507 return(False);
2509 *rdata_len = mdrcnt + 1024;
2510 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
2512 SSVAL(*rparam,0,NERR_Success);
2513 SSVAL(*rparam,2,0); /* converter word */
2515 p = *rdata;
2516 p2 = p + 22;
2519 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
2520 pstrcpy(p2,get_local_machine_name());
2521 strupper_m(p2);
2522 p2 = skip_string(p2,1);
2523 p += 4;
2525 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2526 pstrcpy(p2,current_user_info.smb_name);
2527 p2 = skip_string(p2,1);
2528 p += 4;
2530 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
2531 pstrcpy(p2,lp_workgroup());
2532 strupper_m(p2);
2533 p2 = skip_string(p2,1);
2534 p += 4;
2536 SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
2537 SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
2538 p += 2;
2540 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2541 pstrcpy(p2,lp_workgroup()); /* don't know. login domain?? */
2542 p2 = skip_string(p2,1);
2543 p += 4;
2545 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
2546 pstrcpy(p2,"");
2547 p2 = skip_string(p2,1);
2548 p += 4;
2550 *rdata_len = PTR_DIFF(p2,*rdata);
2552 SSVAL(*rparam,4,*rdata_len);
2554 return(True);
2557 /****************************************************************************
2558 get info about a user
2560 struct user_info_11 {
2561 char usri11_name[21]; 0-20
2562 char usri11_pad; 21
2563 char *usri11_comment; 22-25
2564 char *usri11_usr_comment; 26-29
2565 unsigned short usri11_priv; 30-31
2566 unsigned long usri11_auth_flags; 32-35
2567 long usri11_password_age; 36-39
2568 char *usri11_homedir; 40-43
2569 char *usri11_parms; 44-47
2570 long usri11_last_logon; 48-51
2571 long usri11_last_logoff; 52-55
2572 unsigned short usri11_bad_pw_count; 56-57
2573 unsigned short usri11_num_logons; 58-59
2574 char *usri11_logon_server; 60-63
2575 unsigned short usri11_country_code; 64-65
2576 char *usri11_workstations; 66-69
2577 unsigned long usri11_max_storage; 70-73
2578 unsigned short usri11_units_per_week; 74-75
2579 unsigned char *usri11_logon_hours; 76-79
2580 unsigned short usri11_code_page; 80-81
2583 where:
2585 usri11_name specifies the user name for which information is retireved
2587 usri11_pad aligns the next data structure element to a word boundary
2589 usri11_comment is a null terminated ASCII comment
2591 usri11_user_comment is a null terminated ASCII comment about the user
2593 usri11_priv specifies the level of the privilege assigned to the user.
2594 The possible values are:
2596 Name Value Description
2597 USER_PRIV_GUEST 0 Guest privilege
2598 USER_PRIV_USER 1 User privilege
2599 USER_PRV_ADMIN 2 Administrator privilege
2601 usri11_auth_flags specifies the account operator privileges. The
2602 possible values are:
2604 Name Value Description
2605 AF_OP_PRINT 0 Print operator
2608 Leach, Naik [Page 28]
2612 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2615 AF_OP_COMM 1 Communications operator
2616 AF_OP_SERVER 2 Server operator
2617 AF_OP_ACCOUNTS 3 Accounts operator
2620 usri11_password_age specifies how many seconds have elapsed since the
2621 password was last changed.
2623 usri11_home_dir points to a null terminated ASCII string that contains
2624 the path name of the user's home directory.
2626 usri11_parms points to a null terminated ASCII string that is set
2627 aside for use by applications.
2629 usri11_last_logon specifies the time when the user last logged on.
2630 This value is stored as the number of seconds elapsed since
2631 00:00:00, January 1, 1970.
2633 usri11_last_logoff specifies the time when the user last logged off.
2634 This value is stored as the number of seconds elapsed since
2635 00:00:00, January 1, 1970. A value of 0 means the last logoff
2636 time is unknown.
2638 usri11_bad_pw_count specifies the number of incorrect passwords
2639 entered since the last successful logon.
2641 usri11_log1_num_logons specifies the number of times this user has
2642 logged on. A value of -1 means the number of logons is unknown.
2644 usri11_logon_server points to a null terminated ASCII string that
2645 contains the name of the server to which logon requests are sent.
2646 A null string indicates logon requests should be sent to the
2647 domain controller.
2649 usri11_country_code specifies the country code for the user's language
2650 of choice.
2652 usri11_workstations points to a null terminated ASCII string that
2653 contains the names of workstations the user may log on from.
2654 There may be up to 8 workstations, with the names separated by
2655 commas. A null strings indicates there are no restrictions.
2657 usri11_max_storage specifies the maximum amount of disk space the user
2658 can occupy. A value of 0xffffffff indicates there are no
2659 restrictions.
2661 usri11_units_per_week specifies the equal number of time units into
2662 which a week is divided. This value must be equal to 168.
2664 usri11_logon_hours points to a 21 byte (168 bits) string that
2665 specifies the time during which the user can log on. Each bit
2666 represents one unique hour in a week. The first bit (bit 0, word
2667 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
2671 Leach, Naik [Page 29]
2675 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2678 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
2679 are no restrictions.
2681 usri11_code_page specifies the code page for the user's language of
2682 choice
2684 All of the pointers in this data structure need to be treated
2685 specially. The pointer is a 32 bit pointer. The higher 16 bits need
2686 to be ignored. The converter word returned in the parameters section
2687 needs to be subtracted from the lower 16 bits to calculate an offset
2688 into the return buffer where this ASCII string resides.
2690 There is no auxiliary data in the response.
2692 ****************************************************************************/
2694 #define usri11_name 0
2695 #define usri11_pad 21
2696 #define usri11_comment 22
2697 #define usri11_usr_comment 26
2698 #define usri11_full_name 30
2699 #define usri11_priv 34
2700 #define usri11_auth_flags 36
2701 #define usri11_password_age 40
2702 #define usri11_homedir 44
2703 #define usri11_parms 48
2704 #define usri11_last_logon 52
2705 #define usri11_last_logoff 56
2706 #define usri11_bad_pw_count 60
2707 #define usri11_num_logons 62
2708 #define usri11_logon_server 64
2709 #define usri11_country_code 68
2710 #define usri11_workstations 70
2711 #define usri11_max_storage 74
2712 #define usri11_units_per_week 78
2713 #define usri11_logon_hours 80
2714 #define usri11_code_page 84
2715 #define usri11_end 86
2717 #define USER_PRIV_GUEST 0
2718 #define USER_PRIV_USER 1
2719 #define USER_PRIV_ADMIN 2
2721 #define AF_OP_PRINT 0
2722 #define AF_OP_COMM 1
2723 #define AF_OP_SERVER 2
2724 #define AF_OP_ACCOUNTS 3
2727 static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2728 int mdrcnt,int mprcnt,
2729 char **rdata,char **rparam,
2730 int *rdata_len,int *rparam_len)
2732 char *str1 = param+2;
2733 char *str2 = skip_string(str1,1);
2734 char *UserName = skip_string(str2,1);
2735 char *p = skip_string(UserName,1);
2736 int uLevel = SVAL(p,0);
2737 char *p2;
2738 const char *level_string;
2740 /* get NIS home of a previously validated user - simeon */
2741 /* With share level security vuid will always be zero.
2742 Don't depend on vuser being non-null !!. JRA */
2743 user_struct *vuser = get_valid_user_struct(vuid);
2744 if(vuser != NULL)
2745 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid,
2746 vuser->user.unix_name));
2748 *rparam_len = 6;
2749 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2751 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
2753 /* check it's a supported variant */
2754 if (strcmp(str1,"zWrLh") != 0) return False;
2755 switch( uLevel )
2757 case 0: level_string = "B21"; break;
2758 case 1: level_string = "B21BB16DWzzWz"; break;
2759 case 2: level_string = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
2760 case 10: level_string = "B21Bzzz"; break;
2761 case 11: level_string = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
2762 default: return False;
2765 if (strcmp(level_string,str2) != 0) return False;
2767 *rdata_len = mdrcnt + 1024;
2768 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
2770 SSVAL(*rparam,0,NERR_Success);
2771 SSVAL(*rparam,2,0); /* converter word */
2773 p = *rdata;
2774 p2 = p + usri11_end;
2776 memset(p,0,21);
2777 fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
2779 if (uLevel > 0)
2781 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
2782 *p2 = 0;
2784 if (uLevel >= 10)
2786 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
2787 pstrcpy(p2,"Comment");
2788 p2 = skip_string(p2,1);
2790 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
2791 pstrcpy(p2,"UserComment");
2792 p2 = skip_string(p2,1);
2794 /* EEK! the cifsrap.txt doesn't have this in!!!! */
2795 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
2796 pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName));
2797 p2 = skip_string(p2,1);
2800 if (uLevel == 11) /* modelled after NTAS 3.51 reply */
2802 SSVAL(p,usri11_priv,conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2803 SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
2804 SIVALS(p,usri11_password_age,-1); /* password age */
2805 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
2806 pstrcpy(p2, vuser && vuser->homedir ? vuser->homedir : "");
2807 p2 = skip_string(p2,1);
2808 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
2809 pstrcpy(p2,"");
2810 p2 = skip_string(p2,1);
2811 SIVAL(p,usri11_last_logon,0); /* last logon */
2812 SIVAL(p,usri11_last_logoff,0); /* last logoff */
2813 SSVALS(p,usri11_bad_pw_count,-1); /* bad pw counts */
2814 SSVALS(p,usri11_num_logons,-1); /* num logons */
2815 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
2816 pstrcpy(p2,"\\\\*");
2817 p2 = skip_string(p2,1);
2818 SSVAL(p,usri11_country_code,0); /* country code */
2820 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
2821 pstrcpy(p2,"");
2822 p2 = skip_string(p2,1);
2824 SIVALS(p,usri11_max_storage,-1); /* max storage */
2825 SSVAL(p,usri11_units_per_week,168); /* units per week */
2826 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
2828 /* a simple way to get logon hours at all times. */
2829 memset(p2,0xff,21);
2830 SCVAL(p2,21,0); /* fix zero termination */
2831 p2 = skip_string(p2,1);
2833 SSVAL(p,usri11_code_page,0); /* code page */
2835 if (uLevel == 1 || uLevel == 2)
2837 memset(p+22,' ',16); /* password */
2838 SIVALS(p,38,-1); /* password age */
2839 SSVAL(p,42,
2840 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2841 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
2842 pstrcpy(p2, vuser && vuser->homedir ? vuser->homedir : "");
2843 p2 = skip_string(p2,1);
2844 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
2845 *p2++ = 0;
2846 SSVAL(p,52,0); /* flags */
2847 SIVAL(p,54,PTR_DIFF(p2,*rdata)); /* script_path */
2848 pstrcpy(p2,vuser && vuser->logon_script ? vuser->logon_script : "");
2849 p2 = skip_string(p2,1);
2850 if (uLevel == 2)
2852 SIVAL(p,60,0); /* auth_flags */
2853 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
2854 pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName));
2855 p2 = skip_string(p2,1);
2856 SIVAL(p,68,0); /* urs_comment */
2857 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
2858 pstrcpy(p2,"");
2859 p2 = skip_string(p2,1);
2860 SIVAL(p,76,0); /* workstations */
2861 SIVAL(p,80,0); /* last_logon */
2862 SIVAL(p,84,0); /* last_logoff */
2863 SIVALS(p,88,-1); /* acct_expires */
2864 SIVALS(p,92,-1); /* max_storage */
2865 SSVAL(p,96,168); /* units_per_week */
2866 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
2867 memset(p2,-1,21);
2868 p2 += 21;
2869 SSVALS(p,102,-1); /* bad_pw_count */
2870 SSVALS(p,104,-1); /* num_logons */
2871 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
2872 pstrcpy(p2,"\\\\%L");
2873 standard_sub_conn(conn, p2,0);
2874 p2 = skip_string(p2,1);
2875 SSVAL(p,110,49); /* country_code */
2876 SSVAL(p,112,860); /* code page */
2880 *rdata_len = PTR_DIFF(p2,*rdata);
2882 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
2884 return(True);
2887 static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param,char *data,
2888 int mdrcnt,int mprcnt,
2889 char **rdata,char **rparam,
2890 int *rdata_len,int *rparam_len)
2892 char *str1 = param+2;
2893 char *str2 = skip_string(str1,1);
2894 char *p = skip_string(str2,1);
2895 int uLevel;
2896 struct pack_desc desc;
2897 char* name;
2898 /* With share level security vuid will always be zero.
2899 Don't depend on vuser being non-null !!. JRA */
2900 user_struct *vuser = get_valid_user_struct(vuid);
2901 if(vuser != NULL)
2902 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid,
2903 vuser->user.unix_name));
2905 uLevel = SVAL(p,0);
2906 name = p + 2;
2908 memset((char *)&desc,'\0',sizeof(desc));
2910 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
2912 /* check it's a supported varient */
2913 if (strcmp(str1,"OOWb54WrLh") != 0) return False;
2914 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) return False;
2915 if (mdrcnt > 0) *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
2916 desc.base = *rdata;
2917 desc.buflen = mdrcnt;
2918 desc.subformat = NULL;
2919 desc.format = str2;
2921 if (init_package(&desc,1,0))
2923 PACKI(&desc,"W",0); /* code */
2924 PACKS(&desc,"B21",name); /* eff. name */
2925 PACKS(&desc,"B",""); /* pad */
2926 PACKI(&desc,"W",
2927 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2928 PACKI(&desc,"D",0); /* auth flags XXX */
2929 PACKI(&desc,"W",0); /* num logons */
2930 PACKI(&desc,"W",0); /* bad pw count */
2931 PACKI(&desc,"D",0); /* last logon */
2932 PACKI(&desc,"D",-1); /* last logoff */
2933 PACKI(&desc,"D",-1); /* logoff time */
2934 PACKI(&desc,"D",-1); /* kickoff time */
2935 PACKI(&desc,"D",0); /* password age */
2936 PACKI(&desc,"D",0); /* password can change */
2937 PACKI(&desc,"D",-1); /* password must change */
2939 fstring mypath;
2940 fstrcpy(mypath,"\\\\");
2941 fstrcat(mypath,get_local_machine_name());
2942 strupper_m(mypath);
2943 PACKS(&desc,"z",mypath); /* computer */
2945 PACKS(&desc,"z",lp_workgroup());/* domain */
2947 PACKS(&desc,"z", vuser && vuser->logon_script ? vuser->logon_script :""); /* script path */
2949 PACKI(&desc,"D",0x00000000); /* reserved */
2952 *rdata_len = desc.usedlen;
2953 *rparam_len = 6;
2954 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2955 SSVALS(*rparam,0,desc.errcode);
2956 SSVAL(*rparam,2,0);
2957 SSVAL(*rparam,4,desc.neededlen);
2959 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
2960 return(True);
2963 /****************************************************************************
2964 api_WAccessGetUserPerms
2965 ****************************************************************************/
2967 static BOOL api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid, char *param,char *data,
2968 int mdrcnt,int mprcnt,
2969 char **rdata,char **rparam,
2970 int *rdata_len,int *rparam_len)
2972 char *str1 = param+2;
2973 char *str2 = skip_string(str1,1);
2974 char *user = skip_string(str2,1);
2975 char *resource = skip_string(user,1);
2977 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
2979 /* check it's a supported varient */
2980 if (strcmp(str1,"zzh") != 0) return False;
2981 if (strcmp(str2,"") != 0) return False;
2983 *rparam_len = 6;
2984 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2985 SSVALS(*rparam,0,0); /* errorcode */
2986 SSVAL(*rparam,2,0); /* converter word */
2987 SSVAL(*rparam,4,0x7f); /* permission flags */
2989 return(True);
2992 /****************************************************************************
2993 api_WPrintJobEnumerate
2994 ****************************************************************************/
2996 static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2997 int mdrcnt,int mprcnt,
2998 char **rdata,char **rparam,
2999 int *rdata_len,int *rparam_len)
3001 char *str1 = param+2;
3002 char *str2 = skip_string(str1,1);
3003 char *p = skip_string(str2,1);
3004 int uLevel;
3005 int count;
3006 int i;
3007 int snum;
3008 fstring sharename;
3009 uint32 jobid;
3010 struct pack_desc desc;
3011 print_queue_struct *queue=NULL;
3012 print_status_struct status;
3013 char *tmpdata=NULL;
3015 uLevel = SVAL(p,2);
3017 memset((char *)&desc,'\0',sizeof(desc));
3018 memset((char *)&status,'\0',sizeof(status));
3020 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
3022 /* check it's a supported varient */
3023 if (strcmp(str1,"WWrLh") != 0) return False;
3024 if (!check_printjob_info(&desc,uLevel,str2)) return False;
3026 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
3027 return False;
3029 snum = lp_servicenumber( sharename);
3030 if (snum < 0 || !VALID_SNUM(snum)) return(False);
3032 count = print_queue_status(snum,&queue,&status);
3033 for (i = 0; i < count; i++) {
3034 if (queue[i].job == jobid) break;
3037 if (mdrcnt > 0) {
3038 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3039 desc.base = *rdata;
3040 desc.buflen = mdrcnt;
3041 } else {
3043 * Don't return data but need to get correct length
3044 * init_package will return wrong size if buflen=0
3046 desc.buflen = getlen(desc.format);
3047 desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen );
3050 if (init_package(&desc,1,0)) {
3051 if (i < count) {
3052 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
3053 *rdata_len = desc.usedlen;
3055 else {
3056 desc.errcode = NERR_JobNotFound;
3057 *rdata_len = 0;
3061 *rparam_len = 6;
3062 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3063 SSVALS(*rparam,0,desc.errcode);
3064 SSVAL(*rparam,2,0);
3065 SSVAL(*rparam,4,desc.neededlen);
3067 SAFE_FREE(queue);
3068 SAFE_FREE(tmpdata);
3070 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
3071 return(True);
3074 static BOOL api_WPrintJobEnumerate(connection_struct *conn,uint16 vuid, char *param,char *data,
3075 int mdrcnt,int mprcnt,
3076 char **rdata,char **rparam,
3077 int *rdata_len,int *rparam_len)
3079 char *str1 = param+2;
3080 char *str2 = skip_string(str1,1);
3081 char *p = skip_string(str2,1);
3082 char* name = p;
3083 int uLevel;
3084 int count;
3085 int i, succnt=0;
3086 int snum;
3087 struct pack_desc desc;
3088 print_queue_struct *queue=NULL;
3089 print_status_struct status;
3091 memset((char *)&desc,'\0',sizeof(desc));
3092 memset((char *)&status,'\0',sizeof(status));
3094 p = skip_string(p,1);
3095 uLevel = SVAL(p,0);
3097 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
3099 /* check it's a supported variant */
3100 if (strcmp(str1,"zWrLeh") != 0)
3101 return False;
3103 if (uLevel > 2)
3104 return False; /* defined only for uLevel 0,1,2 */
3106 if (!check_printjob_info(&desc,uLevel,str2))
3107 return False;
3109 snum = find_service(name);
3110 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
3111 return False;
3113 count = print_queue_status(snum,&queue,&status);
3114 if (mdrcnt > 0) *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3115 desc.base = *rdata;
3116 desc.buflen = mdrcnt;
3118 if (init_package(&desc,count,0)) {
3119 succnt = 0;
3120 for (i = 0; i < count; i++) {
3121 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
3122 if (desc.errcode == NERR_Success) succnt = i+1;
3126 *rdata_len = desc.usedlen;
3128 *rparam_len = 8;
3129 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3130 SSVALS(*rparam,0,desc.errcode);
3131 SSVAL(*rparam,2,0);
3132 SSVAL(*rparam,4,succnt);
3133 SSVAL(*rparam,6,count);
3135 SAFE_FREE(queue);
3137 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
3138 return(True);
3141 static int check_printdest_info(struct pack_desc* desc,
3142 int uLevel, char* id)
3144 desc->subformat = NULL;
3145 switch( uLevel ) {
3146 case 0: desc->format = "B9"; break;
3147 case 1: desc->format = "B9B21WWzW"; break;
3148 case 2: desc->format = "z"; break;
3149 case 3: desc->format = "zzzWWzzzWW"; break;
3150 default: return False;
3152 if (strcmp(desc->format,id) != 0) return False;
3153 return True;
3156 static void fill_printdest_info(connection_struct *conn, int snum, int uLevel,
3157 struct pack_desc* desc)
3159 char buf[100];
3160 strncpy(buf,SERVICE(snum),sizeof(buf)-1);
3161 buf[sizeof(buf)-1] = 0;
3162 strupper_m(buf);
3163 if (uLevel <= 1) {
3164 PACKS(desc,"B9",buf); /* szName */
3165 if (uLevel == 1) {
3166 PACKS(desc,"B21",""); /* szUserName */
3167 PACKI(desc,"W",0); /* uJobId */
3168 PACKI(desc,"W",0); /* fsStatus */
3169 PACKS(desc,"z",""); /* pszStatus */
3170 PACKI(desc,"W",0); /* time */
3173 if (uLevel == 2 || uLevel == 3) {
3174 PACKS(desc,"z",buf); /* pszPrinterName */
3175 if (uLevel == 3) {
3176 PACKS(desc,"z",""); /* pszUserName */
3177 PACKS(desc,"z",""); /* pszLogAddr */
3178 PACKI(desc,"W",0); /* uJobId */
3179 PACKI(desc,"W",0); /* fsStatus */
3180 PACKS(desc,"z",""); /* pszStatus */
3181 PACKS(desc,"z",""); /* pszComment */
3182 PACKS(desc,"z","NULL"); /* pszDrivers */
3183 PACKI(desc,"W",0); /* time */
3184 PACKI(desc,"W",0); /* pad1 */
3189 static BOOL api_WPrintDestGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
3190 int mdrcnt,int mprcnt,
3191 char **rdata,char **rparam,
3192 int *rdata_len,int *rparam_len)
3194 char *str1 = param+2;
3195 char *str2 = skip_string(str1,1);
3196 char *p = skip_string(str2,1);
3197 char* PrinterName = p;
3198 int uLevel;
3199 struct pack_desc desc;
3200 int snum;
3201 char *tmpdata=NULL;
3203 memset((char *)&desc,'\0',sizeof(desc));
3205 p = skip_string(p,1);
3206 uLevel = SVAL(p,0);
3208 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
3210 /* check it's a supported varient */
3211 if (strcmp(str1,"zWrLh") != 0) return False;
3212 if (!check_printdest_info(&desc,uLevel,str2)) return False;
3214 snum = find_service(PrinterName);
3215 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) ) {
3216 *rdata_len = 0;
3217 desc.errcode = NERR_DestNotFound;
3218 desc.neededlen = 0;
3220 else {
3221 if (mdrcnt > 0) {
3222 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3223 desc.base = *rdata;
3224 desc.buflen = mdrcnt;
3225 } else {
3227 * Don't return data but need to get correct length
3228 * init_package will return wrong size if buflen=0
3230 desc.buflen = getlen(desc.format);
3231 desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen );
3233 if (init_package(&desc,1,0)) {
3234 fill_printdest_info(conn,snum,uLevel,&desc);
3236 *rdata_len = desc.usedlen;
3239 *rparam_len = 6;
3240 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3241 SSVALS(*rparam,0,desc.errcode);
3242 SSVAL(*rparam,2,0);
3243 SSVAL(*rparam,4,desc.neededlen);
3245 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
3246 SAFE_FREE(tmpdata);
3247 return(True);
3250 static BOOL api_WPrintDestEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3251 int mdrcnt,int mprcnt,
3252 char **rdata,char **rparam,
3253 int *rdata_len,int *rparam_len)
3255 char *str1 = param+2;
3256 char *str2 = skip_string(str1,1);
3257 char *p = skip_string(str2,1);
3258 int uLevel;
3259 int queuecnt;
3260 int i, n, succnt=0;
3261 struct pack_desc desc;
3262 int services = lp_numservices();
3264 memset((char *)&desc,'\0',sizeof(desc));
3266 uLevel = SVAL(p,0);
3268 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
3270 /* check it's a supported varient */
3271 if (strcmp(str1,"WrLeh") != 0) return False;
3272 if (!check_printdest_info(&desc,uLevel,str2)) return False;
3274 queuecnt = 0;
3275 for (i = 0; i < services; i++)
3276 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
3277 queuecnt++;
3279 if (mdrcnt > 0) *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3280 desc.base = *rdata;
3281 desc.buflen = mdrcnt;
3282 if (init_package(&desc,queuecnt,0)) {
3283 succnt = 0;
3284 n = 0;
3285 for (i = 0; i < services; i++) {
3286 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
3287 fill_printdest_info(conn,i,uLevel,&desc);
3288 n++;
3289 if (desc.errcode == NERR_Success) succnt = n;
3294 *rdata_len = desc.usedlen;
3296 *rparam_len = 8;
3297 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3298 SSVALS(*rparam,0,desc.errcode);
3299 SSVAL(*rparam,2,0);
3300 SSVAL(*rparam,4,succnt);
3301 SSVAL(*rparam,6,queuecnt);
3303 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
3304 return(True);
3307 static BOOL api_WPrintDriverEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3308 int mdrcnt,int mprcnt,
3309 char **rdata,char **rparam,
3310 int *rdata_len,int *rparam_len)
3312 char *str1 = param+2;
3313 char *str2 = skip_string(str1,1);
3314 char *p = skip_string(str2,1);
3315 int uLevel;
3316 int succnt;
3317 struct pack_desc desc;
3319 memset((char *)&desc,'\0',sizeof(desc));
3321 uLevel = SVAL(p,0);
3323 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
3325 /* check it's a supported varient */
3326 if (strcmp(str1,"WrLeh") != 0) return False;
3327 if (uLevel != 0 || strcmp(str2,"B41") != 0) return False;
3329 if (mdrcnt > 0) *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3330 desc.base = *rdata;
3331 desc.buflen = mdrcnt;
3332 if (init_package(&desc,1,0)) {
3333 PACKS(&desc,"B41","NULL");
3336 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3338 *rdata_len = desc.usedlen;
3340 *rparam_len = 8;
3341 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3342 SSVALS(*rparam,0,desc.errcode);
3343 SSVAL(*rparam,2,0);
3344 SSVAL(*rparam,4,succnt);
3345 SSVAL(*rparam,6,1);
3347 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
3348 return(True);
3351 static BOOL api_WPrintQProcEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3352 int mdrcnt,int mprcnt,
3353 char **rdata,char **rparam,
3354 int *rdata_len,int *rparam_len)
3356 char *str1 = param+2;
3357 char *str2 = skip_string(str1,1);
3358 char *p = skip_string(str2,1);
3359 int uLevel;
3360 int succnt;
3361 struct pack_desc desc;
3363 memset((char *)&desc,'\0',sizeof(desc));
3365 uLevel = SVAL(p,0);
3367 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
3369 /* check it's a supported varient */
3370 if (strcmp(str1,"WrLeh") != 0) return False;
3371 if (uLevel != 0 || strcmp(str2,"B13") != 0) return False;
3373 if (mdrcnt > 0) *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3374 desc.base = *rdata;
3375 desc.buflen = mdrcnt;
3376 desc.format = str2;
3377 if (init_package(&desc,1,0)) {
3378 PACKS(&desc,"B13","lpd");
3381 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3383 *rdata_len = desc.usedlen;
3385 *rparam_len = 8;
3386 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3387 SSVALS(*rparam,0,desc.errcode);
3388 SSVAL(*rparam,2,0);
3389 SSVAL(*rparam,4,succnt);
3390 SSVAL(*rparam,6,1);
3392 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
3393 return(True);
3396 static BOOL api_WPrintPortEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3397 int mdrcnt,int mprcnt,
3398 char **rdata,char **rparam,
3399 int *rdata_len,int *rparam_len)
3401 char *str1 = param+2;
3402 char *str2 = skip_string(str1,1);
3403 char *p = skip_string(str2,1);
3404 int uLevel;
3405 int succnt;
3406 struct pack_desc desc;
3408 memset((char *)&desc,'\0',sizeof(desc));
3410 uLevel = SVAL(p,0);
3412 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
3414 /* check it's a supported varient */
3415 if (strcmp(str1,"WrLeh") != 0) return False;
3416 if (uLevel != 0 || strcmp(str2,"B9") != 0) return False;
3418 if (mdrcnt > 0) *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3419 memset((char *)&desc,'\0',sizeof(desc));
3420 desc.base = *rdata;
3421 desc.buflen = mdrcnt;
3422 desc.format = str2;
3423 if (init_package(&desc,1,0)) {
3424 PACKS(&desc,"B13","lp0");
3427 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3429 *rdata_len = desc.usedlen;
3431 *rparam_len = 8;
3432 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3433 SSVALS(*rparam,0,desc.errcode);
3434 SSVAL(*rparam,2,0);
3435 SSVAL(*rparam,4,succnt);
3436 SSVAL(*rparam,6,1);
3438 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
3439 return(True);
3443 /****************************************************************************
3444 List open sessions
3445 ****************************************************************************/
3446 static BOOL api_RNetSessionEnum(connection_struct *conn,uint16 vuid, char *param, char *data,
3447 int mdrcnt,int mprcnt,
3448 char **rdata,char **rparam,
3449 int *rdata_len,int *rparam_len)
3452 char *str1 = param+2;
3453 char *str2 = skip_string(str1,1);
3454 char *p = skip_string(str2,1);
3455 int uLevel;
3456 struct pack_desc desc;
3457 struct sessionid *session_list;
3458 int i, num_sessions;
3460 memset((char *)&desc,'\0',sizeof(desc));
3462 uLevel = SVAL(p,0);
3464 DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel));
3465 DEBUG(7,("RNetSessionEnum req string=%s\n",str1));
3466 DEBUG(7,("RNetSessionEnum ret string=%s\n",str2));
3468 /* check it's a supported varient */
3469 if (strcmp(str1,RAP_NetSessionEnum_REQ) != 0) return False;
3470 if (uLevel != 2 || strcmp(str2,RAP_SESSION_INFO_L2) != 0) return False;
3472 num_sessions = list_sessions(&session_list);
3474 if (mdrcnt > 0) *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3475 memset((char *)&desc,'\0',sizeof(desc));
3476 desc.base = *rdata;
3477 desc.buflen = mdrcnt;
3478 desc.format = str2;
3479 if (!init_package(&desc,num_sessions,0)) {
3480 return False;
3483 for(i=0; i<num_sessions; i++) {
3484 PACKS(&desc, "z", session_list[i].remote_machine);
3485 PACKS(&desc, "z", session_list[i].username);
3486 PACKI(&desc, "W", 1); /* num conns */
3487 PACKI(&desc, "W", 0); /* num opens */
3488 PACKI(&desc, "W", 1); /* num users */
3489 PACKI(&desc, "D", 0); /* session time */
3490 PACKI(&desc, "D", 0); /* idle time */
3491 PACKI(&desc, "D", 0); /* flags */
3492 PACKS(&desc, "z", "Unknown Client"); /* client type string */
3495 *rdata_len = desc.usedlen;
3497 *rparam_len = 8;
3498 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3499 SSVALS(*rparam,0,desc.errcode);
3500 SSVAL(*rparam,2,0); /* converter */
3501 SSVAL(*rparam,4,num_sessions); /* count */
3503 DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc.errcode));
3504 return True;
3508 /****************************************************************************
3509 The buffer was too small
3510 ****************************************************************************/
3512 static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param,char *data,
3513 int mdrcnt,int mprcnt,
3514 char **rdata,char **rparam,
3515 int *rdata_len,int *rparam_len)
3517 *rparam_len = MIN(*rparam_len,mprcnt);
3518 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3520 *rdata_len = 0;
3522 SSVAL(*rparam,0,NERR_BufTooSmall);
3524 DEBUG(3,("Supplied buffer too small in API command\n"));
3526 return(True);
3530 /****************************************************************************
3531 The request is not supported
3532 ****************************************************************************/
3534 static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param,char *data,
3535 int mdrcnt,int mprcnt,
3536 char **rdata,char **rparam,
3537 int *rdata_len,int *rparam_len)
3539 *rparam_len = 4;
3540 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3542 *rdata_len = 0;
3544 SSVAL(*rparam,0,NERR_notsupported);
3545 SSVAL(*rparam,2,0); /* converter word */
3547 DEBUG(3,("Unsupported API command\n"));
3549 return(True);
3552 static const struct {
3553 const char *name;
3554 int id;
3555 BOOL (*fn)(connection_struct *,uint16,char *,char *,
3556 int,int,char **,char **,int *,int *);
3557 BOOL auth_user; /* Deny anonymous access? */
3558 } api_commands[] = {
3559 {"RNetShareEnum", RAP_WshareEnum, api_RNetShareEnum, True},
3560 {"RNetShareGetInfo", RAP_WshareGetInfo, api_RNetShareGetInfo},
3561 {"RNetShareAdd", RAP_WshareAdd, api_RNetShareAdd},
3562 {"RNetSessionEnum", RAP_WsessionEnum, api_RNetSessionEnum, True},
3563 {"RNetServerGetInfo", RAP_WserverGetInfo, api_RNetServerGetInfo},
3564 {"RNetGroupEnum", RAP_WGroupEnum, api_RNetGroupEnum, True},
3565 {"RNetGroupGetUsers", RAP_WGroupGetUsers, api_RNetGroupGetUsers, True},
3566 {"RNetUserEnum", RAP_WUserEnum, api_RNetUserEnum, True},
3567 {"RNetUserGetInfo", RAP_WUserGetInfo, api_RNetUserGetInfo},
3568 {"NetUserGetGroups", RAP_WUserGetGroups, api_NetUserGetGroups},
3569 {"NetWkstaGetInfo", RAP_WWkstaGetInfo, api_NetWkstaGetInfo},
3570 {"DosPrintQEnum", RAP_WPrintQEnum, api_DosPrintQEnum, True},
3571 {"DosPrintQGetInfo", RAP_WPrintQGetInfo, api_DosPrintQGetInfo},
3572 {"WPrintQueuePause", RAP_WPrintQPause, api_WPrintQueueCtrl},
3573 {"WPrintQueueResume", RAP_WPrintQContinue, api_WPrintQueueCtrl},
3574 {"WPrintJobEnumerate",RAP_WPrintJobEnum, api_WPrintJobEnumerate},
3575 {"WPrintJobGetInfo", RAP_WPrintJobGetInfo, api_WPrintJobGetInfo},
3576 {"RDosPrintJobDel", RAP_WPrintJobDel, api_RDosPrintJobDel},
3577 {"RDosPrintJobPause", RAP_WPrintJobPause, api_RDosPrintJobDel},
3578 {"RDosPrintJobResume",RAP_WPrintJobContinue, api_RDosPrintJobDel},
3579 {"WPrintDestEnum", RAP_WPrintDestEnum, api_WPrintDestEnum},
3580 {"WPrintDestGetInfo", RAP_WPrintDestGetInfo, api_WPrintDestGetInfo},
3581 {"NetRemoteTOD", RAP_NetRemoteTOD, api_NetRemoteTOD},
3582 {"WPrintQueuePurge", RAP_WPrintQPurge, api_WPrintQueueCtrl},
3583 {"NetServerEnum", RAP_NetServerEnum2, api_RNetServerEnum}, /* anon OK */
3584 {"WAccessGetUserPerms",RAP_WAccessGetUserPerms,api_WAccessGetUserPerms},
3585 {"SetUserPassword", RAP_WUserPasswordSet2, api_SetUserPassword},
3586 {"WWkstaUserLogon", RAP_WWkstaUserLogon, api_WWkstaUserLogon},
3587 {"PrintJobInfo", RAP_WPrintJobSetInfo, api_PrintJobInfo},
3588 {"WPrintDriverEnum", RAP_WPrintDriverEnum, api_WPrintDriverEnum},
3589 {"WPrintQProcEnum", RAP_WPrintQProcessorEnum,api_WPrintQProcEnum},
3590 {"WPrintPortEnum", RAP_WPrintPortEnum, api_WPrintPortEnum},
3591 {"SamOEMChangePassword",RAP_SamOEMChgPasswordUser2_P,api_SamOEMChangePassword}, /* anon OK */
3592 {NULL, -1, api_Unsupported}
3593 /* The following RAP calls are not implemented by Samba:
3595 RAP_WFileEnum2 - anon not OK
3600 /****************************************************************************
3601 Handle remote api calls
3602 ****************************************************************************/
3604 int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data,char *params,
3605 int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
3607 int api_command;
3608 char *rdata = NULL;
3609 char *rparam = NULL;
3610 int rdata_len = 0;
3611 int rparam_len = 0;
3612 BOOL reply=False;
3613 int i;
3615 if (!params) {
3616 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
3617 return 0;
3620 api_command = SVAL(params,0);
3622 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
3623 api_command,
3624 params+2,
3625 skip_string(params+2,1),
3626 tdscnt,tpscnt,mdrcnt,mprcnt));
3628 for (i=0;api_commands[i].name;i++) {
3629 if (api_commands[i].id == api_command && api_commands[i].fn) {
3630 DEBUG(3,("Doing %s\n",api_commands[i].name));
3631 break;
3635 /* Check whether this api call can be done anonymously */
3637 if (api_commands[i].auth_user && lp_restrict_anonymous()) {
3638 user_struct *user = get_valid_user_struct(vuid);
3640 if (!user || user->guest) {
3641 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
3645 rdata = (char *)SMB_MALLOC(1024);
3646 if (rdata) {
3647 memset(rdata,'\0',1024);
3650 rparam = (char *)SMB_MALLOC(1024);
3651 if (rparam) {
3652 memset(rparam,'\0',1024);
3655 if(!rdata || !rparam) {
3656 DEBUG(0,("api_reply: malloc fail !\n"));
3657 SAFE_FREE(rdata);
3658 SAFE_FREE(rparam);
3659 return -1;
3662 reply = api_commands[i].fn(conn,vuid,params,data,mdrcnt,mprcnt,
3663 &rdata,&rparam,&rdata_len,&rparam_len);
3666 if (rdata_len > mdrcnt || rparam_len > mprcnt) {
3667 reply = api_TooSmall(conn,vuid,params,data,mdrcnt,mprcnt,
3668 &rdata,&rparam,&rdata_len,&rparam_len);
3671 /* if we get False back then it's actually unsupported */
3672 if (!reply) {
3673 api_Unsupported(conn,vuid,params,data,mdrcnt,mprcnt,
3674 &rdata,&rparam,&rdata_len,&rparam_len);
3677 send_trans_reply(outbuf, rparam, rparam_len, rdata, rdata_len, False);
3679 SAFE_FREE(rdata);
3680 SAFE_FREE(rparam);
3681 return -1;