r6303: Setting up for 3.0.15pre1
[Samba.git] / source / smbd / lanman.c
blob127480f0b3deef73943514b104d812d859dc224d
1 /*
2 Unix SMB/CIFS implementation.
3 Inter-process communication and named pipe handling
4 Copyright (C) Andrew Tridgell 1992-1998
6 SMB Version handling
7 Copyright (C) John H Terpstra 1995-1998
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 This file handles the named pipe and mailslot calls
25 in the SMBtrans protocol
28 #include "includes.h"
30 extern struct current_user current_user;
31 extern userdom_struct current_user_info;
33 #ifdef CHECK_TYPES
34 #undef CHECK_TYPES
35 #endif
36 #define CHECK_TYPES 0
38 #define NERR_Success 0
39 #define NERR_badpass 86
40 #define NERR_notsupported 50
42 #define NERR_BASE (2100)
43 #define NERR_BufTooSmall (NERR_BASE+23)
44 #define NERR_JobNotFound (NERR_BASE+51)
45 #define NERR_DestNotFound (NERR_BASE+52)
47 #define ACCESS_READ 0x01
48 #define ACCESS_WRITE 0x02
49 #define ACCESS_CREATE 0x04
51 #define SHPWLEN 8 /* share password length */
53 static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param,char *data,
54 int mdrcnt,int mprcnt,
55 char **rdata,char **rparam,
56 int *rdata_len,int *rparam_len);
57 static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param,char *data,
58 int mdrcnt,int mprcnt,
59 char **rdata,char **rparam,
60 int *rdata_len,int *rparam_len);
63 static int CopyExpanded(connection_struct *conn,
64 int snum, char** dst, char* src, int* n)
66 pstring buf;
67 int l;
69 if (!src || !dst || !n || !(*dst)) return(0);
71 StrnCpy(buf,src,sizeof(buf)/2);
72 pstring_sub(buf,"%S",lp_servicename(snum));
73 standard_sub_conn(conn,buf,sizeof(buf));
74 l = push_ascii(*dst,buf,*n, STR_TERMINATE);
75 (*dst) += l;
76 (*n) -= l;
77 return l;
80 static int CopyAndAdvance(char** dst, char* src, int* n)
82 int l;
83 if (!src || !dst || !n || !(*dst)) return(0);
84 l = push_ascii(*dst,src,*n, STR_TERMINATE);
85 (*dst) += l;
86 (*n) -= l;
87 return l;
90 static int StrlenExpanded(connection_struct *conn, int snum, char* s)
92 pstring buf;
93 if (!s) return(0);
94 StrnCpy(buf,s,sizeof(buf)/2);
95 pstring_sub(buf,"%S",lp_servicename(snum));
96 standard_sub_conn(conn,buf,sizeof(buf));
97 return strlen(buf) + 1;
100 static char* Expand(connection_struct *conn, int snum, char* s)
102 static pstring buf;
103 if (!s) return(NULL);
104 StrnCpy(buf,s,sizeof(buf)/2);
105 pstring_sub(buf,"%S",lp_servicename(snum));
106 standard_sub_conn(conn,buf,sizeof(buf));
107 return &buf[0];
110 /*******************************************************************
111 check a API string for validity when we only need to check the prefix
112 ******************************************************************/
113 static BOOL prefix_ok(const char *str, const char *prefix)
115 return(strncmp(str,prefix,strlen(prefix)) == 0);
118 struct pack_desc {
119 const char* format; /* formatstring for structure */
120 const char* subformat; /* subformat for structure */
121 char* base; /* baseaddress of buffer */
122 int buflen; /* remaining size for fixed part; on init: length of base */
123 int subcount; /* count of substructures */
124 char* structbuf; /* pointer into buffer for remaining fixed part */
125 int stringlen; /* remaining size for variable part */
126 char* stringbuf; /* pointer into buffer for remaining variable part */
127 int neededlen; /* total needed size */
128 int usedlen; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
129 const char* curpos; /* current position; pointer into format or subformat */
130 int errcode;
133 static int get_counter(const char** p)
135 int i, n;
136 if (!p || !(*p)) return(1);
137 if (!isdigit((int)**p)) return 1;
138 for (n = 0;;) {
139 i = **p;
140 if (isdigit(i))
141 n = 10 * n + (i - '0');
142 else
143 return n;
144 (*p)++;
148 static int getlen(const char* p)
150 int n = 0;
151 if (!p) return(0);
152 while (*p) {
153 switch( *p++ ) {
154 case 'W': /* word (2 byte) */
155 n += 2;
156 break;
157 case 'K': /* status word? (2 byte) */
158 n += 2;
159 break;
160 case 'N': /* count of substructures (word) at end */
161 n += 2;
162 break;
163 case 'D': /* double word (4 byte) */
164 case 'z': /* offset to zero terminated string (4 byte) */
165 case 'l': /* offset to user data (4 byte) */
166 n += 4;
167 break;
168 case 'b': /* offset to data (with counter) (4 byte) */
169 n += 4;
170 get_counter(&p);
171 break;
172 case 'B': /* byte (with optional counter) */
173 n += get_counter(&p);
174 break;
177 return n;
180 static BOOL init_package(struct pack_desc* p, int count, int subcount)
182 int n = p->buflen;
183 int i;
185 if (!p->format || !p->base) return(False);
187 i = count * getlen(p->format);
188 if (p->subformat) i += subcount * getlen(p->subformat);
189 p->structbuf = p->base;
190 p->neededlen = 0;
191 p->usedlen = 0;
192 p->subcount = 0;
193 p->curpos = p->format;
194 if (i > n) {
195 p->neededlen = i;
196 i = n = 0;
197 #if 0
199 * This is the old error code we used. Aparently
200 * WinNT/2k systems return ERRbuftoosmall (2123) and
201 * OS/2 needs this. I'm leaving this here so we can revert
202 * if needed. JRA.
204 p->errcode = ERRmoredata;
205 #else
206 p->errcode = ERRbuftoosmall;
207 #endif
209 else
210 p->errcode = NERR_Success;
211 p->buflen = i;
212 n -= i;
213 p->stringbuf = p->base + i;
214 p->stringlen = n;
215 return(p->errcode == NERR_Success);
218 static int package(struct pack_desc* p, ...)
220 va_list args;
221 int needed=0, stringneeded;
222 const char* str=NULL;
223 int is_string=0, stringused;
224 int32 temp;
226 va_start(args,p);
228 if (!*p->curpos) {
229 if (!p->subcount)
230 p->curpos = p->format;
231 else {
232 p->curpos = p->subformat;
233 p->subcount--;
236 #if CHECK_TYPES
237 str = va_arg(args,char*);
238 SMB_ASSERT(strncmp(str,p->curpos,strlen(str)) == 0);
239 #endif
240 stringneeded = -1;
242 if (!p->curpos) {
243 va_end(args);
244 return(0);
247 switch( *p->curpos++ ) {
248 case 'W': /* word (2 byte) */
249 needed = 2;
250 temp = va_arg(args,int);
251 if (p->buflen >= needed) SSVAL(p->structbuf,0,temp);
252 break;
253 case 'K': /* status word? (2 byte) */
254 needed = 2;
255 temp = va_arg(args,int);
256 if (p->buflen >= needed) SSVAL(p->structbuf,0,temp);
257 break;
258 case 'N': /* count of substructures (word) at end */
259 needed = 2;
260 p->subcount = va_arg(args,int);
261 if (p->buflen >= needed) SSVAL(p->structbuf,0,p->subcount);
262 break;
263 case 'D': /* double word (4 byte) */
264 needed = 4;
265 temp = va_arg(args,int);
266 if (p->buflen >= needed) SIVAL(p->structbuf,0,temp);
267 break;
268 case 'B': /* byte (with optional counter) */
269 needed = get_counter(&p->curpos);
271 char *s = va_arg(args,char*);
272 if (p->buflen >= needed) StrnCpy(p->structbuf,s?s:"",needed-1);
274 break;
275 case 'z': /* offset to zero terminated string (4 byte) */
276 str = va_arg(args,char*);
277 stringneeded = (str ? strlen(str)+1 : 0);
278 is_string = 1;
279 break;
280 case 'l': /* offset to user data (4 byte) */
281 str = va_arg(args,char*);
282 stringneeded = va_arg(args,int);
283 is_string = 0;
284 break;
285 case 'b': /* offset to data (with counter) (4 byte) */
286 str = va_arg(args,char*);
287 stringneeded = get_counter(&p->curpos);
288 is_string = 0;
289 break;
291 va_end(args);
292 if (stringneeded >= 0) {
293 needed = 4;
294 if (p->buflen >= needed) {
295 stringused = stringneeded;
296 if (stringused > p->stringlen) {
297 stringused = (is_string ? p->stringlen : 0);
298 if (p->errcode == NERR_Success) p->errcode = ERRmoredata;
300 if (!stringused)
301 SIVAL(p->structbuf,0,0);
302 else {
303 SIVAL(p->structbuf,0,PTR_DIFF(p->stringbuf,p->base));
304 memcpy(p->stringbuf,str?str:"",stringused);
305 if (is_string) p->stringbuf[stringused-1] = '\0';
306 p->stringbuf += stringused;
307 p->stringlen -= stringused;
308 p->usedlen += stringused;
311 p->neededlen += stringneeded;
313 p->neededlen += needed;
314 if (p->buflen >= needed) {
315 p->structbuf += needed;
316 p->buflen -= needed;
317 p->usedlen += needed;
319 else {
320 if (p->errcode == NERR_Success) p->errcode = ERRmoredata;
322 return 1;
325 #if CHECK_TYPES
326 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
327 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
328 #else
329 #define PACK(desc,t,v) package(desc,v)
330 #define PACKl(desc,t,v,l) package(desc,v,l)
331 #endif
333 static void PACKI(struct pack_desc* desc, const char *t,int v)
335 PACK(desc,t,v);
338 static void PACKS(struct pack_desc* desc,const char *t,const char *v)
340 PACK(desc,t,v);
344 /****************************************************************************
345 get a print queue
346 ****************************************************************************/
347 static void PackDriverData(struct pack_desc* desc)
349 char drivdata[4+4+32];
350 SIVAL(drivdata,0,sizeof drivdata); /* cb */
351 SIVAL(drivdata,4,1000); /* lVersion */
352 memset(drivdata+8,0,32); /* szDeviceName */
353 push_ascii(drivdata+8,"NULL",-1, STR_TERMINATE);
354 PACKl(desc,"l",drivdata,sizeof drivdata); /* pDriverData */
357 static int check_printq_info(struct pack_desc* desc,
358 int uLevel, char *id1, char *id2)
360 desc->subformat = NULL;
361 switch( uLevel ) {
362 case 0:
363 desc->format = "B13";
364 break;
365 case 1:
366 desc->format = "B13BWWWzzzzzWW";
367 break;
368 case 2:
369 desc->format = "B13BWWWzzzzzWN";
370 desc->subformat = "WB21BB16B10zWWzDDz";
371 break;
372 case 3:
373 desc->format = "zWWWWzzzzWWzzl";
374 break;
375 case 4:
376 desc->format = "zWWWWzzzzWNzzl";
377 desc->subformat = "WWzWWDDzz";
378 break;
379 case 5:
380 desc->format = "z";
381 break;
382 case 51:
383 desc->format = "K";
384 break;
385 case 52:
386 desc->format = "WzzzzzzzzN";
387 desc->subformat = "z";
388 break;
389 default: return False;
391 if (strcmp(desc->format,id1) != 0) return False;
392 if (desc->subformat && strcmp(desc->subformat,id2) != 0) return False;
393 return True;
397 #define RAP_JOB_STATUS_QUEUED 0
398 #define RAP_JOB_STATUS_PAUSED 1
399 #define RAP_JOB_STATUS_SPOOLING 2
400 #define RAP_JOB_STATUS_PRINTING 3
401 #define RAP_JOB_STATUS_PRINTED 4
403 #define RAP_QUEUE_STATUS_PAUSED 1
404 #define RAP_QUEUE_STATUS_ERROR 2
406 /* turn a print job status into a on the wire status
408 static int printj_status(int v)
410 switch (v) {
411 case LPQ_QUEUED:
412 return RAP_JOB_STATUS_QUEUED;
413 case LPQ_PAUSED:
414 return RAP_JOB_STATUS_PAUSED;
415 case LPQ_SPOOLING:
416 return RAP_JOB_STATUS_SPOOLING;
417 case LPQ_PRINTING:
418 return RAP_JOB_STATUS_PRINTING;
420 return 0;
423 /* turn a print queue status into a on the wire status
425 static int printq_status(int v)
427 switch (v) {
428 case LPQ_QUEUED:
429 return 0;
430 case LPQ_PAUSED:
431 return RAP_QUEUE_STATUS_PAUSED;
433 return RAP_QUEUE_STATUS_ERROR;
436 static void fill_printjob_info(connection_struct *conn, int snum, int uLevel,
437 struct pack_desc* desc,
438 print_queue_struct* queue, int n)
440 time_t t = queue->time;
442 /* the client expects localtime */
443 t -= TimeDiff(t);
445 PACKI(desc,"W",pjobid_to_rap(lp_const_servicename(snum),queue->job)); /* uJobId */
446 if (uLevel == 1) {
447 PACKS(desc,"B21",queue->fs_user); /* szUserName */
448 PACKS(desc,"B",""); /* pad */
449 PACKS(desc,"B16",""); /* szNotifyName */
450 PACKS(desc,"B10","PM_Q_RAW"); /* szDataType */
451 PACKS(desc,"z",""); /* pszParms */
452 PACKI(desc,"W",n+1); /* uPosition */
453 PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */
454 PACKS(desc,"z",""); /* pszStatus */
455 PACKI(desc,"D",t); /* ulSubmitted */
456 PACKI(desc,"D",queue->size); /* ulSize */
457 PACKS(desc,"z",queue->fs_file); /* pszComment */
459 if (uLevel == 2 || uLevel == 3 || uLevel == 4) {
460 PACKI(desc,"W",queue->priority); /* uPriority */
461 PACKS(desc,"z",queue->fs_user); /* pszUserName */
462 PACKI(desc,"W",n+1); /* uPosition */
463 PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */
464 PACKI(desc,"D",t); /* ulSubmitted */
465 PACKI(desc,"D",queue->size); /* ulSize */
466 PACKS(desc,"z","Samba"); /* pszComment */
467 PACKS(desc,"z",queue->fs_file); /* pszDocument */
468 if (uLevel == 3) {
469 PACKS(desc,"z",""); /* pszNotifyName */
470 PACKS(desc,"z","PM_Q_RAW"); /* pszDataType */
471 PACKS(desc,"z",""); /* pszParms */
472 PACKS(desc,"z",""); /* pszStatus */
473 PACKS(desc,"z",SERVICE(snum)); /* pszQueue */
474 PACKS(desc,"z","lpd"); /* pszQProcName */
475 PACKS(desc,"z",""); /* pszQProcParms */
476 PACKS(desc,"z","NULL"); /* pszDriverName */
477 PackDriverData(desc); /* pDriverData */
478 PACKS(desc,"z",""); /* pszPrinterName */
479 } else if (uLevel == 4) { /* OS2 */
480 PACKS(desc,"z",""); /* pszSpoolFileName */
481 PACKS(desc,"z",""); /* pszPortName */
482 PACKS(desc,"z",""); /* pszStatus */
483 PACKI(desc,"D",0); /* ulPagesSpooled */
484 PACKI(desc,"D",0); /* ulPagesSent */
485 PACKI(desc,"D",0); /* ulPagesPrinted */
486 PACKI(desc,"D",0); /* ulTimePrinted */
487 PACKI(desc,"D",0); /* ulExtendJobStatus */
488 PACKI(desc,"D",0); /* ulStartPage */
489 PACKI(desc,"D",0); /* ulEndPage */
494 /********************************************************************
495 Return a driver name given an snum.
496 Returns True if from tdb, False otherwise.
497 ********************************************************************/
499 static BOOL get_driver_name(int snum, pstring drivername)
501 NT_PRINTER_INFO_LEVEL *info = NULL;
502 BOOL in_tdb = False;
504 get_a_printer (NULL, &info, 2, lp_servicename(snum));
505 if (info != NULL) {
506 pstrcpy( drivername, info->info_2->drivername);
507 in_tdb = True;
508 free_a_printer(&info, 2);
511 return in_tdb;
514 /********************************************************************
515 Respond to the DosPrintQInfo command with a level of 52
516 This is used to get printer driver information for Win9x clients
517 ********************************************************************/
518 static void fill_printq_info_52(connection_struct *conn, int snum,
519 struct pack_desc* desc, int count )
521 int i;
522 fstring location;
523 NT_PRINTER_DRIVER_INFO_LEVEL driver;
524 NT_PRINTER_INFO_LEVEL *printer = NULL;
526 ZERO_STRUCT(driver);
528 if ( !W_ERROR_IS_OK(get_a_printer( NULL, &printer, 2, lp_servicename(snum))) ) {
529 DEBUG(3,("fill_printq_info_52: Failed to lookup printer [%s]\n",
530 lp_servicename(snum)));
531 goto err;
534 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername,
535 "Windows 4.0", 0)) )
537 DEBUG(3,("fill_printq_info_52: Failed to lookup driver [%s]\n",
538 printer->info_2->drivername));
539 goto err;
542 trim_string(driver.info_3->driverpath, "\\print$\\WIN40\\0\\", 0);
543 trim_string(driver.info_3->datafile, "\\print$\\WIN40\\0\\", 0);
544 trim_string(driver.info_3->helpfile, "\\print$\\WIN40\\0\\", 0);
546 PACKI(desc, "W", 0x0400); /* don't know */
547 PACKS(desc, "z", driver.info_3->name); /* long printer name */
548 PACKS(desc, "z", driver.info_3->driverpath); /* Driverfile Name */
549 PACKS(desc, "z", driver.info_3->datafile); /* Datafile name */
550 PACKS(desc, "z", driver.info_3->monitorname); /* language monitor */
552 fstrcpy(location, "\\\\%L\\print$\\WIN40\\0");
553 standard_sub_basic( "", location, sizeof(location)-1 );
554 PACKS(desc,"z", location); /* share to retrieve files */
556 PACKS(desc,"z", driver.info_3->defaultdatatype); /* default data type */
557 PACKS(desc,"z", driver.info_3->helpfile); /* helpfile name */
558 PACKS(desc,"z", driver.info_3->driverpath); /* driver name */
560 DEBUG(3,("Printer Driver Name: %s:\n",driver.info_3->name));
561 DEBUG(3,("Driver: %s:\n",driver.info_3->driverpath));
562 DEBUG(3,("Data File: %s:\n",driver.info_3->datafile));
563 DEBUG(3,("Language Monitor: %s:\n",driver.info_3->monitorname));
564 DEBUG(3,("Driver Location: %s:\n",location));
565 DEBUG(3,("Data Type: %s:\n",driver.info_3->defaultdatatype));
566 DEBUG(3,("Help File: %s:\n",driver.info_3->helpfile));
567 PACKI(desc,"N",count); /* number of files to copy */
569 for ( i=0; i<count && driver.info_3->dependentfiles && *driver.info_3->dependentfiles[i]; i++)
571 trim_string(driver.info_3->dependentfiles[i], "\\print$\\WIN40\\0\\", 0);
572 PACKS(desc,"z",driver.info_3->dependentfiles[i]); /* driver files to copy */
573 DEBUG(3,("Dependent File: %s:\n",driver.info_3->dependentfiles[i]));
576 /* sanity check */
577 if ( i != count )
578 DEBUG(3,("fill_printq_info_52: file count specified by client [%d] != number of dependent files [%i]\n",
579 count, i));
581 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n", SERVICE(snum),i));
583 desc->errcode=NERR_Success;
584 goto done;
586 err:
587 DEBUG(3,("fill_printq_info: Can't supply driver files\n"));
588 desc->errcode=NERR_notsupported;
590 done:
591 if ( printer )
592 free_a_printer( &printer, 2 );
594 if ( driver.info_3 )
595 free_a_printer_driver( driver, 3 );
599 static void fill_printq_info(connection_struct *conn, int snum, int uLevel,
600 struct pack_desc* desc,
601 int count, print_queue_struct* queue,
602 print_status_struct* status)
604 switch (uLevel) {
605 case 1:
606 case 2:
607 PACKS(desc,"B13",SERVICE(snum));
608 break;
609 case 3:
610 case 4:
611 case 5:
612 PACKS(desc,"z",Expand(conn,snum,SERVICE(snum)));
613 break;
614 case 51:
615 PACKI(desc,"K",printq_status(status->status));
616 break;
619 if (uLevel == 1 || uLevel == 2) {
620 PACKS(desc,"B",""); /* alignment */
621 PACKI(desc,"W",5); /* priority */
622 PACKI(desc,"W",0); /* start time */
623 PACKI(desc,"W",0); /* until time */
624 PACKS(desc,"z",""); /* pSepFile */
625 PACKS(desc,"z","lpd"); /* pPrProc */
626 PACKS(desc,"z",SERVICE(snum)); /* pDestinations */
627 PACKS(desc,"z",""); /* pParms */
628 if (snum < 0) {
629 PACKS(desc,"z","UNKNOWN PRINTER");
630 PACKI(desc,"W",LPSTAT_ERROR);
632 else if (!status || !status->message[0]) {
633 PACKS(desc,"z",Expand(conn,snum,lp_comment(snum)));
634 PACKI(desc,"W",LPSTAT_OK); /* status */
635 } else {
636 PACKS(desc,"z",status->message);
637 PACKI(desc,"W",printq_status(status->status)); /* status */
639 PACKI(desc,(uLevel == 1 ? "W" : "N"),count);
642 if (uLevel == 3 || uLevel == 4) {
643 pstring drivername;
645 PACKI(desc,"W",5); /* uPriority */
646 PACKI(desc,"W",0); /* uStarttime */
647 PACKI(desc,"W",0); /* uUntiltime */
648 PACKI(desc,"W",5); /* pad1 */
649 PACKS(desc,"z",""); /* pszSepFile */
650 PACKS(desc,"z","WinPrint"); /* pszPrProc */
651 PACKS(desc,"z",NULL); /* pszParms */
652 PACKS(desc,"z",NULL); /* pszComment - don't ask.... JRA */
653 /* "don't ask" that it's done this way to fix corrupted
654 Win9X/ME printer comments. */
655 if (!status) {
656 PACKI(desc,"W",LPSTAT_OK); /* fsStatus */
657 } else {
658 PACKI(desc,"W",printq_status(status->status)); /* fsStatus */
660 PACKI(desc,(uLevel == 3 ? "W" : "N"),count); /* cJobs */
661 PACKS(desc,"z",SERVICE(snum)); /* pszPrinters */
662 get_driver_name(snum,drivername);
663 PACKS(desc,"z",drivername); /* pszDriverName */
664 PackDriverData(desc); /* pDriverData */
667 if (uLevel == 2 || uLevel == 4) {
668 int i;
669 for (i=0;i<count;i++)
670 fill_printjob_info(conn,snum,uLevel == 2 ? 1 : 2,desc,&queue[i],i);
673 if (uLevel==52)
674 fill_printq_info_52( conn, snum, desc, count );
677 /* This function returns the number of files for a given driver */
678 static int get_printerdrivernumber(int snum)
680 int result = 0;
681 NT_PRINTER_DRIVER_INFO_LEVEL driver;
682 NT_PRINTER_INFO_LEVEL *printer = NULL;
684 ZERO_STRUCT(driver);
686 if ( !W_ERROR_IS_OK(get_a_printer( NULL, &printer, 2, lp_servicename(snum))) ) {
687 DEBUG(3,("get_printerdrivernumber: Failed to lookup printer [%s]\n",
688 lp_servicename(snum)));
689 goto done;
692 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername,
693 "Windows 4.0", 0)) )
695 DEBUG(3,("get_printerdrivernumber: Failed to lookup driver [%s]\n",
696 printer->info_2->drivername));
697 goto done;
700 /* count the number of files */
701 while ( driver.info_3->dependentfiles && *driver.info_3->dependentfiles[result] )
702 result++;
704 done:
705 if ( printer )
706 free_a_printer( &printer, 2 );
708 if ( driver.info_3 )
709 free_a_printer_driver( driver, 3 );
711 return result;
714 static BOOL api_DosPrintQGetInfo(connection_struct *conn,
715 uint16 vuid, char *param,char *data,
716 int mdrcnt,int mprcnt,
717 char **rdata,char **rparam,
718 int *rdata_len,int *rparam_len)
720 char *str1 = param+2;
721 char *str2 = skip_string(str1,1);
722 char *p = skip_string(str2,1);
723 char *QueueName = p;
724 int uLevel;
725 int count=0;
726 int snum;
727 char* str3;
728 struct pack_desc desc;
729 print_queue_struct *queue=NULL;
730 print_status_struct status;
731 char* tmpdata=NULL;
733 memset((char *)&status,'\0',sizeof(status));
734 memset((char *)&desc,'\0',sizeof(desc));
736 p = skip_string(p,1);
737 uLevel = SVAL(p,0);
738 str3 = p + 4;
740 /* remove any trailing username */
741 if ((p = strchr_m(QueueName,'%')))
742 *p = 0;
744 DEBUG(3,("api_DosPrintQGetInfo uLevel=%d name=%s\n",uLevel,QueueName));
746 /* check it's a supported varient */
747 if (!prefix_ok(str1,"zWrLh"))
748 return False;
749 if (!check_printq_info(&desc,uLevel,str2,str3)) {
751 * Patch from Scott Moomaw <scott@bridgewater.edu>
752 * to return the 'invalid info level' error if an
753 * unknown level was requested.
755 *rdata_len = 0;
756 *rparam_len = 6;
757 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
758 SSVALS(*rparam,0,ERRunknownlevel);
759 SSVAL(*rparam,2,0);
760 SSVAL(*rparam,4,0);
761 return(True);
764 snum = find_service(QueueName);
765 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
766 return False;
768 if (uLevel==52) {
769 count = get_printerdrivernumber(snum);
770 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count));
771 } else {
772 count = print_queue_status(snum, &queue,&status);
775 if (mdrcnt > 0) {
776 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
777 desc.base = *rdata;
778 desc.buflen = mdrcnt;
779 } else {
781 * Don't return data but need to get correct length
782 * init_package will return wrong size if buflen=0
784 desc.buflen = getlen(desc.format);
785 desc.base = tmpdata = (char *) SMB_MALLOC (desc.buflen);
788 if (init_package(&desc,1,count)) {
789 desc.subcount = count;
790 fill_printq_info(conn,snum,uLevel,&desc,count,queue,&status);
793 *rdata_len = desc.usedlen;
796 * We must set the return code to ERRbuftoosmall
797 * in order to support lanman style printing with Win NT/2k
798 * clients --jerry
800 if (!mdrcnt && lp_disable_spoolss())
801 desc.errcode = ERRbuftoosmall;
803 *rdata_len = desc.usedlen;
804 *rparam_len = 6;
805 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
806 SSVALS(*rparam,0,desc.errcode);
807 SSVAL(*rparam,2,0);
808 SSVAL(*rparam,4,desc.neededlen);
810 DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode));
812 SAFE_FREE(queue);
813 SAFE_FREE(tmpdata);
815 return(True);
818 /****************************************************************************
819 View list of all print jobs on all queues.
820 ****************************************************************************/
822 static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid, char* param, char* data,
823 int mdrcnt, int mprcnt,
824 char **rdata, char** rparam,
825 int *rdata_len, int *rparam_len)
827 char *param_format = param+2;
828 char *output_format1 = skip_string(param_format,1);
829 char *p = skip_string(output_format1,1);
830 int uLevel = SVAL(p,0);
831 char *output_format2 = p + 4;
832 int services = lp_numservices();
833 int i, n;
834 struct pack_desc desc;
835 print_queue_struct **queue = NULL;
836 print_status_struct *status = NULL;
837 int* subcntarr = NULL;
838 int queuecnt, subcnt=0, succnt=0;
840 memset((char *)&desc,'\0',sizeof(desc));
842 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
844 if (!prefix_ok(param_format,"WrLeh")) return False;
845 if (!check_printq_info(&desc,uLevel,output_format1,output_format2)) {
847 * Patch from Scott Moomaw <scott@bridgewater.edu>
848 * to return the 'invalid info level' error if an
849 * unknown level was requested.
851 *rdata_len = 0;
852 *rparam_len = 6;
853 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
854 SSVALS(*rparam,0,ERRunknownlevel);
855 SSVAL(*rparam,2,0);
856 SSVAL(*rparam,4,0);
857 return(True);
860 queuecnt = 0;
861 for (i = 0; i < services; i++)
862 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
863 queuecnt++;
864 if (uLevel > 0) {
865 if((queue = SMB_MALLOC_ARRAY(print_queue_struct*, queuecnt)) == NULL) {
866 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
867 return False;
869 memset(queue,0,queuecnt*sizeof(print_queue_struct*));
870 if((status = SMB_MALLOC_ARRAY(print_status_struct,queuecnt)) == NULL) {
871 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
872 return False;
874 memset(status,0,queuecnt*sizeof(print_status_struct));
875 if((subcntarr = SMB_MALLOC_ARRAY(int,queuecnt)) == NULL) {
876 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
877 return False;
879 subcnt = 0;
880 n = 0;
881 for (i = 0; i < services; i++)
882 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
883 subcntarr[n] = print_queue_status(i, &queue[n],&status[n]);
884 subcnt += subcntarr[n];
885 n++;
888 if (mdrcnt > 0) *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
889 desc.base = *rdata;
890 desc.buflen = mdrcnt;
892 if (init_package(&desc,queuecnt,subcnt)) {
893 n = 0;
894 succnt = 0;
895 for (i = 0; i < services; i++)
896 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
897 fill_printq_info(conn,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]);
898 n++;
899 if (desc.errcode == NERR_Success) succnt = n;
903 SAFE_FREE(subcntarr);
905 *rdata_len = desc.usedlen;
906 *rparam_len = 8;
907 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
908 SSVALS(*rparam,0,desc.errcode);
909 SSVAL(*rparam,2,0);
910 SSVAL(*rparam,4,succnt);
911 SSVAL(*rparam,6,queuecnt);
913 for (i = 0; i < queuecnt; i++) {
914 if (queue) SAFE_FREE(queue[i]);
917 SAFE_FREE(queue);
918 SAFE_FREE(status);
920 return True;
923 /****************************************************************************
924 get info level for a server list query
925 ****************************************************************************/
926 static BOOL check_server_info(int uLevel, char* id)
928 switch( uLevel ) {
929 case 0:
930 if (strcmp(id,"B16") != 0) return False;
931 break;
932 case 1:
933 if (strcmp(id,"B16BBDz") != 0) return False;
934 break;
935 default:
936 return False;
938 return True;
941 struct srv_info_struct
943 fstring name;
944 uint32 type;
945 fstring comment;
946 fstring domain;
947 BOOL server_added;
951 /*******************************************************************
952 get server info lists from the files saved by nmbd. Return the
953 number of entries
954 ******************************************************************/
955 static int get_server_info(uint32 servertype,
956 struct srv_info_struct **servers,
957 const char *domain)
959 int count=0;
960 int alloced=0;
961 char **lines;
962 BOOL local_list_only;
963 int i;
965 lines = file_lines_load(lock_path(SERVER_LIST), NULL);
966 if (!lines) {
967 DEBUG(4,("Can't open %s - %s\n",lock_path(SERVER_LIST),strerror(errno)));
968 return(0);
971 /* request for everything is code for request all servers */
972 if (servertype == SV_TYPE_ALL)
973 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
975 local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY);
977 DEBUG(4,("Servertype search: %8x\n",servertype));
979 for (i=0;lines[i];i++) {
980 fstring stype;
981 struct srv_info_struct *s;
982 const char *ptr = lines[i];
983 BOOL ok = True;
985 if (!*ptr) continue;
987 if (count == alloced) {
988 struct srv_info_struct *ts;
990 alloced += 10;
991 ts = SMB_REALLOC_ARRAY(*servers,struct srv_info_struct, alloced);
992 if (!ts) {
993 DEBUG(0,("get_server_info: failed to enlarge servers info struct!\n"));
994 return(0);
996 else *servers = ts;
997 memset((char *)((*servers)+count),'\0',sizeof(**servers)*(alloced-count));
999 s = &(*servers)[count];
1001 if (!next_token(&ptr,s->name , NULL, sizeof(s->name))) continue;
1002 if (!next_token(&ptr,stype , NULL, sizeof(stype))) continue;
1003 if (!next_token(&ptr,s->comment, NULL, sizeof(s->comment))) continue;
1004 if (!next_token(&ptr,s->domain , NULL, sizeof(s->domain))) {
1005 /* this allows us to cope with an old nmbd */
1006 fstrcpy(s->domain,lp_workgroup());
1009 if (sscanf(stype,"%X",&s->type) != 1) {
1010 DEBUG(4,("r:host file "));
1011 ok = False;
1014 /* Filter the servers/domains we return based on what was asked for. */
1016 /* Check to see if we are being asked for a local list only. */
1017 if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) {
1018 DEBUG(4,("r: local list only"));
1019 ok = False;
1022 /* doesn't match up: don't want it */
1023 if (!(servertype & s->type)) {
1024 DEBUG(4,("r:serv type "));
1025 ok = False;
1028 if ((servertype & SV_TYPE_DOMAIN_ENUM) !=
1029 (s->type & SV_TYPE_DOMAIN_ENUM))
1031 DEBUG(4,("s: dom mismatch "));
1032 ok = False;
1035 if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM))
1037 ok = False;
1040 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1041 s->type &= ~SV_TYPE_LOCAL_LIST_ONLY;
1043 if (ok)
1045 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1046 s->name, s->type, s->comment, s->domain));
1048 s->server_added = True;
1049 count++;
1051 else
1053 DEBUG(4,("%20s %8x %25s %15s\n",
1054 s->name, s->type, s->comment, s->domain));
1058 file_lines_free(lines);
1059 return(count);
1063 /*******************************************************************
1064 fill in a server info structure
1065 ******************************************************************/
1066 static int fill_srv_info(struct srv_info_struct *service,
1067 int uLevel, char **buf, int *buflen,
1068 char **stringbuf, int *stringspace, char *baseaddr)
1070 int struct_len;
1071 char* p;
1072 char* p2;
1073 int l2;
1074 int len;
1076 switch (uLevel) {
1077 case 0: struct_len = 16; break;
1078 case 1: struct_len = 26; break;
1079 default: return -1;
1082 if (!buf)
1084 len = 0;
1085 switch (uLevel)
1087 case 1:
1088 len = strlen(service->comment)+1;
1089 break;
1092 if (buflen) *buflen = struct_len;
1093 if (stringspace) *stringspace = len;
1094 return struct_len + len;
1097 len = struct_len;
1098 p = *buf;
1099 if (*buflen < struct_len) return -1;
1100 if (stringbuf)
1102 p2 = *stringbuf;
1103 l2 = *stringspace;
1105 else
1107 p2 = p + struct_len;
1108 l2 = *buflen - struct_len;
1110 if (!baseaddr) baseaddr = p;
1112 switch (uLevel)
1114 case 0:
1115 push_ascii(p,service->name, MAX_NETBIOSNAME_LEN, STR_TERMINATE);
1116 break;
1118 case 1:
1119 push_ascii(p,service->name,MAX_NETBIOSNAME_LEN, STR_TERMINATE);
1120 SIVAL(p,18,service->type);
1121 SIVAL(p,22,PTR_DIFF(p2,baseaddr));
1122 len += CopyAndAdvance(&p2,service->comment,&l2);
1123 break;
1126 if (stringbuf)
1128 *buf = p + struct_len;
1129 *buflen -= struct_len;
1130 *stringbuf = p2;
1131 *stringspace = l2;
1133 else
1135 *buf = p2;
1136 *buflen -= len;
1138 return len;
1142 static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
1144 return(strcmp(s1->name,s2->name));
1147 /****************************************************************************
1148 view list of servers available (or possibly domains). The info is
1149 extracted from lists saved by nmbd on the local host
1150 ****************************************************************************/
1151 static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid, char *param, char *data,
1152 int mdrcnt, int mprcnt, char **rdata,
1153 char **rparam, int *rdata_len, int *rparam_len)
1155 char *str1 = param+2;
1156 char *str2 = skip_string(str1,1);
1157 char *p = skip_string(str2,1);
1158 int uLevel = SVAL(p,0);
1159 int buf_len = SVAL(p,2);
1160 uint32 servertype = IVAL(p,4);
1161 char *p2;
1162 int data_len, fixed_len, string_len;
1163 int f_len = 0, s_len = 0;
1164 struct srv_info_struct *servers=NULL;
1165 int counted=0,total=0;
1166 int i,missed;
1167 fstring domain;
1168 BOOL domain_request;
1169 BOOL local_request;
1171 /* If someone sets all the bits they don't really mean to set
1172 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1173 known servers. */
1175 if (servertype == SV_TYPE_ALL)
1176 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1178 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1179 any other bit (they may just set this bit on it's own) they
1180 want all the locally seen servers. However this bit can be
1181 set on its own so set the requested servers to be
1182 ALL - DOMAIN_ENUM. */
1184 if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM))
1185 servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
1187 domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
1188 local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
1190 p += 8;
1192 if (!prefix_ok(str1,"WrLehD")) return False;
1193 if (!check_server_info(uLevel,str2)) return False;
1195 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1196 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1197 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1199 if (strcmp(str1, "WrLehDz") == 0) {
1200 pull_ascii_fstring(domain, p);
1201 } else {
1202 fstrcpy(domain, lp_workgroup());
1205 if (lp_browse_list())
1206 total = get_server_info(servertype,&servers,domain);
1208 data_len = fixed_len = string_len = 0;
1209 missed = 0;
1211 if (total > 0)
1212 qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
1215 char *lastname=NULL;
1217 for (i=0;i<total;i++)
1219 struct srv_info_struct *s = &servers[i];
1220 if (lastname && strequal(lastname,s->name)) continue;
1221 lastname = s->name;
1222 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1223 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1224 s->name, s->type, s->comment, s->domain));
1226 if (data_len <= buf_len) {
1227 counted++;
1228 fixed_len += f_len;
1229 string_len += s_len;
1230 } else {
1231 missed++;
1236 *rdata_len = fixed_len + string_len;
1237 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
1238 memset(*rdata,'\0',*rdata_len);
1240 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1241 p = *rdata;
1242 f_len = fixed_len;
1243 s_len = string_len;
1246 char *lastname=NULL;
1247 int count2 = counted;
1248 for (i = 0; i < total && count2;i++)
1250 struct srv_info_struct *s = &servers[i];
1251 if (lastname && strequal(lastname,s->name)) continue;
1252 lastname = s->name;
1253 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1254 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1255 s->name, s->type, s->comment, s->domain));
1256 count2--;
1260 *rparam_len = 8;
1261 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1262 SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata));
1263 SSVAL(*rparam,2,0);
1264 SSVAL(*rparam,4,counted);
1265 SSVAL(*rparam,6,counted+missed);
1267 SAFE_FREE(servers);
1269 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1270 domain,uLevel,counted,counted+missed));
1272 return(True);
1275 /****************************************************************************
1276 command 0x34 - suspected of being a "Lookup Names" stub api
1277 ****************************************************************************/
1278 static BOOL api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid, char *param, char *data,
1279 int mdrcnt, int mprcnt, char **rdata,
1280 char **rparam, int *rdata_len, int *rparam_len)
1282 char *str1 = param+2;
1283 char *str2 = skip_string(str1,1);
1284 char *p = skip_string(str2,1);
1285 int uLevel = SVAL(p,0);
1286 int buf_len = SVAL(p,2);
1287 int counted=0;
1288 int missed=0;
1290 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1291 str1, str2, p, uLevel, buf_len));
1293 if (!prefix_ok(str1,"zWrLeh")) return False;
1295 *rdata_len = 0;
1297 *rparam_len = 8;
1298 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1300 SSVAL(*rparam,0,0x08AC); /* informational warning message */
1301 SSVAL(*rparam,2,0);
1302 SSVAL(*rparam,4,counted);
1303 SSVAL(*rparam,6,counted+missed);
1305 return(True);
1308 /****************************************************************************
1309 get info about a share
1310 ****************************************************************************/
1311 static BOOL check_share_info(int uLevel, char* id)
1313 switch( uLevel ) {
1314 case 0:
1315 if (strcmp(id,"B13") != 0) return False;
1316 break;
1317 case 1:
1318 if (strcmp(id,"B13BWz") != 0) return False;
1319 break;
1320 case 2:
1321 if (strcmp(id,"B13BWzWWWzB9B") != 0) return False;
1322 break;
1323 case 91:
1324 if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) return False;
1325 break;
1326 default: return False;
1328 return True;
1331 static int fill_share_info(connection_struct *conn, int snum, int uLevel,
1332 char** buf, int* buflen,
1333 char** stringbuf, int* stringspace, char* baseaddr)
1335 int struct_len;
1336 char* p;
1337 char* p2;
1338 int l2;
1339 int len;
1341 switch( uLevel ) {
1342 case 0: struct_len = 13; break;
1343 case 1: struct_len = 20; break;
1344 case 2: struct_len = 40; break;
1345 case 91: struct_len = 68; break;
1346 default: return -1;
1350 if (!buf)
1352 len = 0;
1353 if (uLevel > 0) len += StrlenExpanded(conn,snum,lp_comment(snum));
1354 if (uLevel > 1) len += strlen(lp_pathname(snum)) + 1;
1355 if (buflen) *buflen = struct_len;
1356 if (stringspace) *stringspace = len;
1357 return struct_len + len;
1360 len = struct_len;
1361 p = *buf;
1362 if ((*buflen) < struct_len) return -1;
1363 if (stringbuf)
1365 p2 = *stringbuf;
1366 l2 = *stringspace;
1368 else
1370 p2 = p + struct_len;
1371 l2 = (*buflen) - struct_len;
1373 if (!baseaddr) baseaddr = p;
1375 push_ascii(p,lp_servicename(snum),13, STR_TERMINATE);
1377 if (uLevel > 0)
1379 int type;
1380 SCVAL(p,13,0);
1381 type = STYPE_DISKTREE;
1382 if (lp_print_ok(snum)) type = STYPE_PRINTQ;
1383 if (strequal("IPC",lp_fstype(snum))) type = STYPE_IPC;
1384 SSVAL(p,14,type); /* device type */
1385 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1386 len += CopyExpanded(conn,snum,&p2,lp_comment(snum),&l2);
1389 if (uLevel > 1)
1391 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1392 SSVALS(p,22,-1); /* max uses */
1393 SSVAL(p,24,1); /* current uses */
1394 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1395 len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1396 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1399 if (uLevel > 2)
1401 memset(p+40,0,SHPWLEN+2);
1402 SSVAL(p,50,0);
1403 SIVAL(p,52,0);
1404 SSVAL(p,56,0);
1405 SSVAL(p,58,0);
1406 SIVAL(p,60,0);
1407 SSVAL(p,64,0);
1408 SSVAL(p,66,0);
1411 if (stringbuf)
1413 (*buf) = p + struct_len;
1414 (*buflen) -= struct_len;
1415 (*stringbuf) = p2;
1416 (*stringspace) = l2;
1418 else
1420 (*buf) = p2;
1421 (*buflen) -= len;
1423 return len;
1426 static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
1427 int mdrcnt,int mprcnt,
1428 char **rdata,char **rparam,
1429 int *rdata_len,int *rparam_len)
1431 char *str1 = param+2;
1432 char *str2 = skip_string(str1,1);
1433 char *netname = skip_string(str2,1);
1434 char *p = skip_string(netname,1);
1435 int uLevel = SVAL(p,0);
1436 int snum = find_service(netname);
1438 if (snum < 0) return False;
1440 /* check it's a supported varient */
1441 if (!prefix_ok(str1,"zWrLh")) return False;
1442 if (!check_share_info(uLevel,str2)) return False;
1444 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
1445 p = *rdata;
1446 *rdata_len = fill_share_info(conn,snum,uLevel,&p,&mdrcnt,0,0,0);
1447 if (*rdata_len < 0) return False;
1449 *rparam_len = 6;
1450 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1451 SSVAL(*rparam,0,NERR_Success);
1452 SSVAL(*rparam,2,0); /* converter word */
1453 SSVAL(*rparam,4,*rdata_len);
1455 return(True);
1458 /****************************************************************************
1459 View the list of available shares.
1461 This function is the server side of the NetShareEnum() RAP call.
1462 It fills the return buffer with share names and share comments.
1463 Note that the return buffer normally (in all known cases) allows only
1464 twelve byte strings for share names (plus one for a nul terminator).
1465 Share names longer than 12 bytes must be skipped.
1466 ****************************************************************************/
1467 static BOOL api_RNetShareEnum( connection_struct *conn,
1468 uint16 vuid,
1469 char *param,
1470 char *data,
1471 int mdrcnt,
1472 int mprcnt,
1473 char **rdata,
1474 char **rparam,
1475 int *rdata_len,
1476 int *rparam_len )
1478 char *str1 = param+2;
1479 char *str2 = skip_string(str1,1);
1480 char *p = skip_string(str2,1);
1481 int uLevel = SVAL(p,0);
1482 int buf_len = SVAL(p,2);
1483 char *p2;
1484 int count=lp_numservices();
1485 int total=0,counted=0;
1486 BOOL missed = False;
1487 int i;
1488 int data_len, fixed_len, string_len;
1489 int f_len = 0, s_len = 0;
1491 if (!prefix_ok(str1,"WrLeh")) return False;
1492 if (!check_share_info(uLevel,str2)) return False;
1494 data_len = fixed_len = string_len = 0;
1495 for (i=0;i<count;i++) {
1496 fstring servicename_dos;
1497 if (!(lp_browseable(i) && lp_snum_ok(i)))
1498 continue;
1499 push_ascii_fstring(servicename_dos, lp_servicename(i));
1500 if( lp_browseable( i )
1501 && lp_snum_ok( i )
1502 && (strlen(servicename_dos) < 13) ) /* Maximum name length. */
1504 total++;
1505 data_len += fill_share_info(conn,i,uLevel,0,&f_len,0,&s_len,0);
1506 if (data_len <= buf_len)
1508 counted++;
1509 fixed_len += f_len;
1510 string_len += s_len;
1512 else
1513 missed = True;
1516 *rdata_len = fixed_len + string_len;
1517 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
1518 memset(*rdata,0,*rdata_len);
1520 p2 = (*rdata) + fixed_len; /* auxiliary data (strings) will go here */
1521 p = *rdata;
1522 f_len = fixed_len;
1523 s_len = string_len;
1524 for( i = 0; i < count; i++ )
1526 fstring servicename_dos;
1527 if (!(lp_browseable(i) && lp_snum_ok(i)))
1528 continue;
1529 push_ascii_fstring(servicename_dos, lp_servicename(i));
1530 if( lp_browseable( i )
1531 && lp_snum_ok( i )
1532 && (strlen(servicename_dos) < 13) )
1534 if( fill_share_info( conn,i,uLevel,&p,&f_len,&p2,&s_len,*rdata ) < 0 )
1535 break;
1539 *rparam_len = 8;
1540 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1541 SSVAL(*rparam,0,missed ? ERRmoredata : NERR_Success);
1542 SSVAL(*rparam,2,0);
1543 SSVAL(*rparam,4,counted);
1544 SSVAL(*rparam,6,total);
1546 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1547 counted,total,uLevel,
1548 buf_len,*rdata_len,mdrcnt));
1549 return(True);
1550 } /* api_RNetShareEnum */
1552 /****************************************************************************
1553 Add a share
1554 ****************************************************************************/
1555 static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid, char *param,char *data,
1556 int mdrcnt,int mprcnt,
1557 char **rdata,char **rparam,
1558 int *rdata_len,int *rparam_len)
1560 char *str1 = param+2;
1561 char *str2 = skip_string(str1,1);
1562 char *p = skip_string(str2,1);
1563 int uLevel = SVAL(p,0);
1564 fstring sharename;
1565 fstring comment;
1566 pstring pathname;
1567 char *command, *cmdname;
1568 unsigned int offset;
1569 int snum;
1570 int res = ERRunsup;
1572 /* check it's a supported varient */
1573 if (!prefix_ok(str1,RAP_WShareAdd_REQ)) return False;
1574 if (!check_share_info(uLevel,str2)) return False;
1575 if (uLevel != 2) return False;
1577 pull_ascii_fstring(sharename,data);
1578 snum = find_service(sharename);
1579 if (snum >= 0) { /* already exists */
1580 res = ERRfilexists;
1581 goto error_exit;
1584 /* only support disk share adds */
1585 if (SVAL(data,14)!=STYPE_DISKTREE) return False;
1587 offset = IVAL(data, 16);
1588 if (offset >= mdrcnt) {
1589 res = ERRinvalidparam;
1590 goto error_exit;
1592 pull_ascii_fstring(comment, offset? (data+offset) : "");
1594 offset = IVAL(data, 26);
1595 if (offset >= mdrcnt) {
1596 res = ERRinvalidparam;
1597 goto error_exit;
1599 pull_ascii_pstring(pathname, offset? (data+offset) : "");
1601 string_replace(sharename, '"', ' ');
1602 string_replace(pathname, '"', ' ');
1603 string_replace(comment, '"', ' ');
1605 cmdname = lp_add_share_cmd();
1607 if (!cmdname || *cmdname == '\0') return False;
1609 asprintf(&command, "%s \"%s\" \"%s\" \"%s\" \"%s\"",
1610 lp_add_share_cmd(), dyn_CONFIGFILE, sharename, pathname, comment);
1612 if (command) {
1613 DEBUG(10,("api_RNetShareAdd: Running [%s]\n", command ));
1614 if ((res = smbrun(command, NULL)) != 0) {
1615 DEBUG(1,("api_RNetShareAdd: Running [%s] returned (%d)\n", command, res ));
1616 SAFE_FREE(command);
1617 res = ERRnoaccess;
1618 goto error_exit;
1619 } else {
1620 SAFE_FREE(command);
1621 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
1623 } else return False;
1625 *rparam_len = 6;
1626 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1627 SSVAL(*rparam,0,NERR_Success);
1628 SSVAL(*rparam,2,0); /* converter word */
1629 SSVAL(*rparam,4,*rdata_len);
1630 *rdata_len = 0;
1632 return True;
1634 error_exit:
1635 *rparam_len = 4;
1636 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1637 *rdata_len = 0;
1638 SSVAL(*rparam,0,res);
1639 SSVAL(*rparam,2,0);
1640 return True;
1644 /****************************************************************************
1645 view list of groups available
1646 ****************************************************************************/
1647 static BOOL api_RNetGroupEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
1648 int mdrcnt,int mprcnt,
1649 char **rdata,char **rparam,
1650 int *rdata_len,int *rparam_len)
1652 int i;
1653 int errflags=0;
1654 int resume_context, cli_buf_size;
1655 char *str1 = param+2;
1656 char *str2 = skip_string(str1,1);
1657 char *p = skip_string(str2,1);
1659 struct pdb_search *search;
1660 struct samr_displayentry *entries;
1662 int num_entries;
1664 if (strcmp(str1,"WrLeh") != 0)
1665 return False;
1667 /* parameters
1668 * W-> resume context (number of users to skip)
1669 * r -> return parameter pointer to receive buffer
1670 * L -> length of receive buffer
1671 * e -> return parameter number of entries
1672 * h -> return parameter total number of users
1674 if (strcmp("B21",str2) != 0)
1675 return False;
1677 /* get list of domain groups SID_DOMAIN_GRP=2 */
1678 become_root();
1679 search = pdb_search_groups();
1680 unbecome_root();
1682 if (search == NULL) {
1683 DEBUG(3,("api_RNetGroupEnum:failed to get group list"));
1684 return False;
1687 resume_context = SVAL(p,0);
1688 cli_buf_size=SVAL(p+2,0);
1689 DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: "
1690 "%d\n", resume_context, cli_buf_size));
1692 become_root();
1693 num_entries = pdb_search_entries(search, resume_context, 0xffffffff,
1694 &entries);
1695 unbecome_root();
1697 *rdata_len = cli_buf_size;
1698 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
1700 p = *rdata;
1702 for(i=0; i<num_entries; i++) {
1703 fstring name;
1704 fstrcpy(name, entries[i].account_name);
1705 if( ((PTR_DIFF(p,*rdata)+21) <= *rdata_len) ) {
1706 /* truncate the name at 21 chars. */
1707 memcpy(p, name, 21);
1708 DEBUG(10,("adding entry %d group %s\n", i, p));
1709 p += 21;
1710 p += 5; /* Both NT4 and W2k3SP1 do padding here.
1711 No idea why... */
1712 } else {
1713 /* set overflow error */
1714 DEBUG(3,("overflow on entry %d group %s\n", i, name));
1715 errflags=234;
1716 break;
1720 pdb_search_destroy(search);
1722 *rdata_len = PTR_DIFF(p,*rdata);
1724 *rparam_len = 8;
1725 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1727 SSVAL(*rparam, 0, errflags);
1728 SSVAL(*rparam, 2, 0); /* converter word */
1729 SSVAL(*rparam, 4, i); /* is this right?? */
1730 SSVAL(*rparam, 6, resume_context+num_entries); /* is this right?? */
1732 return(True);
1735 /*******************************************************************
1736 get groups that a user is a member of
1737 ******************************************************************/
1738 static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *param,char *data,
1739 int mdrcnt,int mprcnt,
1740 char **rdata,char **rparam,
1741 int *rdata_len,int *rparam_len)
1743 char *str1 = param+2;
1744 char *str2 = skip_string(str1,1);
1745 char *UserName = skip_string(str2,1);
1746 char *p = skip_string(UserName,1);
1747 int uLevel = SVAL(p,0);
1748 const char *level_string;
1749 int count=0;
1750 SAM_ACCOUNT *sampw = NULL;
1751 BOOL ret = False;
1752 DOM_SID *sids;
1753 gid_t *gids;
1754 int num_groups;
1755 int i;
1756 fstring grp_domain;
1757 fstring grp_name;
1758 enum SID_NAME_USE grp_type;
1759 struct passwd *passwd;
1760 NTSTATUS result;
1762 *rparam_len = 8;
1763 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1765 /* check it's a supported varient */
1767 if ( strcmp(str1,"zWrLeh") != 0 )
1768 return False;
1770 switch( uLevel ) {
1771 case 0:
1772 level_string = "B21";
1773 break;
1774 default:
1775 return False;
1778 if (strcmp(level_string,str2) != 0)
1779 return False;
1781 *rdata_len = mdrcnt + 1024;
1782 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
1784 SSVAL(*rparam,0,NERR_Success);
1785 SSVAL(*rparam,2,0); /* converter word */
1787 p = *rdata;
1789 /* Lookup the user information; This should only be one of
1790 our accounts (not remote domains) */
1792 passwd = getpwnam_alloc(UserName);
1794 if (passwd == NULL)
1795 return False;
1797 pdb_init_sam( &sampw );
1799 become_root(); /* ROOT BLOCK */
1801 if ( !pdb_getsampwnam(sampw, UserName) )
1802 goto out;
1804 sids = NULL;
1805 num_groups = 0;
1807 result = pdb_enum_group_memberships(pdb_get_username(sampw),
1808 passwd->pw_gid,
1809 &sids, &gids, &num_groups);
1811 if (!NT_STATUS_IS_OK(result))
1812 goto out;
1814 for (i=0; i<num_groups; i++) {
1816 if ( lookup_sid(&sids[i], grp_domain, grp_name, &grp_type) ) {
1817 pstrcpy(p, grp_name);
1818 p += 21;
1819 count++;
1823 SAFE_FREE(sids);
1825 *rdata_len = PTR_DIFF(p,*rdata);
1827 SSVAL(*rparam,4,count); /* is this right?? */
1828 SSVAL(*rparam,6,count); /* is this right?? */
1830 ret = True;
1832 out:
1833 unbecome_root(); /* END ROOT BLOCK */
1835 pdb_free_sam( &sampw );
1836 passwd_free(&passwd);
1838 return ret;
1841 /*******************************************************************
1842 get all users
1843 ******************************************************************/
1844 static BOOL api_RNetUserEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
1845 int mdrcnt,int mprcnt,
1846 char **rdata,char **rparam,
1847 int *rdata_len,int *rparam_len)
1849 int count_sent=0;
1850 int num_users=0;
1851 int errflags=0;
1852 int i, resume_context, cli_buf_size;
1853 struct pdb_search *search;
1854 struct samr_displayentry *users;
1856 char *str1 = param+2;
1857 char *str2 = skip_string(str1,1);
1858 char *p = skip_string(str2,1);
1860 if (strcmp(str1,"WrLeh") != 0)
1861 return False;
1862 /* parameters
1863 * W-> resume context (number of users to skip)
1864 * r -> return parameter pointer to receive buffer
1865 * L -> length of receive buffer
1866 * e -> return parameter number of entries
1867 * h -> return parameter total number of users
1870 resume_context = SVAL(p,0);
1871 cli_buf_size=SVAL(p+2,0);
1872 DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n", resume_context, cli_buf_size));
1874 *rparam_len = 8;
1875 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1877 /* check it's a supported varient */
1878 if (strcmp("B21",str2) != 0)
1879 return False;
1881 *rdata_len = cli_buf_size;
1882 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
1884 p = *rdata;
1886 become_root();
1887 search = pdb_search_users(ACB_NORMAL);
1888 unbecome_root();
1889 if (search == NULL) {
1890 DEBUG(0, ("api_RNetUserEnum:unable to open sam database.\n"));
1891 return False;
1894 become_root();
1895 num_users = pdb_search_entries(search, resume_context, 0xffffffff,
1896 &users);
1897 unbecome_root();
1899 errflags=NERR_Success;
1901 for (i=0; i<num_users; i++) {
1902 const char *name = users[i].account_name;
1904 if(((PTR_DIFF(p,*rdata)+21)<=*rdata_len)&&(strlen(name)<=21)) {
1905 pstrcpy(p,name);
1906 DEBUG(10,("api_RNetUserEnum:adding entry %d username "
1907 "%s\n",count_sent,p));
1908 p += 21;
1909 count_sent++;
1910 } else {
1911 /* set overflow error */
1912 DEBUG(10,("api_RNetUserEnum:overflow on entry %d "
1913 "username %s\n",count_sent,name));
1914 errflags=234;
1915 break;
1919 pdb_search_destroy(search);
1921 *rdata_len = PTR_DIFF(p,*rdata);
1923 SSVAL(*rparam,0,errflags);
1924 SSVAL(*rparam,2,0); /* converter word */
1925 SSVAL(*rparam,4,count_sent); /* is this right?? */
1926 SSVAL(*rparam,6,num_users); /* is this right?? */
1928 return True;
1933 /****************************************************************************
1934 get the time of day info
1935 ****************************************************************************/
1936 static BOOL api_NetRemoteTOD(connection_struct *conn,uint16 vuid, char *param,char *data,
1937 int mdrcnt,int mprcnt,
1938 char **rdata,char **rparam,
1939 int *rdata_len,int *rparam_len)
1941 char *p;
1942 *rparam_len = 4;
1943 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1945 *rdata_len = 21;
1946 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
1948 SSVAL(*rparam,0,NERR_Success);
1949 SSVAL(*rparam,2,0); /* converter word */
1951 p = *rdata;
1954 struct tm *t;
1955 time_t unixdate = time(NULL);
1957 put_dos_date3(p,0,unixdate); /* this is the time that is looked at
1958 by NT in a "net time" operation,
1959 it seems to ignore the one below */
1961 /* the client expects to get localtime, not GMT, in this bit
1962 (I think, this needs testing) */
1963 t = LocalTime(&unixdate);
1965 SIVAL(p,4,0); /* msecs ? */
1966 SCVAL(p,8,t->tm_hour);
1967 SCVAL(p,9,t->tm_min);
1968 SCVAL(p,10,t->tm_sec);
1969 SCVAL(p,11,0); /* hundredths of seconds */
1970 SSVALS(p,12,TimeDiff(unixdate)/60); /* timezone in minutes from GMT */
1971 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
1972 SCVAL(p,16,t->tm_mday);
1973 SCVAL(p,17,t->tm_mon + 1);
1974 SSVAL(p,18,1900+t->tm_year);
1975 SCVAL(p,20,t->tm_wday);
1979 return(True);
1982 /****************************************************************************
1983 Set the user password.
1984 *****************************************************************************/
1986 static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param,char *data,
1987 int mdrcnt,int mprcnt,
1988 char **rdata,char **rparam,
1989 int *rdata_len,int *rparam_len)
1991 char *p = skip_string(param+2,2);
1992 fstring user;
1993 fstring pass1,pass2;
1995 pull_ascii_fstring(user,p);
1997 p = skip_string(p,1);
1999 memset(pass1,'\0',sizeof(pass1));
2000 memset(pass2,'\0',sizeof(pass2));
2001 memcpy(pass1,p,16);
2002 memcpy(pass2,p+16,16);
2004 *rparam_len = 4;
2005 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2007 *rdata_len = 0;
2009 SSVAL(*rparam,0,NERR_badpass);
2010 SSVAL(*rparam,2,0); /* converter word */
2012 DEBUG(3,("Set password for <%s>\n",user));
2015 * Attempt to verify the old password against smbpasswd entries
2016 * Win98 clients send old and new password in plaintext for this call.
2020 auth_serversupplied_info *server_info = NULL;
2021 DATA_BLOB password = data_blob(pass1, strlen(pass1)+1);
2023 if (NT_STATUS_IS_OK(check_plaintext_password(user,password,&server_info))) {
2025 become_root();
2026 if (NT_STATUS_IS_OK(change_oem_password(server_info->sam_account, pass1, pass2, False))) {
2027 SSVAL(*rparam,0,NERR_Success);
2029 unbecome_root();
2031 free_server_info(&server_info);
2033 data_blob_clear_free(&password);
2037 * If the plaintext change failed, attempt
2038 * the old encrypted method. NT will generate this
2039 * after trying the samr method. Note that this
2040 * method is done as a last resort as this
2041 * password change method loses the NT password hash
2042 * and cannot change the UNIX password as no plaintext
2043 * is received.
2046 if(SVAL(*rparam,0) != NERR_Success) {
2047 SAM_ACCOUNT *hnd = NULL;
2049 if (check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &hnd)) {
2050 become_root();
2051 if (change_lanman_password(hnd,(uchar *)pass2)) {
2052 SSVAL(*rparam,0,NERR_Success);
2054 unbecome_root();
2055 pdb_free_sam(&hnd);
2059 memset((char *)pass1,'\0',sizeof(fstring));
2060 memset((char *)pass2,'\0',sizeof(fstring));
2062 return(True);
2065 /****************************************************************************
2066 Set the user password (SamOEM version - gets plaintext).
2067 ****************************************************************************/
2069 static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char *param,char *data,
2070 int mdrcnt,int mprcnt,
2071 char **rdata,char **rparam,
2072 int *rdata_len,int *rparam_len)
2074 fstring user;
2075 char *p = param + 2;
2076 *rparam_len = 2;
2077 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2079 *rdata_len = 0;
2081 SSVAL(*rparam,0,NERR_badpass);
2084 * Check the parameter definition is correct.
2087 if(!strequal(param + 2, "zsT")) {
2088 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", param + 2));
2089 return False;
2091 p = skip_string(p, 1);
2093 if(!strequal(p, "B516B16")) {
2094 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p));
2095 return False;
2097 p = skip_string(p,1);
2098 p += pull_ascii_fstring(user,p);
2100 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user));
2103 * Pass the user through the NT -> unix user mapping
2104 * function.
2107 (void)map_username(user);
2109 if (NT_STATUS_IS_OK(pass_oem_change(user, (uchar*) data, (uchar *)&data[516], NULL, NULL))) {
2110 SSVAL(*rparam,0,NERR_Success);
2113 return(True);
2116 /****************************************************************************
2117 delete a print job
2118 Form: <W> <>
2119 ****************************************************************************/
2120 static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char *param,char *data,
2121 int mdrcnt,int mprcnt,
2122 char **rdata,char **rparam,
2123 int *rdata_len,int *rparam_len)
2125 int function = SVAL(param,0);
2126 char *str1 = param+2;
2127 char *str2 = skip_string(str1,1);
2128 char *p = skip_string(str2,1);
2129 uint32 jobid;
2130 int snum;
2131 fstring sharename;
2132 int errcode;
2133 WERROR werr = WERR_OK;
2135 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
2136 return False;
2138 /* check it's a supported varient */
2139 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
2140 return(False);
2142 *rparam_len = 4;
2143 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2144 *rdata_len = 0;
2146 if (!print_job_exists(sharename, jobid)) {
2147 errcode = NERR_JobNotFound;
2148 goto out;
2151 snum = lp_servicenumber( sharename);
2152 if (snum == -1) {
2153 errcode = NERR_DestNotFound;
2154 goto out;
2157 errcode = NERR_notsupported;
2159 switch (function) {
2160 case 81: /* delete */
2161 if (print_job_delete(&current_user, snum, jobid, &werr))
2162 errcode = NERR_Success;
2163 break;
2164 case 82: /* pause */
2165 if (print_job_pause(&current_user, snum, jobid, &werr))
2166 errcode = NERR_Success;
2167 break;
2168 case 83: /* resume */
2169 if (print_job_resume(&current_user, snum, jobid, &werr))
2170 errcode = NERR_Success;
2171 break;
2174 if (!W_ERROR_IS_OK(werr))
2175 errcode = W_ERROR_V(werr);
2177 out:
2178 SSVAL(*rparam,0,errcode);
2179 SSVAL(*rparam,2,0); /* converter word */
2181 return(True);
2184 /****************************************************************************
2185 Purge a print queue - or pause or resume it.
2186 ****************************************************************************/
2187 static BOOL api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid, char *param,char *data,
2188 int mdrcnt,int mprcnt,
2189 char **rdata,char **rparam,
2190 int *rdata_len,int *rparam_len)
2192 int function = SVAL(param,0);
2193 char *str1 = param+2;
2194 char *str2 = skip_string(str1,1);
2195 char *QueueName = skip_string(str2,1);
2196 int errcode = NERR_notsupported;
2197 int snum;
2198 WERROR werr = WERR_OK;
2200 /* check it's a supported varient */
2201 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
2202 return(False);
2204 *rparam_len = 4;
2205 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2206 *rdata_len = 0;
2208 snum = print_queue_snum(QueueName);
2210 if (snum == -1) {
2211 errcode = NERR_JobNotFound;
2212 goto out;
2215 switch (function) {
2216 case 74: /* Pause queue */
2217 if (print_queue_pause(&current_user, snum, &werr)) errcode = NERR_Success;
2218 break;
2219 case 75: /* Resume queue */
2220 if (print_queue_resume(&current_user, snum, &werr)) errcode = NERR_Success;
2221 break;
2222 case 103: /* Purge */
2223 if (print_queue_purge(&current_user, snum, &werr)) errcode = NERR_Success;
2224 break;
2227 if (!W_ERROR_IS_OK(werr)) errcode = W_ERROR_V(werr);
2229 out:
2230 SSVAL(*rparam,0,errcode);
2231 SSVAL(*rparam,2,0); /* converter word */
2233 return(True);
2237 /****************************************************************************
2238 set the property of a print job (undocumented?)
2239 ? function = 0xb -> set name of print job
2240 ? function = 0x6 -> move print job up/down
2241 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
2242 or <WWsTP> <WB21BB16B10zWWzDDz>
2243 ****************************************************************************/
2244 static int check_printjob_info(struct pack_desc* desc,
2245 int uLevel, char* id)
2247 desc->subformat = NULL;
2248 switch( uLevel ) {
2249 case 0: desc->format = "W"; break;
2250 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
2251 case 2: desc->format = "WWzWWDDzz"; break;
2252 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
2253 case 4: desc->format = "WWzWWDDzzzzzDDDDDDD"; break;
2254 default: return False;
2256 if (strcmp(desc->format,id) != 0) return False;
2257 return True;
2260 static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,char *data,
2261 int mdrcnt,int mprcnt,
2262 char **rdata,char **rparam,
2263 int *rdata_len,int *rparam_len)
2265 struct pack_desc desc;
2266 char *str1 = param+2;
2267 char *str2 = skip_string(str1,1);
2268 char *p = skip_string(str2,1);
2269 uint32 jobid;
2270 int snum;
2271 fstring sharename;
2272 int uLevel = SVAL(p,2);
2273 int function = SVAL(p,4);
2274 int place, errcode;
2276 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
2277 return False;
2278 *rparam_len = 4;
2279 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2281 if ( (snum = lp_servicenumber(sharename)) == -1 ) {
2282 DEBUG(0,("api_PrintJobInfo: unable to get service number from sharename [%s]\n",
2283 sharename));
2284 return False;
2287 *rdata_len = 0;
2289 /* check it's a supported varient */
2290 if ((strcmp(str1,"WWsTP")) ||
2291 (!check_printjob_info(&desc,uLevel,str2)))
2292 return(False);
2294 if (!print_job_exists(sharename, jobid)) {
2295 errcode=NERR_JobNotFound;
2296 goto out;
2299 errcode = NERR_notsupported;
2301 switch (function) {
2302 case 0x6:
2303 /* change job place in the queue,
2304 data gives the new place */
2305 place = SVAL(data,0);
2306 if (print_job_set_place(snum, jobid, place)) {
2307 errcode=NERR_Success;
2309 break;
2311 case 0xb:
2312 /* change print job name, data gives the name */
2313 if (print_job_set_name(snum, jobid, data)) {
2314 errcode=NERR_Success;
2316 break;
2318 default:
2319 return False;
2322 out:
2323 SSVALS(*rparam,0,errcode);
2324 SSVAL(*rparam,2,0); /* converter word */
2326 return(True);
2330 /****************************************************************************
2331 get info about the server
2332 ****************************************************************************/
2333 static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2334 int mdrcnt,int mprcnt,
2335 char **rdata,char **rparam,
2336 int *rdata_len,int *rparam_len)
2338 char *str1 = param+2;
2339 char *str2 = skip_string(str1,1);
2340 char *p = skip_string(str2,1);
2341 int uLevel = SVAL(p,0);
2342 char *p2;
2343 int struct_len;
2345 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
2347 /* check it's a supported varient */
2348 if (!prefix_ok(str1,"WrLh")) return False;
2349 switch( uLevel ) {
2350 case 0:
2351 if (strcmp(str2,"B16") != 0) return False;
2352 struct_len = 16;
2353 break;
2354 case 1:
2355 if (strcmp(str2,"B16BBDz") != 0) return False;
2356 struct_len = 26;
2357 break;
2358 case 2:
2359 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")
2360 != 0) return False;
2361 struct_len = 134;
2362 break;
2363 case 3:
2364 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz")
2365 != 0) return False;
2366 struct_len = 144;
2367 break;
2368 case 20:
2369 if (strcmp(str2,"DN") != 0) return False;
2370 struct_len = 6;
2371 break;
2372 case 50:
2373 if (strcmp(str2,"B16BBDzWWzzz") != 0) return False;
2374 struct_len = 42;
2375 break;
2376 default: return False;
2379 *rdata_len = mdrcnt;
2380 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
2382 p = *rdata;
2383 p2 = p + struct_len;
2384 if (uLevel != 20) {
2385 srvstr_push(NULL, p,get_local_machine_name(),16,
2386 STR_ASCII|STR_UPPER|STR_TERMINATE);
2388 p += 16;
2389 if (uLevel > 0)
2391 struct srv_info_struct *servers=NULL;
2392 int i,count;
2393 pstring comment;
2394 uint32 servertype= lp_default_server_announce();
2396 push_ascii(comment,lp_serverstring(), MAX_SERVER_STRING_LENGTH,STR_TERMINATE);
2398 if ((count=get_server_info(SV_TYPE_ALL,&servers,lp_workgroup()))>0) {
2399 for (i=0;i<count;i++) {
2400 if (strequal(servers[i].name,get_local_machine_name())) {
2401 servertype = servers[i].type;
2402 push_ascii(comment,servers[i].comment,sizeof(pstring),STR_TERMINATE);
2406 SAFE_FREE(servers);
2408 SCVAL(p,0,lp_major_announce_version());
2409 SCVAL(p,1,lp_minor_announce_version());
2410 SIVAL(p,2,servertype);
2412 if (mdrcnt == struct_len) {
2413 SIVAL(p,6,0);
2414 } else {
2415 SIVAL(p,6,PTR_DIFF(p2,*rdata));
2416 standard_sub_conn(conn,comment,sizeof(comment));
2417 StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
2418 p2 = skip_string(p2,1);
2421 if (uLevel > 1)
2423 return False; /* not yet implemented */
2426 *rdata_len = PTR_DIFF(p2,*rdata);
2428 *rparam_len = 6;
2429 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2430 SSVAL(*rparam,0,NERR_Success);
2431 SSVAL(*rparam,2,0); /* converter word */
2432 SSVAL(*rparam,4,*rdata_len);
2434 return(True);
2438 /****************************************************************************
2439 get info about the server
2440 ****************************************************************************/
2441 static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2442 int mdrcnt,int mprcnt,
2443 char **rdata,char **rparam,
2444 int *rdata_len,int *rparam_len)
2446 char *str1 = param+2;
2447 char *str2 = skip_string(str1,1);
2448 char *p = skip_string(str2,1);
2449 char *p2;
2450 int level = SVAL(p,0);
2452 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
2454 *rparam_len = 6;
2455 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2457 /* check it's a supported varient */
2458 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz")))
2459 return(False);
2461 *rdata_len = mdrcnt + 1024;
2462 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
2464 SSVAL(*rparam,0,NERR_Success);
2465 SSVAL(*rparam,2,0); /* converter word */
2467 p = *rdata;
2468 p2 = p + 22;
2471 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
2472 pstrcpy(p2,get_local_machine_name());
2473 strupper_m(p2);
2474 p2 = skip_string(p2,1);
2475 p += 4;
2477 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2478 pstrcpy(p2,current_user_info.smb_name);
2479 p2 = skip_string(p2,1);
2480 p += 4;
2482 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
2483 pstrcpy(p2,lp_workgroup());
2484 strupper_m(p2);
2485 p2 = skip_string(p2,1);
2486 p += 4;
2488 SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
2489 SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
2490 p += 2;
2492 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2493 pstrcpy(p2,lp_workgroup()); /* don't know. login domain?? */
2494 p2 = skip_string(p2,1);
2495 p += 4;
2497 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
2498 pstrcpy(p2,"");
2499 p2 = skip_string(p2,1);
2500 p += 4;
2502 *rdata_len = PTR_DIFF(p2,*rdata);
2504 SSVAL(*rparam,4,*rdata_len);
2506 return(True);
2509 /****************************************************************************
2510 get info about a user
2512 struct user_info_11 {
2513 char usri11_name[21]; 0-20
2514 char usri11_pad; 21
2515 char *usri11_comment; 22-25
2516 char *usri11_usr_comment; 26-29
2517 unsigned short usri11_priv; 30-31
2518 unsigned long usri11_auth_flags; 32-35
2519 long usri11_password_age; 36-39
2520 char *usri11_homedir; 40-43
2521 char *usri11_parms; 44-47
2522 long usri11_last_logon; 48-51
2523 long usri11_last_logoff; 52-55
2524 unsigned short usri11_bad_pw_count; 56-57
2525 unsigned short usri11_num_logons; 58-59
2526 char *usri11_logon_server; 60-63
2527 unsigned short usri11_country_code; 64-65
2528 char *usri11_workstations; 66-69
2529 unsigned long usri11_max_storage; 70-73
2530 unsigned short usri11_units_per_week; 74-75
2531 unsigned char *usri11_logon_hours; 76-79
2532 unsigned short usri11_code_page; 80-81
2535 where:
2537 usri11_name specifies the user name for which information is retireved
2539 usri11_pad aligns the next data structure element to a word boundary
2541 usri11_comment is a null terminated ASCII comment
2543 usri11_user_comment is a null terminated ASCII comment about the user
2545 usri11_priv specifies the level of the privilege assigned to the user.
2546 The possible values are:
2548 Name Value Description
2549 USER_PRIV_GUEST 0 Guest privilege
2550 USER_PRIV_USER 1 User privilege
2551 USER_PRV_ADMIN 2 Administrator privilege
2553 usri11_auth_flags specifies the account operator privileges. The
2554 possible values are:
2556 Name Value Description
2557 AF_OP_PRINT 0 Print operator
2560 Leach, Naik [Page 28]
2564 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2567 AF_OP_COMM 1 Communications operator
2568 AF_OP_SERVER 2 Server operator
2569 AF_OP_ACCOUNTS 3 Accounts operator
2572 usri11_password_age specifies how many seconds have elapsed since the
2573 password was last changed.
2575 usri11_home_dir points to a null terminated ASCII string that contains
2576 the path name of the user's home directory.
2578 usri11_parms points to a null terminated ASCII string that is set
2579 aside for use by applications.
2581 usri11_last_logon specifies the time when the user last logged on.
2582 This value is stored as the number of seconds elapsed since
2583 00:00:00, January 1, 1970.
2585 usri11_last_logoff specifies the time when the user last logged off.
2586 This value is stored as the number of seconds elapsed since
2587 00:00:00, January 1, 1970. A value of 0 means the last logoff
2588 time is unknown.
2590 usri11_bad_pw_count specifies the number of incorrect passwords
2591 entered since the last successful logon.
2593 usri11_log1_num_logons specifies the number of times this user has
2594 logged on. A value of -1 means the number of logons is unknown.
2596 usri11_logon_server points to a null terminated ASCII string that
2597 contains the name of the server to which logon requests are sent.
2598 A null string indicates logon requests should be sent to the
2599 domain controller.
2601 usri11_country_code specifies the country code for the user's language
2602 of choice.
2604 usri11_workstations points to a null terminated ASCII string that
2605 contains the names of workstations the user may log on from.
2606 There may be up to 8 workstations, with the names separated by
2607 commas. A null strings indicates there are no restrictions.
2609 usri11_max_storage specifies the maximum amount of disk space the user
2610 can occupy. A value of 0xffffffff indicates there are no
2611 restrictions.
2613 usri11_units_per_week specifies the equal number of time units into
2614 which a week is divided. This value must be equal to 168.
2616 usri11_logon_hours points to a 21 byte (168 bits) string that
2617 specifies the time during which the user can log on. Each bit
2618 represents one unique hour in a week. The first bit (bit 0, word
2619 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
2623 Leach, Naik [Page 29]
2627 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2630 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
2631 are no restrictions.
2633 usri11_code_page specifies the code page for the user's language of
2634 choice
2636 All of the pointers in this data structure need to be treated
2637 specially. The pointer is a 32 bit pointer. The higher 16 bits need
2638 to be ignored. The converter word returned in the parameters section
2639 needs to be subtracted from the lower 16 bits to calculate an offset
2640 into the return buffer where this ASCII string resides.
2642 There is no auxiliary data in the response.
2644 ****************************************************************************/
2646 #define usri11_name 0
2647 #define usri11_pad 21
2648 #define usri11_comment 22
2649 #define usri11_usr_comment 26
2650 #define usri11_full_name 30
2651 #define usri11_priv 34
2652 #define usri11_auth_flags 36
2653 #define usri11_password_age 40
2654 #define usri11_homedir 44
2655 #define usri11_parms 48
2656 #define usri11_last_logon 52
2657 #define usri11_last_logoff 56
2658 #define usri11_bad_pw_count 60
2659 #define usri11_num_logons 62
2660 #define usri11_logon_server 64
2661 #define usri11_country_code 68
2662 #define usri11_workstations 70
2663 #define usri11_max_storage 74
2664 #define usri11_units_per_week 78
2665 #define usri11_logon_hours 80
2666 #define usri11_code_page 84
2667 #define usri11_end 86
2669 #define USER_PRIV_GUEST 0
2670 #define USER_PRIV_USER 1
2671 #define USER_PRIV_ADMIN 2
2673 #define AF_OP_PRINT 0
2674 #define AF_OP_COMM 1
2675 #define AF_OP_SERVER 2
2676 #define AF_OP_ACCOUNTS 3
2679 static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2680 int mdrcnt,int mprcnt,
2681 char **rdata,char **rparam,
2682 int *rdata_len,int *rparam_len)
2684 char *str1 = param+2;
2685 char *str2 = skip_string(str1,1);
2686 char *UserName = skip_string(str2,1);
2687 char *p = skip_string(UserName,1);
2688 int uLevel = SVAL(p,0);
2689 char *p2;
2690 const char *level_string;
2692 /* get NIS home of a previously validated user - simeon */
2693 /* With share level security vuid will always be zero.
2694 Don't depend on vuser being non-null !!. JRA */
2695 user_struct *vuser = get_valid_user_struct(vuid);
2696 if(vuser != NULL)
2697 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid,
2698 vuser->user.unix_name));
2700 *rparam_len = 6;
2701 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2703 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
2705 /* check it's a supported variant */
2706 if (strcmp(str1,"zWrLh") != 0) return False;
2707 switch( uLevel )
2709 case 0: level_string = "B21"; break;
2710 case 1: level_string = "B21BB16DWzzWz"; break;
2711 case 2: level_string = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
2712 case 10: level_string = "B21Bzzz"; break;
2713 case 11: level_string = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
2714 default: return False;
2717 if (strcmp(level_string,str2) != 0) return False;
2719 *rdata_len = mdrcnt + 1024;
2720 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
2722 SSVAL(*rparam,0,NERR_Success);
2723 SSVAL(*rparam,2,0); /* converter word */
2725 p = *rdata;
2726 p2 = p + usri11_end;
2728 memset(p,0,21);
2729 fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
2731 if (uLevel > 0)
2733 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
2734 *p2 = 0;
2736 if (uLevel >= 10)
2738 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
2739 pstrcpy(p2,"Comment");
2740 p2 = skip_string(p2,1);
2742 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
2743 pstrcpy(p2,"UserComment");
2744 p2 = skip_string(p2,1);
2746 /* EEK! the cifsrap.txt doesn't have this in!!!! */
2747 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
2748 pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName));
2749 p2 = skip_string(p2,1);
2752 if (uLevel == 11) /* modelled after NTAS 3.51 reply */
2754 SSVAL(p,usri11_priv,conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2755 SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
2756 SIVALS(p,usri11_password_age,-1); /* password age */
2757 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
2758 pstrcpy(p2, vuser && vuser->homedir ? vuser->homedir : "");
2759 p2 = skip_string(p2,1);
2760 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
2761 pstrcpy(p2,"");
2762 p2 = skip_string(p2,1);
2763 SIVAL(p,usri11_last_logon,0); /* last logon */
2764 SIVAL(p,usri11_last_logoff,0); /* last logoff */
2765 SSVALS(p,usri11_bad_pw_count,-1); /* bad pw counts */
2766 SSVALS(p,usri11_num_logons,-1); /* num logons */
2767 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
2768 pstrcpy(p2,"\\\\*");
2769 p2 = skip_string(p2,1);
2770 SSVAL(p,usri11_country_code,0); /* country code */
2772 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
2773 pstrcpy(p2,"");
2774 p2 = skip_string(p2,1);
2776 SIVALS(p,usri11_max_storage,-1); /* max storage */
2777 SSVAL(p,usri11_units_per_week,168); /* units per week */
2778 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
2780 /* a simple way to get logon hours at all times. */
2781 memset(p2,0xff,21);
2782 SCVAL(p2,21,0); /* fix zero termination */
2783 p2 = skip_string(p2,1);
2785 SSVAL(p,usri11_code_page,0); /* code page */
2787 if (uLevel == 1 || uLevel == 2)
2789 memset(p+22,' ',16); /* password */
2790 SIVALS(p,38,-1); /* password age */
2791 SSVAL(p,42,
2792 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2793 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
2794 pstrcpy(p2, vuser && vuser->homedir ? vuser->homedir : "");
2795 p2 = skip_string(p2,1);
2796 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
2797 *p2++ = 0;
2798 SSVAL(p,52,0); /* flags */
2799 SIVAL(p,54,PTR_DIFF(p2,*rdata)); /* script_path */
2800 pstrcpy(p2,vuser && vuser->logon_script ? vuser->logon_script : "");
2801 p2 = skip_string(p2,1);
2802 if (uLevel == 2)
2804 SIVAL(p,60,0); /* auth_flags */
2805 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
2806 pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName));
2807 p2 = skip_string(p2,1);
2808 SIVAL(p,68,0); /* urs_comment */
2809 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
2810 pstrcpy(p2,"");
2811 p2 = skip_string(p2,1);
2812 SIVAL(p,76,0); /* workstations */
2813 SIVAL(p,80,0); /* last_logon */
2814 SIVAL(p,84,0); /* last_logoff */
2815 SIVALS(p,88,-1); /* acct_expires */
2816 SIVALS(p,92,-1); /* max_storage */
2817 SSVAL(p,96,168); /* units_per_week */
2818 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
2819 memset(p2,-1,21);
2820 p2 += 21;
2821 SSVALS(p,102,-1); /* bad_pw_count */
2822 SSVALS(p,104,-1); /* num_logons */
2823 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
2824 pstrcpy(p2,"\\\\%L");
2825 standard_sub_conn(conn, p2,0);
2826 p2 = skip_string(p2,1);
2827 SSVAL(p,110,49); /* country_code */
2828 SSVAL(p,112,860); /* code page */
2832 *rdata_len = PTR_DIFF(p2,*rdata);
2834 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
2836 return(True);
2839 static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param,char *data,
2840 int mdrcnt,int mprcnt,
2841 char **rdata,char **rparam,
2842 int *rdata_len,int *rparam_len)
2844 char *str1 = param+2;
2845 char *str2 = skip_string(str1,1);
2846 char *p = skip_string(str2,1);
2847 int uLevel;
2848 struct pack_desc desc;
2849 char* name;
2850 /* With share level security vuid will always be zero.
2851 Don't depend on vuser being non-null !!. JRA */
2852 user_struct *vuser = get_valid_user_struct(vuid);
2853 if(vuser != NULL)
2854 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid,
2855 vuser->user.unix_name));
2857 uLevel = SVAL(p,0);
2858 name = p + 2;
2860 memset((char *)&desc,'\0',sizeof(desc));
2862 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
2864 /* check it's a supported varient */
2865 if (strcmp(str1,"OOWb54WrLh") != 0) return False;
2866 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) return False;
2867 if (mdrcnt > 0) *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
2868 desc.base = *rdata;
2869 desc.buflen = mdrcnt;
2870 desc.subformat = NULL;
2871 desc.format = str2;
2873 if (init_package(&desc,1,0))
2875 PACKI(&desc,"W",0); /* code */
2876 PACKS(&desc,"B21",name); /* eff. name */
2877 PACKS(&desc,"B",""); /* pad */
2878 PACKI(&desc,"W",
2879 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2880 PACKI(&desc,"D",0); /* auth flags XXX */
2881 PACKI(&desc,"W",0); /* num logons */
2882 PACKI(&desc,"W",0); /* bad pw count */
2883 PACKI(&desc,"D",0); /* last logon */
2884 PACKI(&desc,"D",-1); /* last logoff */
2885 PACKI(&desc,"D",-1); /* logoff time */
2886 PACKI(&desc,"D",-1); /* kickoff time */
2887 PACKI(&desc,"D",0); /* password age */
2888 PACKI(&desc,"D",0); /* password can change */
2889 PACKI(&desc,"D",-1); /* password must change */
2891 fstring mypath;
2892 fstrcpy(mypath,"\\\\");
2893 fstrcat(mypath,get_local_machine_name());
2894 strupper_m(mypath);
2895 PACKS(&desc,"z",mypath); /* computer */
2897 PACKS(&desc,"z",lp_workgroup());/* domain */
2899 PACKS(&desc,"z", vuser && vuser->logon_script ? vuser->logon_script :""); /* script path */
2901 PACKI(&desc,"D",0x00000000); /* reserved */
2904 *rdata_len = desc.usedlen;
2905 *rparam_len = 6;
2906 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2907 SSVALS(*rparam,0,desc.errcode);
2908 SSVAL(*rparam,2,0);
2909 SSVAL(*rparam,4,desc.neededlen);
2911 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
2912 return(True);
2916 /****************************************************************************
2917 api_WAccessGetUserPerms
2918 ****************************************************************************/
2919 static BOOL api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid, char *param,char *data,
2920 int mdrcnt,int mprcnt,
2921 char **rdata,char **rparam,
2922 int *rdata_len,int *rparam_len)
2924 char *str1 = param+2;
2925 char *str2 = skip_string(str1,1);
2926 char *user = skip_string(str2,1);
2927 char *resource = skip_string(user,1);
2929 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
2931 /* check it's a supported varient */
2932 if (strcmp(str1,"zzh") != 0) return False;
2933 if (strcmp(str2,"") != 0) return False;
2935 *rparam_len = 6;
2936 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2937 SSVALS(*rparam,0,0); /* errorcode */
2938 SSVAL(*rparam,2,0); /* converter word */
2939 SSVAL(*rparam,4,0x7f); /* permission flags */
2941 return(True);
2944 /****************************************************************************
2945 api_WPrintJobEnumerate
2946 ****************************************************************************/
2947 static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2948 int mdrcnt,int mprcnt,
2949 char **rdata,char **rparam,
2950 int *rdata_len,int *rparam_len)
2952 char *str1 = param+2;
2953 char *str2 = skip_string(str1,1);
2954 char *p = skip_string(str2,1);
2955 int uLevel;
2956 int count;
2957 int i;
2958 int snum;
2959 fstring sharename;
2960 uint32 jobid;
2961 struct pack_desc desc;
2962 print_queue_struct *queue=NULL;
2963 print_status_struct status;
2964 char *tmpdata=NULL;
2966 uLevel = SVAL(p,2);
2968 memset((char *)&desc,'\0',sizeof(desc));
2969 memset((char *)&status,'\0',sizeof(status));
2971 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
2973 /* check it's a supported varient */
2974 if (strcmp(str1,"WWrLh") != 0) return False;
2975 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2977 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
2978 return False;
2980 snum = lp_servicenumber( sharename);
2981 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2983 count = print_queue_status(snum,&queue,&status);
2984 for (i = 0; i < count; i++) {
2985 if (queue[i].job == jobid) break;
2988 if (mdrcnt > 0) {
2989 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
2990 desc.base = *rdata;
2991 desc.buflen = mdrcnt;
2992 } else {
2994 * Don't return data but need to get correct length
2995 * init_package will return wrong size if buflen=0
2997 desc.buflen = getlen(desc.format);
2998 desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen );
3001 if (init_package(&desc,1,0)) {
3002 if (i < count) {
3003 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
3004 *rdata_len = desc.usedlen;
3006 else {
3007 desc.errcode = NERR_JobNotFound;
3008 *rdata_len = 0;
3012 *rparam_len = 6;
3013 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3014 SSVALS(*rparam,0,desc.errcode);
3015 SSVAL(*rparam,2,0);
3016 SSVAL(*rparam,4,desc.neededlen);
3018 SAFE_FREE(queue);
3019 SAFE_FREE(tmpdata);
3021 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
3022 return(True);
3025 static BOOL api_WPrintJobEnumerate(connection_struct *conn,uint16 vuid, char *param,char *data,
3026 int mdrcnt,int mprcnt,
3027 char **rdata,char **rparam,
3028 int *rdata_len,int *rparam_len)
3030 char *str1 = param+2;
3031 char *str2 = skip_string(str1,1);
3032 char *p = skip_string(str2,1);
3033 char* name = p;
3034 int uLevel;
3035 int count;
3036 int i, succnt=0;
3037 int snum;
3038 struct pack_desc desc;
3039 print_queue_struct *queue=NULL;
3040 print_status_struct status;
3042 memset((char *)&desc,'\0',sizeof(desc));
3043 memset((char *)&status,'\0',sizeof(status));
3045 p = skip_string(p,1);
3046 uLevel = SVAL(p,0);
3048 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
3050 /* check it's a supported variant */
3051 if (strcmp(str1,"zWrLeh") != 0)
3052 return False;
3054 if (uLevel > 2)
3055 return False; /* defined only for uLevel 0,1,2 */
3057 if (!check_printjob_info(&desc,uLevel,str2))
3058 return False;
3060 snum = find_service(name);
3061 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
3062 return False;
3064 count = print_queue_status(snum,&queue,&status);
3065 if (mdrcnt > 0) *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3066 desc.base = *rdata;
3067 desc.buflen = mdrcnt;
3069 if (init_package(&desc,count,0)) {
3070 succnt = 0;
3071 for (i = 0; i < count; i++) {
3072 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
3073 if (desc.errcode == NERR_Success) succnt = i+1;
3077 *rdata_len = desc.usedlen;
3079 *rparam_len = 8;
3080 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3081 SSVALS(*rparam,0,desc.errcode);
3082 SSVAL(*rparam,2,0);
3083 SSVAL(*rparam,4,succnt);
3084 SSVAL(*rparam,6,count);
3086 SAFE_FREE(queue);
3088 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
3089 return(True);
3092 static int check_printdest_info(struct pack_desc* desc,
3093 int uLevel, char* id)
3095 desc->subformat = NULL;
3096 switch( uLevel ) {
3097 case 0: desc->format = "B9"; break;
3098 case 1: desc->format = "B9B21WWzW"; break;
3099 case 2: desc->format = "z"; break;
3100 case 3: desc->format = "zzzWWzzzWW"; break;
3101 default: return False;
3103 if (strcmp(desc->format,id) != 0) return False;
3104 return True;
3107 static void fill_printdest_info(connection_struct *conn, int snum, int uLevel,
3108 struct pack_desc* desc)
3110 char buf[100];
3111 strncpy(buf,SERVICE(snum),sizeof(buf)-1);
3112 buf[sizeof(buf)-1] = 0;
3113 strupper_m(buf);
3114 if (uLevel <= 1) {
3115 PACKS(desc,"B9",buf); /* szName */
3116 if (uLevel == 1) {
3117 PACKS(desc,"B21",""); /* szUserName */
3118 PACKI(desc,"W",0); /* uJobId */
3119 PACKI(desc,"W",0); /* fsStatus */
3120 PACKS(desc,"z",""); /* pszStatus */
3121 PACKI(desc,"W",0); /* time */
3124 if (uLevel == 2 || uLevel == 3) {
3125 PACKS(desc,"z",buf); /* pszPrinterName */
3126 if (uLevel == 3) {
3127 PACKS(desc,"z",""); /* pszUserName */
3128 PACKS(desc,"z",""); /* pszLogAddr */
3129 PACKI(desc,"W",0); /* uJobId */
3130 PACKI(desc,"W",0); /* fsStatus */
3131 PACKS(desc,"z",""); /* pszStatus */
3132 PACKS(desc,"z",""); /* pszComment */
3133 PACKS(desc,"z","NULL"); /* pszDrivers */
3134 PACKI(desc,"W",0); /* time */
3135 PACKI(desc,"W",0); /* pad1 */
3140 static BOOL api_WPrintDestGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
3141 int mdrcnt,int mprcnt,
3142 char **rdata,char **rparam,
3143 int *rdata_len,int *rparam_len)
3145 char *str1 = param+2;
3146 char *str2 = skip_string(str1,1);
3147 char *p = skip_string(str2,1);
3148 char* PrinterName = p;
3149 int uLevel;
3150 struct pack_desc desc;
3151 int snum;
3152 char *tmpdata=NULL;
3154 memset((char *)&desc,'\0',sizeof(desc));
3156 p = skip_string(p,1);
3157 uLevel = SVAL(p,0);
3159 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
3161 /* check it's a supported varient */
3162 if (strcmp(str1,"zWrLh") != 0) return False;
3163 if (!check_printdest_info(&desc,uLevel,str2)) return False;
3165 snum = find_service(PrinterName);
3166 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) ) {
3167 *rdata_len = 0;
3168 desc.errcode = NERR_DestNotFound;
3169 desc.neededlen = 0;
3171 else {
3172 if (mdrcnt > 0) {
3173 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3174 desc.base = *rdata;
3175 desc.buflen = mdrcnt;
3176 } else {
3178 * Don't return data but need to get correct length
3179 * init_package will return wrong size if buflen=0
3181 desc.buflen = getlen(desc.format);
3182 desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen );
3184 if (init_package(&desc,1,0)) {
3185 fill_printdest_info(conn,snum,uLevel,&desc);
3187 *rdata_len = desc.usedlen;
3190 *rparam_len = 6;
3191 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3192 SSVALS(*rparam,0,desc.errcode);
3193 SSVAL(*rparam,2,0);
3194 SSVAL(*rparam,4,desc.neededlen);
3196 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
3197 SAFE_FREE(tmpdata);
3198 return(True);
3201 static BOOL api_WPrintDestEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3202 int mdrcnt,int mprcnt,
3203 char **rdata,char **rparam,
3204 int *rdata_len,int *rparam_len)
3206 char *str1 = param+2;
3207 char *str2 = skip_string(str1,1);
3208 char *p = skip_string(str2,1);
3209 int uLevel;
3210 int queuecnt;
3211 int i, n, succnt=0;
3212 struct pack_desc desc;
3213 int services = lp_numservices();
3215 memset((char *)&desc,'\0',sizeof(desc));
3217 uLevel = SVAL(p,0);
3219 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
3221 /* check it's a supported varient */
3222 if (strcmp(str1,"WrLeh") != 0) return False;
3223 if (!check_printdest_info(&desc,uLevel,str2)) return False;
3225 queuecnt = 0;
3226 for (i = 0; i < services; i++)
3227 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
3228 queuecnt++;
3230 if (mdrcnt > 0) *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3231 desc.base = *rdata;
3232 desc.buflen = mdrcnt;
3233 if (init_package(&desc,queuecnt,0)) {
3234 succnt = 0;
3235 n = 0;
3236 for (i = 0; i < services; i++) {
3237 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
3238 fill_printdest_info(conn,i,uLevel,&desc);
3239 n++;
3240 if (desc.errcode == NERR_Success) succnt = n;
3245 *rdata_len = desc.usedlen;
3247 *rparam_len = 8;
3248 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3249 SSVALS(*rparam,0,desc.errcode);
3250 SSVAL(*rparam,2,0);
3251 SSVAL(*rparam,4,succnt);
3252 SSVAL(*rparam,6,queuecnt);
3254 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
3255 return(True);
3258 static BOOL api_WPrintDriverEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3259 int mdrcnt,int mprcnt,
3260 char **rdata,char **rparam,
3261 int *rdata_len,int *rparam_len)
3263 char *str1 = param+2;
3264 char *str2 = skip_string(str1,1);
3265 char *p = skip_string(str2,1);
3266 int uLevel;
3267 int succnt;
3268 struct pack_desc desc;
3270 memset((char *)&desc,'\0',sizeof(desc));
3272 uLevel = SVAL(p,0);
3274 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
3276 /* check it's a supported varient */
3277 if (strcmp(str1,"WrLeh") != 0) return False;
3278 if (uLevel != 0 || strcmp(str2,"B41") != 0) return False;
3280 if (mdrcnt > 0) *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3281 desc.base = *rdata;
3282 desc.buflen = mdrcnt;
3283 if (init_package(&desc,1,0)) {
3284 PACKS(&desc,"B41","NULL");
3287 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3289 *rdata_len = desc.usedlen;
3291 *rparam_len = 8;
3292 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3293 SSVALS(*rparam,0,desc.errcode);
3294 SSVAL(*rparam,2,0);
3295 SSVAL(*rparam,4,succnt);
3296 SSVAL(*rparam,6,1);
3298 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
3299 return(True);
3302 static BOOL api_WPrintQProcEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3303 int mdrcnt,int mprcnt,
3304 char **rdata,char **rparam,
3305 int *rdata_len,int *rparam_len)
3307 char *str1 = param+2;
3308 char *str2 = skip_string(str1,1);
3309 char *p = skip_string(str2,1);
3310 int uLevel;
3311 int succnt;
3312 struct pack_desc desc;
3314 memset((char *)&desc,'\0',sizeof(desc));
3316 uLevel = SVAL(p,0);
3318 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
3320 /* check it's a supported varient */
3321 if (strcmp(str1,"WrLeh") != 0) return False;
3322 if (uLevel != 0 || strcmp(str2,"B13") != 0) return False;
3324 if (mdrcnt > 0) *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3325 desc.base = *rdata;
3326 desc.buflen = mdrcnt;
3327 desc.format = str2;
3328 if (init_package(&desc,1,0)) {
3329 PACKS(&desc,"B13","lpd");
3332 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3334 *rdata_len = desc.usedlen;
3336 *rparam_len = 8;
3337 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3338 SSVALS(*rparam,0,desc.errcode);
3339 SSVAL(*rparam,2,0);
3340 SSVAL(*rparam,4,succnt);
3341 SSVAL(*rparam,6,1);
3343 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
3344 return(True);
3347 static BOOL api_WPrintPortEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3348 int mdrcnt,int mprcnt,
3349 char **rdata,char **rparam,
3350 int *rdata_len,int *rparam_len)
3352 char *str1 = param+2;
3353 char *str2 = skip_string(str1,1);
3354 char *p = skip_string(str2,1);
3355 int uLevel;
3356 int succnt;
3357 struct pack_desc desc;
3359 memset((char *)&desc,'\0',sizeof(desc));
3361 uLevel = SVAL(p,0);
3363 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
3365 /* check it's a supported varient */
3366 if (strcmp(str1,"WrLeh") != 0) return False;
3367 if (uLevel != 0 || strcmp(str2,"B9") != 0) return False;
3369 if (mdrcnt > 0) *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3370 memset((char *)&desc,'\0',sizeof(desc));
3371 desc.base = *rdata;
3372 desc.buflen = mdrcnt;
3373 desc.format = str2;
3374 if (init_package(&desc,1,0)) {
3375 PACKS(&desc,"B13","lp0");
3378 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3380 *rdata_len = desc.usedlen;
3382 *rparam_len = 8;
3383 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3384 SSVALS(*rparam,0,desc.errcode);
3385 SSVAL(*rparam,2,0);
3386 SSVAL(*rparam,4,succnt);
3387 SSVAL(*rparam,6,1);
3389 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
3390 return(True);
3394 /****************************************************************************
3395 List open sessions
3396 ****************************************************************************/
3397 static BOOL api_RNetSessionEnum(connection_struct *conn,uint16 vuid, char *param, char *data,
3398 int mdrcnt,int mprcnt,
3399 char **rdata,char **rparam,
3400 int *rdata_len,int *rparam_len)
3403 char *str1 = param+2;
3404 char *str2 = skip_string(str1,1);
3405 char *p = skip_string(str2,1);
3406 int uLevel;
3407 struct pack_desc desc;
3408 struct sessionid *session_list;
3409 int i, num_sessions;
3411 memset((char *)&desc,'\0',sizeof(desc));
3413 uLevel = SVAL(p,0);
3415 DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel));
3416 DEBUG(7,("RNetSessionEnum req string=%s\n",str1));
3417 DEBUG(7,("RNetSessionEnum ret string=%s\n",str2));
3419 /* check it's a supported varient */
3420 if (strcmp(str1,RAP_NetSessionEnum_REQ) != 0) return False;
3421 if (uLevel != 2 || strcmp(str2,RAP_SESSION_INFO_L2) != 0) return False;
3423 num_sessions = list_sessions(&session_list);
3425 if (mdrcnt > 0) *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3426 memset((char *)&desc,'\0',sizeof(desc));
3427 desc.base = *rdata;
3428 desc.buflen = mdrcnt;
3429 desc.format = str2;
3430 if (!init_package(&desc,num_sessions,0)) {
3431 return False;
3434 for(i=0; i<num_sessions; i++) {
3435 PACKS(&desc, "z", session_list[i].remote_machine);
3436 PACKS(&desc, "z", session_list[i].username);
3437 PACKI(&desc, "W", 1); /* num conns */
3438 PACKI(&desc, "W", 0); /* num opens */
3439 PACKI(&desc, "W", 1); /* num users */
3440 PACKI(&desc, "D", 0); /* session time */
3441 PACKI(&desc, "D", 0); /* idle time */
3442 PACKI(&desc, "D", 0); /* flags */
3443 PACKS(&desc, "z", "Unknown Client"); /* client type string */
3446 *rdata_len = desc.usedlen;
3448 *rparam_len = 8;
3449 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3450 SSVALS(*rparam,0,desc.errcode);
3451 SSVAL(*rparam,2,0); /* converter */
3452 SSVAL(*rparam,4,num_sessions); /* count */
3454 DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc.errcode));
3455 return True;
3459 /****************************************************************************
3460 The buffer was too small
3461 ****************************************************************************/
3463 static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param,char *data,
3464 int mdrcnt,int mprcnt,
3465 char **rdata,char **rparam,
3466 int *rdata_len,int *rparam_len)
3468 *rparam_len = MIN(*rparam_len,mprcnt);
3469 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3471 *rdata_len = 0;
3473 SSVAL(*rparam,0,NERR_BufTooSmall);
3475 DEBUG(3,("Supplied buffer too small in API command\n"));
3477 return(True);
3481 /****************************************************************************
3482 The request is not supported
3483 ****************************************************************************/
3485 static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param,char *data,
3486 int mdrcnt,int mprcnt,
3487 char **rdata,char **rparam,
3488 int *rdata_len,int *rparam_len)
3490 *rparam_len = 4;
3491 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3493 *rdata_len = 0;
3495 SSVAL(*rparam,0,NERR_notsupported);
3496 SSVAL(*rparam,2,0); /* converter word */
3498 DEBUG(3,("Unsupported API command\n"));
3500 return(True);
3506 static const struct
3508 const char *name;
3509 int id;
3510 BOOL (*fn)(connection_struct *,uint16,char *,char *,
3511 int,int,char **,char **,int *,int *);
3512 BOOL auth_user; /* Deny anonymous access? */
3513 } api_commands[] = {
3514 {"RNetShareEnum", RAP_WshareEnum, api_RNetShareEnum, True},
3515 {"RNetShareGetInfo", RAP_WshareGetInfo, api_RNetShareGetInfo},
3516 {"RNetShareAdd", RAP_WshareAdd, api_RNetShareAdd},
3517 {"RNetSessionEnum", RAP_WsessionEnum, api_RNetSessionEnum, True},
3518 {"RNetServerGetInfo", RAP_WserverGetInfo, api_RNetServerGetInfo},
3519 {"RNetGroupEnum", RAP_WGroupEnum, api_RNetGroupEnum, True},
3520 {"RNetGroupGetUsers", RAP_WGroupGetUsers, api_RNetGroupGetUsers, True},
3521 {"RNetUserEnum", RAP_WUserEnum, api_RNetUserEnum, True},
3522 {"RNetUserGetInfo", RAP_WUserGetInfo, api_RNetUserGetInfo},
3523 {"NetUserGetGroups", RAP_WUserGetGroups, api_NetUserGetGroups},
3524 {"NetWkstaGetInfo", RAP_WWkstaGetInfo, api_NetWkstaGetInfo},
3525 {"DosPrintQEnum", RAP_WPrintQEnum, api_DosPrintQEnum, True},
3526 {"DosPrintQGetInfo", RAP_WPrintQGetInfo, api_DosPrintQGetInfo},
3527 {"WPrintQueuePause", RAP_WPrintQPause, api_WPrintQueueCtrl},
3528 {"WPrintQueueResume", RAP_WPrintQContinue, api_WPrintQueueCtrl},
3529 {"WPrintJobEnumerate",RAP_WPrintJobEnum, api_WPrintJobEnumerate},
3530 {"WPrintJobGetInfo", RAP_WPrintJobGetInfo, api_WPrintJobGetInfo},
3531 {"RDosPrintJobDel", RAP_WPrintJobDel, api_RDosPrintJobDel},
3532 {"RDosPrintJobPause", RAP_WPrintJobPause, api_RDosPrintJobDel},
3533 {"RDosPrintJobResume",RAP_WPrintJobContinue, api_RDosPrintJobDel},
3534 {"WPrintDestEnum", RAP_WPrintDestEnum, api_WPrintDestEnum},
3535 {"WPrintDestGetInfo", RAP_WPrintDestGetInfo, api_WPrintDestGetInfo},
3536 {"NetRemoteTOD", RAP_NetRemoteTOD, api_NetRemoteTOD},
3537 {"WPrintQueuePurge", RAP_WPrintQPurge, api_WPrintQueueCtrl},
3538 {"NetServerEnum", RAP_NetServerEnum2, api_RNetServerEnum}, /* anon OK */
3539 {"WAccessGetUserPerms",RAP_WAccessGetUserPerms,api_WAccessGetUserPerms},
3540 {"SetUserPassword", RAP_WUserPasswordSet2, api_SetUserPassword},
3541 {"WWkstaUserLogon", RAP_WWkstaUserLogon, api_WWkstaUserLogon},
3542 {"PrintJobInfo", RAP_WPrintJobSetInfo, api_PrintJobInfo},
3543 {"WPrintDriverEnum", RAP_WPrintDriverEnum, api_WPrintDriverEnum},
3544 {"WPrintQProcEnum", RAP_WPrintQProcessorEnum,api_WPrintQProcEnum},
3545 {"WPrintPortEnum", RAP_WPrintPortEnum, api_WPrintPortEnum},
3546 {"SamOEMChangePassword",RAP_SamOEMChgPasswordUser2_P,api_SamOEMChangePassword}, /* anon OK */
3547 {NULL, -1, api_Unsupported}};
3549 /* The following RAP calls are not implemented by Samba:
3551 RAP_WFileEnum2 - anon not OK
3554 /****************************************************************************
3555 Handle remote api calls
3556 ****************************************************************************/
3558 int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data,char *params,
3559 int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
3561 int api_command;
3562 char *rdata = NULL;
3563 char *rparam = NULL;
3564 int rdata_len = 0;
3565 int rparam_len = 0;
3566 BOOL reply=False;
3567 int i;
3569 if (!params) {
3570 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
3571 return 0;
3574 api_command = SVAL(params,0);
3576 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
3577 api_command,
3578 params+2,
3579 skip_string(params+2,1),
3580 tdscnt,tpscnt,mdrcnt,mprcnt));
3582 for (i=0;api_commands[i].name;i++) {
3583 if (api_commands[i].id == api_command && api_commands[i].fn) {
3584 DEBUG(3,("Doing %s\n",api_commands[i].name));
3585 break;
3589 /* Check whether this api call can be done anonymously */
3591 if (api_commands[i].auth_user && lp_restrict_anonymous()) {
3592 user_struct *user = get_valid_user_struct(vuid);
3594 if (!user || user->guest)
3595 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
3598 rdata = (char *)SMB_MALLOC(1024);
3599 if (rdata)
3600 memset(rdata,'\0',1024);
3602 rparam = (char *)SMB_MALLOC(1024);
3603 if (rparam)
3604 memset(rparam,'\0',1024);
3606 if(!rdata || !rparam) {
3607 DEBUG(0,("api_reply: malloc fail !\n"));
3608 return -1;
3611 reply = api_commands[i].fn(conn,vuid,params,data,mdrcnt,mprcnt,
3612 &rdata,&rparam,&rdata_len,&rparam_len);
3615 if (rdata_len > mdrcnt ||
3616 rparam_len > mprcnt) {
3617 reply = api_TooSmall(conn,vuid,params,data,mdrcnt,mprcnt,
3618 &rdata,&rparam,&rdata_len,&rparam_len);
3621 /* if we get False back then it's actually unsupported */
3622 if (!reply)
3623 api_Unsupported(conn,vuid,params,data,mdrcnt,mprcnt,
3624 &rdata,&rparam,&rdata_len,&rparam_len);
3626 send_trans_reply(outbuf, rparam, rparam_len, rdata, rdata_len, False);
3628 SAFE_FREE(rdata);
3629 SAFE_FREE(rparam);
3631 return -1;