r5165: BUG 2295: always use get_local_machine_name() rather than digging in the glova...
[Samba/bb.git] / source / smbd / lanman.c
blobd8c5201ce679cb3d838796fe525cf405cf7b81be
1 /*
2 Unix SMB/CIFS implementation.
3 Inter-process communication and named pipe handling
4 Copyright (C) Andrew Tridgell 1992-1998
6 SMB Version handling
7 Copyright (C) John H Terpstra 1995-1998
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 This file handles the named pipe and mailslot calls
25 in the SMBtrans protocol
28 #include "includes.h"
30 #ifdef CHECK_TYPES
31 #undef CHECK_TYPES
32 #endif
33 #define CHECK_TYPES 0
35 #define NERR_Success 0
36 #define NERR_badpass 86
37 #define NERR_notsupported 50
39 #define NERR_BASE (2100)
40 #define NERR_BufTooSmall (NERR_BASE+23)
41 #define NERR_JobNotFound (NERR_BASE+51)
42 #define NERR_DestNotFound (NERR_BASE+52)
44 #define ACCESS_READ 0x01
45 #define ACCESS_WRITE 0x02
46 #define ACCESS_CREATE 0x04
48 #define SHPWLEN 8 /* share password length */
50 static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param,char *data,
51 int mdrcnt,int mprcnt,
52 char **rdata,char **rparam,
53 int *rdata_len,int *rparam_len);
54 static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param,char *data,
55 int mdrcnt,int mprcnt,
56 char **rdata,char **rparam,
57 int *rdata_len,int *rparam_len);
60 static int CopyExpanded(connection_struct *conn,
61 int snum, char** dst, char* src, int* n)
63 pstring buf;
64 int l;
66 if (!src || !dst || !n || !(*dst)) return(0);
68 StrnCpy(buf,src,sizeof(buf)/2);
69 pstring_sub(buf,"%S",lp_servicename(snum));
70 standard_sub_conn(conn,buf,sizeof(buf));
71 l = push_ascii(*dst,buf,*n, STR_TERMINATE);
72 (*dst) += l;
73 (*n) -= l;
74 return l;
77 static int CopyAndAdvance(char** dst, char* src, int* n)
79 int l;
80 if (!src || !dst || !n || !(*dst)) return(0);
81 l = push_ascii(*dst,src,*n, STR_TERMINATE);
82 (*dst) += l;
83 (*n) -= l;
84 return l;
87 static int StrlenExpanded(connection_struct *conn, int snum, char* s)
89 pstring buf;
90 if (!s) return(0);
91 StrnCpy(buf,s,sizeof(buf)/2);
92 pstring_sub(buf,"%S",lp_servicename(snum));
93 standard_sub_conn(conn,buf,sizeof(buf));
94 return strlen(buf) + 1;
97 static char* Expand(connection_struct *conn, int snum, char* s)
99 static pstring buf;
100 if (!s) return(NULL);
101 StrnCpy(buf,s,sizeof(buf)/2);
102 pstring_sub(buf,"%S",lp_servicename(snum));
103 standard_sub_conn(conn,buf,sizeof(buf));
104 return &buf[0];
107 /*******************************************************************
108 check a API string for validity when we only need to check the prefix
109 ******************************************************************/
110 static BOOL prefix_ok(const char *str, const char *prefix)
112 return(strncmp(str,prefix,strlen(prefix)) == 0);
115 struct pack_desc {
116 const char* format; /* formatstring for structure */
117 const char* subformat; /* subformat for structure */
118 char* base; /* baseaddress of buffer */
119 int buflen; /* remaining size for fixed part; on init: length of base */
120 int subcount; /* count of substructures */
121 char* structbuf; /* pointer into buffer for remaining fixed part */
122 int stringlen; /* remaining size for variable part */
123 char* stringbuf; /* pointer into buffer for remaining variable part */
124 int neededlen; /* total needed size */
125 int usedlen; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
126 const char* curpos; /* current position; pointer into format or subformat */
127 int errcode;
130 static int get_counter(const char** p)
132 int i, n;
133 if (!p || !(*p)) return(1);
134 if (!isdigit((int)**p)) return 1;
135 for (n = 0;;) {
136 i = **p;
137 if (isdigit(i))
138 n = 10 * n + (i - '0');
139 else
140 return n;
141 (*p)++;
145 static int getlen(const char* p)
147 int n = 0;
148 if (!p) return(0);
149 while (*p) {
150 switch( *p++ ) {
151 case 'W': /* word (2 byte) */
152 n += 2;
153 break;
154 case 'K': /* status word? (2 byte) */
155 n += 2;
156 break;
157 case 'N': /* count of substructures (word) at end */
158 n += 2;
159 break;
160 case 'D': /* double word (4 byte) */
161 case 'z': /* offset to zero terminated string (4 byte) */
162 case 'l': /* offset to user data (4 byte) */
163 n += 4;
164 break;
165 case 'b': /* offset to data (with counter) (4 byte) */
166 n += 4;
167 get_counter(&p);
168 break;
169 case 'B': /* byte (with optional counter) */
170 n += get_counter(&p);
171 break;
174 return n;
177 static BOOL init_package(struct pack_desc* p, int count, int subcount)
179 int n = p->buflen;
180 int i;
182 if (!p->format || !p->base) return(False);
184 i = count * getlen(p->format);
185 if (p->subformat) i += subcount * getlen(p->subformat);
186 p->structbuf = p->base;
187 p->neededlen = 0;
188 p->usedlen = 0;
189 p->subcount = 0;
190 p->curpos = p->format;
191 if (i > n) {
192 p->neededlen = i;
193 i = n = 0;
194 #if 0
196 * This is the old error code we used. Aparently
197 * WinNT/2k systems return ERRbuftoosmall (2123) and
198 * OS/2 needs this. I'm leaving this here so we can revert
199 * if needed. JRA.
201 p->errcode = ERRmoredata;
202 #else
203 p->errcode = ERRbuftoosmall;
204 #endif
206 else
207 p->errcode = NERR_Success;
208 p->buflen = i;
209 n -= i;
210 p->stringbuf = p->base + i;
211 p->stringlen = n;
212 return(p->errcode == NERR_Success);
215 static int package(struct pack_desc* p, ...)
217 va_list args;
218 int needed=0, stringneeded;
219 const char* str=NULL;
220 int is_string=0, stringused;
221 int32 temp;
223 va_start(args,p);
225 if (!*p->curpos) {
226 if (!p->subcount)
227 p->curpos = p->format;
228 else {
229 p->curpos = p->subformat;
230 p->subcount--;
233 #if CHECK_TYPES
234 str = va_arg(args,char*);
235 SMB_ASSERT(strncmp(str,p->curpos,strlen(str)) == 0);
236 #endif
237 stringneeded = -1;
239 if (!p->curpos) {
240 va_end(args);
241 return(0);
244 switch( *p->curpos++ ) {
245 case 'W': /* word (2 byte) */
246 needed = 2;
247 temp = va_arg(args,int);
248 if (p->buflen >= needed) SSVAL(p->structbuf,0,temp);
249 break;
250 case 'K': /* status word? (2 byte) */
251 needed = 2;
252 temp = va_arg(args,int);
253 if (p->buflen >= needed) SSVAL(p->structbuf,0,temp);
254 break;
255 case 'N': /* count of substructures (word) at end */
256 needed = 2;
257 p->subcount = va_arg(args,int);
258 if (p->buflen >= needed) SSVAL(p->structbuf,0,p->subcount);
259 break;
260 case 'D': /* double word (4 byte) */
261 needed = 4;
262 temp = va_arg(args,int);
263 if (p->buflen >= needed) SIVAL(p->structbuf,0,temp);
264 break;
265 case 'B': /* byte (with optional counter) */
266 needed = get_counter(&p->curpos);
268 char *s = va_arg(args,char*);
269 if (p->buflen >= needed) StrnCpy(p->structbuf,s?s:"",needed-1);
271 break;
272 case 'z': /* offset to zero terminated string (4 byte) */
273 str = va_arg(args,char*);
274 stringneeded = (str ? strlen(str)+1 : 0);
275 is_string = 1;
276 break;
277 case 'l': /* offset to user data (4 byte) */
278 str = va_arg(args,char*);
279 stringneeded = va_arg(args,int);
280 is_string = 0;
281 break;
282 case 'b': /* offset to data (with counter) (4 byte) */
283 str = va_arg(args,char*);
284 stringneeded = get_counter(&p->curpos);
285 is_string = 0;
286 break;
288 va_end(args);
289 if (stringneeded >= 0) {
290 needed = 4;
291 if (p->buflen >= needed) {
292 stringused = stringneeded;
293 if (stringused > p->stringlen) {
294 stringused = (is_string ? p->stringlen : 0);
295 if (p->errcode == NERR_Success) p->errcode = ERRmoredata;
297 if (!stringused)
298 SIVAL(p->structbuf,0,0);
299 else {
300 SIVAL(p->structbuf,0,PTR_DIFF(p->stringbuf,p->base));
301 memcpy(p->stringbuf,str?str:"",stringused);
302 if (is_string) p->stringbuf[stringused-1] = '\0';
303 p->stringbuf += stringused;
304 p->stringlen -= stringused;
305 p->usedlen += stringused;
308 p->neededlen += stringneeded;
310 p->neededlen += needed;
311 if (p->buflen >= needed) {
312 p->structbuf += needed;
313 p->buflen -= needed;
314 p->usedlen += needed;
316 else {
317 if (p->errcode == NERR_Success) p->errcode = ERRmoredata;
319 return 1;
322 #if CHECK_TYPES
323 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
324 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
325 #else
326 #define PACK(desc,t,v) package(desc,v)
327 #define PACKl(desc,t,v,l) package(desc,v,l)
328 #endif
330 static void PACKI(struct pack_desc* desc, const char *t,int v)
332 PACK(desc,t,v);
335 static void PACKS(struct pack_desc* desc,const char *t,const char *v)
337 PACK(desc,t,v);
341 /****************************************************************************
342 get a print queue
343 ****************************************************************************/
344 static void PackDriverData(struct pack_desc* desc)
346 char drivdata[4+4+32];
347 SIVAL(drivdata,0,sizeof drivdata); /* cb */
348 SIVAL(drivdata,4,1000); /* lVersion */
349 memset(drivdata+8,0,32); /* szDeviceName */
350 push_ascii(drivdata+8,"NULL",-1, STR_TERMINATE);
351 PACKl(desc,"l",drivdata,sizeof drivdata); /* pDriverData */
354 static int check_printq_info(struct pack_desc* desc,
355 int uLevel, char *id1, char *id2)
357 desc->subformat = NULL;
358 switch( uLevel ) {
359 case 0:
360 desc->format = "B13";
361 break;
362 case 1:
363 desc->format = "B13BWWWzzzzzWW";
364 break;
365 case 2:
366 desc->format = "B13BWWWzzzzzWN";
367 desc->subformat = "WB21BB16B10zWWzDDz";
368 break;
369 case 3:
370 desc->format = "zWWWWzzzzWWzzl";
371 break;
372 case 4:
373 desc->format = "zWWWWzzzzWNzzl";
374 desc->subformat = "WWzWWDDzz";
375 break;
376 case 5:
377 desc->format = "z";
378 break;
379 case 51:
380 desc->format = "K";
381 break;
382 case 52:
383 desc->format = "WzzzzzzzzN";
384 desc->subformat = "z";
385 break;
386 default: return False;
388 if (strcmp(desc->format,id1) != 0) return False;
389 if (desc->subformat && strcmp(desc->subformat,id2) != 0) return False;
390 return True;
394 #define RAP_JOB_STATUS_QUEUED 0
395 #define RAP_JOB_STATUS_PAUSED 1
396 #define RAP_JOB_STATUS_SPOOLING 2
397 #define RAP_JOB_STATUS_PRINTING 3
398 #define RAP_JOB_STATUS_PRINTED 4
400 #define RAP_QUEUE_STATUS_PAUSED 1
401 #define RAP_QUEUE_STATUS_ERROR 2
403 /* turn a print job status into a on the wire status
405 static int printj_status(int v)
407 switch (v) {
408 case LPQ_QUEUED:
409 return RAP_JOB_STATUS_QUEUED;
410 case LPQ_PAUSED:
411 return RAP_JOB_STATUS_PAUSED;
412 case LPQ_SPOOLING:
413 return RAP_JOB_STATUS_SPOOLING;
414 case LPQ_PRINTING:
415 return RAP_JOB_STATUS_PRINTING;
417 return 0;
420 /* turn a print queue status into a on the wire status
422 static int printq_status(int v)
424 switch (v) {
425 case LPQ_QUEUED:
426 return 0;
427 case LPQ_PAUSED:
428 return RAP_QUEUE_STATUS_PAUSED;
430 return RAP_QUEUE_STATUS_ERROR;
433 static void fill_printjob_info(connection_struct *conn, int snum, int uLevel,
434 struct pack_desc* desc,
435 print_queue_struct* queue, int n)
437 time_t t = queue->time;
439 /* the client expects localtime */
440 t -= TimeDiff(t);
442 PACKI(desc,"W",pjobid_to_rap(lp_const_servicename(snum),queue->job)); /* uJobId */
443 if (uLevel == 1) {
444 PACKS(desc,"B21",queue->fs_user); /* szUserName */
445 PACKS(desc,"B",""); /* pad */
446 PACKS(desc,"B16",""); /* szNotifyName */
447 PACKS(desc,"B10","PM_Q_RAW"); /* szDataType */
448 PACKS(desc,"z",""); /* pszParms */
449 PACKI(desc,"W",n+1); /* uPosition */
450 PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */
451 PACKS(desc,"z",""); /* pszStatus */
452 PACKI(desc,"D",t); /* ulSubmitted */
453 PACKI(desc,"D",queue->size); /* ulSize */
454 PACKS(desc,"z",queue->fs_file); /* pszComment */
456 if (uLevel == 2 || uLevel == 3 || uLevel == 4) {
457 PACKI(desc,"W",queue->priority); /* uPriority */
458 PACKS(desc,"z",queue->fs_user); /* pszUserName */
459 PACKI(desc,"W",n+1); /* uPosition */
460 PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */
461 PACKI(desc,"D",t); /* ulSubmitted */
462 PACKI(desc,"D",queue->size); /* ulSize */
463 PACKS(desc,"z","Samba"); /* pszComment */
464 PACKS(desc,"z",queue->fs_file); /* pszDocument */
465 if (uLevel == 3) {
466 PACKS(desc,"z",""); /* pszNotifyName */
467 PACKS(desc,"z","PM_Q_RAW"); /* pszDataType */
468 PACKS(desc,"z",""); /* pszParms */
469 PACKS(desc,"z",""); /* pszStatus */
470 PACKS(desc,"z",SERVICE(snum)); /* pszQueue */
471 PACKS(desc,"z","lpd"); /* pszQProcName */
472 PACKS(desc,"z",""); /* pszQProcParms */
473 PACKS(desc,"z","NULL"); /* pszDriverName */
474 PackDriverData(desc); /* pDriverData */
475 PACKS(desc,"z",""); /* pszPrinterName */
476 } else if (uLevel == 4) { /* OS2 */
477 PACKS(desc,"z",""); /* pszSpoolFileName */
478 PACKS(desc,"z",""); /* pszPortName */
479 PACKS(desc,"z",""); /* pszStatus */
480 PACKI(desc,"D",0); /* ulPagesSpooled */
481 PACKI(desc,"D",0); /* ulPagesSent */
482 PACKI(desc,"D",0); /* ulPagesPrinted */
483 PACKI(desc,"D",0); /* ulTimePrinted */
484 PACKI(desc,"D",0); /* ulExtendJobStatus */
485 PACKI(desc,"D",0); /* ulStartPage */
486 PACKI(desc,"D",0); /* ulEndPage */
491 /********************************************************************
492 Return a driver name given an snum.
493 Returns True if from tdb, False otherwise.
494 ********************************************************************/
496 static BOOL get_driver_name(int snum, pstring drivername)
498 NT_PRINTER_INFO_LEVEL *info = NULL;
499 BOOL in_tdb = False;
501 get_a_printer (NULL, &info, 2, lp_servicename(snum));
502 if (info != NULL) {
503 pstrcpy( drivername, info->info_2->drivername);
504 in_tdb = True;
505 free_a_printer(&info, 2);
508 return in_tdb;
511 /********************************************************************
512 Respond to the DosPrintQInfo command with a level of 52
513 This is used to get printer driver information for Win9x clients
514 ********************************************************************/
515 static void fill_printq_info_52(connection_struct *conn, int snum,
516 struct pack_desc* desc, int count )
518 int i;
519 fstring location;
520 NT_PRINTER_DRIVER_INFO_LEVEL driver;
521 NT_PRINTER_INFO_LEVEL *printer = NULL;
523 ZERO_STRUCT(driver);
525 if ( !W_ERROR_IS_OK(get_a_printer( NULL, &printer, 2, lp_servicename(snum))) ) {
526 DEBUG(3,("fill_printq_info_52: Failed to lookup printer [%s]\n",
527 lp_servicename(snum)));
528 goto err;
531 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername,
532 "Windows 4.0", 0)) )
534 DEBUG(3,("fill_printq_info_52: Failed to lookup driver [%s]\n",
535 printer->info_2->drivername));
536 goto err;
539 trim_string(driver.info_3->driverpath, "\\print$\\WIN40\\0\\", 0);
540 trim_string(driver.info_3->datafile, "\\print$\\WIN40\\0\\", 0);
541 trim_string(driver.info_3->helpfile, "\\print$\\WIN40\\0\\", 0);
543 PACKI(desc, "W", 0x0400); /* don't know */
544 PACKS(desc, "z", driver.info_3->name); /* long printer name */
545 PACKS(desc, "z", driver.info_3->driverpath); /* Driverfile Name */
546 PACKS(desc, "z", driver.info_3->datafile); /* Datafile name */
547 PACKS(desc, "z", driver.info_3->monitorname); /* language monitor */
549 fstrcpy(location, "\\\\%L\\print$\\WIN40\\0");
550 standard_sub_basic( "", location, sizeof(location)-1 );
551 PACKS(desc,"z", location); /* share to retrieve files */
553 PACKS(desc,"z", driver.info_3->defaultdatatype); /* default data type */
554 PACKS(desc,"z", driver.info_3->helpfile); /* helpfile name */
555 PACKS(desc,"z", driver.info_3->driverpath); /* driver name */
557 DEBUG(3,("Printer Driver Name: %s:\n",driver.info_3->name));
558 DEBUG(3,("Driver: %s:\n",driver.info_3->driverpath));
559 DEBUG(3,("Data File: %s:\n",driver.info_3->datafile));
560 DEBUG(3,("Language Monitor: %s:\n",driver.info_3->monitorname));
561 DEBUG(3,("Driver Location: %s:\n",location));
562 DEBUG(3,("Data Type: %s:\n",driver.info_3->defaultdatatype));
563 DEBUG(3,("Help File: %s:\n",driver.info_3->helpfile));
564 PACKI(desc,"N",count); /* number of files to copy */
566 for ( i=0; i<count && driver.info_3->dependentfiles && *driver.info_3->dependentfiles[i]; i++)
568 trim_string(driver.info_3->dependentfiles[i], "\\print$\\WIN40\\0\\", 0);
569 PACKS(desc,"z",driver.info_3->dependentfiles[i]); /* driver files to copy */
570 DEBUG(3,("Dependent File: %s:\n",driver.info_3->dependentfiles[i]));
573 /* sanity check */
574 if ( i != count )
575 DEBUG(3,("fill_printq_info_52: file count specified by client [%d] != number of dependent files [%i]\n",
576 count, i));
578 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n", SERVICE(snum),i));
580 desc->errcode=NERR_Success;
581 goto done;
583 err:
584 DEBUG(3,("fill_printq_info: Can't supply driver files\n"));
585 desc->errcode=NERR_notsupported;
587 done:
588 if ( printer )
589 free_a_printer( &printer, 2 );
591 if ( driver.info_3 )
592 free_a_printer_driver( driver, 3 );
596 static void fill_printq_info(connection_struct *conn, int snum, int uLevel,
597 struct pack_desc* desc,
598 int count, print_queue_struct* queue,
599 print_status_struct* status)
601 switch (uLevel) {
602 case 1:
603 case 2:
604 PACKS(desc,"B13",SERVICE(snum));
605 break;
606 case 3:
607 case 4:
608 case 5:
609 PACKS(desc,"z",Expand(conn,snum,SERVICE(snum)));
610 break;
611 case 51:
612 PACKI(desc,"K",printq_status(status->status));
613 break;
616 if (uLevel == 1 || uLevel == 2) {
617 PACKS(desc,"B",""); /* alignment */
618 PACKI(desc,"W",5); /* priority */
619 PACKI(desc,"W",0); /* start time */
620 PACKI(desc,"W",0); /* until time */
621 PACKS(desc,"z",""); /* pSepFile */
622 PACKS(desc,"z","lpd"); /* pPrProc */
623 PACKS(desc,"z",SERVICE(snum)); /* pDestinations */
624 PACKS(desc,"z",""); /* pParms */
625 if (snum < 0) {
626 PACKS(desc,"z","UNKNOWN PRINTER");
627 PACKI(desc,"W",LPSTAT_ERROR);
629 else if (!status || !status->message[0]) {
630 PACKS(desc,"z",Expand(conn,snum,lp_comment(snum)));
631 PACKI(desc,"W",LPSTAT_OK); /* status */
632 } else {
633 PACKS(desc,"z",status->message);
634 PACKI(desc,"W",printq_status(status->status)); /* status */
636 PACKI(desc,(uLevel == 1 ? "W" : "N"),count);
639 if (uLevel == 3 || uLevel == 4) {
640 pstring drivername;
642 PACKI(desc,"W",5); /* uPriority */
643 PACKI(desc,"W",0); /* uStarttime */
644 PACKI(desc,"W",0); /* uUntiltime */
645 PACKI(desc,"W",5); /* pad1 */
646 PACKS(desc,"z",""); /* pszSepFile */
647 PACKS(desc,"z","WinPrint"); /* pszPrProc */
648 PACKS(desc,"z",NULL); /* pszParms */
649 PACKS(desc,"z",NULL); /* pszComment - don't ask.... JRA */
650 /* "don't ask" that it's done this way to fix corrupted
651 Win9X/ME printer comments. */
652 if (!status) {
653 PACKI(desc,"W",LPSTAT_OK); /* fsStatus */
654 } else {
655 PACKI(desc,"W",printq_status(status->status)); /* fsStatus */
657 PACKI(desc,(uLevel == 3 ? "W" : "N"),count); /* cJobs */
658 PACKS(desc,"z",SERVICE(snum)); /* pszPrinters */
659 get_driver_name(snum,drivername);
660 PACKS(desc,"z",drivername); /* pszDriverName */
661 PackDriverData(desc); /* pDriverData */
664 if (uLevel == 2 || uLevel == 4) {
665 int i;
666 for (i=0;i<count;i++)
667 fill_printjob_info(conn,snum,uLevel == 2 ? 1 : 2,desc,&queue[i],i);
670 if (uLevel==52)
671 fill_printq_info_52( conn, snum, desc, count );
674 /* This function returns the number of files for a given driver */
675 static int get_printerdrivernumber(int snum)
677 int result = 0;
678 NT_PRINTER_DRIVER_INFO_LEVEL driver;
679 NT_PRINTER_INFO_LEVEL *printer = NULL;
681 ZERO_STRUCT(driver);
683 if ( !W_ERROR_IS_OK(get_a_printer( NULL, &printer, 2, lp_servicename(snum))) ) {
684 DEBUG(3,("get_printerdrivernumber: Failed to lookup printer [%s]\n",
685 lp_servicename(snum)));
686 goto done;
689 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername,
690 "Windows 4.0", 0)) )
692 DEBUG(3,("get_printerdrivernumber: Failed to lookup driver [%s]\n",
693 printer->info_2->drivername));
694 goto done;
697 /* count the number of files */
698 while ( driver.info_3->dependentfiles && *driver.info_3->dependentfiles[result] )
699 result++;
701 done:
702 if ( printer )
703 free_a_printer( &printer, 2 );
705 if ( driver.info_3 )
706 free_a_printer_driver( driver, 3 );
708 return result;
711 static BOOL api_DosPrintQGetInfo(connection_struct *conn,
712 uint16 vuid, char *param,char *data,
713 int mdrcnt,int mprcnt,
714 char **rdata,char **rparam,
715 int *rdata_len,int *rparam_len)
717 char *str1 = param+2;
718 char *str2 = skip_string(str1,1);
719 char *p = skip_string(str2,1);
720 char *QueueName = p;
721 int uLevel;
722 int count=0;
723 int snum;
724 char* str3;
725 struct pack_desc desc;
726 print_queue_struct *queue=NULL;
727 print_status_struct status;
728 char* tmpdata=NULL;
730 memset((char *)&status,'\0',sizeof(status));
731 memset((char *)&desc,'\0',sizeof(desc));
733 p = skip_string(p,1);
734 uLevel = SVAL(p,0);
735 str3 = p + 4;
737 /* remove any trailing username */
738 if ((p = strchr_m(QueueName,'%')))
739 *p = 0;
741 DEBUG(3,("api_DosPrintQGetInfo uLevel=%d name=%s\n",uLevel,QueueName));
743 /* check it's a supported varient */
744 if (!prefix_ok(str1,"zWrLh"))
745 return False;
746 if (!check_printq_info(&desc,uLevel,str2,str3)) {
748 * Patch from Scott Moomaw <scott@bridgewater.edu>
749 * to return the 'invalid info level' error if an
750 * unknown level was requested.
752 *rdata_len = 0;
753 *rparam_len = 6;
754 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
755 SSVALS(*rparam,0,ERRunknownlevel);
756 SSVAL(*rparam,2,0);
757 SSVAL(*rparam,4,0);
758 return(True);
761 snum = find_service(QueueName);
762 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
763 return False;
765 if (uLevel==52) {
766 count = get_printerdrivernumber(snum);
767 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count));
768 } else {
769 count = print_queue_status(snum, &queue,&status);
772 if (mdrcnt > 0) {
773 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
774 desc.base = *rdata;
775 desc.buflen = mdrcnt;
776 } else {
778 * Don't return data but need to get correct length
779 * init_package will return wrong size if buflen=0
781 desc.buflen = getlen(desc.format);
782 desc.base = tmpdata = (char *) SMB_MALLOC (desc.buflen);
785 if (init_package(&desc,1,count)) {
786 desc.subcount = count;
787 fill_printq_info(conn,snum,uLevel,&desc,count,queue,&status);
790 *rdata_len = desc.usedlen;
793 * We must set the return code to ERRbuftoosmall
794 * in order to support lanman style printing with Win NT/2k
795 * clients --jerry
797 if (!mdrcnt && lp_disable_spoolss())
798 desc.errcode = ERRbuftoosmall;
800 *rdata_len = desc.usedlen;
801 *rparam_len = 6;
802 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
803 SSVALS(*rparam,0,desc.errcode);
804 SSVAL(*rparam,2,0);
805 SSVAL(*rparam,4,desc.neededlen);
807 DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode));
809 SAFE_FREE(queue);
810 SAFE_FREE(tmpdata);
812 return(True);
815 /****************************************************************************
816 View list of all print jobs on all queues.
817 ****************************************************************************/
819 static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid, char* param, char* data,
820 int mdrcnt, int mprcnt,
821 char **rdata, char** rparam,
822 int *rdata_len, int *rparam_len)
824 char *param_format = param+2;
825 char *output_format1 = skip_string(param_format,1);
826 char *p = skip_string(output_format1,1);
827 int uLevel = SVAL(p,0);
828 char *output_format2 = p + 4;
829 int services = lp_numservices();
830 int i, n;
831 struct pack_desc desc;
832 print_queue_struct **queue = NULL;
833 print_status_struct *status = NULL;
834 int* subcntarr = NULL;
835 int queuecnt, subcnt=0, succnt=0;
837 memset((char *)&desc,'\0',sizeof(desc));
839 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
841 if (!prefix_ok(param_format,"WrLeh")) return False;
842 if (!check_printq_info(&desc,uLevel,output_format1,output_format2)) {
844 * Patch from Scott Moomaw <scott@bridgewater.edu>
845 * to return the 'invalid info level' error if an
846 * unknown level was requested.
848 *rdata_len = 0;
849 *rparam_len = 6;
850 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
851 SSVALS(*rparam,0,ERRunknownlevel);
852 SSVAL(*rparam,2,0);
853 SSVAL(*rparam,4,0);
854 return(True);
857 queuecnt = 0;
858 for (i = 0; i < services; i++)
859 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
860 queuecnt++;
861 if (uLevel > 0) {
862 if((queue = SMB_MALLOC_ARRAY(print_queue_struct*, queuecnt)) == NULL) {
863 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
864 return False;
866 memset(queue,0,queuecnt*sizeof(print_queue_struct*));
867 if((status = SMB_MALLOC_ARRAY(print_status_struct,queuecnt)) == NULL) {
868 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
869 return False;
871 memset(status,0,queuecnt*sizeof(print_status_struct));
872 if((subcntarr = SMB_MALLOC_ARRAY(int,queuecnt)) == NULL) {
873 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
874 return False;
876 subcnt = 0;
877 n = 0;
878 for (i = 0; i < services; i++)
879 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
880 subcntarr[n] = print_queue_status(i, &queue[n],&status[n]);
881 subcnt += subcntarr[n];
882 n++;
885 if (mdrcnt > 0) *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
886 desc.base = *rdata;
887 desc.buflen = mdrcnt;
889 if (init_package(&desc,queuecnt,subcnt)) {
890 n = 0;
891 succnt = 0;
892 for (i = 0; i < services; i++)
893 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
894 fill_printq_info(conn,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]);
895 n++;
896 if (desc.errcode == NERR_Success) succnt = n;
900 SAFE_FREE(subcntarr);
902 *rdata_len = desc.usedlen;
903 *rparam_len = 8;
904 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
905 SSVALS(*rparam,0,desc.errcode);
906 SSVAL(*rparam,2,0);
907 SSVAL(*rparam,4,succnt);
908 SSVAL(*rparam,6,queuecnt);
910 for (i = 0; i < queuecnt; i++) {
911 if (queue) SAFE_FREE(queue[i]);
914 SAFE_FREE(queue);
915 SAFE_FREE(status);
917 return True;
920 /****************************************************************************
921 get info level for a server list query
922 ****************************************************************************/
923 static BOOL check_server_info(int uLevel, char* id)
925 switch( uLevel ) {
926 case 0:
927 if (strcmp(id,"B16") != 0) return False;
928 break;
929 case 1:
930 if (strcmp(id,"B16BBDz") != 0) return False;
931 break;
932 default:
933 return False;
935 return True;
938 struct srv_info_struct
940 fstring name;
941 uint32 type;
942 fstring comment;
943 fstring domain;
944 BOOL server_added;
948 /*******************************************************************
949 get server info lists from the files saved by nmbd. Return the
950 number of entries
951 ******************************************************************/
952 static int get_server_info(uint32 servertype,
953 struct srv_info_struct **servers,
954 const char *domain)
956 int count=0;
957 int alloced=0;
958 char **lines;
959 BOOL local_list_only;
960 int i;
962 lines = file_lines_load(lock_path(SERVER_LIST), NULL);
963 if (!lines) {
964 DEBUG(4,("Can't open %s - %s\n",lock_path(SERVER_LIST),strerror(errno)));
965 return(0);
968 /* request for everything is code for request all servers */
969 if (servertype == SV_TYPE_ALL)
970 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
972 local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY);
974 DEBUG(4,("Servertype search: %8x\n",servertype));
976 for (i=0;lines[i];i++) {
977 fstring stype;
978 struct srv_info_struct *s;
979 const char *ptr = lines[i];
980 BOOL ok = True;
982 if (!*ptr) continue;
984 if (count == alloced) {
985 struct srv_info_struct *ts;
987 alloced += 10;
988 ts = SMB_REALLOC_ARRAY(*servers,struct srv_info_struct, alloced);
989 if (!ts) {
990 DEBUG(0,("get_server_info: failed to enlarge servers info struct!\n"));
991 return(0);
993 else *servers = ts;
994 memset((char *)((*servers)+count),'\0',sizeof(**servers)*(alloced-count));
996 s = &(*servers)[count];
998 if (!next_token(&ptr,s->name , NULL, sizeof(s->name))) continue;
999 if (!next_token(&ptr,stype , NULL, sizeof(stype))) continue;
1000 if (!next_token(&ptr,s->comment, NULL, sizeof(s->comment))) continue;
1001 if (!next_token(&ptr,s->domain , NULL, sizeof(s->domain))) {
1002 /* this allows us to cope with an old nmbd */
1003 fstrcpy(s->domain,lp_workgroup());
1006 if (sscanf(stype,"%X",&s->type) != 1) {
1007 DEBUG(4,("r:host file "));
1008 ok = False;
1011 /* Filter the servers/domains we return based on what was asked for. */
1013 /* Check to see if we are being asked for a local list only. */
1014 if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) {
1015 DEBUG(4,("r: local list only"));
1016 ok = False;
1019 /* doesn't match up: don't want it */
1020 if (!(servertype & s->type)) {
1021 DEBUG(4,("r:serv type "));
1022 ok = False;
1025 if ((servertype & SV_TYPE_DOMAIN_ENUM) !=
1026 (s->type & SV_TYPE_DOMAIN_ENUM))
1028 DEBUG(4,("s: dom mismatch "));
1029 ok = False;
1032 if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM))
1034 ok = False;
1037 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1038 s->type &= ~SV_TYPE_LOCAL_LIST_ONLY;
1040 if (ok)
1042 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1043 s->name, s->type, s->comment, s->domain));
1045 s->server_added = True;
1046 count++;
1048 else
1050 DEBUG(4,("%20s %8x %25s %15s\n",
1051 s->name, s->type, s->comment, s->domain));
1055 file_lines_free(lines);
1056 return(count);
1060 /*******************************************************************
1061 fill in a server info structure
1062 ******************************************************************/
1063 static int fill_srv_info(struct srv_info_struct *service,
1064 int uLevel, char **buf, int *buflen,
1065 char **stringbuf, int *stringspace, char *baseaddr)
1067 int struct_len;
1068 char* p;
1069 char* p2;
1070 int l2;
1071 int len;
1073 switch (uLevel) {
1074 case 0: struct_len = 16; break;
1075 case 1: struct_len = 26; break;
1076 default: return -1;
1079 if (!buf)
1081 len = 0;
1082 switch (uLevel)
1084 case 1:
1085 len = strlen(service->comment)+1;
1086 break;
1089 if (buflen) *buflen = struct_len;
1090 if (stringspace) *stringspace = len;
1091 return struct_len + len;
1094 len = struct_len;
1095 p = *buf;
1096 if (*buflen < struct_len) return -1;
1097 if (stringbuf)
1099 p2 = *stringbuf;
1100 l2 = *stringspace;
1102 else
1104 p2 = p + struct_len;
1105 l2 = *buflen - struct_len;
1107 if (!baseaddr) baseaddr = p;
1109 switch (uLevel)
1111 case 0:
1112 push_ascii(p,service->name, MAX_NETBIOSNAME_LEN, STR_TERMINATE);
1113 break;
1115 case 1:
1116 push_ascii(p,service->name,MAX_NETBIOSNAME_LEN, STR_TERMINATE);
1117 SIVAL(p,18,service->type);
1118 SIVAL(p,22,PTR_DIFF(p2,baseaddr));
1119 len += CopyAndAdvance(&p2,service->comment,&l2);
1120 break;
1123 if (stringbuf)
1125 *buf = p + struct_len;
1126 *buflen -= struct_len;
1127 *stringbuf = p2;
1128 *stringspace = l2;
1130 else
1132 *buf = p2;
1133 *buflen -= len;
1135 return len;
1139 static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
1141 return(strcmp(s1->name,s2->name));
1144 /****************************************************************************
1145 view list of servers available (or possibly domains). The info is
1146 extracted from lists saved by nmbd on the local host
1147 ****************************************************************************/
1148 static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid, char *param, char *data,
1149 int mdrcnt, int mprcnt, char **rdata,
1150 char **rparam, int *rdata_len, int *rparam_len)
1152 char *str1 = param+2;
1153 char *str2 = skip_string(str1,1);
1154 char *p = skip_string(str2,1);
1155 int uLevel = SVAL(p,0);
1156 int buf_len = SVAL(p,2);
1157 uint32 servertype = IVAL(p,4);
1158 char *p2;
1159 int data_len, fixed_len, string_len;
1160 int f_len = 0, s_len = 0;
1161 struct srv_info_struct *servers=NULL;
1162 int counted=0,total=0;
1163 int i,missed;
1164 fstring domain;
1165 BOOL domain_request;
1166 BOOL local_request;
1168 /* If someone sets all the bits they don't really mean to set
1169 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1170 known servers. */
1172 if (servertype == SV_TYPE_ALL)
1173 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1175 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1176 any other bit (they may just set this bit on it's own) they
1177 want all the locally seen servers. However this bit can be
1178 set on its own so set the requested servers to be
1179 ALL - DOMAIN_ENUM. */
1181 if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM))
1182 servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
1184 domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
1185 local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
1187 p += 8;
1189 if (!prefix_ok(str1,"WrLehD")) return False;
1190 if (!check_server_info(uLevel,str2)) return False;
1192 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1193 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1194 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1196 if (strcmp(str1, "WrLehDz") == 0) {
1197 pull_ascii_fstring(domain, p);
1198 } else {
1199 fstrcpy(domain, lp_workgroup());
1202 if (lp_browse_list())
1203 total = get_server_info(servertype,&servers,domain);
1205 data_len = fixed_len = string_len = 0;
1206 missed = 0;
1208 if (total > 0)
1209 qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
1212 char *lastname=NULL;
1214 for (i=0;i<total;i++)
1216 struct srv_info_struct *s = &servers[i];
1217 if (lastname && strequal(lastname,s->name)) continue;
1218 lastname = s->name;
1219 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1220 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1221 s->name, s->type, s->comment, s->domain));
1223 if (data_len <= buf_len) {
1224 counted++;
1225 fixed_len += f_len;
1226 string_len += s_len;
1227 } else {
1228 missed++;
1233 *rdata_len = fixed_len + string_len;
1234 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
1235 memset(*rdata,'\0',*rdata_len);
1237 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1238 p = *rdata;
1239 f_len = fixed_len;
1240 s_len = string_len;
1243 char *lastname=NULL;
1244 int count2 = counted;
1245 for (i = 0; i < total && count2;i++)
1247 struct srv_info_struct *s = &servers[i];
1248 if (lastname && strequal(lastname,s->name)) continue;
1249 lastname = s->name;
1250 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1251 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1252 s->name, s->type, s->comment, s->domain));
1253 count2--;
1257 *rparam_len = 8;
1258 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1259 SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata));
1260 SSVAL(*rparam,2,0);
1261 SSVAL(*rparam,4,counted);
1262 SSVAL(*rparam,6,counted+missed);
1264 SAFE_FREE(servers);
1266 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1267 domain,uLevel,counted,counted+missed));
1269 return(True);
1272 /****************************************************************************
1273 command 0x34 - suspected of being a "Lookup Names" stub api
1274 ****************************************************************************/
1275 static BOOL api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid, char *param, char *data,
1276 int mdrcnt, int mprcnt, char **rdata,
1277 char **rparam, int *rdata_len, int *rparam_len)
1279 char *str1 = param+2;
1280 char *str2 = skip_string(str1,1);
1281 char *p = skip_string(str2,1);
1282 int uLevel = SVAL(p,0);
1283 int buf_len = SVAL(p,2);
1284 int counted=0;
1285 int missed=0;
1287 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1288 str1, str2, p, uLevel, buf_len));
1290 if (!prefix_ok(str1,"zWrLeh")) return False;
1292 *rdata_len = 0;
1294 *rparam_len = 8;
1295 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1297 SSVAL(*rparam,0,0x08AC); /* informational warning message */
1298 SSVAL(*rparam,2,0);
1299 SSVAL(*rparam,4,counted);
1300 SSVAL(*rparam,6,counted+missed);
1302 return(True);
1305 /****************************************************************************
1306 get info about a share
1307 ****************************************************************************/
1308 static BOOL check_share_info(int uLevel, char* id)
1310 switch( uLevel ) {
1311 case 0:
1312 if (strcmp(id,"B13") != 0) return False;
1313 break;
1314 case 1:
1315 if (strcmp(id,"B13BWz") != 0) return False;
1316 break;
1317 case 2:
1318 if (strcmp(id,"B13BWzWWWzB9B") != 0) return False;
1319 break;
1320 case 91:
1321 if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) return False;
1322 break;
1323 default: return False;
1325 return True;
1328 static int fill_share_info(connection_struct *conn, int snum, int uLevel,
1329 char** buf, int* buflen,
1330 char** stringbuf, int* stringspace, char* baseaddr)
1332 int struct_len;
1333 char* p;
1334 char* p2;
1335 int l2;
1336 int len;
1338 switch( uLevel ) {
1339 case 0: struct_len = 13; break;
1340 case 1: struct_len = 20; break;
1341 case 2: struct_len = 40; break;
1342 case 91: struct_len = 68; break;
1343 default: return -1;
1347 if (!buf)
1349 len = 0;
1350 if (uLevel > 0) len += StrlenExpanded(conn,snum,lp_comment(snum));
1351 if (uLevel > 1) len += strlen(lp_pathname(snum)) + 1;
1352 if (buflen) *buflen = struct_len;
1353 if (stringspace) *stringspace = len;
1354 return struct_len + len;
1357 len = struct_len;
1358 p = *buf;
1359 if ((*buflen) < struct_len) return -1;
1360 if (stringbuf)
1362 p2 = *stringbuf;
1363 l2 = *stringspace;
1365 else
1367 p2 = p + struct_len;
1368 l2 = (*buflen) - struct_len;
1370 if (!baseaddr) baseaddr = p;
1372 push_ascii(p,lp_servicename(snum),13, STR_TERMINATE);
1374 if (uLevel > 0)
1376 int type;
1377 SCVAL(p,13,0);
1378 type = STYPE_DISKTREE;
1379 if (lp_print_ok(snum)) type = STYPE_PRINTQ;
1380 if (strequal("IPC",lp_fstype(snum))) type = STYPE_IPC;
1381 SSVAL(p,14,type); /* device type */
1382 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1383 len += CopyExpanded(conn,snum,&p2,lp_comment(snum),&l2);
1386 if (uLevel > 1)
1388 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1389 SSVALS(p,22,-1); /* max uses */
1390 SSVAL(p,24,1); /* current uses */
1391 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1392 len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1393 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1396 if (uLevel > 2)
1398 memset(p+40,0,SHPWLEN+2);
1399 SSVAL(p,50,0);
1400 SIVAL(p,52,0);
1401 SSVAL(p,56,0);
1402 SSVAL(p,58,0);
1403 SIVAL(p,60,0);
1404 SSVAL(p,64,0);
1405 SSVAL(p,66,0);
1408 if (stringbuf)
1410 (*buf) = p + struct_len;
1411 (*buflen) -= struct_len;
1412 (*stringbuf) = p2;
1413 (*stringspace) = l2;
1415 else
1417 (*buf) = p2;
1418 (*buflen) -= len;
1420 return len;
1423 static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
1424 int mdrcnt,int mprcnt,
1425 char **rdata,char **rparam,
1426 int *rdata_len,int *rparam_len)
1428 char *str1 = param+2;
1429 char *str2 = skip_string(str1,1);
1430 char *netname = skip_string(str2,1);
1431 char *p = skip_string(netname,1);
1432 int uLevel = SVAL(p,0);
1433 int snum = find_service(netname);
1435 if (snum < 0) return False;
1437 /* check it's a supported varient */
1438 if (!prefix_ok(str1,"zWrLh")) return False;
1439 if (!check_share_info(uLevel,str2)) return False;
1441 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
1442 p = *rdata;
1443 *rdata_len = fill_share_info(conn,snum,uLevel,&p,&mdrcnt,0,0,0);
1444 if (*rdata_len < 0) return False;
1446 *rparam_len = 6;
1447 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1448 SSVAL(*rparam,0,NERR_Success);
1449 SSVAL(*rparam,2,0); /* converter word */
1450 SSVAL(*rparam,4,*rdata_len);
1452 return(True);
1455 /****************************************************************************
1456 View the list of available shares.
1458 This function is the server side of the NetShareEnum() RAP call.
1459 It fills the return buffer with share names and share comments.
1460 Note that the return buffer normally (in all known cases) allows only
1461 twelve byte strings for share names (plus one for a nul terminator).
1462 Share names longer than 12 bytes must be skipped.
1463 ****************************************************************************/
1464 static BOOL api_RNetShareEnum( connection_struct *conn,
1465 uint16 vuid,
1466 char *param,
1467 char *data,
1468 int mdrcnt,
1469 int mprcnt,
1470 char **rdata,
1471 char **rparam,
1472 int *rdata_len,
1473 int *rparam_len )
1475 char *str1 = param+2;
1476 char *str2 = skip_string(str1,1);
1477 char *p = skip_string(str2,1);
1478 int uLevel = SVAL(p,0);
1479 int buf_len = SVAL(p,2);
1480 char *p2;
1481 int count=lp_numservices();
1482 int total=0,counted=0;
1483 BOOL missed = False;
1484 int i;
1485 int data_len, fixed_len, string_len;
1486 int f_len = 0, s_len = 0;
1488 if (!prefix_ok(str1,"WrLeh")) return False;
1489 if (!check_share_info(uLevel,str2)) return False;
1491 data_len = fixed_len = string_len = 0;
1492 for (i=0;i<count;i++) {
1493 fstring servicename_dos;
1494 if (!(lp_browseable(i) && lp_snum_ok(i)))
1495 continue;
1496 push_ascii_fstring(servicename_dos, lp_servicename(i));
1497 if( lp_browseable( i )
1498 && lp_snum_ok( i )
1499 && (strlen(servicename_dos) < 13) ) /* Maximum name length. */
1501 total++;
1502 data_len += fill_share_info(conn,i,uLevel,0,&f_len,0,&s_len,0);
1503 if (data_len <= buf_len)
1505 counted++;
1506 fixed_len += f_len;
1507 string_len += s_len;
1509 else
1510 missed = True;
1513 *rdata_len = fixed_len + string_len;
1514 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
1515 memset(*rdata,0,*rdata_len);
1517 p2 = (*rdata) + fixed_len; /* auxiliary data (strings) will go here */
1518 p = *rdata;
1519 f_len = fixed_len;
1520 s_len = string_len;
1521 for( i = 0; i < count; i++ )
1523 fstring servicename_dos;
1524 if (!(lp_browseable(i) && lp_snum_ok(i)))
1525 continue;
1526 push_ascii_fstring(servicename_dos, lp_servicename(i));
1527 if( lp_browseable( i )
1528 && lp_snum_ok( i )
1529 && (strlen(servicename_dos) < 13) )
1531 if( fill_share_info( conn,i,uLevel,&p,&f_len,&p2,&s_len,*rdata ) < 0 )
1532 break;
1536 *rparam_len = 8;
1537 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1538 SSVAL(*rparam,0,missed ? ERRmoredata : NERR_Success);
1539 SSVAL(*rparam,2,0);
1540 SSVAL(*rparam,4,counted);
1541 SSVAL(*rparam,6,total);
1543 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1544 counted,total,uLevel,
1545 buf_len,*rdata_len,mdrcnt));
1546 return(True);
1547 } /* api_RNetShareEnum */
1549 /****************************************************************************
1550 Add a share
1551 ****************************************************************************/
1552 static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid, char *param,char *data,
1553 int mdrcnt,int mprcnt,
1554 char **rdata,char **rparam,
1555 int *rdata_len,int *rparam_len)
1557 char *str1 = param+2;
1558 char *str2 = skip_string(str1,1);
1559 char *p = skip_string(str2,1);
1560 int uLevel = SVAL(p,0);
1561 fstring sharename;
1562 fstring comment;
1563 pstring pathname;
1564 char *command, *cmdname;
1565 unsigned int offset;
1566 int snum;
1567 int res = ERRunsup;
1569 /* check it's a supported varient */
1570 if (!prefix_ok(str1,RAP_WShareAdd_REQ)) return False;
1571 if (!check_share_info(uLevel,str2)) return False;
1572 if (uLevel != 2) return False;
1574 pull_ascii_fstring(sharename,data);
1575 snum = find_service(sharename);
1576 if (snum >= 0) { /* already exists */
1577 res = ERRfilexists;
1578 goto error_exit;
1581 /* only support disk share adds */
1582 if (SVAL(data,14)!=STYPE_DISKTREE) return False;
1584 offset = IVAL(data, 16);
1585 if (offset >= mdrcnt) {
1586 res = ERRinvalidparam;
1587 goto error_exit;
1589 pull_ascii_fstring(comment, offset? (data+offset) : "");
1591 offset = IVAL(data, 26);
1592 if (offset >= mdrcnt) {
1593 res = ERRinvalidparam;
1594 goto error_exit;
1596 pull_ascii_pstring(pathname, offset? (data+offset) : "");
1598 string_replace(sharename, '"', ' ');
1599 string_replace(pathname, '"', ' ');
1600 string_replace(comment, '"', ' ');
1602 cmdname = lp_add_share_cmd();
1604 if (!cmdname || *cmdname == '\0') return False;
1606 asprintf(&command, "%s \"%s\" \"%s\" \"%s\" \"%s\"",
1607 lp_add_share_cmd(), dyn_CONFIGFILE, sharename, pathname, comment);
1609 if (command) {
1610 DEBUG(10,("api_RNetShareAdd: Running [%s]\n", command ));
1611 if ((res = smbrun(command, NULL)) != 0) {
1612 DEBUG(1,("api_RNetShareAdd: Running [%s] returned (%d)\n", command, res ));
1613 SAFE_FREE(command);
1614 res = ERRnoaccess;
1615 goto error_exit;
1616 } else {
1617 SAFE_FREE(command);
1618 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
1620 } else return False;
1622 *rparam_len = 6;
1623 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1624 SSVAL(*rparam,0,NERR_Success);
1625 SSVAL(*rparam,2,0); /* converter word */
1626 SSVAL(*rparam,4,*rdata_len);
1627 *rdata_len = 0;
1629 return True;
1631 error_exit:
1632 *rparam_len = 4;
1633 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1634 *rdata_len = 0;
1635 SSVAL(*rparam,0,res);
1636 SSVAL(*rparam,2,0);
1637 return True;
1641 /****************************************************************************
1642 view list of groups available
1643 ****************************************************************************/
1644 static BOOL api_RNetGroupEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
1645 int mdrcnt,int mprcnt,
1646 char **rdata,char **rparam,
1647 int *rdata_len,int *rparam_len)
1649 int i;
1650 int errflags=0;
1651 int resume_context, cli_buf_size;
1652 char *str1 = param+2;
1653 char *str2 = skip_string(str1,1);
1654 char *p = skip_string(str2,1);
1655 BOOL ret;
1657 GROUP_MAP *group_list;
1658 int num_entries;
1660 if (strcmp(str1,"WrLeh") != 0)
1661 return False;
1663 /* parameters
1664 * W-> resume context (number of users to skip)
1665 * r -> return parameter pointer to receive buffer
1666 * L -> length of receive buffer
1667 * e -> return parameter number of entries
1668 * h -> return parameter total number of users
1670 if (strcmp("B21",str2) != 0)
1671 return False;
1673 /* get list of domain groups SID_DOMAIN_GRP=2 */
1674 become_root();
1675 ret = pdb_enum_group_mapping(SID_NAME_DOM_GRP , &group_list, &num_entries, False);
1676 unbecome_root();
1678 if( !ret ) {
1679 DEBUG(3,("api_RNetGroupEnum:failed to get group list"));
1680 return False;
1683 resume_context = SVAL(p,0);
1684 cli_buf_size=SVAL(p+2,0);
1685 DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: %d\n", resume_context, cli_buf_size));
1687 *rdata_len = cli_buf_size;
1688 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
1690 p = *rdata;
1692 for(i=resume_context; i<num_entries; i++) {
1693 char* name=group_list[i].nt_name;
1694 if( ((PTR_DIFF(p,*rdata)+21) <= *rdata_len) ) {
1695 /* truncate the name at 21 chars. */
1696 memcpy(p, name, 21);
1697 DEBUG(10,("adding entry %d group %s\n", i, p));
1698 p += 21;
1699 } else {
1700 /* set overflow error */
1701 DEBUG(3,("overflow on entry %d group %s\n", i, name));
1702 errflags=234;
1703 break;
1707 *rdata_len = PTR_DIFF(p,*rdata);
1709 *rparam_len = 8;
1710 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1712 SSVAL(*rparam, 0, errflags);
1713 SSVAL(*rparam, 2, 0); /* converter word */
1714 SSVAL(*rparam, 4, i-resume_context); /* is this right?? */
1715 SSVAL(*rparam, 6, num_entries); /* is this right?? */
1717 return(True);
1720 /*******************************************************************
1721 get groups that a user is a member of
1722 ******************************************************************/
1723 static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *param,char *data,
1724 int mdrcnt,int mprcnt,
1725 char **rdata,char **rparam,
1726 int *rdata_len,int *rparam_len)
1728 char *str1 = param+2;
1729 char *str2 = skip_string(str1,1);
1730 char *UserName = skip_string(str2,1);
1731 char *p = skip_string(UserName,1);
1732 int uLevel = SVAL(p,0);
1733 const char *level_string;
1734 int count=0;
1735 SAM_ACCOUNT *sampw = NULL;
1736 BOOL ret = False;
1737 DOM_SID *sids;
1738 gid_t *gids;
1739 int num_groups;
1740 int i;
1741 fstring grp_domain;
1742 fstring grp_name;
1743 enum SID_NAME_USE grp_type;
1744 struct passwd *passwd;
1745 NTSTATUS result;
1747 *rparam_len = 8;
1748 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1750 /* check it's a supported varient */
1752 if ( strcmp(str1,"zWrLeh") != 0 )
1753 return False;
1755 switch( uLevel ) {
1756 case 0:
1757 level_string = "B21";
1758 break;
1759 default:
1760 return False;
1763 if (strcmp(level_string,str2) != 0)
1764 return False;
1766 *rdata_len = mdrcnt + 1024;
1767 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
1769 SSVAL(*rparam,0,NERR_Success);
1770 SSVAL(*rparam,2,0); /* converter word */
1772 p = *rdata;
1774 /* Lookup the user information; This should only be one of
1775 our accounts (not remote domains) */
1777 passwd = getpwnam_alloc(UserName);
1779 if (passwd == NULL)
1780 return False;
1782 pdb_init_sam( &sampw );
1784 become_root(); /* ROOT BLOCK */
1786 if ( !pdb_getsampwnam(sampw, UserName) )
1787 goto out;
1789 sids = NULL;
1790 num_groups = 0;
1792 result = pdb_enum_group_memberships(pdb_get_username(sampw),
1793 passwd->pw_gid,
1794 &sids, &gids, &num_groups);
1796 if (!NT_STATUS_IS_OK(result))
1797 goto out;
1799 for (i=0; i<num_groups; i++) {
1801 if ( lookup_sid(&sids[i], grp_domain, grp_name, &grp_type) ) {
1802 pstrcpy(p, grp_name);
1803 p += 21;
1804 count++;
1808 SAFE_FREE(sids);
1810 *rdata_len = PTR_DIFF(p,*rdata);
1812 SSVAL(*rparam,4,count); /* is this right?? */
1813 SSVAL(*rparam,6,count); /* is this right?? */
1815 ret = True;
1817 out:
1818 unbecome_root(); /* END ROOT BLOCK */
1820 pdb_free_sam( &sampw );
1821 passwd_free(&passwd);
1823 return ret;
1826 /*******************************************************************
1827 get all users
1828 ******************************************************************/
1829 static BOOL api_RNetUserEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
1830 int mdrcnt,int mprcnt,
1831 char **rdata,char **rparam,
1832 int *rdata_len,int *rparam_len)
1834 SAM_ACCOUNT *pwd=NULL;
1835 int count_sent=0;
1836 int count_total=0;
1837 int errflags=0;
1838 int resume_context, cli_buf_size;
1840 char *str1 = param+2;
1841 char *str2 = skip_string(str1,1);
1842 char *p = skip_string(str2,1);
1844 if (strcmp(str1,"WrLeh") != 0)
1845 return False;
1846 /* parameters
1847 * W-> resume context (number of users to skip)
1848 * r -> return parameter pointer to receive buffer
1849 * L -> length of receive buffer
1850 * e -> return parameter number of entries
1851 * h -> return parameter total number of users
1854 resume_context = SVAL(p,0);
1855 cli_buf_size=SVAL(p+2,0);
1856 DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n", resume_context, cli_buf_size));
1858 *rparam_len = 8;
1859 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1861 /* check it's a supported varient */
1862 if (strcmp("B21",str2) != 0)
1863 return False;
1865 *rdata_len = cli_buf_size;
1866 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
1868 p = *rdata;
1870 /* to get user list enumerations for NetUserEnum in B21 format */
1871 pdb_init_sam(&pwd);
1873 /* Open the passgrp file - not for update. */
1874 become_root();
1875 if(!pdb_setsampwent(False, 0)) {
1876 DEBUG(0, ("api_RNetUserEnum:unable to open sam database.\n"));
1877 unbecome_root();
1878 return False;
1880 errflags=NERR_Success;
1882 while ( pdb_getsampwent(pwd) ) {
1883 const char *name=pdb_get_username(pwd);
1884 if ((name) && (*(name+strlen(name)-1)!='$')) {
1885 count_total++;
1886 if(count_total>=resume_context) {
1887 if( ((PTR_DIFF(p,*rdata)+21)<=*rdata_len)&&(strlen(name)<=21) ) {
1888 pstrcpy(p,name);
1889 DEBUG(10,("api_RNetUserEnum:adding entry %d username %s\n",count_sent,p));
1890 p += 21;
1891 count_sent++;
1892 } else {
1893 /* set overflow error */
1894 DEBUG(10,("api_RNetUserEnum:overflow on entry %d username %s\n",count_sent,name));
1895 errflags=234;
1896 break;
1902 pdb_endsampwent();
1903 unbecome_root();
1905 pdb_free_sam(&pwd);
1907 *rdata_len = PTR_DIFF(p,*rdata);
1909 SSVAL(*rparam,0,errflags);
1910 SSVAL(*rparam,2,0); /* converter word */
1911 SSVAL(*rparam,4,count_sent); /* is this right?? */
1912 SSVAL(*rparam,6,count_total); /* is this right?? */
1914 return True;
1919 /****************************************************************************
1920 get the time of day info
1921 ****************************************************************************/
1922 static BOOL api_NetRemoteTOD(connection_struct *conn,uint16 vuid, char *param,char *data,
1923 int mdrcnt,int mprcnt,
1924 char **rdata,char **rparam,
1925 int *rdata_len,int *rparam_len)
1927 char *p;
1928 *rparam_len = 4;
1929 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1931 *rdata_len = 21;
1932 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
1934 SSVAL(*rparam,0,NERR_Success);
1935 SSVAL(*rparam,2,0); /* converter word */
1937 p = *rdata;
1940 struct tm *t;
1941 time_t unixdate = time(NULL);
1943 put_dos_date3(p,0,unixdate); /* this is the time that is looked at
1944 by NT in a "net time" operation,
1945 it seems to ignore the one below */
1947 /* the client expects to get localtime, not GMT, in this bit
1948 (I think, this needs testing) */
1949 t = LocalTime(&unixdate);
1951 SIVAL(p,4,0); /* msecs ? */
1952 SCVAL(p,8,t->tm_hour);
1953 SCVAL(p,9,t->tm_min);
1954 SCVAL(p,10,t->tm_sec);
1955 SCVAL(p,11,0); /* hundredths of seconds */
1956 SSVALS(p,12,TimeDiff(unixdate)/60); /* timezone in minutes from GMT */
1957 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
1958 SCVAL(p,16,t->tm_mday);
1959 SCVAL(p,17,t->tm_mon + 1);
1960 SSVAL(p,18,1900+t->tm_year);
1961 SCVAL(p,20,t->tm_wday);
1965 return(True);
1968 /****************************************************************************
1969 Set the user password.
1970 *****************************************************************************/
1972 static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param,char *data,
1973 int mdrcnt,int mprcnt,
1974 char **rdata,char **rparam,
1975 int *rdata_len,int *rparam_len)
1977 char *p = skip_string(param+2,2);
1978 fstring user;
1979 fstring pass1,pass2;
1981 pull_ascii_fstring(user,p);
1983 p = skip_string(p,1);
1985 memset(pass1,'\0',sizeof(pass1));
1986 memset(pass2,'\0',sizeof(pass2));
1987 memcpy(pass1,p,16);
1988 memcpy(pass2,p+16,16);
1990 *rparam_len = 4;
1991 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1993 *rdata_len = 0;
1995 SSVAL(*rparam,0,NERR_badpass);
1996 SSVAL(*rparam,2,0); /* converter word */
1998 DEBUG(3,("Set password for <%s>\n",user));
2001 * Attempt to verify the old password against smbpasswd entries
2002 * Win98 clients send old and new password in plaintext for this call.
2006 auth_serversupplied_info *server_info = NULL;
2007 DATA_BLOB password = data_blob(pass1, strlen(pass1)+1);
2009 if (NT_STATUS_IS_OK(check_plaintext_password(user,password,&server_info))) {
2011 become_root();
2012 if (NT_STATUS_IS_OK(change_oem_password(server_info->sam_account, pass1, pass2, False))) {
2013 SSVAL(*rparam,0,NERR_Success);
2015 unbecome_root();
2017 free_server_info(&server_info);
2019 data_blob_clear_free(&password);
2023 * If the plaintext change failed, attempt
2024 * the old encrypted method. NT will generate this
2025 * after trying the samr method. Note that this
2026 * method is done as a last resort as this
2027 * password change method loses the NT password hash
2028 * and cannot change the UNIX password as no plaintext
2029 * is received.
2032 if(SVAL(*rparam,0) != NERR_Success) {
2033 SAM_ACCOUNT *hnd = NULL;
2035 if (check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &hnd)) {
2036 become_root();
2037 if (change_lanman_password(hnd,(uchar *)pass2)) {
2038 SSVAL(*rparam,0,NERR_Success);
2040 unbecome_root();
2041 pdb_free_sam(&hnd);
2045 memset((char *)pass1,'\0',sizeof(fstring));
2046 memset((char *)pass2,'\0',sizeof(fstring));
2048 return(True);
2051 /****************************************************************************
2052 Set the user password (SamOEM version - gets plaintext).
2053 ****************************************************************************/
2055 static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char *param,char *data,
2056 int mdrcnt,int mprcnt,
2057 char **rdata,char **rparam,
2058 int *rdata_len,int *rparam_len)
2060 fstring user;
2061 char *p = param + 2;
2062 *rparam_len = 2;
2063 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2065 *rdata_len = 0;
2067 SSVAL(*rparam,0,NERR_badpass);
2070 * Check the parameter definition is correct.
2073 if(!strequal(param + 2, "zsT")) {
2074 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", param + 2));
2075 return False;
2077 p = skip_string(p, 1);
2079 if(!strequal(p, "B516B16")) {
2080 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p));
2081 return False;
2083 p = skip_string(p,1);
2084 p += pull_ascii_fstring(user,p);
2086 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user));
2089 * Pass the user through the NT -> unix user mapping
2090 * function.
2093 (void)map_username(user);
2095 if (NT_STATUS_IS_OK(pass_oem_change(user, (uchar*) data, (uchar *)&data[516], NULL, NULL))) {
2096 SSVAL(*rparam,0,NERR_Success);
2099 return(True);
2102 /****************************************************************************
2103 delete a print job
2104 Form: <W> <>
2105 ****************************************************************************/
2106 static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char *param,char *data,
2107 int mdrcnt,int mprcnt,
2108 char **rdata,char **rparam,
2109 int *rdata_len,int *rparam_len)
2111 int function = SVAL(param,0);
2112 char *str1 = param+2;
2113 char *str2 = skip_string(str1,1);
2114 char *p = skip_string(str2,1);
2115 uint32 jobid;
2116 int snum;
2117 fstring sharename;
2118 int errcode;
2119 extern struct current_user current_user;
2120 WERROR werr = WERR_OK;
2122 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
2123 return False;
2125 /* check it's a supported varient */
2126 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
2127 return(False);
2129 *rparam_len = 4;
2130 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2131 *rdata_len = 0;
2133 if (!print_job_exists(sharename, jobid)) {
2134 errcode = NERR_JobNotFound;
2135 goto out;
2138 snum = lp_servicenumber( sharename);
2139 if (snum == -1) {
2140 errcode = NERR_DestNotFound;
2141 goto out;
2144 errcode = NERR_notsupported;
2146 switch (function) {
2147 case 81: /* delete */
2148 if (print_job_delete(&current_user, snum, jobid, &werr))
2149 errcode = NERR_Success;
2150 break;
2151 case 82: /* pause */
2152 if (print_job_pause(&current_user, snum, jobid, &werr))
2153 errcode = NERR_Success;
2154 break;
2155 case 83: /* resume */
2156 if (print_job_resume(&current_user, snum, jobid, &werr))
2157 errcode = NERR_Success;
2158 break;
2161 if (!W_ERROR_IS_OK(werr))
2162 errcode = W_ERROR_V(werr);
2164 out:
2165 SSVAL(*rparam,0,errcode);
2166 SSVAL(*rparam,2,0); /* converter word */
2168 return(True);
2171 /****************************************************************************
2172 Purge a print queue - or pause or resume it.
2173 ****************************************************************************/
2174 static BOOL api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid, char *param,char *data,
2175 int mdrcnt,int mprcnt,
2176 char **rdata,char **rparam,
2177 int *rdata_len,int *rparam_len)
2179 int function = SVAL(param,0);
2180 char *str1 = param+2;
2181 char *str2 = skip_string(str1,1);
2182 char *QueueName = skip_string(str2,1);
2183 int errcode = NERR_notsupported;
2184 int snum;
2185 WERROR werr = WERR_OK;
2186 extern struct current_user current_user;
2188 /* check it's a supported varient */
2189 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
2190 return(False);
2192 *rparam_len = 4;
2193 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2194 *rdata_len = 0;
2196 snum = print_queue_snum(QueueName);
2198 if (snum == -1) {
2199 errcode = NERR_JobNotFound;
2200 goto out;
2203 switch (function) {
2204 case 74: /* Pause queue */
2205 if (print_queue_pause(&current_user, snum, &werr)) errcode = NERR_Success;
2206 break;
2207 case 75: /* Resume queue */
2208 if (print_queue_resume(&current_user, snum, &werr)) errcode = NERR_Success;
2209 break;
2210 case 103: /* Purge */
2211 if (print_queue_purge(&current_user, snum, &werr)) errcode = NERR_Success;
2212 break;
2215 if (!W_ERROR_IS_OK(werr)) errcode = W_ERROR_V(werr);
2217 out:
2218 SSVAL(*rparam,0,errcode);
2219 SSVAL(*rparam,2,0); /* converter word */
2221 return(True);
2225 /****************************************************************************
2226 set the property of a print job (undocumented?)
2227 ? function = 0xb -> set name of print job
2228 ? function = 0x6 -> move print job up/down
2229 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
2230 or <WWsTP> <WB21BB16B10zWWzDDz>
2231 ****************************************************************************/
2232 static int check_printjob_info(struct pack_desc* desc,
2233 int uLevel, char* id)
2235 desc->subformat = NULL;
2236 switch( uLevel ) {
2237 case 0: desc->format = "W"; break;
2238 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
2239 case 2: desc->format = "WWzWWDDzz"; break;
2240 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
2241 case 4: desc->format = "WWzWWDDzzzzzDDDDDDD"; break;
2242 default: return False;
2244 if (strcmp(desc->format,id) != 0) return False;
2245 return True;
2248 static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,char *data,
2249 int mdrcnt,int mprcnt,
2250 char **rdata,char **rparam,
2251 int *rdata_len,int *rparam_len)
2253 struct pack_desc desc;
2254 char *str1 = param+2;
2255 char *str2 = skip_string(str1,1);
2256 char *p = skip_string(str2,1);
2257 uint32 jobid;
2258 int snum;
2259 fstring sharename;
2260 int uLevel = SVAL(p,2);
2261 int function = SVAL(p,4);
2262 int place, errcode;
2264 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
2265 return False;
2266 *rparam_len = 4;
2267 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2269 if ( (snum = lp_servicenumber(sharename)) == -1 ) {
2270 DEBUG(0,("api_PrintJobInfo: unable to get service number from sharename [%s]\n",
2271 sharename));
2272 return False;
2275 *rdata_len = 0;
2277 /* check it's a supported varient */
2278 if ((strcmp(str1,"WWsTP")) ||
2279 (!check_printjob_info(&desc,uLevel,str2)))
2280 return(False);
2282 if (!print_job_exists(sharename, jobid)) {
2283 errcode=NERR_JobNotFound;
2284 goto out;
2287 errcode = NERR_notsupported;
2289 switch (function) {
2290 case 0x6:
2291 /* change job place in the queue,
2292 data gives the new place */
2293 place = SVAL(data,0);
2294 if (print_job_set_place(snum, jobid, place)) {
2295 errcode=NERR_Success;
2297 break;
2299 case 0xb:
2300 /* change print job name, data gives the name */
2301 if (print_job_set_name(snum, jobid, data)) {
2302 errcode=NERR_Success;
2304 break;
2306 default:
2307 return False;
2310 out:
2311 SSVALS(*rparam,0,errcode);
2312 SSVAL(*rparam,2,0); /* converter word */
2314 return(True);
2318 /****************************************************************************
2319 get info about the server
2320 ****************************************************************************/
2321 static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2322 int mdrcnt,int mprcnt,
2323 char **rdata,char **rparam,
2324 int *rdata_len,int *rparam_len)
2326 char *str1 = param+2;
2327 char *str2 = skip_string(str1,1);
2328 char *p = skip_string(str2,1);
2329 int uLevel = SVAL(p,0);
2330 char *p2;
2331 int struct_len;
2333 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
2335 /* check it's a supported varient */
2336 if (!prefix_ok(str1,"WrLh")) return False;
2337 switch( uLevel ) {
2338 case 0:
2339 if (strcmp(str2,"B16") != 0) return False;
2340 struct_len = 16;
2341 break;
2342 case 1:
2343 if (strcmp(str2,"B16BBDz") != 0) return False;
2344 struct_len = 26;
2345 break;
2346 case 2:
2347 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")
2348 != 0) return False;
2349 struct_len = 134;
2350 break;
2351 case 3:
2352 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz")
2353 != 0) return False;
2354 struct_len = 144;
2355 break;
2356 case 20:
2357 if (strcmp(str2,"DN") != 0) return False;
2358 struct_len = 6;
2359 break;
2360 case 50:
2361 if (strcmp(str2,"B16BBDzWWzzz") != 0) return False;
2362 struct_len = 42;
2363 break;
2364 default: return False;
2367 *rdata_len = mdrcnt;
2368 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
2370 p = *rdata;
2371 p2 = p + struct_len;
2372 if (uLevel != 20) {
2373 srvstr_push(NULL, p,get_local_machine_name(),16,
2374 STR_ASCII|STR_UPPER|STR_TERMINATE);
2376 p += 16;
2377 if (uLevel > 0)
2379 struct srv_info_struct *servers=NULL;
2380 int i,count;
2381 pstring comment;
2382 uint32 servertype= lp_default_server_announce();
2384 push_ascii(comment,lp_serverstring(), MAX_SERVER_STRING_LENGTH,STR_TERMINATE);
2386 if ((count=get_server_info(SV_TYPE_ALL,&servers,lp_workgroup()))>0) {
2387 for (i=0;i<count;i++) {
2388 if (strequal(servers[i].name,get_local_machine_name())) {
2389 servertype = servers[i].type;
2390 push_ascii(comment,servers[i].comment,sizeof(pstring),STR_TERMINATE);
2394 SAFE_FREE(servers);
2396 SCVAL(p,0,lp_major_announce_version());
2397 SCVAL(p,1,lp_minor_announce_version());
2398 SIVAL(p,2,servertype);
2400 if (mdrcnt == struct_len) {
2401 SIVAL(p,6,0);
2402 } else {
2403 SIVAL(p,6,PTR_DIFF(p2,*rdata));
2404 standard_sub_conn(conn,comment,sizeof(comment));
2405 StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
2406 p2 = skip_string(p2,1);
2409 if (uLevel > 1)
2411 return False; /* not yet implemented */
2414 *rdata_len = PTR_DIFF(p2,*rdata);
2416 *rparam_len = 6;
2417 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2418 SSVAL(*rparam,0,NERR_Success);
2419 SSVAL(*rparam,2,0); /* converter word */
2420 SSVAL(*rparam,4,*rdata_len);
2422 return(True);
2426 /****************************************************************************
2427 get info about the server
2428 ****************************************************************************/
2429 static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2430 int mdrcnt,int mprcnt,
2431 char **rdata,char **rparam,
2432 int *rdata_len,int *rparam_len)
2434 char *str1 = param+2;
2435 char *str2 = skip_string(str1,1);
2436 char *p = skip_string(str2,1);
2437 char *p2;
2438 extern userdom_struct current_user_info;
2439 int level = SVAL(p,0);
2441 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
2443 *rparam_len = 6;
2444 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2446 /* check it's a supported varient */
2447 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz")))
2448 return(False);
2450 *rdata_len = mdrcnt + 1024;
2451 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
2453 SSVAL(*rparam,0,NERR_Success);
2454 SSVAL(*rparam,2,0); /* converter word */
2456 p = *rdata;
2457 p2 = p + 22;
2460 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
2461 pstrcpy(p2,get_local_machine_name());
2462 strupper_m(p2);
2463 p2 = skip_string(p2,1);
2464 p += 4;
2466 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2467 pstrcpy(p2,current_user_info.smb_name);
2468 p2 = skip_string(p2,1);
2469 p += 4;
2471 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
2472 pstrcpy(p2,lp_workgroup());
2473 strupper_m(p2);
2474 p2 = skip_string(p2,1);
2475 p += 4;
2477 SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
2478 SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
2479 p += 2;
2481 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2482 pstrcpy(p2,lp_workgroup()); /* don't know. login domain?? */
2483 p2 = skip_string(p2,1);
2484 p += 4;
2486 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
2487 pstrcpy(p2,"");
2488 p2 = skip_string(p2,1);
2489 p += 4;
2491 *rdata_len = PTR_DIFF(p2,*rdata);
2493 SSVAL(*rparam,4,*rdata_len);
2495 return(True);
2498 /****************************************************************************
2499 get info about a user
2501 struct user_info_11 {
2502 char usri11_name[21]; 0-20
2503 char usri11_pad; 21
2504 char *usri11_comment; 22-25
2505 char *usri11_usr_comment; 26-29
2506 unsigned short usri11_priv; 30-31
2507 unsigned long usri11_auth_flags; 32-35
2508 long usri11_password_age; 36-39
2509 char *usri11_homedir; 40-43
2510 char *usri11_parms; 44-47
2511 long usri11_last_logon; 48-51
2512 long usri11_last_logoff; 52-55
2513 unsigned short usri11_bad_pw_count; 56-57
2514 unsigned short usri11_num_logons; 58-59
2515 char *usri11_logon_server; 60-63
2516 unsigned short usri11_country_code; 64-65
2517 char *usri11_workstations; 66-69
2518 unsigned long usri11_max_storage; 70-73
2519 unsigned short usri11_units_per_week; 74-75
2520 unsigned char *usri11_logon_hours; 76-79
2521 unsigned short usri11_code_page; 80-81
2524 where:
2526 usri11_name specifies the user name for which information is retireved
2528 usri11_pad aligns the next data structure element to a word boundary
2530 usri11_comment is a null terminated ASCII comment
2532 usri11_user_comment is a null terminated ASCII comment about the user
2534 usri11_priv specifies the level of the privilege assigned to the user.
2535 The possible values are:
2537 Name Value Description
2538 USER_PRIV_GUEST 0 Guest privilege
2539 USER_PRIV_USER 1 User privilege
2540 USER_PRV_ADMIN 2 Administrator privilege
2542 usri11_auth_flags specifies the account operator privileges. The
2543 possible values are:
2545 Name Value Description
2546 AF_OP_PRINT 0 Print operator
2549 Leach, Naik [Page 28]
2553 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2556 AF_OP_COMM 1 Communications operator
2557 AF_OP_SERVER 2 Server operator
2558 AF_OP_ACCOUNTS 3 Accounts operator
2561 usri11_password_age specifies how many seconds have elapsed since the
2562 password was last changed.
2564 usri11_home_dir points to a null terminated ASCII string that contains
2565 the path name of the user's home directory.
2567 usri11_parms points to a null terminated ASCII string that is set
2568 aside for use by applications.
2570 usri11_last_logon specifies the time when the user last logged on.
2571 This value is stored as the number of seconds elapsed since
2572 00:00:00, January 1, 1970.
2574 usri11_last_logoff specifies the time when the user last logged off.
2575 This value is stored as the number of seconds elapsed since
2576 00:00:00, January 1, 1970. A value of 0 means the last logoff
2577 time is unknown.
2579 usri11_bad_pw_count specifies the number of incorrect passwords
2580 entered since the last successful logon.
2582 usri11_log1_num_logons specifies the number of times this user has
2583 logged on. A value of -1 means the number of logons is unknown.
2585 usri11_logon_server points to a null terminated ASCII string that
2586 contains the name of the server to which logon requests are sent.
2587 A null string indicates logon requests should be sent to the
2588 domain controller.
2590 usri11_country_code specifies the country code for the user's language
2591 of choice.
2593 usri11_workstations points to a null terminated ASCII string that
2594 contains the names of workstations the user may log on from.
2595 There may be up to 8 workstations, with the names separated by
2596 commas. A null strings indicates there are no restrictions.
2598 usri11_max_storage specifies the maximum amount of disk space the user
2599 can occupy. A value of 0xffffffff indicates there are no
2600 restrictions.
2602 usri11_units_per_week specifies the equal number of time units into
2603 which a week is divided. This value must be equal to 168.
2605 usri11_logon_hours points to a 21 byte (168 bits) string that
2606 specifies the time during which the user can log on. Each bit
2607 represents one unique hour in a week. The first bit (bit 0, word
2608 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
2612 Leach, Naik [Page 29]
2616 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2619 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
2620 are no restrictions.
2622 usri11_code_page specifies the code page for the user's language of
2623 choice
2625 All of the pointers in this data structure need to be treated
2626 specially. The pointer is a 32 bit pointer. The higher 16 bits need
2627 to be ignored. The converter word returned in the parameters section
2628 needs to be subtracted from the lower 16 bits to calculate an offset
2629 into the return buffer where this ASCII string resides.
2631 There is no auxiliary data in the response.
2633 ****************************************************************************/
2635 #define usri11_name 0
2636 #define usri11_pad 21
2637 #define usri11_comment 22
2638 #define usri11_usr_comment 26
2639 #define usri11_full_name 30
2640 #define usri11_priv 34
2641 #define usri11_auth_flags 36
2642 #define usri11_password_age 40
2643 #define usri11_homedir 44
2644 #define usri11_parms 48
2645 #define usri11_last_logon 52
2646 #define usri11_last_logoff 56
2647 #define usri11_bad_pw_count 60
2648 #define usri11_num_logons 62
2649 #define usri11_logon_server 64
2650 #define usri11_country_code 68
2651 #define usri11_workstations 70
2652 #define usri11_max_storage 74
2653 #define usri11_units_per_week 78
2654 #define usri11_logon_hours 80
2655 #define usri11_code_page 84
2656 #define usri11_end 86
2658 #define USER_PRIV_GUEST 0
2659 #define USER_PRIV_USER 1
2660 #define USER_PRIV_ADMIN 2
2662 #define AF_OP_PRINT 0
2663 #define AF_OP_COMM 1
2664 #define AF_OP_SERVER 2
2665 #define AF_OP_ACCOUNTS 3
2668 static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2669 int mdrcnt,int mprcnt,
2670 char **rdata,char **rparam,
2671 int *rdata_len,int *rparam_len)
2673 char *str1 = param+2;
2674 char *str2 = skip_string(str1,1);
2675 char *UserName = skip_string(str2,1);
2676 char *p = skip_string(UserName,1);
2677 int uLevel = SVAL(p,0);
2678 char *p2;
2679 const char *level_string;
2681 /* get NIS home of a previously validated user - simeon */
2682 /* With share level security vuid will always be zero.
2683 Don't depend on vuser being non-null !!. JRA */
2684 user_struct *vuser = get_valid_user_struct(vuid);
2685 if(vuser != NULL)
2686 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid,
2687 vuser->user.unix_name));
2689 *rparam_len = 6;
2690 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2692 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
2694 /* check it's a supported variant */
2695 if (strcmp(str1,"zWrLh") != 0) return False;
2696 switch( uLevel )
2698 case 0: level_string = "B21"; break;
2699 case 1: level_string = "B21BB16DWzzWz"; break;
2700 case 2: level_string = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
2701 case 10: level_string = "B21Bzzz"; break;
2702 case 11: level_string = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
2703 default: return False;
2706 if (strcmp(level_string,str2) != 0) return False;
2708 *rdata_len = mdrcnt + 1024;
2709 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
2711 SSVAL(*rparam,0,NERR_Success);
2712 SSVAL(*rparam,2,0); /* converter word */
2714 p = *rdata;
2715 p2 = p + usri11_end;
2717 memset(p,0,21);
2718 fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
2720 if (uLevel > 0)
2722 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
2723 *p2 = 0;
2725 if (uLevel >= 10)
2727 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
2728 pstrcpy(p2,"Comment");
2729 p2 = skip_string(p2,1);
2731 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
2732 pstrcpy(p2,"UserComment");
2733 p2 = skip_string(p2,1);
2735 /* EEK! the cifsrap.txt doesn't have this in!!!! */
2736 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
2737 pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName));
2738 p2 = skip_string(p2,1);
2741 if (uLevel == 11) /* modelled after NTAS 3.51 reply */
2743 SSVAL(p,usri11_priv,conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2744 SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
2745 SIVALS(p,usri11_password_age,-1); /* password age */
2746 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
2747 pstrcpy(p2, vuser && vuser->homedir ? vuser->homedir : "");
2748 p2 = skip_string(p2,1);
2749 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
2750 pstrcpy(p2,"");
2751 p2 = skip_string(p2,1);
2752 SIVAL(p,usri11_last_logon,0); /* last logon */
2753 SIVAL(p,usri11_last_logoff,0); /* last logoff */
2754 SSVALS(p,usri11_bad_pw_count,-1); /* bad pw counts */
2755 SSVALS(p,usri11_num_logons,-1); /* num logons */
2756 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
2757 pstrcpy(p2,"\\\\*");
2758 p2 = skip_string(p2,1);
2759 SSVAL(p,usri11_country_code,0); /* country code */
2761 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
2762 pstrcpy(p2,"");
2763 p2 = skip_string(p2,1);
2765 SIVALS(p,usri11_max_storage,-1); /* max storage */
2766 SSVAL(p,usri11_units_per_week,168); /* units per week */
2767 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
2769 /* a simple way to get logon hours at all times. */
2770 memset(p2,0xff,21);
2771 SCVAL(p2,21,0); /* fix zero termination */
2772 p2 = skip_string(p2,1);
2774 SSVAL(p,usri11_code_page,0); /* code page */
2776 if (uLevel == 1 || uLevel == 2)
2778 memset(p+22,' ',16); /* password */
2779 SIVALS(p,38,-1); /* password age */
2780 SSVAL(p,42,
2781 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2782 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
2783 pstrcpy(p2, vuser && vuser->homedir ? vuser->homedir : "");
2784 p2 = skip_string(p2,1);
2785 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
2786 *p2++ = 0;
2787 SSVAL(p,52,0); /* flags */
2788 SIVAL(p,54,PTR_DIFF(p2,*rdata)); /* script_path */
2789 pstrcpy(p2,vuser && vuser->logon_script ? vuser->logon_script : "");
2790 p2 = skip_string(p2,1);
2791 if (uLevel == 2)
2793 SIVAL(p,60,0); /* auth_flags */
2794 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
2795 pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName));
2796 p2 = skip_string(p2,1);
2797 SIVAL(p,68,0); /* urs_comment */
2798 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
2799 pstrcpy(p2,"");
2800 p2 = skip_string(p2,1);
2801 SIVAL(p,76,0); /* workstations */
2802 SIVAL(p,80,0); /* last_logon */
2803 SIVAL(p,84,0); /* last_logoff */
2804 SIVALS(p,88,-1); /* acct_expires */
2805 SIVALS(p,92,-1); /* max_storage */
2806 SSVAL(p,96,168); /* units_per_week */
2807 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
2808 memset(p2,-1,21);
2809 p2 += 21;
2810 SSVALS(p,102,-1); /* bad_pw_count */
2811 SSVALS(p,104,-1); /* num_logons */
2812 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
2813 pstrcpy(p2,"\\\\%L");
2814 standard_sub_conn(conn, p2,0);
2815 p2 = skip_string(p2,1);
2816 SSVAL(p,110,49); /* country_code */
2817 SSVAL(p,112,860); /* code page */
2821 *rdata_len = PTR_DIFF(p2,*rdata);
2823 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
2825 return(True);
2828 static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param,char *data,
2829 int mdrcnt,int mprcnt,
2830 char **rdata,char **rparam,
2831 int *rdata_len,int *rparam_len)
2833 char *str1 = param+2;
2834 char *str2 = skip_string(str1,1);
2835 char *p = skip_string(str2,1);
2836 int uLevel;
2837 struct pack_desc desc;
2838 char* name;
2839 /* With share level security vuid will always be zero.
2840 Don't depend on vuser being non-null !!. JRA */
2841 user_struct *vuser = get_valid_user_struct(vuid);
2842 if(vuser != NULL)
2843 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid,
2844 vuser->user.unix_name));
2846 uLevel = SVAL(p,0);
2847 name = p + 2;
2849 memset((char *)&desc,'\0',sizeof(desc));
2851 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
2853 /* check it's a supported varient */
2854 if (strcmp(str1,"OOWb54WrLh") != 0) return False;
2855 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) return False;
2856 if (mdrcnt > 0) *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
2857 desc.base = *rdata;
2858 desc.buflen = mdrcnt;
2859 desc.subformat = NULL;
2860 desc.format = str2;
2862 if (init_package(&desc,1,0))
2864 PACKI(&desc,"W",0); /* code */
2865 PACKS(&desc,"B21",name); /* eff. name */
2866 PACKS(&desc,"B",""); /* pad */
2867 PACKI(&desc,"W",
2868 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2869 PACKI(&desc,"D",0); /* auth flags XXX */
2870 PACKI(&desc,"W",0); /* num logons */
2871 PACKI(&desc,"W",0); /* bad pw count */
2872 PACKI(&desc,"D",0); /* last logon */
2873 PACKI(&desc,"D",-1); /* last logoff */
2874 PACKI(&desc,"D",-1); /* logoff time */
2875 PACKI(&desc,"D",-1); /* kickoff time */
2876 PACKI(&desc,"D",0); /* password age */
2877 PACKI(&desc,"D",0); /* password can change */
2878 PACKI(&desc,"D",-1); /* password must change */
2880 fstring mypath;
2881 fstrcpy(mypath,"\\\\");
2882 fstrcat(mypath,get_local_machine_name());
2883 strupper_m(mypath);
2884 PACKS(&desc,"z",mypath); /* computer */
2886 PACKS(&desc,"z",lp_workgroup());/* domain */
2888 PACKS(&desc,"z", vuser && vuser->logon_script ? vuser->logon_script :""); /* script path */
2890 PACKI(&desc,"D",0x00000000); /* reserved */
2893 *rdata_len = desc.usedlen;
2894 *rparam_len = 6;
2895 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2896 SSVALS(*rparam,0,desc.errcode);
2897 SSVAL(*rparam,2,0);
2898 SSVAL(*rparam,4,desc.neededlen);
2900 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
2901 return(True);
2905 /****************************************************************************
2906 api_WAccessGetUserPerms
2907 ****************************************************************************/
2908 static BOOL api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid, char *param,char *data,
2909 int mdrcnt,int mprcnt,
2910 char **rdata,char **rparam,
2911 int *rdata_len,int *rparam_len)
2913 char *str1 = param+2;
2914 char *str2 = skip_string(str1,1);
2915 char *user = skip_string(str2,1);
2916 char *resource = skip_string(user,1);
2918 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
2920 /* check it's a supported varient */
2921 if (strcmp(str1,"zzh") != 0) return False;
2922 if (strcmp(str2,"") != 0) return False;
2924 *rparam_len = 6;
2925 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2926 SSVALS(*rparam,0,0); /* errorcode */
2927 SSVAL(*rparam,2,0); /* converter word */
2928 SSVAL(*rparam,4,0x7f); /* permission flags */
2930 return(True);
2933 /****************************************************************************
2934 api_WPrintJobEnumerate
2935 ****************************************************************************/
2936 static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2937 int mdrcnt,int mprcnt,
2938 char **rdata,char **rparam,
2939 int *rdata_len,int *rparam_len)
2941 char *str1 = param+2;
2942 char *str2 = skip_string(str1,1);
2943 char *p = skip_string(str2,1);
2944 int uLevel;
2945 int count;
2946 int i;
2947 int snum;
2948 fstring sharename;
2949 uint32 jobid;
2950 struct pack_desc desc;
2951 print_queue_struct *queue=NULL;
2952 print_status_struct status;
2953 char *tmpdata=NULL;
2955 uLevel = SVAL(p,2);
2957 memset((char *)&desc,'\0',sizeof(desc));
2958 memset((char *)&status,'\0',sizeof(status));
2960 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
2962 /* check it's a supported varient */
2963 if (strcmp(str1,"WWrLh") != 0) return False;
2964 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2966 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
2967 return False;
2969 snum = lp_servicenumber( sharename);
2970 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2972 count = print_queue_status(snum,&queue,&status);
2973 for (i = 0; i < count; i++) {
2974 if (queue[i].job == jobid) break;
2977 if (mdrcnt > 0) {
2978 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
2979 desc.base = *rdata;
2980 desc.buflen = mdrcnt;
2981 } else {
2983 * Don't return data but need to get correct length
2984 * init_package will return wrong size if buflen=0
2986 desc.buflen = getlen(desc.format);
2987 desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen );
2990 if (init_package(&desc,1,0)) {
2991 if (i < count) {
2992 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
2993 *rdata_len = desc.usedlen;
2995 else {
2996 desc.errcode = NERR_JobNotFound;
2997 *rdata_len = 0;
3001 *rparam_len = 6;
3002 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3003 SSVALS(*rparam,0,desc.errcode);
3004 SSVAL(*rparam,2,0);
3005 SSVAL(*rparam,4,desc.neededlen);
3007 SAFE_FREE(queue);
3008 SAFE_FREE(tmpdata);
3010 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
3011 return(True);
3014 static BOOL api_WPrintJobEnumerate(connection_struct *conn,uint16 vuid, char *param,char *data,
3015 int mdrcnt,int mprcnt,
3016 char **rdata,char **rparam,
3017 int *rdata_len,int *rparam_len)
3019 char *str1 = param+2;
3020 char *str2 = skip_string(str1,1);
3021 char *p = skip_string(str2,1);
3022 char* name = p;
3023 int uLevel;
3024 int count;
3025 int i, succnt=0;
3026 int snum;
3027 struct pack_desc desc;
3028 print_queue_struct *queue=NULL;
3029 print_status_struct status;
3031 memset((char *)&desc,'\0',sizeof(desc));
3032 memset((char *)&status,'\0',sizeof(status));
3034 p = skip_string(p,1);
3035 uLevel = SVAL(p,0);
3037 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
3039 /* check it's a supported variant */
3040 if (strcmp(str1,"zWrLeh") != 0)
3041 return False;
3043 if (uLevel > 2)
3044 return False; /* defined only for uLevel 0,1,2 */
3046 if (!check_printjob_info(&desc,uLevel,str2))
3047 return False;
3049 snum = find_service(name);
3050 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
3051 return False;
3053 count = print_queue_status(snum,&queue,&status);
3054 if (mdrcnt > 0) *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3055 desc.base = *rdata;
3056 desc.buflen = mdrcnt;
3058 if (init_package(&desc,count,0)) {
3059 succnt = 0;
3060 for (i = 0; i < count; i++) {
3061 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
3062 if (desc.errcode == NERR_Success) succnt = i+1;
3066 *rdata_len = desc.usedlen;
3068 *rparam_len = 8;
3069 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3070 SSVALS(*rparam,0,desc.errcode);
3071 SSVAL(*rparam,2,0);
3072 SSVAL(*rparam,4,succnt);
3073 SSVAL(*rparam,6,count);
3075 SAFE_FREE(queue);
3077 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
3078 return(True);
3081 static int check_printdest_info(struct pack_desc* desc,
3082 int uLevel, char* id)
3084 desc->subformat = NULL;
3085 switch( uLevel ) {
3086 case 0: desc->format = "B9"; break;
3087 case 1: desc->format = "B9B21WWzW"; break;
3088 case 2: desc->format = "z"; break;
3089 case 3: desc->format = "zzzWWzzzWW"; break;
3090 default: return False;
3092 if (strcmp(desc->format,id) != 0) return False;
3093 return True;
3096 static void fill_printdest_info(connection_struct *conn, int snum, int uLevel,
3097 struct pack_desc* desc)
3099 char buf[100];
3100 strncpy(buf,SERVICE(snum),sizeof(buf)-1);
3101 buf[sizeof(buf)-1] = 0;
3102 strupper_m(buf);
3103 if (uLevel <= 1) {
3104 PACKS(desc,"B9",buf); /* szName */
3105 if (uLevel == 1) {
3106 PACKS(desc,"B21",""); /* szUserName */
3107 PACKI(desc,"W",0); /* uJobId */
3108 PACKI(desc,"W",0); /* fsStatus */
3109 PACKS(desc,"z",""); /* pszStatus */
3110 PACKI(desc,"W",0); /* time */
3113 if (uLevel == 2 || uLevel == 3) {
3114 PACKS(desc,"z",buf); /* pszPrinterName */
3115 if (uLevel == 3) {
3116 PACKS(desc,"z",""); /* pszUserName */
3117 PACKS(desc,"z",""); /* pszLogAddr */
3118 PACKI(desc,"W",0); /* uJobId */
3119 PACKI(desc,"W",0); /* fsStatus */
3120 PACKS(desc,"z",""); /* pszStatus */
3121 PACKS(desc,"z",""); /* pszComment */
3122 PACKS(desc,"z","NULL"); /* pszDrivers */
3123 PACKI(desc,"W",0); /* time */
3124 PACKI(desc,"W",0); /* pad1 */
3129 static BOOL api_WPrintDestGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
3130 int mdrcnt,int mprcnt,
3131 char **rdata,char **rparam,
3132 int *rdata_len,int *rparam_len)
3134 char *str1 = param+2;
3135 char *str2 = skip_string(str1,1);
3136 char *p = skip_string(str2,1);
3137 char* PrinterName = p;
3138 int uLevel;
3139 struct pack_desc desc;
3140 int snum;
3141 char *tmpdata=NULL;
3143 memset((char *)&desc,'\0',sizeof(desc));
3145 p = skip_string(p,1);
3146 uLevel = SVAL(p,0);
3148 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
3150 /* check it's a supported varient */
3151 if (strcmp(str1,"zWrLh") != 0) return False;
3152 if (!check_printdest_info(&desc,uLevel,str2)) return False;
3154 snum = find_service(PrinterName);
3155 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) ) {
3156 *rdata_len = 0;
3157 desc.errcode = NERR_DestNotFound;
3158 desc.neededlen = 0;
3160 else {
3161 if (mdrcnt > 0) {
3162 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3163 desc.base = *rdata;
3164 desc.buflen = mdrcnt;
3165 } else {
3167 * Don't return data but need to get correct length
3168 * init_package will return wrong size if buflen=0
3170 desc.buflen = getlen(desc.format);
3171 desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen );
3173 if (init_package(&desc,1,0)) {
3174 fill_printdest_info(conn,snum,uLevel,&desc);
3176 *rdata_len = desc.usedlen;
3179 *rparam_len = 6;
3180 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3181 SSVALS(*rparam,0,desc.errcode);
3182 SSVAL(*rparam,2,0);
3183 SSVAL(*rparam,4,desc.neededlen);
3185 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
3186 SAFE_FREE(tmpdata);
3187 return(True);
3190 static BOOL api_WPrintDestEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3191 int mdrcnt,int mprcnt,
3192 char **rdata,char **rparam,
3193 int *rdata_len,int *rparam_len)
3195 char *str1 = param+2;
3196 char *str2 = skip_string(str1,1);
3197 char *p = skip_string(str2,1);
3198 int uLevel;
3199 int queuecnt;
3200 int i, n, succnt=0;
3201 struct pack_desc desc;
3202 int services = lp_numservices();
3204 memset((char *)&desc,'\0',sizeof(desc));
3206 uLevel = SVAL(p,0);
3208 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
3210 /* check it's a supported varient */
3211 if (strcmp(str1,"WrLeh") != 0) return False;
3212 if (!check_printdest_info(&desc,uLevel,str2)) return False;
3214 queuecnt = 0;
3215 for (i = 0; i < services; i++)
3216 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
3217 queuecnt++;
3219 if (mdrcnt > 0) *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3220 desc.base = *rdata;
3221 desc.buflen = mdrcnt;
3222 if (init_package(&desc,queuecnt,0)) {
3223 succnt = 0;
3224 n = 0;
3225 for (i = 0; i < services; i++) {
3226 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
3227 fill_printdest_info(conn,i,uLevel,&desc);
3228 n++;
3229 if (desc.errcode == NERR_Success) succnt = n;
3234 *rdata_len = desc.usedlen;
3236 *rparam_len = 8;
3237 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3238 SSVALS(*rparam,0,desc.errcode);
3239 SSVAL(*rparam,2,0);
3240 SSVAL(*rparam,4,succnt);
3241 SSVAL(*rparam,6,queuecnt);
3243 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
3244 return(True);
3247 static BOOL api_WPrintDriverEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3248 int mdrcnt,int mprcnt,
3249 char **rdata,char **rparam,
3250 int *rdata_len,int *rparam_len)
3252 char *str1 = param+2;
3253 char *str2 = skip_string(str1,1);
3254 char *p = skip_string(str2,1);
3255 int uLevel;
3256 int succnt;
3257 struct pack_desc desc;
3259 memset((char *)&desc,'\0',sizeof(desc));
3261 uLevel = SVAL(p,0);
3263 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
3265 /* check it's a supported varient */
3266 if (strcmp(str1,"WrLeh") != 0) return False;
3267 if (uLevel != 0 || strcmp(str2,"B41") != 0) return False;
3269 if (mdrcnt > 0) *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3270 desc.base = *rdata;
3271 desc.buflen = mdrcnt;
3272 if (init_package(&desc,1,0)) {
3273 PACKS(&desc,"B41","NULL");
3276 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3278 *rdata_len = desc.usedlen;
3280 *rparam_len = 8;
3281 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3282 SSVALS(*rparam,0,desc.errcode);
3283 SSVAL(*rparam,2,0);
3284 SSVAL(*rparam,4,succnt);
3285 SSVAL(*rparam,6,1);
3287 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
3288 return(True);
3291 static BOOL api_WPrintQProcEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3292 int mdrcnt,int mprcnt,
3293 char **rdata,char **rparam,
3294 int *rdata_len,int *rparam_len)
3296 char *str1 = param+2;
3297 char *str2 = skip_string(str1,1);
3298 char *p = skip_string(str2,1);
3299 int uLevel;
3300 int succnt;
3301 struct pack_desc desc;
3303 memset((char *)&desc,'\0',sizeof(desc));
3305 uLevel = SVAL(p,0);
3307 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
3309 /* check it's a supported varient */
3310 if (strcmp(str1,"WrLeh") != 0) return False;
3311 if (uLevel != 0 || strcmp(str2,"B13") != 0) return False;
3313 if (mdrcnt > 0) *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3314 desc.base = *rdata;
3315 desc.buflen = mdrcnt;
3316 desc.format = str2;
3317 if (init_package(&desc,1,0)) {
3318 PACKS(&desc,"B13","lpd");
3321 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3323 *rdata_len = desc.usedlen;
3325 *rparam_len = 8;
3326 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3327 SSVALS(*rparam,0,desc.errcode);
3328 SSVAL(*rparam,2,0);
3329 SSVAL(*rparam,4,succnt);
3330 SSVAL(*rparam,6,1);
3332 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
3333 return(True);
3336 static BOOL api_WPrintPortEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3337 int mdrcnt,int mprcnt,
3338 char **rdata,char **rparam,
3339 int *rdata_len,int *rparam_len)
3341 char *str1 = param+2;
3342 char *str2 = skip_string(str1,1);
3343 char *p = skip_string(str2,1);
3344 int uLevel;
3345 int succnt;
3346 struct pack_desc desc;
3348 memset((char *)&desc,'\0',sizeof(desc));
3350 uLevel = SVAL(p,0);
3352 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
3354 /* check it's a supported varient */
3355 if (strcmp(str1,"WrLeh") != 0) return False;
3356 if (uLevel != 0 || strcmp(str2,"B9") != 0) return False;
3358 if (mdrcnt > 0) *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3359 memset((char *)&desc,'\0',sizeof(desc));
3360 desc.base = *rdata;
3361 desc.buflen = mdrcnt;
3362 desc.format = str2;
3363 if (init_package(&desc,1,0)) {
3364 PACKS(&desc,"B13","lp0");
3367 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3369 *rdata_len = desc.usedlen;
3371 *rparam_len = 8;
3372 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3373 SSVALS(*rparam,0,desc.errcode);
3374 SSVAL(*rparam,2,0);
3375 SSVAL(*rparam,4,succnt);
3376 SSVAL(*rparam,6,1);
3378 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
3379 return(True);
3383 /****************************************************************************
3384 List open sessions
3385 ****************************************************************************/
3386 static BOOL api_RNetSessionEnum(connection_struct *conn,uint16 vuid, char *param, char *data,
3387 int mdrcnt,int mprcnt,
3388 char **rdata,char **rparam,
3389 int *rdata_len,int *rparam_len)
3392 char *str1 = param+2;
3393 char *str2 = skip_string(str1,1);
3394 char *p = skip_string(str2,1);
3395 int uLevel;
3396 struct pack_desc desc;
3397 struct sessionid *session_list;
3398 int i, num_sessions;
3400 memset((char *)&desc,'\0',sizeof(desc));
3402 uLevel = SVAL(p,0);
3404 DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel));
3405 DEBUG(7,("RNetSessionEnum req string=%s\n",str1));
3406 DEBUG(7,("RNetSessionEnum ret string=%s\n",str2));
3408 /* check it's a supported varient */
3409 if (strcmp(str1,RAP_NetSessionEnum_REQ) != 0) return False;
3410 if (uLevel != 2 || strcmp(str2,RAP_SESSION_INFO_L2) != 0) return False;
3412 num_sessions = list_sessions(&session_list);
3414 if (mdrcnt > 0) *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3415 memset((char *)&desc,'\0',sizeof(desc));
3416 desc.base = *rdata;
3417 desc.buflen = mdrcnt;
3418 desc.format = str2;
3419 if (!init_package(&desc,num_sessions,0)) {
3420 return False;
3423 for(i=0; i<num_sessions; i++) {
3424 PACKS(&desc, "z", session_list[i].remote_machine);
3425 PACKS(&desc, "z", session_list[i].username);
3426 PACKI(&desc, "W", 1); /* num conns */
3427 PACKI(&desc, "W", 0); /* num opens */
3428 PACKI(&desc, "W", 1); /* num users */
3429 PACKI(&desc, "D", 0); /* session time */
3430 PACKI(&desc, "D", 0); /* idle time */
3431 PACKI(&desc, "D", 0); /* flags */
3432 PACKS(&desc, "z", "Unknown Client"); /* client type string */
3435 *rdata_len = desc.usedlen;
3437 *rparam_len = 8;
3438 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3439 SSVALS(*rparam,0,desc.errcode);
3440 SSVAL(*rparam,2,0); /* converter */
3441 SSVAL(*rparam,4,num_sessions); /* count */
3443 DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc.errcode));
3444 return True;
3448 /****************************************************************************
3449 The buffer was too small
3450 ****************************************************************************/
3452 static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param,char *data,
3453 int mdrcnt,int mprcnt,
3454 char **rdata,char **rparam,
3455 int *rdata_len,int *rparam_len)
3457 *rparam_len = MIN(*rparam_len,mprcnt);
3458 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3460 *rdata_len = 0;
3462 SSVAL(*rparam,0,NERR_BufTooSmall);
3464 DEBUG(3,("Supplied buffer too small in API command\n"));
3466 return(True);
3470 /****************************************************************************
3471 The request is not supported
3472 ****************************************************************************/
3474 static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param,char *data,
3475 int mdrcnt,int mprcnt,
3476 char **rdata,char **rparam,
3477 int *rdata_len,int *rparam_len)
3479 *rparam_len = 4;
3480 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3482 *rdata_len = 0;
3484 SSVAL(*rparam,0,NERR_notsupported);
3485 SSVAL(*rparam,2,0); /* converter word */
3487 DEBUG(3,("Unsupported API command\n"));
3489 return(True);
3495 static const struct
3497 const char *name;
3498 int id;
3499 BOOL (*fn)(connection_struct *,uint16,char *,char *,
3500 int,int,char **,char **,int *,int *);
3501 BOOL auth_user; /* Deny anonymous access? */
3502 } api_commands[] = {
3503 {"RNetShareEnum", RAP_WshareEnum, api_RNetShareEnum, True},
3504 {"RNetShareGetInfo", RAP_WshareGetInfo, api_RNetShareGetInfo},
3505 {"RNetShareAdd", RAP_WshareAdd, api_RNetShareAdd},
3506 {"RNetSessionEnum", RAP_WsessionEnum, api_RNetSessionEnum, True},
3507 {"RNetServerGetInfo", RAP_WserverGetInfo, api_RNetServerGetInfo},
3508 {"RNetGroupEnum", RAP_WGroupEnum, api_RNetGroupEnum, True},
3509 {"RNetGroupGetUsers", RAP_WGroupGetUsers, api_RNetGroupGetUsers, True},
3510 {"RNetUserEnum", RAP_WUserEnum, api_RNetUserEnum, True},
3511 {"RNetUserGetInfo", RAP_WUserGetInfo, api_RNetUserGetInfo},
3512 {"NetUserGetGroups", RAP_WUserGetGroups, api_NetUserGetGroups},
3513 {"NetWkstaGetInfo", RAP_WWkstaGetInfo, api_NetWkstaGetInfo},
3514 {"DosPrintQEnum", RAP_WPrintQEnum, api_DosPrintQEnum, True},
3515 {"DosPrintQGetInfo", RAP_WPrintQGetInfo, api_DosPrintQGetInfo},
3516 {"WPrintQueuePause", RAP_WPrintQPause, api_WPrintQueueCtrl},
3517 {"WPrintQueueResume", RAP_WPrintQContinue, api_WPrintQueueCtrl},
3518 {"WPrintJobEnumerate",RAP_WPrintJobEnum, api_WPrintJobEnumerate},
3519 {"WPrintJobGetInfo", RAP_WPrintJobGetInfo, api_WPrintJobGetInfo},
3520 {"RDosPrintJobDel", RAP_WPrintJobDel, api_RDosPrintJobDel},
3521 {"RDosPrintJobPause", RAP_WPrintJobPause, api_RDosPrintJobDel},
3522 {"RDosPrintJobResume",RAP_WPrintJobContinue, api_RDosPrintJobDel},
3523 {"WPrintDestEnum", RAP_WPrintDestEnum, api_WPrintDestEnum},
3524 {"WPrintDestGetInfo", RAP_WPrintDestGetInfo, api_WPrintDestGetInfo},
3525 {"NetRemoteTOD", RAP_NetRemoteTOD, api_NetRemoteTOD},
3526 {"WPrintQueuePurge", RAP_WPrintQPurge, api_WPrintQueueCtrl},
3527 {"NetServerEnum", RAP_NetServerEnum2, api_RNetServerEnum}, /* anon OK */
3528 {"WAccessGetUserPerms",RAP_WAccessGetUserPerms,api_WAccessGetUserPerms},
3529 {"SetUserPassword", RAP_WUserPasswordSet2, api_SetUserPassword},
3530 {"WWkstaUserLogon", RAP_WWkstaUserLogon, api_WWkstaUserLogon},
3531 {"PrintJobInfo", RAP_WPrintJobSetInfo, api_PrintJobInfo},
3532 {"WPrintDriverEnum", RAP_WPrintDriverEnum, api_WPrintDriverEnum},
3533 {"WPrintQProcEnum", RAP_WPrintQProcessorEnum,api_WPrintQProcEnum},
3534 {"WPrintPortEnum", RAP_WPrintPortEnum, api_WPrintPortEnum},
3535 {"SamOEMChangePassword",RAP_SamOEMChgPasswordUser2_P,api_SamOEMChangePassword}, /* anon OK */
3536 {NULL, -1, api_Unsupported}};
3538 /* The following RAP calls are not implemented by Samba:
3540 RAP_WFileEnum2 - anon not OK
3543 /****************************************************************************
3544 Handle remote api calls
3545 ****************************************************************************/
3547 int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data,char *params,
3548 int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
3550 int api_command;
3551 char *rdata = NULL;
3552 char *rparam = NULL;
3553 int rdata_len = 0;
3554 int rparam_len = 0;
3555 BOOL reply=False;
3556 int i;
3558 if (!params) {
3559 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
3560 return 0;
3563 api_command = SVAL(params,0);
3565 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
3566 api_command,
3567 params+2,
3568 skip_string(params+2,1),
3569 tdscnt,tpscnt,mdrcnt,mprcnt));
3571 for (i=0;api_commands[i].name;i++) {
3572 if (api_commands[i].id == api_command && api_commands[i].fn) {
3573 DEBUG(3,("Doing %s\n",api_commands[i].name));
3574 break;
3578 /* Check whether this api call can be done anonymously */
3580 if (api_commands[i].auth_user && lp_restrict_anonymous()) {
3581 user_struct *user = get_valid_user_struct(vuid);
3583 if (!user || user->guest)
3584 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
3587 rdata = (char *)SMB_MALLOC(1024);
3588 if (rdata)
3589 memset(rdata,'\0',1024);
3591 rparam = (char *)SMB_MALLOC(1024);
3592 if (rparam)
3593 memset(rparam,'\0',1024);
3595 if(!rdata || !rparam) {
3596 DEBUG(0,("api_reply: malloc fail !\n"));
3597 return -1;
3600 reply = api_commands[i].fn(conn,vuid,params,data,mdrcnt,mprcnt,
3601 &rdata,&rparam,&rdata_len,&rparam_len);
3604 if (rdata_len > mdrcnt ||
3605 rparam_len > mprcnt) {
3606 reply = api_TooSmall(conn,vuid,params,data,mdrcnt,mprcnt,
3607 &rdata,&rparam,&rdata_len,&rparam_len);
3610 /* if we get False back then it's actually unsupported */
3611 if (!reply)
3612 api_Unsupported(conn,vuid,params,data,mdrcnt,mprcnt,
3613 &rdata,&rparam,&rdata_len,&rparam_len);
3615 send_trans_reply(outbuf, rparam, rparam_len, rdata, rdata_len, False);
3617 SAFE_FREE(rdata);
3618 SAFE_FREE(rparam);
3620 return -1;