r1383: sync from 3.0 tree
[Samba.git] / source / smbd / lanman.c
blobdd9708356e7a600b959c3d349b65df20fb33c09c
1 /*
2 Unix SMB/CIFS implementation.
3 Inter-process communication and named pipe handling
4 Copyright (C) Andrew Tridgell 1992-1998
6 SMB Version handling
7 Copyright (C) John H Terpstra 1995-1998
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 This file handles the named pipe and mailslot calls
25 in the SMBtrans protocol
28 #include "includes.h"
30 #ifdef CHECK_TYPES
31 #undef CHECK_TYPES
32 #endif
33 #define CHECK_TYPES 0
35 extern fstring local_machine;
37 #define NERR_Success 0
38 #define NERR_badpass 86
39 #define NERR_notsupported 50
41 #define NERR_BASE (2100)
42 #define NERR_BufTooSmall (NERR_BASE+23)
43 #define NERR_JobNotFound (NERR_BASE+51)
44 #define NERR_DestNotFound (NERR_BASE+52)
46 #define ACCESS_READ 0x01
47 #define ACCESS_WRITE 0x02
48 #define ACCESS_CREATE 0x04
50 #define SHPWLEN 8 /* share password length */
52 static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param,char *data,
53 int mdrcnt,int mprcnt,
54 char **rdata,char **rparam,
55 int *rdata_len,int *rparam_len);
56 static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param,char *data,
57 int mdrcnt,int mprcnt,
58 char **rdata,char **rparam,
59 int *rdata_len,int *rparam_len);
62 static int CopyExpanded(connection_struct *conn,
63 int snum, char** dst, char* src, int* n)
65 pstring buf;
66 int l;
68 if (!src || !dst || !n || !(*dst)) return(0);
70 StrnCpy(buf,src,sizeof(buf)/2);
71 pstring_sub(buf,"%S",lp_servicename(snum));
72 standard_sub_conn(conn,buf,sizeof(buf));
73 l = push_ascii(*dst,buf,*n, STR_TERMINATE);
74 (*dst) += l;
75 (*n) -= l;
76 return l;
79 static int CopyAndAdvance(char** dst, char* src, int* n)
81 int l;
82 if (!src || !dst || !n || !(*dst)) return(0);
83 l = push_ascii(*dst,src,*n, STR_TERMINATE);
84 (*dst) += l;
85 (*n) -= l;
86 return l;
89 static int StrlenExpanded(connection_struct *conn, int snum, char* s)
91 pstring buf;
92 if (!s) return(0);
93 StrnCpy(buf,s,sizeof(buf)/2);
94 pstring_sub(buf,"%S",lp_servicename(snum));
95 standard_sub_conn(conn,buf,sizeof(buf));
96 return strlen(buf) + 1;
99 static char* Expand(connection_struct *conn, int snum, char* s)
101 static pstring buf;
102 if (!s) return(NULL);
103 StrnCpy(buf,s,sizeof(buf)/2);
104 pstring_sub(buf,"%S",lp_servicename(snum));
105 standard_sub_conn(conn,buf,sizeof(buf));
106 return &buf[0];
109 /*******************************************************************
110 check a API string for validity when we only need to check the prefix
111 ******************************************************************/
112 static BOOL prefix_ok(const char *str, const char *prefix)
114 return(strncmp(str,prefix,strlen(prefix)) == 0);
117 struct pack_desc {
118 const char* format; /* formatstring for structure */
119 const char* subformat; /* subformat for structure */
120 char* base; /* baseaddress of buffer */
121 int buflen; /* remaining size for fixed part; on init: length of base */
122 int subcount; /* count of substructures */
123 char* structbuf; /* pointer into buffer for remaining fixed part */
124 int stringlen; /* remaining size for variable part */
125 char* stringbuf; /* pointer into buffer for remaining variable part */
126 int neededlen; /* total needed size */
127 int usedlen; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
128 const char* curpos; /* current position; pointer into format or subformat */
129 int errcode;
132 static int get_counter(const char** p)
134 int i, n;
135 if (!p || !(*p)) return(1);
136 if (!isdigit((int)**p)) return 1;
137 for (n = 0;;) {
138 i = **p;
139 if (isdigit(i))
140 n = 10 * n + (i - '0');
141 else
142 return n;
143 (*p)++;
147 static int getlen(const char* p)
149 int n = 0;
150 if (!p) return(0);
151 while (*p) {
152 switch( *p++ ) {
153 case 'W': /* word (2 byte) */
154 n += 2;
155 break;
156 case 'K': /* status word? (2 byte) */
157 n += 2;
158 break;
159 case 'N': /* count of substructures (word) at end */
160 n += 2;
161 break;
162 case 'D': /* double word (4 byte) */
163 case 'z': /* offset to zero terminated string (4 byte) */
164 case 'l': /* offset to user data (4 byte) */
165 n += 4;
166 break;
167 case 'b': /* offset to data (with counter) (4 byte) */
168 n += 4;
169 get_counter(&p);
170 break;
171 case 'B': /* byte (with optional counter) */
172 n += get_counter(&p);
173 break;
176 return n;
179 static BOOL init_package(struct pack_desc* p, int count, int subcount)
181 int n = p->buflen;
182 int i;
184 if (!p->format || !p->base) return(False);
186 i = count * getlen(p->format);
187 if (p->subformat) i += subcount * getlen(p->subformat);
188 p->structbuf = p->base;
189 p->neededlen = 0;
190 p->usedlen = 0;
191 p->subcount = 0;
192 p->curpos = p->format;
193 if (i > n) {
194 p->neededlen = i;
195 i = n = 0;
196 #if 0
198 * This is the old error code we used. Aparently
199 * WinNT/2k systems return ERRbuftoosmall (2123) and
200 * OS/2 needs this. I'm leaving this here so we can revert
201 * if needed. JRA.
203 p->errcode = ERRmoredata;
204 #else
205 p->errcode = ERRbuftoosmall;
206 #endif
208 else
209 p->errcode = NERR_Success;
210 p->buflen = i;
211 n -= i;
212 p->stringbuf = p->base + i;
213 p->stringlen = n;
214 return(p->errcode == NERR_Success);
217 static int package(struct pack_desc* p, ...)
219 va_list args;
220 int needed=0, stringneeded;
221 const char* str=NULL;
222 int is_string=0, stringused;
223 int32 temp;
225 va_start(args,p);
227 if (!*p->curpos) {
228 if (!p->subcount)
229 p->curpos = p->format;
230 else {
231 p->curpos = p->subformat;
232 p->subcount--;
235 #if CHECK_TYPES
236 str = va_arg(args,char*);
237 SMB_ASSERT(strncmp(str,p->curpos,strlen(str)) == 0);
238 #endif
239 stringneeded = -1;
241 if (!p->curpos) {
242 va_end(args);
243 return(0);
246 switch( *p->curpos++ ) {
247 case 'W': /* word (2 byte) */
248 needed = 2;
249 temp = va_arg(args,int);
250 if (p->buflen >= needed) SSVAL(p->structbuf,0,temp);
251 break;
252 case 'K': /* status word? (2 byte) */
253 needed = 2;
254 temp = va_arg(args,int);
255 if (p->buflen >= needed) SSVAL(p->structbuf,0,temp);
256 break;
257 case 'N': /* count of substructures (word) at end */
258 needed = 2;
259 p->subcount = va_arg(args,int);
260 if (p->buflen >= needed) SSVAL(p->structbuf,0,p->subcount);
261 break;
262 case 'D': /* double word (4 byte) */
263 needed = 4;
264 temp = va_arg(args,int);
265 if (p->buflen >= needed) SIVAL(p->structbuf,0,temp);
266 break;
267 case 'B': /* byte (with optional counter) */
268 needed = get_counter(&p->curpos);
270 char *s = va_arg(args,char*);
271 if (p->buflen >= needed) StrnCpy(p->structbuf,s?s:"",needed-1);
273 break;
274 case 'z': /* offset to zero terminated string (4 byte) */
275 str = va_arg(args,char*);
276 stringneeded = (str ? strlen(str)+1 : 0);
277 is_string = 1;
278 break;
279 case 'l': /* offset to user data (4 byte) */
280 str = va_arg(args,char*);
281 stringneeded = va_arg(args,int);
282 is_string = 0;
283 break;
284 case 'b': /* offset to data (with counter) (4 byte) */
285 str = va_arg(args,char*);
286 stringneeded = get_counter(&p->curpos);
287 is_string = 0;
288 break;
290 va_end(args);
291 if (stringneeded >= 0) {
292 needed = 4;
293 if (p->buflen >= needed) {
294 stringused = stringneeded;
295 if (stringused > p->stringlen) {
296 stringused = (is_string ? p->stringlen : 0);
297 if (p->errcode == NERR_Success) p->errcode = ERRmoredata;
299 if (!stringused)
300 SIVAL(p->structbuf,0,0);
301 else {
302 SIVAL(p->structbuf,0,PTR_DIFF(p->stringbuf,p->base));
303 memcpy(p->stringbuf,str?str:"",stringused);
304 if (is_string) p->stringbuf[stringused-1] = '\0';
305 p->stringbuf += stringused;
306 p->stringlen -= stringused;
307 p->usedlen += stringused;
310 p->neededlen += stringneeded;
312 p->neededlen += needed;
313 if (p->buflen >= needed) {
314 p->structbuf += needed;
315 p->buflen -= needed;
316 p->usedlen += needed;
318 else {
319 if (p->errcode == NERR_Success) p->errcode = ERRmoredata;
321 return 1;
324 #if CHECK_TYPES
325 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
326 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
327 #else
328 #define PACK(desc,t,v) package(desc,v)
329 #define PACKl(desc,t,v,l) package(desc,v,l)
330 #endif
332 static void PACKI(struct pack_desc* desc, const char *t,int v)
334 PACK(desc,t,v);
337 static void PACKS(struct pack_desc* desc,const char *t,const char *v)
339 PACK(desc,t,v);
343 /****************************************************************************
344 get a print queue
345 ****************************************************************************/
346 static void PackDriverData(struct pack_desc* desc)
348 char drivdata[4+4+32];
349 SIVAL(drivdata,0,sizeof drivdata); /* cb */
350 SIVAL(drivdata,4,1000); /* lVersion */
351 memset(drivdata+8,0,32); /* szDeviceName */
352 push_ascii(drivdata+8,"NULL",-1, STR_TERMINATE);
353 PACKl(desc,"l",drivdata,sizeof drivdata); /* pDriverData */
356 static int check_printq_info(struct pack_desc* desc,
357 int uLevel, char *id1, char *id2)
359 desc->subformat = NULL;
360 switch( uLevel ) {
361 case 0:
362 desc->format = "B13";
363 break;
364 case 1:
365 desc->format = "B13BWWWzzzzzWW";
366 break;
367 case 2:
368 desc->format = "B13BWWWzzzzzWN";
369 desc->subformat = "WB21BB16B10zWWzDDz";
370 break;
371 case 3:
372 desc->format = "zWWWWzzzzWWzzl";
373 break;
374 case 4:
375 desc->format = "zWWWWzzzzWNzzl";
376 desc->subformat = "WWzWWDDzz";
377 break;
378 case 5:
379 desc->format = "z";
380 break;
381 case 51:
382 desc->format = "K";
383 break;
384 case 52:
385 desc->format = "WzzzzzzzzN";
386 desc->subformat = "z";
387 break;
388 default: return False;
390 if (strcmp(desc->format,id1) != 0) return False;
391 if (desc->subformat && strcmp(desc->subformat,id2) != 0) return False;
392 return True;
396 #define RAP_JOB_STATUS_QUEUED 0
397 #define RAP_JOB_STATUS_PAUSED 1
398 #define RAP_JOB_STATUS_SPOOLING 2
399 #define RAP_JOB_STATUS_PRINTING 3
400 #define RAP_JOB_STATUS_PRINTED 4
402 #define RAP_QUEUE_STATUS_PAUSED 1
403 #define RAP_QUEUE_STATUS_ERROR 2
405 /* turn a print job status into a on the wire status
407 static int printj_status(int v)
409 switch (v) {
410 case LPQ_QUEUED:
411 return RAP_JOB_STATUS_QUEUED;
412 case LPQ_PAUSED:
413 return RAP_JOB_STATUS_PAUSED;
414 case LPQ_SPOOLING:
415 return RAP_JOB_STATUS_SPOOLING;
416 case LPQ_PRINTING:
417 return RAP_JOB_STATUS_PRINTING;
419 return 0;
422 /* turn a print queue status into a on the wire status
424 static int printq_status(int v)
426 switch (v) {
427 case LPQ_QUEUED:
428 return 0;
429 case LPQ_PAUSED:
430 return RAP_QUEUE_STATUS_PAUSED;
432 return RAP_QUEUE_STATUS_ERROR;
435 static void fill_printjob_info(connection_struct *conn, int snum, int uLevel,
436 struct pack_desc* desc,
437 print_queue_struct* queue, int n)
439 time_t t = queue->time;
441 /* the client expects localtime */
442 t -= TimeDiff(t);
444 PACKI(desc,"W",pjobid_to_rap(snum,queue->job)); /* uJobId */
445 if (uLevel == 1) {
446 PACKS(desc,"B21",queue->fs_user); /* szUserName */
447 PACKS(desc,"B",""); /* pad */
448 PACKS(desc,"B16",""); /* szNotifyName */
449 PACKS(desc,"B10","PM_Q_RAW"); /* szDataType */
450 PACKS(desc,"z",""); /* pszParms */
451 PACKI(desc,"W",n+1); /* uPosition */
452 PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */
453 PACKS(desc,"z",""); /* pszStatus */
454 PACKI(desc,"D",t); /* ulSubmitted */
455 PACKI(desc,"D",queue->size); /* ulSize */
456 PACKS(desc,"z",queue->fs_file); /* pszComment */
458 if (uLevel == 2 || uLevel == 3 || uLevel == 4) {
459 PACKI(desc,"W",queue->priority); /* uPriority */
460 PACKS(desc,"z",queue->fs_user); /* pszUserName */
461 PACKI(desc,"W",n+1); /* uPosition */
462 PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */
463 PACKI(desc,"D",t); /* ulSubmitted */
464 PACKI(desc,"D",queue->size); /* ulSize */
465 PACKS(desc,"z","Samba"); /* pszComment */
466 PACKS(desc,"z",queue->fs_file); /* pszDocument */
467 if (uLevel == 3) {
468 PACKS(desc,"z",""); /* pszNotifyName */
469 PACKS(desc,"z","PM_Q_RAW"); /* pszDataType */
470 PACKS(desc,"z",""); /* pszParms */
471 PACKS(desc,"z",""); /* pszStatus */
472 PACKS(desc,"z",SERVICE(snum)); /* pszQueue */
473 PACKS(desc,"z","lpd"); /* pszQProcName */
474 PACKS(desc,"z",""); /* pszQProcParms */
475 PACKS(desc,"z","NULL"); /* pszDriverName */
476 PackDriverData(desc); /* pDriverData */
477 PACKS(desc,"z",""); /* pszPrinterName */
478 } else if (uLevel == 4) { /* OS2 */
479 PACKS(desc,"z",""); /* pszSpoolFileName */
480 PACKS(desc,"z",""); /* pszPortName */
481 PACKS(desc,"z",""); /* pszStatus */
482 PACKI(desc,"D",0); /* ulPagesSpooled */
483 PACKI(desc,"D",0); /* ulPagesSent */
484 PACKI(desc,"D",0); /* ulPagesPrinted */
485 PACKI(desc,"D",0); /* ulTimePrinted */
486 PACKI(desc,"D",0); /* ulExtendJobStatus */
487 PACKI(desc,"D",0); /* ulStartPage */
488 PACKI(desc,"D",0); /* ulEndPage */
493 /********************************************************************
494 Return a driver name given an snum.
495 Returns True if from tdb, False otherwise.
496 ********************************************************************/
498 static BOOL get_driver_name(int snum, pstring drivername)
500 NT_PRINTER_INFO_LEVEL *info = NULL;
501 BOOL in_tdb = False;
503 get_a_printer (NULL, &info, 2, lp_servicename(snum));
504 if (info != NULL) {
505 pstrcpy( drivername, info->info_2->drivername);
506 in_tdb = True;
507 free_a_printer(&info, 2);
510 return in_tdb;
513 /********************************************************************
514 Respond to the DosPrintQInfo command with a level of 52
515 This is used to get printer driver information for Win9x clients
516 ********************************************************************/
517 static void fill_printq_info_52(connection_struct *conn, int snum,
518 struct pack_desc* desc, int count )
520 int i;
521 fstring location;
522 NT_PRINTER_DRIVER_INFO_LEVEL driver;
523 NT_PRINTER_INFO_LEVEL *printer = NULL;
525 ZERO_STRUCT(driver);
527 if ( !W_ERROR_IS_OK(get_a_printer( NULL, &printer, 2, lp_servicename(snum))) ) {
528 DEBUG(3,("fill_printq_info_52: Failed to lookup printer [%s]\n",
529 lp_servicename(snum)));
530 goto err;
533 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername,
534 "Windows 4.0", 0)) )
536 DEBUG(3,("fill_printq_info_52: Failed to lookup driver [%s]\n",
537 printer->info_2->drivername));
538 goto err;
541 trim_string(driver.info_3->driverpath, "\\print$\\WIN40\\0\\", 0);
542 trim_string(driver.info_3->datafile, "\\print$\\WIN40\\0\\", 0);
543 trim_string(driver.info_3->helpfile, "\\print$\\WIN40\\0\\", 0);
545 PACKI(desc, "W", 0x0400); /* don't know */
546 PACKS(desc, "z", driver.info_3->name); /* long printer name */
547 PACKS(desc, "z", driver.info_3->driverpath); /* Driverfile Name */
548 PACKS(desc, "z", driver.info_3->datafile); /* Datafile name */
549 PACKS(desc, "z", driver.info_3->monitorname); /* language monitor */
551 fstrcpy(location, "\\\\");
552 fstrcat(location, get_called_name());
553 fstrcat(location, "\\print$\\WIN40\\0");
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 = REALLOC(*rparam,*rparam_len);
758 SSVALS(*rparam,0,ERRunknownlevel);
759 SSVAL(*rparam,2,0);
760 SSVAL(*rparam,4,0);
761 return(True);
764 snum = lp_servicenumber(QueueName);
765 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
766 int pnum = lp_servicenumber(PRINTERS_NAME);
767 if (pnum >= 0) {
768 lp_add_printer(QueueName,pnum);
769 snum = lp_servicenumber(QueueName);
773 if (snum < 0 || !VALID_SNUM(snum))
774 return(False);
776 if (uLevel==52) {
777 count = get_printerdrivernumber(snum);
778 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count));
779 } else {
780 count = print_queue_status(snum, &queue,&status);
783 if (mdrcnt > 0) {
784 *rdata = REALLOC(*rdata,mdrcnt);
785 desc.base = *rdata;
786 desc.buflen = mdrcnt;
787 } else {
789 * Don't return data but need to get correct length
790 * init_package will return wrong size if buflen=0
792 desc.buflen = getlen(desc.format);
793 desc.base = tmpdata = (char *) malloc (desc.buflen);
796 if (init_package(&desc,1,count)) {
797 desc.subcount = count;
798 fill_printq_info(conn,snum,uLevel,&desc,count,queue,&status);
801 *rdata_len = desc.usedlen;
804 * We must set the return code to ERRbuftoosmall
805 * in order to support lanman style printing with Win NT/2k
806 * clients --jerry
808 if (!mdrcnt && lp_disable_spoolss())
809 desc.errcode = ERRbuftoosmall;
811 *rdata_len = desc.usedlen;
812 *rparam_len = 6;
813 *rparam = REALLOC(*rparam,*rparam_len);
814 SSVALS(*rparam,0,desc.errcode);
815 SSVAL(*rparam,2,0);
816 SSVAL(*rparam,4,desc.neededlen);
818 DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode));
820 SAFE_FREE(queue);
821 SAFE_FREE(tmpdata);
823 return(True);
826 /****************************************************************************
827 View list of all print jobs on all queues.
828 ****************************************************************************/
830 static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid, char* param, char* data,
831 int mdrcnt, int mprcnt,
832 char **rdata, char** rparam,
833 int *rdata_len, int *rparam_len)
835 char *param_format = param+2;
836 char *output_format1 = skip_string(param_format,1);
837 char *p = skip_string(output_format1,1);
838 int uLevel = SVAL(p,0);
839 char *output_format2 = p + 4;
840 int services = lp_numservices();
841 int i, n;
842 struct pack_desc desc;
843 print_queue_struct **queue = NULL;
844 print_status_struct *status = NULL;
845 int* subcntarr = NULL;
846 int queuecnt, subcnt=0, succnt=0;
848 memset((char *)&desc,'\0',sizeof(desc));
850 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
852 if (!prefix_ok(param_format,"WrLeh")) return False;
853 if (!check_printq_info(&desc,uLevel,output_format1,output_format2)) {
855 * Patch from Scott Moomaw <scott@bridgewater.edu>
856 * to return the 'invalid info level' error if an
857 * unknown level was requested.
859 *rdata_len = 0;
860 *rparam_len = 6;
861 *rparam = REALLOC(*rparam,*rparam_len);
862 SSVALS(*rparam,0,ERRunknownlevel);
863 SSVAL(*rparam,2,0);
864 SSVAL(*rparam,4,0);
865 return(True);
868 queuecnt = 0;
869 for (i = 0; i < services; i++)
870 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
871 queuecnt++;
872 if (uLevel > 0) {
873 if((queue = (print_queue_struct**)malloc(queuecnt*sizeof(print_queue_struct*))) == NULL) {
874 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
875 return False;
877 memset(queue,0,queuecnt*sizeof(print_queue_struct*));
878 if((status = (print_status_struct*)malloc(queuecnt*sizeof(print_status_struct))) == NULL) {
879 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
880 return False;
882 memset(status,0,queuecnt*sizeof(print_status_struct));
883 if((subcntarr = (int*)malloc(queuecnt*sizeof(int))) == NULL) {
884 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
885 return False;
887 subcnt = 0;
888 n = 0;
889 for (i = 0; i < services; i++)
890 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
891 subcntarr[n] = print_queue_status(i, &queue[n],&status[n]);
892 subcnt += subcntarr[n];
893 n++;
896 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
897 desc.base = *rdata;
898 desc.buflen = mdrcnt;
900 if (init_package(&desc,queuecnt,subcnt)) {
901 n = 0;
902 succnt = 0;
903 for (i = 0; i < services; i++)
904 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
905 fill_printq_info(conn,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]);
906 n++;
907 if (desc.errcode == NERR_Success) succnt = n;
911 SAFE_FREE(subcntarr);
913 *rdata_len = desc.usedlen;
914 *rparam_len = 8;
915 *rparam = REALLOC(*rparam,*rparam_len);
916 SSVALS(*rparam,0,desc.errcode);
917 SSVAL(*rparam,2,0);
918 SSVAL(*rparam,4,succnt);
919 SSVAL(*rparam,6,queuecnt);
921 for (i = 0; i < queuecnt; i++) {
922 if (queue) SAFE_FREE(queue[i]);
925 SAFE_FREE(queue);
926 SAFE_FREE(status);
928 return True;
931 /****************************************************************************
932 get info level for a server list query
933 ****************************************************************************/
934 static BOOL check_server_info(int uLevel, char* id)
936 switch( uLevel ) {
937 case 0:
938 if (strcmp(id,"B16") != 0) return False;
939 break;
940 case 1:
941 if (strcmp(id,"B16BBDz") != 0) return False;
942 break;
943 default:
944 return False;
946 return True;
949 struct srv_info_struct
951 fstring name;
952 uint32 type;
953 fstring comment;
954 fstring domain;
955 BOOL server_added;
959 /*******************************************************************
960 get server info lists from the files saved by nmbd. Return the
961 number of entries
962 ******************************************************************/
963 static int get_server_info(uint32 servertype,
964 struct srv_info_struct **servers,
965 const char *domain)
967 int count=0;
968 int alloced=0;
969 char **lines;
970 BOOL local_list_only;
971 int i;
973 lines = file_lines_load(lock_path(SERVER_LIST), NULL);
974 if (!lines) {
975 DEBUG(4,("Can't open %s - %s\n",lock_path(SERVER_LIST),strerror(errno)));
976 return(0);
979 /* request for everything is code for request all servers */
980 if (servertype == SV_TYPE_ALL)
981 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
983 local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY);
985 DEBUG(4,("Servertype search: %8x\n",servertype));
987 for (i=0;lines[i];i++) {
988 fstring stype;
989 struct srv_info_struct *s;
990 const char *ptr = lines[i];
991 BOOL ok = True;
993 if (!*ptr) continue;
995 if (count == alloced) {
996 struct srv_info_struct *ts;
998 alloced += 10;
999 ts = (struct srv_info_struct *)
1000 Realloc(*servers,sizeof(**servers)*alloced);
1001 if (!ts) {
1002 DEBUG(0,("get_server_info: failed to enlarge servers info struct!\n"));
1003 return(0);
1005 else *servers = ts;
1006 memset((char *)((*servers)+count),'\0',sizeof(**servers)*(alloced-count));
1008 s = &(*servers)[count];
1010 if (!next_token(&ptr,s->name , NULL, sizeof(s->name))) continue;
1011 if (!next_token(&ptr,stype , NULL, sizeof(stype))) continue;
1012 if (!next_token(&ptr,s->comment, NULL, sizeof(s->comment))) continue;
1013 if (!next_token(&ptr,s->domain , NULL, sizeof(s->domain))) {
1014 /* this allows us to cope with an old nmbd */
1015 fstrcpy(s->domain,lp_workgroup());
1018 if (sscanf(stype,"%X",&s->type) != 1) {
1019 DEBUG(4,("r:host file "));
1020 ok = False;
1023 /* Filter the servers/domains we return based on what was asked for. */
1025 /* Check to see if we are being asked for a local list only. */
1026 if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) {
1027 DEBUG(4,("r: local list only"));
1028 ok = False;
1031 /* doesn't match up: don't want it */
1032 if (!(servertype & s->type)) {
1033 DEBUG(4,("r:serv type "));
1034 ok = False;
1037 if ((servertype & SV_TYPE_DOMAIN_ENUM) !=
1038 (s->type & SV_TYPE_DOMAIN_ENUM))
1040 DEBUG(4,("s: dom mismatch "));
1041 ok = False;
1044 if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM))
1046 ok = False;
1049 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1050 s->type &= ~SV_TYPE_LOCAL_LIST_ONLY;
1052 if (ok)
1054 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1055 s->name, s->type, s->comment, s->domain));
1057 s->server_added = True;
1058 count++;
1060 else
1062 DEBUG(4,("%20s %8x %25s %15s\n",
1063 s->name, s->type, s->comment, s->domain));
1067 file_lines_free(lines);
1068 return(count);
1072 /*******************************************************************
1073 fill in a server info structure
1074 ******************************************************************/
1075 static int fill_srv_info(struct srv_info_struct *service,
1076 int uLevel, char **buf, int *buflen,
1077 char **stringbuf, int *stringspace, char *baseaddr)
1079 int struct_len;
1080 char* p;
1081 char* p2;
1082 int l2;
1083 int len;
1085 switch (uLevel) {
1086 case 0: struct_len = 16; break;
1087 case 1: struct_len = 26; break;
1088 default: return -1;
1091 if (!buf)
1093 len = 0;
1094 switch (uLevel)
1096 case 1:
1097 len = strlen(service->comment)+1;
1098 break;
1101 if (buflen) *buflen = struct_len;
1102 if (stringspace) *stringspace = len;
1103 return struct_len + len;
1106 len = struct_len;
1107 p = *buf;
1108 if (*buflen < struct_len) return -1;
1109 if (stringbuf)
1111 p2 = *stringbuf;
1112 l2 = *stringspace;
1114 else
1116 p2 = p + struct_len;
1117 l2 = *buflen - struct_len;
1119 if (!baseaddr) baseaddr = p;
1121 switch (uLevel)
1123 case 0:
1124 push_ascii(p,service->name, MAX_NETBIOSNAME_LEN, STR_TERMINATE);
1125 break;
1127 case 1:
1128 push_ascii(p,service->name,MAX_NETBIOSNAME_LEN, STR_TERMINATE);
1129 SIVAL(p,18,service->type);
1130 SIVAL(p,22,PTR_DIFF(p2,baseaddr));
1131 len += CopyAndAdvance(&p2,service->comment,&l2);
1132 break;
1135 if (stringbuf)
1137 *buf = p + struct_len;
1138 *buflen -= struct_len;
1139 *stringbuf = p2;
1140 *stringspace = l2;
1142 else
1144 *buf = p2;
1145 *buflen -= len;
1147 return len;
1151 static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
1153 return(strcmp(s1->name,s2->name));
1156 /****************************************************************************
1157 view list of servers available (or possibly domains). The info is
1158 extracted from lists saved by nmbd on the local host
1159 ****************************************************************************/
1160 static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid, char *param, char *data,
1161 int mdrcnt, int mprcnt, char **rdata,
1162 char **rparam, int *rdata_len, int *rparam_len)
1164 char *str1 = param+2;
1165 char *str2 = skip_string(str1,1);
1166 char *p = skip_string(str2,1);
1167 int uLevel = SVAL(p,0);
1168 int buf_len = SVAL(p,2);
1169 uint32 servertype = IVAL(p,4);
1170 char *p2;
1171 int data_len, fixed_len, string_len;
1172 int f_len = 0, s_len = 0;
1173 struct srv_info_struct *servers=NULL;
1174 int counted=0,total=0;
1175 int i,missed;
1176 fstring domain;
1177 BOOL domain_request;
1178 BOOL local_request;
1180 /* If someone sets all the bits they don't really mean to set
1181 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1182 known servers. */
1184 if (servertype == SV_TYPE_ALL)
1185 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1187 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1188 any other bit (they may just set this bit on it's own) they
1189 want all the locally seen servers. However this bit can be
1190 set on its own so set the requested servers to be
1191 ALL - DOMAIN_ENUM. */
1193 if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM))
1194 servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
1196 domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
1197 local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
1199 p += 8;
1201 if (!prefix_ok(str1,"WrLehD")) return False;
1202 if (!check_server_info(uLevel,str2)) return False;
1204 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1205 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1206 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1208 if (strcmp(str1, "WrLehDz") == 0) {
1209 pull_ascii_fstring(domain, p);
1210 } else {
1211 fstrcpy(domain, lp_workgroup());
1214 if (lp_browse_list())
1215 total = get_server_info(servertype,&servers,domain);
1217 data_len = fixed_len = string_len = 0;
1218 missed = 0;
1220 if (total > 0)
1221 qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
1224 char *lastname=NULL;
1226 for (i=0;i<total;i++)
1228 struct srv_info_struct *s = &servers[i];
1229 if (lastname && strequal(lastname,s->name)) continue;
1230 lastname = s->name;
1231 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1232 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1233 s->name, s->type, s->comment, s->domain));
1235 if (data_len <= buf_len) {
1236 counted++;
1237 fixed_len += f_len;
1238 string_len += s_len;
1239 } else {
1240 missed++;
1245 *rdata_len = fixed_len + string_len;
1246 *rdata = REALLOC(*rdata,*rdata_len);
1247 memset(*rdata,'\0',*rdata_len);
1249 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1250 p = *rdata;
1251 f_len = fixed_len;
1252 s_len = string_len;
1255 char *lastname=NULL;
1256 int count2 = counted;
1257 for (i = 0; i < total && count2;i++)
1259 struct srv_info_struct *s = &servers[i];
1260 if (lastname && strequal(lastname,s->name)) continue;
1261 lastname = s->name;
1262 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1263 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1264 s->name, s->type, s->comment, s->domain));
1265 count2--;
1269 *rparam_len = 8;
1270 *rparam = REALLOC(*rparam,*rparam_len);
1271 SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata));
1272 SSVAL(*rparam,2,0);
1273 SSVAL(*rparam,4,counted);
1274 SSVAL(*rparam,6,counted+missed);
1276 SAFE_FREE(servers);
1278 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1279 domain,uLevel,counted,counted+missed));
1281 return(True);
1284 /****************************************************************************
1285 command 0x34 - suspected of being a "Lookup Names" stub api
1286 ****************************************************************************/
1287 static BOOL api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid, char *param, char *data,
1288 int mdrcnt, int mprcnt, char **rdata,
1289 char **rparam, int *rdata_len, int *rparam_len)
1291 char *str1 = param+2;
1292 char *str2 = skip_string(str1,1);
1293 char *p = skip_string(str2,1);
1294 int uLevel = SVAL(p,0);
1295 int buf_len = SVAL(p,2);
1296 int counted=0;
1297 int missed=0;
1299 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1300 str1, str2, p, uLevel, buf_len));
1302 if (!prefix_ok(str1,"zWrLeh")) return False;
1304 *rdata_len = 0;
1306 *rparam_len = 8;
1307 *rparam = REALLOC(*rparam,*rparam_len);
1309 SSVAL(*rparam,0,0x08AC); /* informational warning message */
1310 SSVAL(*rparam,2,0);
1311 SSVAL(*rparam,4,counted);
1312 SSVAL(*rparam,6,counted+missed);
1314 return(True);
1317 /****************************************************************************
1318 get info about a share
1319 ****************************************************************************/
1320 static BOOL check_share_info(int uLevel, char* id)
1322 switch( uLevel ) {
1323 case 0:
1324 if (strcmp(id,"B13") != 0) return False;
1325 break;
1326 case 1:
1327 if (strcmp(id,"B13BWz") != 0) return False;
1328 break;
1329 case 2:
1330 if (strcmp(id,"B13BWzWWWzB9B") != 0) return False;
1331 break;
1332 case 91:
1333 if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) return False;
1334 break;
1335 default: return False;
1337 return True;
1340 static int fill_share_info(connection_struct *conn, int snum, int uLevel,
1341 char** buf, int* buflen,
1342 char** stringbuf, int* stringspace, char* baseaddr)
1344 int struct_len;
1345 char* p;
1346 char* p2;
1347 int l2;
1348 int len;
1350 switch( uLevel ) {
1351 case 0: struct_len = 13; break;
1352 case 1: struct_len = 20; break;
1353 case 2: struct_len = 40; break;
1354 case 91: struct_len = 68; break;
1355 default: return -1;
1359 if (!buf)
1361 len = 0;
1362 if (uLevel > 0) len += StrlenExpanded(conn,snum,lp_comment(snum));
1363 if (uLevel > 1) len += strlen(lp_pathname(snum)) + 1;
1364 if (buflen) *buflen = struct_len;
1365 if (stringspace) *stringspace = len;
1366 return struct_len + len;
1369 len = struct_len;
1370 p = *buf;
1371 if ((*buflen) < struct_len) return -1;
1372 if (stringbuf)
1374 p2 = *stringbuf;
1375 l2 = *stringspace;
1377 else
1379 p2 = p + struct_len;
1380 l2 = (*buflen) - struct_len;
1382 if (!baseaddr) baseaddr = p;
1384 push_ascii(p,lp_servicename(snum),13, STR_TERMINATE);
1386 if (uLevel > 0)
1388 int type;
1389 SCVAL(p,13,0);
1390 type = STYPE_DISKTREE;
1391 if (lp_print_ok(snum)) type = STYPE_PRINTQ;
1392 if (strequal("IPC",lp_fstype(snum))) type = STYPE_IPC;
1393 SSVAL(p,14,type); /* device type */
1394 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1395 len += CopyExpanded(conn,snum,&p2,lp_comment(snum),&l2);
1398 if (uLevel > 1)
1400 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1401 SSVALS(p,22,-1); /* max uses */
1402 SSVAL(p,24,1); /* current uses */
1403 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1404 len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1405 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1408 if (uLevel > 2)
1410 memset(p+40,0,SHPWLEN+2);
1411 SSVAL(p,50,0);
1412 SIVAL(p,52,0);
1413 SSVAL(p,56,0);
1414 SSVAL(p,58,0);
1415 SIVAL(p,60,0);
1416 SSVAL(p,64,0);
1417 SSVAL(p,66,0);
1420 if (stringbuf)
1422 (*buf) = p + struct_len;
1423 (*buflen) -= struct_len;
1424 (*stringbuf) = p2;
1425 (*stringspace) = l2;
1427 else
1429 (*buf) = p2;
1430 (*buflen) -= len;
1432 return len;
1435 static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
1436 int mdrcnt,int mprcnt,
1437 char **rdata,char **rparam,
1438 int *rdata_len,int *rparam_len)
1440 char *str1 = param+2;
1441 char *str2 = skip_string(str1,1);
1442 char *netname = skip_string(str2,1);
1443 char *p = skip_string(netname,1);
1444 int uLevel = SVAL(p,0);
1445 int snum = find_service(netname);
1447 if (snum < 0) return False;
1449 /* check it's a supported varient */
1450 if (!prefix_ok(str1,"zWrLh")) return False;
1451 if (!check_share_info(uLevel,str2)) return False;
1453 *rdata = REALLOC(*rdata,mdrcnt);
1454 p = *rdata;
1455 *rdata_len = fill_share_info(conn,snum,uLevel,&p,&mdrcnt,0,0,0);
1456 if (*rdata_len < 0) return False;
1458 *rparam_len = 6;
1459 *rparam = REALLOC(*rparam,*rparam_len);
1460 SSVAL(*rparam,0,NERR_Success);
1461 SSVAL(*rparam,2,0); /* converter word */
1462 SSVAL(*rparam,4,*rdata_len);
1464 return(True);
1467 /****************************************************************************
1468 View the list of available shares.
1470 This function is the server side of the NetShareEnum() RAP call.
1471 It fills the return buffer with share names and share comments.
1472 Note that the return buffer normally (in all known cases) allows only
1473 twelve byte strings for share names (plus one for a nul terminator).
1474 Share names longer than 12 bytes must be skipped.
1475 ****************************************************************************/
1476 static BOOL api_RNetShareEnum( connection_struct *conn,
1477 uint16 vuid,
1478 char *param,
1479 char *data,
1480 int mdrcnt,
1481 int mprcnt,
1482 char **rdata,
1483 char **rparam,
1484 int *rdata_len,
1485 int *rparam_len )
1487 char *str1 = param+2;
1488 char *str2 = skip_string(str1,1);
1489 char *p = skip_string(str2,1);
1490 int uLevel = SVAL(p,0);
1491 int buf_len = SVAL(p,2);
1492 char *p2;
1493 int count=lp_numservices();
1494 int total=0,counted=0;
1495 BOOL missed = False;
1496 int i;
1497 int data_len, fixed_len, string_len;
1498 int f_len = 0, s_len = 0;
1500 if (!prefix_ok(str1,"WrLeh")) return False;
1501 if (!check_share_info(uLevel,str2)) return False;
1503 data_len = fixed_len = string_len = 0;
1504 for (i=0;i<count;i++)
1505 if( lp_browseable( i )
1506 && lp_snum_ok( i )
1507 && (strlen( lp_servicename( i ) ) < 13) ) /* Maximum name length. */
1509 total++;
1510 data_len += fill_share_info(conn,i,uLevel,0,&f_len,0,&s_len,0);
1511 if (data_len <= buf_len)
1513 counted++;
1514 fixed_len += f_len;
1515 string_len += s_len;
1517 else
1518 missed = True;
1520 *rdata_len = fixed_len + string_len;
1521 *rdata = REALLOC(*rdata,*rdata_len);
1522 memset(*rdata,0,*rdata_len);
1524 p2 = (*rdata) + fixed_len; /* auxiliary data (strings) will go here */
1525 p = *rdata;
1526 f_len = fixed_len;
1527 s_len = string_len;
1528 for( i = 0; i < count; i++ )
1530 if( lp_browseable( i )
1531 && lp_snum_ok( i )
1532 && (strlen( lp_servicename( i ) ) < 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 = REALLOC(*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 = REALLOC(*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 = REALLOC(*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);
1658 BOOL ret;
1660 GROUP_MAP *group_list;
1661 int num_entries;
1663 if (strcmp(str1,"WrLeh") != 0)
1664 return False;
1666 /* parameters
1667 * W-> resume context (number of users to skip)
1668 * r -> return parameter pointer to receive buffer
1669 * L -> length of receive buffer
1670 * e -> return parameter number of entries
1671 * h -> return parameter total number of users
1673 if (strcmp("B21",str2) != 0)
1674 return False;
1676 /* get list of domain groups SID_DOMAIN_GRP=2 */
1677 become_root();
1678 ret = pdb_enum_group_mapping(SID_NAME_DOM_GRP , &group_list, &num_entries, False);
1679 unbecome_root();
1681 if( !ret ) {
1682 DEBUG(3,("api_RNetGroupEnum:failed to get group list"));
1683 return False;
1686 resume_context = SVAL(p,0);
1687 cli_buf_size=SVAL(p+2,0);
1688 DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: %d\n", resume_context, cli_buf_size));
1690 *rdata_len = cli_buf_size;
1691 *rdata = REALLOC(*rdata,*rdata_len);
1693 p = *rdata;
1695 for(i=resume_context; i<num_entries; i++) {
1696 char* name=group_list[i].nt_name;
1697 if( ((PTR_DIFF(p,*rdata)+21) <= *rdata_len) ) {
1698 /* truncate the name at 21 chars. */
1699 memcpy(p, name, 21);
1700 DEBUG(10,("adding entry %d group %s\n", i, p));
1701 p += 21;
1702 } else {
1703 /* set overflow error */
1704 DEBUG(3,("overflow on entry %d group %s\n", i, name));
1705 errflags=234;
1706 break;
1710 *rdata_len = PTR_DIFF(p,*rdata);
1712 *rparam_len = 8;
1713 *rparam = REALLOC(*rparam,*rparam_len);
1715 SSVAL(*rparam, 0, errflags);
1716 SSVAL(*rparam, 2, 0); /* converter word */
1717 SSVAL(*rparam, 4, i-resume_context); /* is this right?? */
1718 SSVAL(*rparam, 6, num_entries); /* is this right?? */
1720 return(True);
1723 /*******************************************************************
1724 get groups that a user is a member of
1725 ******************************************************************/
1726 static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *param,char *data,
1727 int mdrcnt,int mprcnt,
1728 char **rdata,char **rparam,
1729 int *rdata_len,int *rparam_len)
1731 char *str1 = param+2;
1732 char *str2 = skip_string(str1,1);
1733 char *UserName = skip_string(str2,1);
1734 char *p = skip_string(UserName,1);
1735 int uLevel = SVAL(p,0);
1736 const char *level_string;
1737 int count=0;
1738 SAM_ACCOUNT *sampw = NULL;
1739 BOOL ret = False;
1740 DOM_GID *gids = NULL;
1741 int num_groups = 0;
1742 int i;
1743 fstring grp_domain;
1744 fstring grp_name;
1745 enum SID_NAME_USE grp_type;
1746 DOM_SID sid, dom_sid;
1748 *rparam_len = 8;
1749 *rparam = REALLOC(*rparam,*rparam_len);
1751 /* check it's a supported varient */
1753 if ( strcmp(str1,"zWrLeh") != 0 )
1754 return False;
1756 switch( uLevel ) {
1757 case 0:
1758 level_string = "B21";
1759 break;
1760 default:
1761 return False;
1764 if (strcmp(level_string,str2) != 0)
1765 return False;
1767 *rdata_len = mdrcnt + 1024;
1768 *rdata = REALLOC(*rdata,*rdata_len);
1770 SSVAL(*rparam,0,NERR_Success);
1771 SSVAL(*rparam,2,0); /* converter word */
1773 p = *rdata;
1775 /* Lookup the user information; This should only be one of
1776 our accounts (not remote domains) */
1778 pdb_init_sam( &sampw );
1780 become_root(); /* ROOT BLOCK */
1782 if ( !pdb_getsampwnam(sampw, UserName) )
1783 goto out;
1785 /* this next set of code is horribly inefficient, but since
1786 it is rarely called, I'm going to leave it like this since
1787 it easier to follow --jerry */
1789 /* get the list of group SIDs */
1791 if ( !get_domain_user_groups(conn->mem_ctx, &num_groups, &gids, sampw) ) {
1792 DEBUG(1,("api_NetUserGetGroups: get_domain_user_groups() failed!\n"));
1793 goto out;
1796 /* convert to names (we don't support universal groups so the domain
1797 can only be ours) */
1799 sid_copy( &dom_sid, get_global_sam_sid() );
1800 for (i=0; i<num_groups; i++) {
1802 /* make the DOM_GID into a DOM_SID and then lookup
1803 the name */
1805 sid_copy( &sid, &dom_sid );
1806 sid_append_rid( &sid, gids[i].g_rid );
1808 if ( lookup_sid(&sid, grp_domain, grp_name, &grp_type) ) {
1809 pstrcpy(p, grp_name);
1810 p += 21;
1811 count++;
1815 *rdata_len = PTR_DIFF(p,*rdata);
1817 SSVAL(*rparam,4,count); /* is this right?? */
1818 SSVAL(*rparam,6,count); /* is this right?? */
1820 ret = True;
1822 out:
1823 unbecome_root(); /* END ROOT BLOCK */
1825 pdb_free_sam( &sampw );
1827 return ret;
1830 /*******************************************************************
1831 get all users
1832 ******************************************************************/
1833 static BOOL api_RNetUserEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
1834 int mdrcnt,int mprcnt,
1835 char **rdata,char **rparam,
1836 int *rdata_len,int *rparam_len)
1838 SAM_ACCOUNT *pwd=NULL;
1839 int count_sent=0;
1840 int count_total=0;
1841 int errflags=0;
1842 int resume_context, cli_buf_size;
1844 char *str1 = param+2;
1845 char *str2 = skip_string(str1,1);
1846 char *p = skip_string(str2,1);
1848 if (strcmp(str1,"WrLeh") != 0)
1849 return False;
1850 /* parameters
1851 * W-> resume context (number of users to skip)
1852 * r -> return parameter pointer to receive buffer
1853 * L -> length of receive buffer
1854 * e -> return parameter number of entries
1855 * h -> return parameter total number of users
1858 resume_context = SVAL(p,0);
1859 cli_buf_size=SVAL(p+2,0);
1860 DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n", resume_context, cli_buf_size));
1862 *rparam_len = 8;
1863 *rparam = REALLOC(*rparam,*rparam_len);
1865 /* check it's a supported varient */
1866 if (strcmp("B21",str2) != 0)
1867 return False;
1869 *rdata_len = cli_buf_size;
1870 *rdata = REALLOC(*rdata,*rdata_len);
1872 p = *rdata;
1874 /* to get user list enumerations for NetUserEnum in B21 format */
1875 pdb_init_sam(&pwd);
1877 /* Open the passgrp file - not for update. */
1878 become_root();
1879 if(!pdb_setsampwent(False)) {
1880 DEBUG(0, ("api_RNetUserEnum:unable to open sam database.\n"));
1881 unbecome_root();
1882 return False;
1884 errflags=NERR_Success;
1886 while ( pdb_getsampwent(pwd) ) {
1887 const char *name=pdb_get_username(pwd);
1888 if ((name) && (*(name+strlen(name)-1)!='$')) {
1889 count_total++;
1890 if(count_total>=resume_context) {
1891 if( ((PTR_DIFF(p,*rdata)+21)<=*rdata_len)&&(strlen(name)<=21) ) {
1892 pstrcpy(p,name);
1893 DEBUG(10,("api_RNetUserEnum:adding entry %d username %s\n",count_sent,p));
1894 p += 21;
1895 count_sent++;
1896 } else {
1897 /* set overflow error */
1898 DEBUG(10,("api_RNetUserEnum:overflow on entry %d username %s\n",count_sent,name));
1899 errflags=234;
1900 break;
1906 pdb_endsampwent();
1907 unbecome_root();
1909 pdb_free_sam(&pwd);
1911 *rdata_len = PTR_DIFF(p,*rdata);
1913 SSVAL(*rparam,0,errflags);
1914 SSVAL(*rparam,2,0); /* converter word */
1915 SSVAL(*rparam,4,count_sent); /* is this right?? */
1916 SSVAL(*rparam,6,count_total); /* is this right?? */
1918 return True;
1923 /****************************************************************************
1924 get the time of day info
1925 ****************************************************************************/
1926 static BOOL api_NetRemoteTOD(connection_struct *conn,uint16 vuid, char *param,char *data,
1927 int mdrcnt,int mprcnt,
1928 char **rdata,char **rparam,
1929 int *rdata_len,int *rparam_len)
1931 char *p;
1932 *rparam_len = 4;
1933 *rparam = REALLOC(*rparam,*rparam_len);
1935 *rdata_len = 21;
1936 *rdata = REALLOC(*rdata,*rdata_len);
1938 SSVAL(*rparam,0,NERR_Success);
1939 SSVAL(*rparam,2,0); /* converter word */
1941 p = *rdata;
1944 struct tm *t;
1945 time_t unixdate = time(NULL);
1947 put_dos_date3(p,0,unixdate); /* this is the time that is looked at
1948 by NT in a "net time" operation,
1949 it seems to ignore the one below */
1951 /* the client expects to get localtime, not GMT, in this bit
1952 (I think, this needs testing) */
1953 t = LocalTime(&unixdate);
1955 SIVAL(p,4,0); /* msecs ? */
1956 SCVAL(p,8,t->tm_hour);
1957 SCVAL(p,9,t->tm_min);
1958 SCVAL(p,10,t->tm_sec);
1959 SCVAL(p,11,0); /* hundredths of seconds */
1960 SSVALS(p,12,TimeDiff(unixdate)/60); /* timezone in minutes from GMT */
1961 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
1962 SCVAL(p,16,t->tm_mday);
1963 SCVAL(p,17,t->tm_mon + 1);
1964 SSVAL(p,18,1900+t->tm_year);
1965 SCVAL(p,20,t->tm_wday);
1969 return(True);
1972 /****************************************************************************
1973 Set the user password.
1974 *****************************************************************************/
1976 static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param,char *data,
1977 int mdrcnt,int mprcnt,
1978 char **rdata,char **rparam,
1979 int *rdata_len,int *rparam_len)
1981 char *p = skip_string(param+2,2);
1982 fstring user;
1983 fstring pass1,pass2;
1985 pull_ascii_fstring(user,p);
1987 p = skip_string(p,1);
1989 memset(pass1,'\0',sizeof(pass1));
1990 memset(pass2,'\0',sizeof(pass2));
1991 memcpy(pass1,p,16);
1992 memcpy(pass2,p+16,16);
1994 *rparam_len = 4;
1995 *rparam = REALLOC(*rparam,*rparam_len);
1997 *rdata_len = 0;
1999 SSVAL(*rparam,0,NERR_badpass);
2000 SSVAL(*rparam,2,0); /* converter word */
2002 DEBUG(3,("Set password for <%s>\n",user));
2005 * Attempt to verify the old password against smbpasswd entries
2006 * Win98 clients send old and new password in plaintext for this call.
2010 auth_serversupplied_info *server_info = NULL;
2011 DATA_BLOB password = data_blob(pass1, strlen(pass1)+1);
2013 if (NT_STATUS_IS_OK(check_plaintext_password(user,password,&server_info))) {
2015 become_root();
2016 if (NT_STATUS_IS_OK(change_oem_password(server_info->sam_account, pass1, pass2, False))) {
2017 SSVAL(*rparam,0,NERR_Success);
2019 unbecome_root();
2021 free_server_info(&server_info);
2023 data_blob_clear_free(&password);
2027 * If the plaintext change failed, attempt
2028 * the old encrypted method. NT will generate this
2029 * after trying the samr method. Note that this
2030 * method is done as a last resort as this
2031 * password change method loses the NT password hash
2032 * and cannot change the UNIX password as no plaintext
2033 * is received.
2036 if(SVAL(*rparam,0) != NERR_Success) {
2037 SAM_ACCOUNT *hnd = NULL;
2039 if (check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &hnd)) {
2040 become_root();
2041 if (change_lanman_password(hnd,(uchar *)pass2)) {
2042 SSVAL(*rparam,0,NERR_Success);
2044 unbecome_root();
2045 pdb_free_sam(&hnd);
2049 memset((char *)pass1,'\0',sizeof(fstring));
2050 memset((char *)pass2,'\0',sizeof(fstring));
2052 return(True);
2055 /****************************************************************************
2056 Set the user password (SamOEM version - gets plaintext).
2057 ****************************************************************************/
2059 static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char *param,char *data,
2060 int mdrcnt,int mprcnt,
2061 char **rdata,char **rparam,
2062 int *rdata_len,int *rparam_len)
2064 fstring user;
2065 char *p = param + 2;
2066 *rparam_len = 2;
2067 *rparam = REALLOC(*rparam,*rparam_len);
2069 *rdata_len = 0;
2071 SSVAL(*rparam,0,NERR_badpass);
2074 * Check the parameter definition is correct.
2077 if(!strequal(param + 2, "zsT")) {
2078 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", param + 2));
2079 return False;
2081 p = skip_string(p, 1);
2083 if(!strequal(p, "B516B16")) {
2084 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p));
2085 return False;
2087 p = skip_string(p,1);
2088 p += pull_ascii_fstring(user,p);
2090 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user));
2093 * Pass the user through the NT -> unix user mapping
2094 * function.
2097 (void)map_username(user);
2099 if (NT_STATUS_IS_OK(pass_oem_change(user, (uchar*) data, (uchar *)&data[516], NULL, NULL))) {
2100 SSVAL(*rparam,0,NERR_Success);
2103 return(True);
2106 /****************************************************************************
2107 delete a print job
2108 Form: <W> <>
2109 ****************************************************************************/
2110 static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char *param,char *data,
2111 int mdrcnt,int mprcnt,
2112 char **rdata,char **rparam,
2113 int *rdata_len,int *rparam_len)
2115 int function = SVAL(param,0);
2116 char *str1 = param+2;
2117 char *str2 = skip_string(str1,1);
2118 char *p = skip_string(str2,1);
2119 uint32 jobid;
2120 int snum;
2121 int errcode;
2122 extern struct current_user current_user;
2123 WERROR werr = WERR_OK;
2125 if(!rap_to_pjobid(SVAL(p,0),&snum,&jobid))
2126 return False;
2128 /* check it's a supported varient */
2129 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
2130 return(False);
2132 *rparam_len = 4;
2133 *rparam = REALLOC(*rparam,*rparam_len);
2134 *rdata_len = 0;
2136 if (!print_job_exists(snum, jobid)) {
2137 errcode = NERR_JobNotFound;
2138 goto out;
2141 errcode = NERR_notsupported;
2143 switch (function) {
2144 case 81: /* delete */
2145 if (print_job_delete(&current_user, snum, jobid, &werr))
2146 errcode = NERR_Success;
2147 break;
2148 case 82: /* pause */
2149 if (print_job_pause(&current_user, snum, jobid, &werr))
2150 errcode = NERR_Success;
2151 break;
2152 case 83: /* resume */
2153 if (print_job_resume(&current_user, snum, jobid, &werr))
2154 errcode = NERR_Success;
2155 break;
2158 if (!W_ERROR_IS_OK(werr))
2159 errcode = W_ERROR_V(werr);
2161 out:
2162 SSVAL(*rparam,0,errcode);
2163 SSVAL(*rparam,2,0); /* converter word */
2165 return(True);
2168 /****************************************************************************
2169 Purge a print queue - or pause or resume it.
2170 ****************************************************************************/
2171 static BOOL api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid, char *param,char *data,
2172 int mdrcnt,int mprcnt,
2173 char **rdata,char **rparam,
2174 int *rdata_len,int *rparam_len)
2176 int function = SVAL(param,0);
2177 char *str1 = param+2;
2178 char *str2 = skip_string(str1,1);
2179 char *QueueName = skip_string(str2,1);
2180 int errcode = NERR_notsupported;
2181 int snum;
2182 WERROR werr = WERR_OK;
2183 extern struct current_user current_user;
2185 /* check it's a supported varient */
2186 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
2187 return(False);
2189 *rparam_len = 4;
2190 *rparam = REALLOC(*rparam,*rparam_len);
2191 *rdata_len = 0;
2193 snum = print_queue_snum(QueueName);
2195 if (snum == -1) {
2196 errcode = NERR_JobNotFound;
2197 goto out;
2200 switch (function) {
2201 case 74: /* Pause queue */
2202 if (print_queue_pause(&current_user, snum, &werr)) errcode = NERR_Success;
2203 break;
2204 case 75: /* Resume queue */
2205 if (print_queue_resume(&current_user, snum, &werr)) errcode = NERR_Success;
2206 break;
2207 case 103: /* Purge */
2208 if (print_queue_purge(&current_user, snum, &werr)) errcode = NERR_Success;
2209 break;
2212 if (!W_ERROR_IS_OK(werr)) errcode = W_ERROR_V(werr);
2214 out:
2215 SSVAL(*rparam,0,errcode);
2216 SSVAL(*rparam,2,0); /* converter word */
2218 return(True);
2222 /****************************************************************************
2223 set the property of a print job (undocumented?)
2224 ? function = 0xb -> set name of print job
2225 ? function = 0x6 -> move print job up/down
2226 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
2227 or <WWsTP> <WB21BB16B10zWWzDDz>
2228 ****************************************************************************/
2229 static int check_printjob_info(struct pack_desc* desc,
2230 int uLevel, char* id)
2232 desc->subformat = NULL;
2233 switch( uLevel ) {
2234 case 0: desc->format = "W"; break;
2235 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
2236 case 2: desc->format = "WWzWWDDzz"; break;
2237 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
2238 case 4: desc->format = "WWzWWDDzzzzzDDDDDDD"; break;
2239 default: return False;
2241 if (strcmp(desc->format,id) != 0) return False;
2242 return True;
2245 static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,char *data,
2246 int mdrcnt,int mprcnt,
2247 char **rdata,char **rparam,
2248 int *rdata_len,int *rparam_len)
2250 struct pack_desc desc;
2251 char *str1 = param+2;
2252 char *str2 = skip_string(str1,1);
2253 char *p = skip_string(str2,1);
2254 uint32 jobid;
2255 int snum;
2256 int uLevel = SVAL(p,2);
2257 int function = SVAL(p,4);
2258 int place, errcode;
2260 if(!rap_to_pjobid(SVAL(p,0),&snum,&jobid))
2261 return False;
2262 *rparam_len = 4;
2263 *rparam = REALLOC(*rparam,*rparam_len);
2265 *rdata_len = 0;
2267 /* check it's a supported varient */
2268 if ((strcmp(str1,"WWsTP")) ||
2269 (!check_printjob_info(&desc,uLevel,str2)))
2270 return(False);
2272 if (!print_job_exists(snum, jobid)) {
2273 errcode=NERR_JobNotFound;
2274 goto out;
2277 errcode = NERR_notsupported;
2279 switch (function) {
2280 case 0x6:
2281 /* change job place in the queue,
2282 data gives the new place */
2283 place = SVAL(data,0);
2284 if (print_job_set_place(snum, jobid, place)) {
2285 errcode=NERR_Success;
2287 break;
2289 case 0xb:
2290 /* change print job name, data gives the name */
2291 if (print_job_set_name(snum, jobid, data)) {
2292 errcode=NERR_Success;
2294 break;
2296 default:
2297 return False;
2300 out:
2301 SSVALS(*rparam,0,errcode);
2302 SSVAL(*rparam,2,0); /* converter word */
2304 return(True);
2308 /****************************************************************************
2309 get info about the server
2310 ****************************************************************************/
2311 static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2312 int mdrcnt,int mprcnt,
2313 char **rdata,char **rparam,
2314 int *rdata_len,int *rparam_len)
2316 char *str1 = param+2;
2317 char *str2 = skip_string(str1,1);
2318 char *p = skip_string(str2,1);
2319 int uLevel = SVAL(p,0);
2320 char *p2;
2321 int struct_len;
2323 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
2325 /* check it's a supported varient */
2326 if (!prefix_ok(str1,"WrLh")) return False;
2327 switch( uLevel ) {
2328 case 0:
2329 if (strcmp(str2,"B16") != 0) return False;
2330 struct_len = 16;
2331 break;
2332 case 1:
2333 if (strcmp(str2,"B16BBDz") != 0) return False;
2334 struct_len = 26;
2335 break;
2336 case 2:
2337 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")
2338 != 0) return False;
2339 struct_len = 134;
2340 break;
2341 case 3:
2342 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz")
2343 != 0) return False;
2344 struct_len = 144;
2345 break;
2346 case 20:
2347 if (strcmp(str2,"DN") != 0) return False;
2348 struct_len = 6;
2349 break;
2350 case 50:
2351 if (strcmp(str2,"B16BBDzWWzzz") != 0) return False;
2352 struct_len = 42;
2353 break;
2354 default: return False;
2357 *rdata_len = mdrcnt;
2358 *rdata = REALLOC(*rdata,*rdata_len);
2360 p = *rdata;
2361 p2 = p + struct_len;
2362 if (uLevel != 20) {
2363 srvstr_push(NULL, p,local_machine,16,
2364 STR_ASCII|STR_UPPER|STR_TERMINATE);
2366 p += 16;
2367 if (uLevel > 0)
2369 struct srv_info_struct *servers=NULL;
2370 int i,count;
2371 pstring comment;
2372 uint32 servertype= lp_default_server_announce();
2374 push_ascii(comment,lp_serverstring(), MAX_SERVER_STRING_LENGTH,STR_TERMINATE);
2376 if ((count=get_server_info(SV_TYPE_ALL,&servers,lp_workgroup()))>0) {
2377 for (i=0;i<count;i++) {
2378 if (strequal(servers[i].name,local_machine)) {
2379 servertype = servers[i].type;
2380 push_ascii(comment,servers[i].comment,sizeof(pstring),STR_TERMINATE);
2384 SAFE_FREE(servers);
2386 SCVAL(p,0,lp_major_announce_version());
2387 SCVAL(p,1,lp_minor_announce_version());
2388 SIVAL(p,2,servertype);
2390 if (mdrcnt == struct_len) {
2391 SIVAL(p,6,0);
2392 } else {
2393 SIVAL(p,6,PTR_DIFF(p2,*rdata));
2394 standard_sub_conn(conn,comment,sizeof(comment));
2395 StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
2396 p2 = skip_string(p2,1);
2399 if (uLevel > 1)
2401 return False; /* not yet implemented */
2404 *rdata_len = PTR_DIFF(p2,*rdata);
2406 *rparam_len = 6;
2407 *rparam = REALLOC(*rparam,*rparam_len);
2408 SSVAL(*rparam,0,NERR_Success);
2409 SSVAL(*rparam,2,0); /* converter word */
2410 SSVAL(*rparam,4,*rdata_len);
2412 return(True);
2416 /****************************************************************************
2417 get info about the server
2418 ****************************************************************************/
2419 static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2420 int mdrcnt,int mprcnt,
2421 char **rdata,char **rparam,
2422 int *rdata_len,int *rparam_len)
2424 char *str1 = param+2;
2425 char *str2 = skip_string(str1,1);
2426 char *p = skip_string(str2,1);
2427 char *p2;
2428 extern userdom_struct current_user_info;
2429 int level = SVAL(p,0);
2431 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
2433 *rparam_len = 6;
2434 *rparam = REALLOC(*rparam,*rparam_len);
2436 /* check it's a supported varient */
2437 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz")))
2438 return(False);
2440 *rdata_len = mdrcnt + 1024;
2441 *rdata = REALLOC(*rdata,*rdata_len);
2443 SSVAL(*rparam,0,NERR_Success);
2444 SSVAL(*rparam,2,0); /* converter word */
2446 p = *rdata;
2447 p2 = p + 22;
2450 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
2451 pstrcpy(p2,local_machine);
2452 strupper_m(p2);
2453 p2 = skip_string(p2,1);
2454 p += 4;
2456 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2457 pstrcpy(p2,current_user_info.smb_name);
2458 p2 = skip_string(p2,1);
2459 p += 4;
2461 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
2462 pstrcpy(p2,lp_workgroup());
2463 strupper_m(p2);
2464 p2 = skip_string(p2,1);
2465 p += 4;
2467 SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
2468 SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
2469 p += 2;
2471 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2472 pstrcpy(p2,lp_workgroup()); /* don't know. login domain?? */
2473 p2 = skip_string(p2,1);
2474 p += 4;
2476 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
2477 pstrcpy(p2,"");
2478 p2 = skip_string(p2,1);
2479 p += 4;
2481 *rdata_len = PTR_DIFF(p2,*rdata);
2483 SSVAL(*rparam,4,*rdata_len);
2485 return(True);
2488 /****************************************************************************
2489 get info about a user
2491 struct user_info_11 {
2492 char usri11_name[21]; 0-20
2493 char usri11_pad; 21
2494 char *usri11_comment; 22-25
2495 char *usri11_usr_comment; 26-29
2496 unsigned short usri11_priv; 30-31
2497 unsigned long usri11_auth_flags; 32-35
2498 long usri11_password_age; 36-39
2499 char *usri11_homedir; 40-43
2500 char *usri11_parms; 44-47
2501 long usri11_last_logon; 48-51
2502 long usri11_last_logoff; 52-55
2503 unsigned short usri11_bad_pw_count; 56-57
2504 unsigned short usri11_num_logons; 58-59
2505 char *usri11_logon_server; 60-63
2506 unsigned short usri11_country_code; 64-65
2507 char *usri11_workstations; 66-69
2508 unsigned long usri11_max_storage; 70-73
2509 unsigned short usri11_units_per_week; 74-75
2510 unsigned char *usri11_logon_hours; 76-79
2511 unsigned short usri11_code_page; 80-81
2514 where:
2516 usri11_name specifies the user name for which information is retireved
2518 usri11_pad aligns the next data structure element to a word boundary
2520 usri11_comment is a null terminated ASCII comment
2522 usri11_user_comment is a null terminated ASCII comment about the user
2524 usri11_priv specifies the level of the privilege assigned to the user.
2525 The possible values are:
2527 Name Value Description
2528 USER_PRIV_GUEST 0 Guest privilege
2529 USER_PRIV_USER 1 User privilege
2530 USER_PRV_ADMIN 2 Administrator privilege
2532 usri11_auth_flags specifies the account operator privileges. The
2533 possible values are:
2535 Name Value Description
2536 AF_OP_PRINT 0 Print operator
2539 Leach, Naik [Page 28]
2543 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2546 AF_OP_COMM 1 Communications operator
2547 AF_OP_SERVER 2 Server operator
2548 AF_OP_ACCOUNTS 3 Accounts operator
2551 usri11_password_age specifies how many seconds have elapsed since the
2552 password was last changed.
2554 usri11_home_dir points to a null terminated ASCII string that contains
2555 the path name of the user's home directory.
2557 usri11_parms points to a null terminated ASCII string that is set
2558 aside for use by applications.
2560 usri11_last_logon specifies the time when the user last logged on.
2561 This value is stored as the number of seconds elapsed since
2562 00:00:00, January 1, 1970.
2564 usri11_last_logoff specifies the time when the user last logged off.
2565 This value is stored as the number of seconds elapsed since
2566 00:00:00, January 1, 1970. A value of 0 means the last logoff
2567 time is unknown.
2569 usri11_bad_pw_count specifies the number of incorrect passwords
2570 entered since the last successful logon.
2572 usri11_log1_num_logons specifies the number of times this user has
2573 logged on. A value of -1 means the number of logons is unknown.
2575 usri11_logon_server points to a null terminated ASCII string that
2576 contains the name of the server to which logon requests are sent.
2577 A null string indicates logon requests should be sent to the
2578 domain controller.
2580 usri11_country_code specifies the country code for the user's language
2581 of choice.
2583 usri11_workstations points to a null terminated ASCII string that
2584 contains the names of workstations the user may log on from.
2585 There may be up to 8 workstations, with the names separated by
2586 commas. A null strings indicates there are no restrictions.
2588 usri11_max_storage specifies the maximum amount of disk space the user
2589 can occupy. A value of 0xffffffff indicates there are no
2590 restrictions.
2592 usri11_units_per_week specifies the equal number of time units into
2593 which a week is divided. This value must be equal to 168.
2595 usri11_logon_hours points to a 21 byte (168 bits) string that
2596 specifies the time during which the user can log on. Each bit
2597 represents one unique hour in a week. The first bit (bit 0, word
2598 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
2602 Leach, Naik [Page 29]
2606 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2609 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
2610 are no restrictions.
2612 usri11_code_page specifies the code page for the user's language of
2613 choice
2615 All of the pointers in this data structure need to be treated
2616 specially. The pointer is a 32 bit pointer. The higher 16 bits need
2617 to be ignored. The converter word returned in the parameters section
2618 needs to be subtracted from the lower 16 bits to calculate an offset
2619 into the return buffer where this ASCII string resides.
2621 There is no auxiliary data in the response.
2623 ****************************************************************************/
2625 #define usri11_name 0
2626 #define usri11_pad 21
2627 #define usri11_comment 22
2628 #define usri11_usr_comment 26
2629 #define usri11_full_name 30
2630 #define usri11_priv 34
2631 #define usri11_auth_flags 36
2632 #define usri11_password_age 40
2633 #define usri11_homedir 44
2634 #define usri11_parms 48
2635 #define usri11_last_logon 52
2636 #define usri11_last_logoff 56
2637 #define usri11_bad_pw_count 60
2638 #define usri11_num_logons 62
2639 #define usri11_logon_server 64
2640 #define usri11_country_code 68
2641 #define usri11_workstations 70
2642 #define usri11_max_storage 74
2643 #define usri11_units_per_week 78
2644 #define usri11_logon_hours 80
2645 #define usri11_code_page 84
2646 #define usri11_end 86
2648 #define USER_PRIV_GUEST 0
2649 #define USER_PRIV_USER 1
2650 #define USER_PRIV_ADMIN 2
2652 #define AF_OP_PRINT 0
2653 #define AF_OP_COMM 1
2654 #define AF_OP_SERVER 2
2655 #define AF_OP_ACCOUNTS 3
2658 static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2659 int mdrcnt,int mprcnt,
2660 char **rdata,char **rparam,
2661 int *rdata_len,int *rparam_len)
2663 char *str1 = param+2;
2664 char *str2 = skip_string(str1,1);
2665 char *UserName = skip_string(str2,1);
2666 char *p = skip_string(UserName,1);
2667 int uLevel = SVAL(p,0);
2668 char *p2;
2669 const char *level_string;
2671 /* get NIS home of a previously validated user - simeon */
2672 /* With share level security vuid will always be zero.
2673 Don't depend on vuser being non-null !!. JRA */
2674 user_struct *vuser = get_valid_user_struct(vuid);
2675 if(vuser != NULL)
2676 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid,
2677 vuser->user.unix_name));
2679 *rparam_len = 6;
2680 *rparam = REALLOC(*rparam,*rparam_len);
2682 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
2684 /* check it's a supported variant */
2685 if (strcmp(str1,"zWrLh") != 0) return False;
2686 switch( uLevel )
2688 case 0: level_string = "B21"; break;
2689 case 1: level_string = "B21BB16DWzzWz"; break;
2690 case 2: level_string = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
2691 case 10: level_string = "B21Bzzz"; break;
2692 case 11: level_string = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
2693 default: return False;
2696 if (strcmp(level_string,str2) != 0) return False;
2698 *rdata_len = mdrcnt + 1024;
2699 *rdata = REALLOC(*rdata,*rdata_len);
2701 SSVAL(*rparam,0,NERR_Success);
2702 SSVAL(*rparam,2,0); /* converter word */
2704 p = *rdata;
2705 p2 = p + usri11_end;
2707 memset(p,0,21);
2708 fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
2710 if (uLevel > 0)
2712 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
2713 *p2 = 0;
2715 if (uLevel >= 10)
2717 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
2718 pstrcpy(p2,"Comment");
2719 p2 = skip_string(p2,1);
2721 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
2722 pstrcpy(p2,"UserComment");
2723 p2 = skip_string(p2,1);
2725 /* EEK! the cifsrap.txt doesn't have this in!!!! */
2726 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
2727 pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName));
2728 p2 = skip_string(p2,1);
2731 if (uLevel == 11) /* modelled after NTAS 3.51 reply */
2733 SSVAL(p,usri11_priv,conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2734 SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
2735 SIVALS(p,usri11_password_age,-1); /* password age */
2736 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
2737 pstrcpy(p2, vuser && vuser->homedir ? vuser->homedir : "");
2738 p2 = skip_string(p2,1);
2739 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
2740 pstrcpy(p2,"");
2741 p2 = skip_string(p2,1);
2742 SIVAL(p,usri11_last_logon,0); /* last logon */
2743 SIVAL(p,usri11_last_logoff,0); /* last logoff */
2744 SSVALS(p,usri11_bad_pw_count,-1); /* bad pw counts */
2745 SSVALS(p,usri11_num_logons,-1); /* num logons */
2746 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
2747 pstrcpy(p2,"\\\\*");
2748 p2 = skip_string(p2,1);
2749 SSVAL(p,usri11_country_code,0); /* country code */
2751 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
2752 pstrcpy(p2,"");
2753 p2 = skip_string(p2,1);
2755 SIVALS(p,usri11_max_storage,-1); /* max storage */
2756 SSVAL(p,usri11_units_per_week,168); /* units per week */
2757 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
2759 /* a simple way to get logon hours at all times. */
2760 memset(p2,0xff,21);
2761 SCVAL(p2,21,0); /* fix zero termination */
2762 p2 = skip_string(p2,1);
2764 SSVAL(p,usri11_code_page,0); /* code page */
2766 if (uLevel == 1 || uLevel == 2)
2768 memset(p+22,' ',16); /* password */
2769 SIVALS(p,38,-1); /* password age */
2770 SSVAL(p,42,
2771 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2772 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
2773 pstrcpy(p2, vuser && vuser->homedir ? vuser->homedir : "");
2774 p2 = skip_string(p2,1);
2775 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
2776 *p2++ = 0;
2777 SSVAL(p,52,0); /* flags */
2778 SIVAL(p,54,PTR_DIFF(p2,*rdata)); /* script_path */
2779 pstrcpy(p2,vuser && vuser->logon_script ? vuser->logon_script : "");
2780 p2 = skip_string(p2,1);
2781 if (uLevel == 2)
2783 SIVAL(p,60,0); /* auth_flags */
2784 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
2785 pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName));
2786 p2 = skip_string(p2,1);
2787 SIVAL(p,68,0); /* urs_comment */
2788 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
2789 pstrcpy(p2,"");
2790 p2 = skip_string(p2,1);
2791 SIVAL(p,76,0); /* workstations */
2792 SIVAL(p,80,0); /* last_logon */
2793 SIVAL(p,84,0); /* last_logoff */
2794 SIVALS(p,88,-1); /* acct_expires */
2795 SIVALS(p,92,-1); /* max_storage */
2796 SSVAL(p,96,168); /* units_per_week */
2797 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
2798 memset(p2,-1,21);
2799 p2 += 21;
2800 SSVALS(p,102,-1); /* bad_pw_count */
2801 SSVALS(p,104,-1); /* num_logons */
2802 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
2803 pstrcpy(p2,"\\\\%L");
2804 standard_sub_conn(conn, p2,0);
2805 p2 = skip_string(p2,1);
2806 SSVAL(p,110,49); /* country_code */
2807 SSVAL(p,112,860); /* code page */
2811 *rdata_len = PTR_DIFF(p2,*rdata);
2813 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
2815 return(True);
2818 static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param,char *data,
2819 int mdrcnt,int mprcnt,
2820 char **rdata,char **rparam,
2821 int *rdata_len,int *rparam_len)
2823 char *str1 = param+2;
2824 char *str2 = skip_string(str1,1);
2825 char *p = skip_string(str2,1);
2826 int uLevel;
2827 struct pack_desc desc;
2828 char* name;
2829 /* With share level security vuid will always be zero.
2830 Don't depend on vuser being non-null !!. JRA */
2831 user_struct *vuser = get_valid_user_struct(vuid);
2832 if(vuser != NULL)
2833 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid,
2834 vuser->user.unix_name));
2836 uLevel = SVAL(p,0);
2837 name = p + 2;
2839 memset((char *)&desc,'\0',sizeof(desc));
2841 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
2843 /* check it's a supported varient */
2844 if (strcmp(str1,"OOWb54WrLh") != 0) return False;
2845 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) return False;
2846 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2847 desc.base = *rdata;
2848 desc.buflen = mdrcnt;
2849 desc.subformat = NULL;
2850 desc.format = str2;
2852 if (init_package(&desc,1,0))
2854 PACKI(&desc,"W",0); /* code */
2855 PACKS(&desc,"B21",name); /* eff. name */
2856 PACKS(&desc,"B",""); /* pad */
2857 PACKI(&desc,"W",
2858 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2859 PACKI(&desc,"D",0); /* auth flags XXX */
2860 PACKI(&desc,"W",0); /* num logons */
2861 PACKI(&desc,"W",0); /* bad pw count */
2862 PACKI(&desc,"D",0); /* last logon */
2863 PACKI(&desc,"D",-1); /* last logoff */
2864 PACKI(&desc,"D",-1); /* logoff time */
2865 PACKI(&desc,"D",-1); /* kickoff time */
2866 PACKI(&desc,"D",0); /* password age */
2867 PACKI(&desc,"D",0); /* password can change */
2868 PACKI(&desc,"D",-1); /* password must change */
2870 fstring mypath;
2871 fstrcpy(mypath,"\\\\");
2872 fstrcat(mypath,local_machine);
2873 strupper_m(mypath);
2874 PACKS(&desc,"z",mypath); /* computer */
2876 PACKS(&desc,"z",lp_workgroup());/* domain */
2878 PACKS(&desc,"z", vuser && vuser->logon_script ? vuser->logon_script :""); /* script path */
2880 PACKI(&desc,"D",0x00000000); /* reserved */
2883 *rdata_len = desc.usedlen;
2884 *rparam_len = 6;
2885 *rparam = REALLOC(*rparam,*rparam_len);
2886 SSVALS(*rparam,0,desc.errcode);
2887 SSVAL(*rparam,2,0);
2888 SSVAL(*rparam,4,desc.neededlen);
2890 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
2891 return(True);
2895 /****************************************************************************
2896 api_WAccessGetUserPerms
2897 ****************************************************************************/
2898 static BOOL api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid, char *param,char *data,
2899 int mdrcnt,int mprcnt,
2900 char **rdata,char **rparam,
2901 int *rdata_len,int *rparam_len)
2903 char *str1 = param+2;
2904 char *str2 = skip_string(str1,1);
2905 char *user = skip_string(str2,1);
2906 char *resource = skip_string(user,1);
2908 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
2910 /* check it's a supported varient */
2911 if (strcmp(str1,"zzh") != 0) return False;
2912 if (strcmp(str2,"") != 0) return False;
2914 *rparam_len = 6;
2915 *rparam = REALLOC(*rparam,*rparam_len);
2916 SSVALS(*rparam,0,0); /* errorcode */
2917 SSVAL(*rparam,2,0); /* converter word */
2918 SSVAL(*rparam,4,0x7f); /* permission flags */
2920 return(True);
2923 /****************************************************************************
2924 api_WPrintJobEnumerate
2925 ****************************************************************************/
2926 static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2927 int mdrcnt,int mprcnt,
2928 char **rdata,char **rparam,
2929 int *rdata_len,int *rparam_len)
2931 char *str1 = param+2;
2932 char *str2 = skip_string(str1,1);
2933 char *p = skip_string(str2,1);
2934 int uLevel;
2935 int count;
2936 int i;
2937 int snum;
2938 uint32 jobid;
2939 struct pack_desc desc;
2940 print_queue_struct *queue=NULL;
2941 print_status_struct status;
2942 char *tmpdata=NULL;
2944 uLevel = SVAL(p,2);
2946 memset((char *)&desc,'\0',sizeof(desc));
2947 memset((char *)&status,'\0',sizeof(status));
2949 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
2951 /* check it's a supported varient */
2952 if (strcmp(str1,"WWrLh") != 0) return False;
2953 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2955 if(!rap_to_pjobid(SVAL(p,0),&snum,&jobid))
2956 return False;
2958 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2960 count = print_queue_status(snum,&queue,&status);
2961 for (i = 0; i < count; i++) {
2962 if (queue[i].job == jobid) break;
2965 if (mdrcnt > 0) {
2966 *rdata = REALLOC(*rdata,mdrcnt);
2967 desc.base = *rdata;
2968 desc.buflen = mdrcnt;
2969 } else {
2971 * Don't return data but need to get correct length
2972 * init_package will return wrong size if buflen=0
2974 desc.buflen = getlen(desc.format);
2975 desc.base = tmpdata = (char *)malloc ( desc.buflen );
2978 if (init_package(&desc,1,0)) {
2979 if (i < count) {
2980 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
2981 *rdata_len = desc.usedlen;
2983 else {
2984 desc.errcode = NERR_JobNotFound;
2985 *rdata_len = 0;
2989 *rparam_len = 6;
2990 *rparam = REALLOC(*rparam,*rparam_len);
2991 SSVALS(*rparam,0,desc.errcode);
2992 SSVAL(*rparam,2,0);
2993 SSVAL(*rparam,4,desc.neededlen);
2995 SAFE_FREE(queue);
2996 SAFE_FREE(tmpdata);
2998 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
2999 return(True);
3002 static BOOL api_WPrintJobEnumerate(connection_struct *conn,uint16 vuid, char *param,char *data,
3003 int mdrcnt,int mprcnt,
3004 char **rdata,char **rparam,
3005 int *rdata_len,int *rparam_len)
3007 char *str1 = param+2;
3008 char *str2 = skip_string(str1,1);
3009 char *p = skip_string(str2,1);
3010 char* name = p;
3011 int uLevel;
3012 int count;
3013 int i, succnt=0;
3014 int snum;
3015 struct pack_desc desc;
3016 print_queue_struct *queue=NULL;
3017 print_status_struct status;
3019 memset((char *)&desc,'\0',sizeof(desc));
3020 memset((char *)&status,'\0',sizeof(status));
3022 p = skip_string(p,1);
3023 uLevel = SVAL(p,0);
3025 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
3027 /* check it's a supported variant */
3028 if (strcmp(str1,"zWrLeh") != 0) return False;
3029 if (uLevel > 2) return False; /* defined only for uLevel 0,1,2 */
3030 if (!check_printjob_info(&desc,uLevel,str2)) return False;
3032 snum = lp_servicenumber(name);
3033 if (snum < 0 && pcap_printername_ok(name,NULL)) {
3034 int pnum = lp_servicenumber(PRINTERS_NAME);
3035 if (pnum >= 0) {
3036 lp_add_printer(name,pnum);
3037 snum = lp_servicenumber(name);
3041 if (snum < 0 || !VALID_SNUM(snum)) return(False);
3043 count = print_queue_status(snum,&queue,&status);
3044 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3045 desc.base = *rdata;
3046 desc.buflen = mdrcnt;
3048 if (init_package(&desc,count,0)) {
3049 succnt = 0;
3050 for (i = 0; i < count; i++) {
3051 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
3052 if (desc.errcode == NERR_Success) succnt = i+1;
3056 *rdata_len = desc.usedlen;
3058 *rparam_len = 8;
3059 *rparam = REALLOC(*rparam,*rparam_len);
3060 SSVALS(*rparam,0,desc.errcode);
3061 SSVAL(*rparam,2,0);
3062 SSVAL(*rparam,4,succnt);
3063 SSVAL(*rparam,6,count);
3065 SAFE_FREE(queue);
3067 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
3068 return(True);
3071 static int check_printdest_info(struct pack_desc* desc,
3072 int uLevel, char* id)
3074 desc->subformat = NULL;
3075 switch( uLevel ) {
3076 case 0: desc->format = "B9"; break;
3077 case 1: desc->format = "B9B21WWzW"; break;
3078 case 2: desc->format = "z"; break;
3079 case 3: desc->format = "zzzWWzzzWW"; break;
3080 default: return False;
3082 if (strcmp(desc->format,id) != 0) return False;
3083 return True;
3086 static void fill_printdest_info(connection_struct *conn, int snum, int uLevel,
3087 struct pack_desc* desc)
3089 char buf[100];
3090 strncpy(buf,SERVICE(snum),sizeof(buf)-1);
3091 buf[sizeof(buf)-1] = 0;
3092 strupper_m(buf);
3093 if (uLevel <= 1) {
3094 PACKS(desc,"B9",buf); /* szName */
3095 if (uLevel == 1) {
3096 PACKS(desc,"B21",""); /* szUserName */
3097 PACKI(desc,"W",0); /* uJobId */
3098 PACKI(desc,"W",0); /* fsStatus */
3099 PACKS(desc,"z",""); /* pszStatus */
3100 PACKI(desc,"W",0); /* time */
3103 if (uLevel == 2 || uLevel == 3) {
3104 PACKS(desc,"z",buf); /* pszPrinterName */
3105 if (uLevel == 3) {
3106 PACKS(desc,"z",""); /* pszUserName */
3107 PACKS(desc,"z",""); /* pszLogAddr */
3108 PACKI(desc,"W",0); /* uJobId */
3109 PACKI(desc,"W",0); /* fsStatus */
3110 PACKS(desc,"z",""); /* pszStatus */
3111 PACKS(desc,"z",""); /* pszComment */
3112 PACKS(desc,"z","NULL"); /* pszDrivers */
3113 PACKI(desc,"W",0); /* time */
3114 PACKI(desc,"W",0); /* pad1 */
3119 static BOOL api_WPrintDestGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
3120 int mdrcnt,int mprcnt,
3121 char **rdata,char **rparam,
3122 int *rdata_len,int *rparam_len)
3124 char *str1 = param+2;
3125 char *str2 = skip_string(str1,1);
3126 char *p = skip_string(str2,1);
3127 char* PrinterName = p;
3128 int uLevel;
3129 struct pack_desc desc;
3130 int snum;
3131 char *tmpdata=NULL;
3133 memset((char *)&desc,'\0',sizeof(desc));
3135 p = skip_string(p,1);
3136 uLevel = SVAL(p,0);
3138 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
3140 /* check it's a supported varient */
3141 if (strcmp(str1,"zWrLh") != 0) return False;
3142 if (!check_printdest_info(&desc,uLevel,str2)) return False;
3144 snum = lp_servicenumber(PrinterName);
3145 if (snum < 0 && pcap_printername_ok(PrinterName,NULL)) {
3146 int pnum = lp_servicenumber(PRINTERS_NAME);
3147 if (pnum >= 0) {
3148 lp_add_printer(PrinterName,pnum);
3149 snum = lp_servicenumber(PrinterName);
3153 if (snum < 0) {
3154 *rdata_len = 0;
3155 desc.errcode = NERR_DestNotFound;
3156 desc.neededlen = 0;
3158 else {
3159 if (mdrcnt > 0) {
3160 *rdata = REALLOC(*rdata,mdrcnt);
3161 desc.base = *rdata;
3162 desc.buflen = mdrcnt;
3163 } else {
3165 * Don't return data but need to get correct length
3166 * init_package will return wrong size if buflen=0
3168 desc.buflen = getlen(desc.format);
3169 desc.base = tmpdata = (char *)malloc ( desc.buflen );
3171 if (init_package(&desc,1,0)) {
3172 fill_printdest_info(conn,snum,uLevel,&desc);
3174 *rdata_len = desc.usedlen;
3177 *rparam_len = 6;
3178 *rparam = REALLOC(*rparam,*rparam_len);
3179 SSVALS(*rparam,0,desc.errcode);
3180 SSVAL(*rparam,2,0);
3181 SSVAL(*rparam,4,desc.neededlen);
3183 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
3184 SAFE_FREE(tmpdata);
3185 return(True);
3188 static BOOL api_WPrintDestEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3189 int mdrcnt,int mprcnt,
3190 char **rdata,char **rparam,
3191 int *rdata_len,int *rparam_len)
3193 char *str1 = param+2;
3194 char *str2 = skip_string(str1,1);
3195 char *p = skip_string(str2,1);
3196 int uLevel;
3197 int queuecnt;
3198 int i, n, succnt=0;
3199 struct pack_desc desc;
3200 int services = lp_numservices();
3202 memset((char *)&desc,'\0',sizeof(desc));
3204 uLevel = SVAL(p,0);
3206 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
3208 /* check it's a supported varient */
3209 if (strcmp(str1,"WrLeh") != 0) return False;
3210 if (!check_printdest_info(&desc,uLevel,str2)) return False;
3212 queuecnt = 0;
3213 for (i = 0; i < services; i++)
3214 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
3215 queuecnt++;
3217 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3218 desc.base = *rdata;
3219 desc.buflen = mdrcnt;
3220 if (init_package(&desc,queuecnt,0)) {
3221 succnt = 0;
3222 n = 0;
3223 for (i = 0; i < services; i++) {
3224 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
3225 fill_printdest_info(conn,i,uLevel,&desc);
3226 n++;
3227 if (desc.errcode == NERR_Success) succnt = n;
3232 *rdata_len = desc.usedlen;
3234 *rparam_len = 8;
3235 *rparam = REALLOC(*rparam,*rparam_len);
3236 SSVALS(*rparam,0,desc.errcode);
3237 SSVAL(*rparam,2,0);
3238 SSVAL(*rparam,4,succnt);
3239 SSVAL(*rparam,6,queuecnt);
3241 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
3242 return(True);
3245 static BOOL api_WPrintDriverEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3246 int mdrcnt,int mprcnt,
3247 char **rdata,char **rparam,
3248 int *rdata_len,int *rparam_len)
3250 char *str1 = param+2;
3251 char *str2 = skip_string(str1,1);
3252 char *p = skip_string(str2,1);
3253 int uLevel;
3254 int succnt;
3255 struct pack_desc desc;
3257 memset((char *)&desc,'\0',sizeof(desc));
3259 uLevel = SVAL(p,0);
3261 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
3263 /* check it's a supported varient */
3264 if (strcmp(str1,"WrLeh") != 0) return False;
3265 if (uLevel != 0 || strcmp(str2,"B41") != 0) return False;
3267 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3268 desc.base = *rdata;
3269 desc.buflen = mdrcnt;
3270 if (init_package(&desc,1,0)) {
3271 PACKS(&desc,"B41","NULL");
3274 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3276 *rdata_len = desc.usedlen;
3278 *rparam_len = 8;
3279 *rparam = REALLOC(*rparam,*rparam_len);
3280 SSVALS(*rparam,0,desc.errcode);
3281 SSVAL(*rparam,2,0);
3282 SSVAL(*rparam,4,succnt);
3283 SSVAL(*rparam,6,1);
3285 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
3286 return(True);
3289 static BOOL api_WPrintQProcEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3290 int mdrcnt,int mprcnt,
3291 char **rdata,char **rparam,
3292 int *rdata_len,int *rparam_len)
3294 char *str1 = param+2;
3295 char *str2 = skip_string(str1,1);
3296 char *p = skip_string(str2,1);
3297 int uLevel;
3298 int succnt;
3299 struct pack_desc desc;
3301 memset((char *)&desc,'\0',sizeof(desc));
3303 uLevel = SVAL(p,0);
3305 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
3307 /* check it's a supported varient */
3308 if (strcmp(str1,"WrLeh") != 0) return False;
3309 if (uLevel != 0 || strcmp(str2,"B13") != 0) return False;
3311 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3312 desc.base = *rdata;
3313 desc.buflen = mdrcnt;
3314 desc.format = str2;
3315 if (init_package(&desc,1,0)) {
3316 PACKS(&desc,"B13","lpd");
3319 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3321 *rdata_len = desc.usedlen;
3323 *rparam_len = 8;
3324 *rparam = REALLOC(*rparam,*rparam_len);
3325 SSVALS(*rparam,0,desc.errcode);
3326 SSVAL(*rparam,2,0);
3327 SSVAL(*rparam,4,succnt);
3328 SSVAL(*rparam,6,1);
3330 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
3331 return(True);
3334 static BOOL api_WPrintPortEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3335 int mdrcnt,int mprcnt,
3336 char **rdata,char **rparam,
3337 int *rdata_len,int *rparam_len)
3339 char *str1 = param+2;
3340 char *str2 = skip_string(str1,1);
3341 char *p = skip_string(str2,1);
3342 int uLevel;
3343 int succnt;
3344 struct pack_desc desc;
3346 memset((char *)&desc,'\0',sizeof(desc));
3348 uLevel = SVAL(p,0);
3350 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
3352 /* check it's a supported varient */
3353 if (strcmp(str1,"WrLeh") != 0) return False;
3354 if (uLevel != 0 || strcmp(str2,"B9") != 0) return False;
3356 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3357 memset((char *)&desc,'\0',sizeof(desc));
3358 desc.base = *rdata;
3359 desc.buflen = mdrcnt;
3360 desc.format = str2;
3361 if (init_package(&desc,1,0)) {
3362 PACKS(&desc,"B13","lp0");
3365 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3367 *rdata_len = desc.usedlen;
3369 *rparam_len = 8;
3370 *rparam = REALLOC(*rparam,*rparam_len);
3371 SSVALS(*rparam,0,desc.errcode);
3372 SSVAL(*rparam,2,0);
3373 SSVAL(*rparam,4,succnt);
3374 SSVAL(*rparam,6,1);
3376 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
3377 return(True);
3381 /****************************************************************************
3382 List open sessions
3383 ****************************************************************************/
3384 static BOOL api_RNetSessionEnum(connection_struct *conn,uint16 vuid, char *param, char *data,
3385 int mdrcnt,int mprcnt,
3386 char **rdata,char **rparam,
3387 int *rdata_len,int *rparam_len)
3390 char *str1 = param+2;
3391 char *str2 = skip_string(str1,1);
3392 char *p = skip_string(str2,1);
3393 int uLevel;
3394 struct pack_desc desc;
3395 struct sessionid *session_list;
3396 int i, num_sessions;
3398 memset((char *)&desc,'\0',sizeof(desc));
3400 uLevel = SVAL(p,0);
3402 DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel));
3403 DEBUG(7,("RNetSessionEnum req string=%s\n",str1));
3404 DEBUG(7,("RNetSessionEnum ret string=%s\n",str2));
3406 /* check it's a supported varient */
3407 if (strcmp(str1,RAP_NetSessionEnum_REQ) != 0) return False;
3408 if (uLevel != 2 || strcmp(str2,RAP_SESSION_INFO_L2) != 0) return False;
3410 num_sessions = list_sessions(&session_list);
3412 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3413 memset((char *)&desc,'\0',sizeof(desc));
3414 desc.base = *rdata;
3415 desc.buflen = mdrcnt;
3416 desc.format = str2;
3417 if (!init_package(&desc,num_sessions,0)) {
3418 return False;
3421 for(i=0; i<num_sessions; i++) {
3422 PACKS(&desc, "z", session_list[i].remote_machine);
3423 PACKS(&desc, "z", session_list[i].username);
3424 PACKI(&desc, "W", 1); /* num conns */
3425 PACKI(&desc, "W", 0); /* num opens */
3426 PACKI(&desc, "W", 1); /* num users */
3427 PACKI(&desc, "D", 0); /* session time */
3428 PACKI(&desc, "D", 0); /* idle time */
3429 PACKI(&desc, "D", 0); /* flags */
3430 PACKS(&desc, "z", "Unknown Client"); /* client type string */
3433 *rdata_len = desc.usedlen;
3435 *rparam_len = 8;
3436 *rparam = REALLOC(*rparam,*rparam_len);
3437 SSVALS(*rparam,0,desc.errcode);
3438 SSVAL(*rparam,2,0); /* converter */
3439 SSVAL(*rparam,4,num_sessions); /* count */
3441 DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc.errcode));
3442 return True;
3446 /****************************************************************************
3447 The buffer was too small
3448 ****************************************************************************/
3450 static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param,char *data,
3451 int mdrcnt,int mprcnt,
3452 char **rdata,char **rparam,
3453 int *rdata_len,int *rparam_len)
3455 *rparam_len = MIN(*rparam_len,mprcnt);
3456 *rparam = REALLOC(*rparam,*rparam_len);
3458 *rdata_len = 0;
3460 SSVAL(*rparam,0,NERR_BufTooSmall);
3462 DEBUG(3,("Supplied buffer too small in API command\n"));
3464 return(True);
3468 /****************************************************************************
3469 The request is not supported
3470 ****************************************************************************/
3472 static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param,char *data,
3473 int mdrcnt,int mprcnt,
3474 char **rdata,char **rparam,
3475 int *rdata_len,int *rparam_len)
3477 *rparam_len = 4;
3478 *rparam = REALLOC(*rparam,*rparam_len);
3480 *rdata_len = 0;
3482 SSVAL(*rparam,0,NERR_notsupported);
3483 SSVAL(*rparam,2,0); /* converter word */
3485 DEBUG(3,("Unsupported API command\n"));
3487 return(True);
3493 static const struct
3495 const char *name;
3496 int id;
3497 BOOL (*fn)(connection_struct *,uint16,char *,char *,
3498 int,int,char **,char **,int *,int *);
3499 BOOL auth_user; /* Deny anonymous access? */
3500 } api_commands[] = {
3501 {"RNetShareEnum", RAP_WshareEnum, api_RNetShareEnum, True},
3502 {"RNetShareGetInfo", RAP_WshareGetInfo, api_RNetShareGetInfo},
3503 {"RNetShareAdd", RAP_WshareAdd, api_RNetShareAdd},
3504 {"RNetSessionEnum", RAP_WsessionEnum, api_RNetSessionEnum, True},
3505 {"RNetServerGetInfo", RAP_WserverGetInfo, api_RNetServerGetInfo},
3506 {"RNetGroupEnum", RAP_WGroupEnum, api_RNetGroupEnum, True},
3507 {"RNetGroupGetUsers", RAP_WGroupGetUsers, api_RNetGroupGetUsers, True},
3508 {"RNetUserEnum", RAP_WUserEnum, api_RNetUserEnum, True},
3509 {"RNetUserGetInfo", RAP_WUserGetInfo, api_RNetUserGetInfo},
3510 {"NetUserGetGroups", RAP_WUserGetGroups, api_NetUserGetGroups},
3511 {"NetWkstaGetInfo", RAP_WWkstaGetInfo, api_NetWkstaGetInfo},
3512 {"DosPrintQEnum", RAP_WPrintQEnum, api_DosPrintQEnum, True},
3513 {"DosPrintQGetInfo", RAP_WPrintQGetInfo, api_DosPrintQGetInfo},
3514 {"WPrintQueuePause", RAP_WPrintQPause, api_WPrintQueueCtrl},
3515 {"WPrintQueueResume", RAP_WPrintQContinue, api_WPrintQueueCtrl},
3516 {"WPrintJobEnumerate",RAP_WPrintJobEnum, api_WPrintJobEnumerate},
3517 {"WPrintJobGetInfo", RAP_WPrintJobGetInfo, api_WPrintJobGetInfo},
3518 {"RDosPrintJobDel", RAP_WPrintJobDel, api_RDosPrintJobDel},
3519 {"RDosPrintJobPause", RAP_WPrintJobPause, api_RDosPrintJobDel},
3520 {"RDosPrintJobResume",RAP_WPrintJobContinue, api_RDosPrintJobDel},
3521 {"WPrintDestEnum", RAP_WPrintDestEnum, api_WPrintDestEnum},
3522 {"WPrintDestGetInfo", RAP_WPrintDestGetInfo, api_WPrintDestGetInfo},
3523 {"NetRemoteTOD", RAP_NetRemoteTOD, api_NetRemoteTOD},
3524 {"WPrintQueuePurge", RAP_WPrintQPurge, api_WPrintQueueCtrl},
3525 {"NetServerEnum", RAP_NetServerEnum2, api_RNetServerEnum}, /* anon OK */
3526 {"WAccessGetUserPerms",RAP_WAccessGetUserPerms,api_WAccessGetUserPerms},
3527 {"SetUserPassword", RAP_WUserPasswordSet2, api_SetUserPassword},
3528 {"WWkstaUserLogon", RAP_WWkstaUserLogon, api_WWkstaUserLogon},
3529 {"PrintJobInfo", RAP_WPrintJobSetInfo, api_PrintJobInfo},
3530 {"WPrintDriverEnum", RAP_WPrintDriverEnum, api_WPrintDriverEnum},
3531 {"WPrintQProcEnum", RAP_WPrintQProcessorEnum,api_WPrintQProcEnum},
3532 {"WPrintPortEnum", RAP_WPrintPortEnum, api_WPrintPortEnum},
3533 {"SamOEMChangePassword",RAP_SamOEMChgPasswordUser2_P,api_SamOEMChangePassword}, /* anon OK */
3534 {NULL, -1, api_Unsupported}};
3536 /* The following RAP calls are not implemented by Samba:
3538 RAP_WFileEnum2 - anon not OK
3541 /****************************************************************************
3542 Handle remote api calls
3543 ****************************************************************************/
3545 int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data,char *params,
3546 int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
3548 int api_command;
3549 char *rdata = NULL;
3550 char *rparam = NULL;
3551 int rdata_len = 0;
3552 int rparam_len = 0;
3553 BOOL reply=False;
3554 int i;
3556 if (!params) {
3557 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
3558 return 0;
3561 api_command = SVAL(params,0);
3563 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
3564 api_command,
3565 params+2,
3566 skip_string(params+2,1),
3567 tdscnt,tpscnt,mdrcnt,mprcnt));
3569 for (i=0;api_commands[i].name;i++) {
3570 if (api_commands[i].id == api_command && api_commands[i].fn) {
3571 DEBUG(3,("Doing %s\n",api_commands[i].name));
3572 break;
3576 /* Check whether this api call can be done anonymously */
3578 if (api_commands[i].auth_user && lp_restrict_anonymous()) {
3579 user_struct *user = get_valid_user_struct(vuid);
3581 if (!user || user->guest)
3582 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
3585 rdata = (char *)malloc(1024);
3586 if (rdata)
3587 memset(rdata,'\0',1024);
3589 rparam = (char *)malloc(1024);
3590 if (rparam)
3591 memset(rparam,'\0',1024);
3593 if(!rdata || !rparam) {
3594 DEBUG(0,("api_reply: malloc fail !\n"));
3595 return -1;
3598 reply = api_commands[i].fn(conn,vuid,params,data,mdrcnt,mprcnt,
3599 &rdata,&rparam,&rdata_len,&rparam_len);
3602 if (rdata_len > mdrcnt ||
3603 rparam_len > mprcnt) {
3604 reply = api_TooSmall(conn,vuid,params,data,mdrcnt,mprcnt,
3605 &rdata,&rparam,&rdata_len,&rparam_len);
3608 /* if we get False back then it's actually unsupported */
3609 if (!reply)
3610 api_Unsupported(conn,vuid,params,data,mdrcnt,mprcnt,
3611 &rdata,&rparam,&rdata_len,&rparam_len);
3613 send_trans_reply(outbuf, rparam, rparam_len, rdata, rdata_len, False);
3615 SAFE_FREE(rdata);
3616 SAFE_FREE(rparam);
3618 return -1;