r3220: merging current 3.0 code to release branch
[Samba.git] / source / smbd / lanman.c
blob610ee451201e9fda2e38cd66b2e42f6465497a96
1 /*
2 Unix SMB/CIFS implementation.
3 Inter-process communication and named pipe handling
4 Copyright (C) Andrew Tridgell 1992-1998
6 SMB Version handling
7 Copyright (C) John H Terpstra 1995-1998
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 This file handles the named pipe and mailslot calls
25 in the SMBtrans protocol
28 #include "includes.h"
30 #ifdef CHECK_TYPES
31 #undef CHECK_TYPES
32 #endif
33 #define CHECK_TYPES 0
35 extern fstring local_machine;
37 #define NERR_Success 0
38 #define NERR_badpass 86
39 #define NERR_notsupported 50
41 #define NERR_BASE (2100)
42 #define NERR_BufTooSmall (NERR_BASE+23)
43 #define NERR_JobNotFound (NERR_BASE+51)
44 #define NERR_DestNotFound (NERR_BASE+52)
46 #define ACCESS_READ 0x01
47 #define ACCESS_WRITE 0x02
48 #define ACCESS_CREATE 0x04
50 #define SHPWLEN 8 /* share password length */
52 static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param,char *data,
53 int mdrcnt,int mprcnt,
54 char **rdata,char **rparam,
55 int *rdata_len,int *rparam_len);
56 static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param,char *data,
57 int mdrcnt,int mprcnt,
58 char **rdata,char **rparam,
59 int *rdata_len,int *rparam_len);
62 static int CopyExpanded(connection_struct *conn,
63 int snum, char** dst, char* src, int* n)
65 pstring buf;
66 int l;
68 if (!src || !dst || !n || !(*dst)) return(0);
70 StrnCpy(buf,src,sizeof(buf)/2);
71 pstring_sub(buf,"%S",lp_servicename(snum));
72 standard_sub_conn(conn,buf,sizeof(buf));
73 l = push_ascii(*dst,buf,*n, STR_TERMINATE);
74 (*dst) += l;
75 (*n) -= l;
76 return l;
79 static int CopyAndAdvance(char** dst, char* src, int* n)
81 int l;
82 if (!src || !dst || !n || !(*dst)) return(0);
83 l = push_ascii(*dst,src,*n, STR_TERMINATE);
84 (*dst) += l;
85 (*n) -= l;
86 return l;
89 static int StrlenExpanded(connection_struct *conn, int snum, char* s)
91 pstring buf;
92 if (!s) return(0);
93 StrnCpy(buf,s,sizeof(buf)/2);
94 pstring_sub(buf,"%S",lp_servicename(snum));
95 standard_sub_conn(conn,buf,sizeof(buf));
96 return strlen(buf) + 1;
99 static char* Expand(connection_struct *conn, int snum, char* s)
101 static pstring buf;
102 if (!s) return(NULL);
103 StrnCpy(buf,s,sizeof(buf)/2);
104 pstring_sub(buf,"%S",lp_servicename(snum));
105 standard_sub_conn(conn,buf,sizeof(buf));
106 return &buf[0];
109 /*******************************************************************
110 check a API string for validity when we only need to check the prefix
111 ******************************************************************/
112 static BOOL prefix_ok(const char *str, const char *prefix)
114 return(strncmp(str,prefix,strlen(prefix)) == 0);
117 struct pack_desc {
118 const char* format; /* formatstring for structure */
119 const char* subformat; /* subformat for structure */
120 char* base; /* baseaddress of buffer */
121 int buflen; /* remaining size for fixed part; on init: length of base */
122 int subcount; /* count of substructures */
123 char* structbuf; /* pointer into buffer for remaining fixed part */
124 int stringlen; /* remaining size for variable part */
125 char* stringbuf; /* pointer into buffer for remaining variable part */
126 int neededlen; /* total needed size */
127 int usedlen; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
128 const char* curpos; /* current position; pointer into format or subformat */
129 int errcode;
132 static int get_counter(const char** p)
134 int i, n;
135 if (!p || !(*p)) return(1);
136 if (!isdigit((int)**p)) return 1;
137 for (n = 0;;) {
138 i = **p;
139 if (isdigit(i))
140 n = 10 * n + (i - '0');
141 else
142 return n;
143 (*p)++;
147 static int getlen(const char* p)
149 int n = 0;
150 if (!p) return(0);
151 while (*p) {
152 switch( *p++ ) {
153 case 'W': /* word (2 byte) */
154 n += 2;
155 break;
156 case 'K': /* status word? (2 byte) */
157 n += 2;
158 break;
159 case 'N': /* count of substructures (word) at end */
160 n += 2;
161 break;
162 case 'D': /* double word (4 byte) */
163 case 'z': /* offset to zero terminated string (4 byte) */
164 case 'l': /* offset to user data (4 byte) */
165 n += 4;
166 break;
167 case 'b': /* offset to data (with counter) (4 byte) */
168 n += 4;
169 get_counter(&p);
170 break;
171 case 'B': /* byte (with optional counter) */
172 n += get_counter(&p);
173 break;
176 return n;
179 static BOOL init_package(struct pack_desc* p, int count, int subcount)
181 int n = p->buflen;
182 int i;
184 if (!p->format || !p->base) return(False);
186 i = count * getlen(p->format);
187 if (p->subformat) i += subcount * getlen(p->subformat);
188 p->structbuf = p->base;
189 p->neededlen = 0;
190 p->usedlen = 0;
191 p->subcount = 0;
192 p->curpos = p->format;
193 if (i > n) {
194 p->neededlen = i;
195 i = n = 0;
196 #if 0
198 * This is the old error code we used. Aparently
199 * WinNT/2k systems return ERRbuftoosmall (2123) and
200 * OS/2 needs this. I'm leaving this here so we can revert
201 * if needed. JRA.
203 p->errcode = ERRmoredata;
204 #else
205 p->errcode = ERRbuftoosmall;
206 #endif
208 else
209 p->errcode = NERR_Success;
210 p->buflen = i;
211 n -= i;
212 p->stringbuf = p->base + i;
213 p->stringlen = n;
214 return(p->errcode == NERR_Success);
217 static int package(struct pack_desc* p, ...)
219 va_list args;
220 int needed=0, stringneeded;
221 const char* str=NULL;
222 int is_string=0, stringused;
223 int32 temp;
225 va_start(args,p);
227 if (!*p->curpos) {
228 if (!p->subcount)
229 p->curpos = p->format;
230 else {
231 p->curpos = p->subformat;
232 p->subcount--;
235 #if CHECK_TYPES
236 str = va_arg(args,char*);
237 SMB_ASSERT(strncmp(str,p->curpos,strlen(str)) == 0);
238 #endif
239 stringneeded = -1;
241 if (!p->curpos) {
242 va_end(args);
243 return(0);
246 switch( *p->curpos++ ) {
247 case 'W': /* word (2 byte) */
248 needed = 2;
249 temp = va_arg(args,int);
250 if (p->buflen >= needed) SSVAL(p->structbuf,0,temp);
251 break;
252 case 'K': /* status word? (2 byte) */
253 needed = 2;
254 temp = va_arg(args,int);
255 if (p->buflen >= needed) SSVAL(p->structbuf,0,temp);
256 break;
257 case 'N': /* count of substructures (word) at end */
258 needed = 2;
259 p->subcount = va_arg(args,int);
260 if (p->buflen >= needed) SSVAL(p->structbuf,0,p->subcount);
261 break;
262 case 'D': /* double word (4 byte) */
263 needed = 4;
264 temp = va_arg(args,int);
265 if (p->buflen >= needed) SIVAL(p->structbuf,0,temp);
266 break;
267 case 'B': /* byte (with optional counter) */
268 needed = get_counter(&p->curpos);
270 char *s = va_arg(args,char*);
271 if (p->buflen >= needed) StrnCpy(p->structbuf,s?s:"",needed-1);
273 break;
274 case 'z': /* offset to zero terminated string (4 byte) */
275 str = va_arg(args,char*);
276 stringneeded = (str ? strlen(str)+1 : 0);
277 is_string = 1;
278 break;
279 case 'l': /* offset to user data (4 byte) */
280 str = va_arg(args,char*);
281 stringneeded = va_arg(args,int);
282 is_string = 0;
283 break;
284 case 'b': /* offset to data (with counter) (4 byte) */
285 str = va_arg(args,char*);
286 stringneeded = get_counter(&p->curpos);
287 is_string = 0;
288 break;
290 va_end(args);
291 if (stringneeded >= 0) {
292 needed = 4;
293 if (p->buflen >= needed) {
294 stringused = stringneeded;
295 if (stringused > p->stringlen) {
296 stringused = (is_string ? p->stringlen : 0);
297 if (p->errcode == NERR_Success) p->errcode = ERRmoredata;
299 if (!stringused)
300 SIVAL(p->structbuf,0,0);
301 else {
302 SIVAL(p->structbuf,0,PTR_DIFF(p->stringbuf,p->base));
303 memcpy(p->stringbuf,str?str:"",stringused);
304 if (is_string) p->stringbuf[stringused-1] = '\0';
305 p->stringbuf += stringused;
306 p->stringlen -= stringused;
307 p->usedlen += stringused;
310 p->neededlen += stringneeded;
312 p->neededlen += needed;
313 if (p->buflen >= needed) {
314 p->structbuf += needed;
315 p->buflen -= needed;
316 p->usedlen += needed;
318 else {
319 if (p->errcode == NERR_Success) p->errcode = ERRmoredata;
321 return 1;
324 #if CHECK_TYPES
325 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
326 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
327 #else
328 #define PACK(desc,t,v) package(desc,v)
329 #define PACKl(desc,t,v,l) package(desc,v,l)
330 #endif
332 static void PACKI(struct pack_desc* desc, const char *t,int v)
334 PACK(desc,t,v);
337 static void PACKS(struct pack_desc* desc,const char *t,const char *v)
339 PACK(desc,t,v);
343 /****************************************************************************
344 get a print queue
345 ****************************************************************************/
346 static void PackDriverData(struct pack_desc* desc)
348 char drivdata[4+4+32];
349 SIVAL(drivdata,0,sizeof drivdata); /* cb */
350 SIVAL(drivdata,4,1000); /* lVersion */
351 memset(drivdata+8,0,32); /* szDeviceName */
352 push_ascii(drivdata+8,"NULL",-1, STR_TERMINATE);
353 PACKl(desc,"l",drivdata,sizeof drivdata); /* pDriverData */
356 static int check_printq_info(struct pack_desc* desc,
357 int uLevel, char *id1, char *id2)
359 desc->subformat = NULL;
360 switch( uLevel ) {
361 case 0:
362 desc->format = "B13";
363 break;
364 case 1:
365 desc->format = "B13BWWWzzzzzWW";
366 break;
367 case 2:
368 desc->format = "B13BWWWzzzzzWN";
369 desc->subformat = "WB21BB16B10zWWzDDz";
370 break;
371 case 3:
372 desc->format = "zWWWWzzzzWWzzl";
373 break;
374 case 4:
375 desc->format = "zWWWWzzzzWNzzl";
376 desc->subformat = "WWzWWDDzz";
377 break;
378 case 5:
379 desc->format = "z";
380 break;
381 case 51:
382 desc->format = "K";
383 break;
384 case 52:
385 desc->format = "WzzzzzzzzN";
386 desc->subformat = "z";
387 break;
388 default: return False;
390 if (strcmp(desc->format,id1) != 0) return False;
391 if (desc->subformat && strcmp(desc->subformat,id2) != 0) return False;
392 return True;
396 #define RAP_JOB_STATUS_QUEUED 0
397 #define RAP_JOB_STATUS_PAUSED 1
398 #define RAP_JOB_STATUS_SPOOLING 2
399 #define RAP_JOB_STATUS_PRINTING 3
400 #define RAP_JOB_STATUS_PRINTED 4
402 #define RAP_QUEUE_STATUS_PAUSED 1
403 #define RAP_QUEUE_STATUS_ERROR 2
405 /* turn a print job status into a on the wire status
407 static int printj_status(int v)
409 switch (v) {
410 case LPQ_QUEUED:
411 return RAP_JOB_STATUS_QUEUED;
412 case LPQ_PAUSED:
413 return RAP_JOB_STATUS_PAUSED;
414 case LPQ_SPOOLING:
415 return RAP_JOB_STATUS_SPOOLING;
416 case LPQ_PRINTING:
417 return RAP_JOB_STATUS_PRINTING;
419 return 0;
422 /* turn a print queue status into a on the wire status
424 static int printq_status(int v)
426 switch (v) {
427 case LPQ_QUEUED:
428 return 0;
429 case LPQ_PAUSED:
430 return RAP_QUEUE_STATUS_PAUSED;
432 return RAP_QUEUE_STATUS_ERROR;
435 static void fill_printjob_info(connection_struct *conn, int snum, int uLevel,
436 struct pack_desc* desc,
437 print_queue_struct* queue, int n)
439 time_t t = queue->time;
441 /* the client expects localtime */
442 t -= TimeDiff(t);
444 PACKI(desc,"W",pjobid_to_rap(lp_const_servicename(snum),queue->job)); /* uJobId */
445 if (uLevel == 1) {
446 PACKS(desc,"B21",queue->fs_user); /* szUserName */
447 PACKS(desc,"B",""); /* pad */
448 PACKS(desc,"B16",""); /* szNotifyName */
449 PACKS(desc,"B10","PM_Q_RAW"); /* szDataType */
450 PACKS(desc,"z",""); /* pszParms */
451 PACKI(desc,"W",n+1); /* uPosition */
452 PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */
453 PACKS(desc,"z",""); /* pszStatus */
454 PACKI(desc,"D",t); /* ulSubmitted */
455 PACKI(desc,"D",queue->size); /* ulSize */
456 PACKS(desc,"z",queue->fs_file); /* pszComment */
458 if (uLevel == 2 || uLevel == 3 || uLevel == 4) {
459 PACKI(desc,"W",queue->priority); /* uPriority */
460 PACKS(desc,"z",queue->fs_user); /* pszUserName */
461 PACKI(desc,"W",n+1); /* uPosition */
462 PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */
463 PACKI(desc,"D",t); /* ulSubmitted */
464 PACKI(desc,"D",queue->size); /* ulSize */
465 PACKS(desc,"z","Samba"); /* pszComment */
466 PACKS(desc,"z",queue->fs_file); /* pszDocument */
467 if (uLevel == 3) {
468 PACKS(desc,"z",""); /* pszNotifyName */
469 PACKS(desc,"z","PM_Q_RAW"); /* pszDataType */
470 PACKS(desc,"z",""); /* pszParms */
471 PACKS(desc,"z",""); /* pszStatus */
472 PACKS(desc,"z",SERVICE(snum)); /* pszQueue */
473 PACKS(desc,"z","lpd"); /* pszQProcName */
474 PACKS(desc,"z",""); /* pszQProcParms */
475 PACKS(desc,"z","NULL"); /* pszDriverName */
476 PackDriverData(desc); /* pDriverData */
477 PACKS(desc,"z",""); /* pszPrinterName */
478 } else if (uLevel == 4) { /* OS2 */
479 PACKS(desc,"z",""); /* pszSpoolFileName */
480 PACKS(desc,"z",""); /* pszPortName */
481 PACKS(desc,"z",""); /* pszStatus */
482 PACKI(desc,"D",0); /* ulPagesSpooled */
483 PACKI(desc,"D",0); /* ulPagesSent */
484 PACKI(desc,"D",0); /* ulPagesPrinted */
485 PACKI(desc,"D",0); /* ulTimePrinted */
486 PACKI(desc,"D",0); /* ulExtendJobStatus */
487 PACKI(desc,"D",0); /* ulStartPage */
488 PACKI(desc,"D",0); /* ulEndPage */
493 /********************************************************************
494 Return a driver name given an snum.
495 Returns True if from tdb, False otherwise.
496 ********************************************************************/
498 static BOOL get_driver_name(int snum, pstring drivername)
500 NT_PRINTER_INFO_LEVEL *info = NULL;
501 BOOL in_tdb = False;
503 get_a_printer (NULL, &info, 2, lp_servicename(snum));
504 if (info != NULL) {
505 pstrcpy( drivername, info->info_2->drivername);
506 in_tdb = True;
507 free_a_printer(&info, 2);
510 return in_tdb;
513 /********************************************************************
514 Respond to the DosPrintQInfo command with a level of 52
515 This is used to get printer driver information for Win9x clients
516 ********************************************************************/
517 static void fill_printq_info_52(connection_struct *conn, int snum,
518 struct pack_desc* desc, int count )
520 int i;
521 fstring location;
522 NT_PRINTER_DRIVER_INFO_LEVEL driver;
523 NT_PRINTER_INFO_LEVEL *printer = NULL;
525 ZERO_STRUCT(driver);
527 if ( !W_ERROR_IS_OK(get_a_printer( NULL, &printer, 2, lp_servicename(snum))) ) {
528 DEBUG(3,("fill_printq_info_52: Failed to lookup printer [%s]\n",
529 lp_servicename(snum)));
530 goto err;
533 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername,
534 "Windows 4.0", 0)) )
536 DEBUG(3,("fill_printq_info_52: Failed to lookup driver [%s]\n",
537 printer->info_2->drivername));
538 goto err;
541 trim_string(driver.info_3->driverpath, "\\print$\\WIN40\\0\\", 0);
542 trim_string(driver.info_3->datafile, "\\print$\\WIN40\\0\\", 0);
543 trim_string(driver.info_3->helpfile, "\\print$\\WIN40\\0\\", 0);
545 PACKI(desc, "W", 0x0400); /* don't know */
546 PACKS(desc, "z", driver.info_3->name); /* long printer name */
547 PACKS(desc, "z", driver.info_3->driverpath); /* Driverfile Name */
548 PACKS(desc, "z", driver.info_3->datafile); /* Datafile name */
549 PACKS(desc, "z", driver.info_3->monitorname); /* language monitor */
551 fstrcpy(location, "\\\\%L\\print$\\WIN40\\0");
552 standard_sub_basic( "", location, sizeof(location)-1 );
553 PACKS(desc,"z", location); /* share to retrieve files */
555 PACKS(desc,"z", driver.info_3->defaultdatatype); /* default data type */
556 PACKS(desc,"z", driver.info_3->helpfile); /* helpfile name */
557 PACKS(desc,"z", driver.info_3->driverpath); /* driver name */
559 DEBUG(3,("Printer Driver Name: %s:\n",driver.info_3->name));
560 DEBUG(3,("Driver: %s:\n",driver.info_3->driverpath));
561 DEBUG(3,("Data File: %s:\n",driver.info_3->datafile));
562 DEBUG(3,("Language Monitor: %s:\n",driver.info_3->monitorname));
563 DEBUG(3,("Driver Location: %s:\n",location));
564 DEBUG(3,("Data Type: %s:\n",driver.info_3->defaultdatatype));
565 DEBUG(3,("Help File: %s:\n",driver.info_3->helpfile));
566 PACKI(desc,"N",count); /* number of files to copy */
568 for ( i=0; i<count && driver.info_3->dependentfiles && *driver.info_3->dependentfiles[i]; i++)
570 trim_string(driver.info_3->dependentfiles[i], "\\print$\\WIN40\\0\\", 0);
571 PACKS(desc,"z",driver.info_3->dependentfiles[i]); /* driver files to copy */
572 DEBUG(3,("Dependent File: %s:\n",driver.info_3->dependentfiles[i]));
575 /* sanity check */
576 if ( i != count )
577 DEBUG(3,("fill_printq_info_52: file count specified by client [%d] != number of dependent files [%i]\n",
578 count, i));
580 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n", SERVICE(snum),i));
582 desc->errcode=NERR_Success;
583 goto done;
585 err:
586 DEBUG(3,("fill_printq_info: Can't supply driver files\n"));
587 desc->errcode=NERR_notsupported;
589 done:
590 if ( printer )
591 free_a_printer( &printer, 2 );
593 if ( driver.info_3 )
594 free_a_printer_driver( driver, 3 );
598 static void fill_printq_info(connection_struct *conn, int snum, int uLevel,
599 struct pack_desc* desc,
600 int count, print_queue_struct* queue,
601 print_status_struct* status)
603 switch (uLevel) {
604 case 1:
605 case 2:
606 PACKS(desc,"B13",SERVICE(snum));
607 break;
608 case 3:
609 case 4:
610 case 5:
611 PACKS(desc,"z",Expand(conn,snum,SERVICE(snum)));
612 break;
613 case 51:
614 PACKI(desc,"K",printq_status(status->status));
615 break;
618 if (uLevel == 1 || uLevel == 2) {
619 PACKS(desc,"B",""); /* alignment */
620 PACKI(desc,"W",5); /* priority */
621 PACKI(desc,"W",0); /* start time */
622 PACKI(desc,"W",0); /* until time */
623 PACKS(desc,"z",""); /* pSepFile */
624 PACKS(desc,"z","lpd"); /* pPrProc */
625 PACKS(desc,"z",SERVICE(snum)); /* pDestinations */
626 PACKS(desc,"z",""); /* pParms */
627 if (snum < 0) {
628 PACKS(desc,"z","UNKNOWN PRINTER");
629 PACKI(desc,"W",LPSTAT_ERROR);
631 else if (!status || !status->message[0]) {
632 PACKS(desc,"z",Expand(conn,snum,lp_comment(snum)));
633 PACKI(desc,"W",LPSTAT_OK); /* status */
634 } else {
635 PACKS(desc,"z",status->message);
636 PACKI(desc,"W",printq_status(status->status)); /* status */
638 PACKI(desc,(uLevel == 1 ? "W" : "N"),count);
641 if (uLevel == 3 || uLevel == 4) {
642 pstring drivername;
644 PACKI(desc,"W",5); /* uPriority */
645 PACKI(desc,"W",0); /* uStarttime */
646 PACKI(desc,"W",0); /* uUntiltime */
647 PACKI(desc,"W",5); /* pad1 */
648 PACKS(desc,"z",""); /* pszSepFile */
649 PACKS(desc,"z","WinPrint"); /* pszPrProc */
650 PACKS(desc,"z",NULL); /* pszParms */
651 PACKS(desc,"z",NULL); /* pszComment - don't ask.... JRA */
652 /* "don't ask" that it's done this way to fix corrupted
653 Win9X/ME printer comments. */
654 if (!status) {
655 PACKI(desc,"W",LPSTAT_OK); /* fsStatus */
656 } else {
657 PACKI(desc,"W",printq_status(status->status)); /* fsStatus */
659 PACKI(desc,(uLevel == 3 ? "W" : "N"),count); /* cJobs */
660 PACKS(desc,"z",SERVICE(snum)); /* pszPrinters */
661 get_driver_name(snum,drivername);
662 PACKS(desc,"z",drivername); /* pszDriverName */
663 PackDriverData(desc); /* pDriverData */
666 if (uLevel == 2 || uLevel == 4) {
667 int i;
668 for (i=0;i<count;i++)
669 fill_printjob_info(conn,snum,uLevel == 2 ? 1 : 2,desc,&queue[i],i);
672 if (uLevel==52)
673 fill_printq_info_52( conn, snum, desc, count );
676 /* This function returns the number of files for a given driver */
677 static int get_printerdrivernumber(int snum)
679 int result = 0;
680 NT_PRINTER_DRIVER_INFO_LEVEL driver;
681 NT_PRINTER_INFO_LEVEL *printer = NULL;
683 ZERO_STRUCT(driver);
685 if ( !W_ERROR_IS_OK(get_a_printer( NULL, &printer, 2, lp_servicename(snum))) ) {
686 DEBUG(3,("get_printerdrivernumber: Failed to lookup printer [%s]\n",
687 lp_servicename(snum)));
688 goto done;
691 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername,
692 "Windows 4.0", 0)) )
694 DEBUG(3,("get_printerdrivernumber: Failed to lookup driver [%s]\n",
695 printer->info_2->drivername));
696 goto done;
699 /* count the number of files */
700 while ( driver.info_3->dependentfiles && *driver.info_3->dependentfiles[result] )
701 result++;
703 done:
704 if ( printer )
705 free_a_printer( &printer, 2 );
707 if ( driver.info_3 )
708 free_a_printer_driver( driver, 3 );
710 return result;
713 static BOOL api_DosPrintQGetInfo(connection_struct *conn,
714 uint16 vuid, char *param,char *data,
715 int mdrcnt,int mprcnt,
716 char **rdata,char **rparam,
717 int *rdata_len,int *rparam_len)
719 char *str1 = param+2;
720 char *str2 = skip_string(str1,1);
721 char *p = skip_string(str2,1);
722 char *QueueName = p;
723 int uLevel;
724 int count=0;
725 int snum;
726 char* str3;
727 struct pack_desc desc;
728 print_queue_struct *queue=NULL;
729 print_status_struct status;
730 char* tmpdata=NULL;
732 memset((char *)&status,'\0',sizeof(status));
733 memset((char *)&desc,'\0',sizeof(desc));
735 p = skip_string(p,1);
736 uLevel = SVAL(p,0);
737 str3 = p + 4;
739 /* remove any trailing username */
740 if ((p = strchr_m(QueueName,'%')))
741 *p = 0;
743 DEBUG(3,("api_DosPrintQGetInfo uLevel=%d name=%s\n",uLevel,QueueName));
745 /* check it's a supported varient */
746 if (!prefix_ok(str1,"zWrLh"))
747 return False;
748 if (!check_printq_info(&desc,uLevel,str2,str3)) {
750 * Patch from Scott Moomaw <scott@bridgewater.edu>
751 * to return the 'invalid info level' error if an
752 * unknown level was requested.
754 *rdata_len = 0;
755 *rparam_len = 6;
756 *rparam = REALLOC(*rparam,*rparam_len);
757 SSVALS(*rparam,0,ERRunknownlevel);
758 SSVAL(*rparam,2,0);
759 SSVAL(*rparam,4,0);
760 return(True);
763 snum = lp_servicenumber(QueueName);
764 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
765 int pnum = lp_servicenumber(PRINTERS_NAME);
766 if (pnum >= 0) {
767 lp_add_printer(QueueName,pnum);
768 snum = lp_servicenumber(QueueName);
772 if (snum < 0 || !VALID_SNUM(snum))
773 return(False);
775 if (uLevel==52) {
776 count = get_printerdrivernumber(snum);
777 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count));
778 } else {
779 count = print_queue_status(snum, &queue,&status);
782 if (mdrcnt > 0) {
783 *rdata = REALLOC(*rdata,mdrcnt);
784 desc.base = *rdata;
785 desc.buflen = mdrcnt;
786 } else {
788 * Don't return data but need to get correct length
789 * init_package will return wrong size if buflen=0
791 desc.buflen = getlen(desc.format);
792 desc.base = tmpdata = (char *) malloc (desc.buflen);
795 if (init_package(&desc,1,count)) {
796 desc.subcount = count;
797 fill_printq_info(conn,snum,uLevel,&desc,count,queue,&status);
800 *rdata_len = desc.usedlen;
803 * We must set the return code to ERRbuftoosmall
804 * in order to support lanman style printing with Win NT/2k
805 * clients --jerry
807 if (!mdrcnt && lp_disable_spoolss())
808 desc.errcode = ERRbuftoosmall;
810 *rdata_len = desc.usedlen;
811 *rparam_len = 6;
812 *rparam = REALLOC(*rparam,*rparam_len);
813 SSVALS(*rparam,0,desc.errcode);
814 SSVAL(*rparam,2,0);
815 SSVAL(*rparam,4,desc.neededlen);
817 DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode));
819 SAFE_FREE(queue);
820 SAFE_FREE(tmpdata);
822 return(True);
825 /****************************************************************************
826 View list of all print jobs on all queues.
827 ****************************************************************************/
829 static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid, char* param, char* data,
830 int mdrcnt, int mprcnt,
831 char **rdata, char** rparam,
832 int *rdata_len, int *rparam_len)
834 char *param_format = param+2;
835 char *output_format1 = skip_string(param_format,1);
836 char *p = skip_string(output_format1,1);
837 int uLevel = SVAL(p,0);
838 char *output_format2 = p + 4;
839 int services = lp_numservices();
840 int i, n;
841 struct pack_desc desc;
842 print_queue_struct **queue = NULL;
843 print_status_struct *status = NULL;
844 int* subcntarr = NULL;
845 int queuecnt, subcnt=0, succnt=0;
847 memset((char *)&desc,'\0',sizeof(desc));
849 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
851 if (!prefix_ok(param_format,"WrLeh")) return False;
852 if (!check_printq_info(&desc,uLevel,output_format1,output_format2)) {
854 * Patch from Scott Moomaw <scott@bridgewater.edu>
855 * to return the 'invalid info level' error if an
856 * unknown level was requested.
858 *rdata_len = 0;
859 *rparam_len = 6;
860 *rparam = REALLOC(*rparam,*rparam_len);
861 SSVALS(*rparam,0,ERRunknownlevel);
862 SSVAL(*rparam,2,0);
863 SSVAL(*rparam,4,0);
864 return(True);
867 queuecnt = 0;
868 for (i = 0; i < services; i++)
869 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
870 queuecnt++;
871 if (uLevel > 0) {
872 if((queue = (print_queue_struct**)malloc(queuecnt*sizeof(print_queue_struct*))) == NULL) {
873 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
874 return False;
876 memset(queue,0,queuecnt*sizeof(print_queue_struct*));
877 if((status = (print_status_struct*)malloc(queuecnt*sizeof(print_status_struct))) == NULL) {
878 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
879 return False;
881 memset(status,0,queuecnt*sizeof(print_status_struct));
882 if((subcntarr = (int*)malloc(queuecnt*sizeof(int))) == NULL) {
883 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
884 return False;
886 subcnt = 0;
887 n = 0;
888 for (i = 0; i < services; i++)
889 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
890 subcntarr[n] = print_queue_status(i, &queue[n],&status[n]);
891 subcnt += subcntarr[n];
892 n++;
895 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
896 desc.base = *rdata;
897 desc.buflen = mdrcnt;
899 if (init_package(&desc,queuecnt,subcnt)) {
900 n = 0;
901 succnt = 0;
902 for (i = 0; i < services; i++)
903 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
904 fill_printq_info(conn,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]);
905 n++;
906 if (desc.errcode == NERR_Success) succnt = n;
910 SAFE_FREE(subcntarr);
912 *rdata_len = desc.usedlen;
913 *rparam_len = 8;
914 *rparam = REALLOC(*rparam,*rparam_len);
915 SSVALS(*rparam,0,desc.errcode);
916 SSVAL(*rparam,2,0);
917 SSVAL(*rparam,4,succnt);
918 SSVAL(*rparam,6,queuecnt);
920 for (i = 0; i < queuecnt; i++) {
921 if (queue) SAFE_FREE(queue[i]);
924 SAFE_FREE(queue);
925 SAFE_FREE(status);
927 return True;
930 /****************************************************************************
931 get info level for a server list query
932 ****************************************************************************/
933 static BOOL check_server_info(int uLevel, char* id)
935 switch( uLevel ) {
936 case 0:
937 if (strcmp(id,"B16") != 0) return False;
938 break;
939 case 1:
940 if (strcmp(id,"B16BBDz") != 0) return False;
941 break;
942 default:
943 return False;
945 return True;
948 struct srv_info_struct
950 fstring name;
951 uint32 type;
952 fstring comment;
953 fstring domain;
954 BOOL server_added;
958 /*******************************************************************
959 get server info lists from the files saved by nmbd. Return the
960 number of entries
961 ******************************************************************/
962 static int get_server_info(uint32 servertype,
963 struct srv_info_struct **servers,
964 const char *domain)
966 int count=0;
967 int alloced=0;
968 char **lines;
969 BOOL local_list_only;
970 int i;
972 lines = file_lines_load(lock_path(SERVER_LIST), NULL);
973 if (!lines) {
974 DEBUG(4,("Can't open %s - %s\n",lock_path(SERVER_LIST),strerror(errno)));
975 return(0);
978 /* request for everything is code for request all servers */
979 if (servertype == SV_TYPE_ALL)
980 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
982 local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY);
984 DEBUG(4,("Servertype search: %8x\n",servertype));
986 for (i=0;lines[i];i++) {
987 fstring stype;
988 struct srv_info_struct *s;
989 const char *ptr = lines[i];
990 BOOL ok = True;
992 if (!*ptr) continue;
994 if (count == alloced) {
995 struct srv_info_struct *ts;
997 alloced += 10;
998 ts = (struct srv_info_struct *)
999 Realloc(*servers,sizeof(**servers)*alloced);
1000 if (!ts) {
1001 DEBUG(0,("get_server_info: failed to enlarge servers info struct!\n"));
1002 return(0);
1004 else *servers = ts;
1005 memset((char *)((*servers)+count),'\0',sizeof(**servers)*(alloced-count));
1007 s = &(*servers)[count];
1009 if (!next_token(&ptr,s->name , NULL, sizeof(s->name))) continue;
1010 if (!next_token(&ptr,stype , NULL, sizeof(stype))) continue;
1011 if (!next_token(&ptr,s->comment, NULL, sizeof(s->comment))) continue;
1012 if (!next_token(&ptr,s->domain , NULL, sizeof(s->domain))) {
1013 /* this allows us to cope with an old nmbd */
1014 fstrcpy(s->domain,lp_workgroup());
1017 if (sscanf(stype,"%X",&s->type) != 1) {
1018 DEBUG(4,("r:host file "));
1019 ok = False;
1022 /* Filter the servers/domains we return based on what was asked for. */
1024 /* Check to see if we are being asked for a local list only. */
1025 if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) {
1026 DEBUG(4,("r: local list only"));
1027 ok = False;
1030 /* doesn't match up: don't want it */
1031 if (!(servertype & s->type)) {
1032 DEBUG(4,("r:serv type "));
1033 ok = False;
1036 if ((servertype & SV_TYPE_DOMAIN_ENUM) !=
1037 (s->type & SV_TYPE_DOMAIN_ENUM))
1039 DEBUG(4,("s: dom mismatch "));
1040 ok = False;
1043 if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM))
1045 ok = False;
1048 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1049 s->type &= ~SV_TYPE_LOCAL_LIST_ONLY;
1051 if (ok)
1053 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1054 s->name, s->type, s->comment, s->domain));
1056 s->server_added = True;
1057 count++;
1059 else
1061 DEBUG(4,("%20s %8x %25s %15s\n",
1062 s->name, s->type, s->comment, s->domain));
1066 file_lines_free(lines);
1067 return(count);
1071 /*******************************************************************
1072 fill in a server info structure
1073 ******************************************************************/
1074 static int fill_srv_info(struct srv_info_struct *service,
1075 int uLevel, char **buf, int *buflen,
1076 char **stringbuf, int *stringspace, char *baseaddr)
1078 int struct_len;
1079 char* p;
1080 char* p2;
1081 int l2;
1082 int len;
1084 switch (uLevel) {
1085 case 0: struct_len = 16; break;
1086 case 1: struct_len = 26; break;
1087 default: return -1;
1090 if (!buf)
1092 len = 0;
1093 switch (uLevel)
1095 case 1:
1096 len = strlen(service->comment)+1;
1097 break;
1100 if (buflen) *buflen = struct_len;
1101 if (stringspace) *stringspace = len;
1102 return struct_len + len;
1105 len = struct_len;
1106 p = *buf;
1107 if (*buflen < struct_len) return -1;
1108 if (stringbuf)
1110 p2 = *stringbuf;
1111 l2 = *stringspace;
1113 else
1115 p2 = p + struct_len;
1116 l2 = *buflen - struct_len;
1118 if (!baseaddr) baseaddr = p;
1120 switch (uLevel)
1122 case 0:
1123 push_ascii(p,service->name, MAX_NETBIOSNAME_LEN, STR_TERMINATE);
1124 break;
1126 case 1:
1127 push_ascii(p,service->name,MAX_NETBIOSNAME_LEN, STR_TERMINATE);
1128 SIVAL(p,18,service->type);
1129 SIVAL(p,22,PTR_DIFF(p2,baseaddr));
1130 len += CopyAndAdvance(&p2,service->comment,&l2);
1131 break;
1134 if (stringbuf)
1136 *buf = p + struct_len;
1137 *buflen -= struct_len;
1138 *stringbuf = p2;
1139 *stringspace = l2;
1141 else
1143 *buf = p2;
1144 *buflen -= len;
1146 return len;
1150 static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
1152 return(strcmp(s1->name,s2->name));
1155 /****************************************************************************
1156 view list of servers available (or possibly domains). The info is
1157 extracted from lists saved by nmbd on the local host
1158 ****************************************************************************/
1159 static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid, char *param, char *data,
1160 int mdrcnt, int mprcnt, char **rdata,
1161 char **rparam, int *rdata_len, int *rparam_len)
1163 char *str1 = param+2;
1164 char *str2 = skip_string(str1,1);
1165 char *p = skip_string(str2,1);
1166 int uLevel = SVAL(p,0);
1167 int buf_len = SVAL(p,2);
1168 uint32 servertype = IVAL(p,4);
1169 char *p2;
1170 int data_len, fixed_len, string_len;
1171 int f_len = 0, s_len = 0;
1172 struct srv_info_struct *servers=NULL;
1173 int counted=0,total=0;
1174 int i,missed;
1175 fstring domain;
1176 BOOL domain_request;
1177 BOOL local_request;
1179 /* If someone sets all the bits they don't really mean to set
1180 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1181 known servers. */
1183 if (servertype == SV_TYPE_ALL)
1184 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1186 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1187 any other bit (they may just set this bit on it's own) they
1188 want all the locally seen servers. However this bit can be
1189 set on its own so set the requested servers to be
1190 ALL - DOMAIN_ENUM. */
1192 if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM))
1193 servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
1195 domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
1196 local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
1198 p += 8;
1200 if (!prefix_ok(str1,"WrLehD")) return False;
1201 if (!check_server_info(uLevel,str2)) return False;
1203 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1204 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1205 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1207 if (strcmp(str1, "WrLehDz") == 0) {
1208 pull_ascii_fstring(domain, p);
1209 } else {
1210 fstrcpy(domain, lp_workgroup());
1213 if (lp_browse_list())
1214 total = get_server_info(servertype,&servers,domain);
1216 data_len = fixed_len = string_len = 0;
1217 missed = 0;
1219 if (total > 0)
1220 qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
1223 char *lastname=NULL;
1225 for (i=0;i<total;i++)
1227 struct srv_info_struct *s = &servers[i];
1228 if (lastname && strequal(lastname,s->name)) continue;
1229 lastname = s->name;
1230 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1231 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1232 s->name, s->type, s->comment, s->domain));
1234 if (data_len <= buf_len) {
1235 counted++;
1236 fixed_len += f_len;
1237 string_len += s_len;
1238 } else {
1239 missed++;
1244 *rdata_len = fixed_len + string_len;
1245 *rdata = REALLOC(*rdata,*rdata_len);
1246 memset(*rdata,'\0',*rdata_len);
1248 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1249 p = *rdata;
1250 f_len = fixed_len;
1251 s_len = string_len;
1254 char *lastname=NULL;
1255 int count2 = counted;
1256 for (i = 0; i < total && count2;i++)
1258 struct srv_info_struct *s = &servers[i];
1259 if (lastname && strequal(lastname,s->name)) continue;
1260 lastname = s->name;
1261 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1262 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1263 s->name, s->type, s->comment, s->domain));
1264 count2--;
1268 *rparam_len = 8;
1269 *rparam = REALLOC(*rparam,*rparam_len);
1270 SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata));
1271 SSVAL(*rparam,2,0);
1272 SSVAL(*rparam,4,counted);
1273 SSVAL(*rparam,6,counted+missed);
1275 SAFE_FREE(servers);
1277 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1278 domain,uLevel,counted,counted+missed));
1280 return(True);
1283 /****************************************************************************
1284 command 0x34 - suspected of being a "Lookup Names" stub api
1285 ****************************************************************************/
1286 static BOOL api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid, char *param, char *data,
1287 int mdrcnt, int mprcnt, char **rdata,
1288 char **rparam, int *rdata_len, int *rparam_len)
1290 char *str1 = param+2;
1291 char *str2 = skip_string(str1,1);
1292 char *p = skip_string(str2,1);
1293 int uLevel = SVAL(p,0);
1294 int buf_len = SVAL(p,2);
1295 int counted=0;
1296 int missed=0;
1298 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1299 str1, str2, p, uLevel, buf_len));
1301 if (!prefix_ok(str1,"zWrLeh")) return False;
1303 *rdata_len = 0;
1305 *rparam_len = 8;
1306 *rparam = REALLOC(*rparam,*rparam_len);
1308 SSVAL(*rparam,0,0x08AC); /* informational warning message */
1309 SSVAL(*rparam,2,0);
1310 SSVAL(*rparam,4,counted);
1311 SSVAL(*rparam,6,counted+missed);
1313 return(True);
1316 /****************************************************************************
1317 get info about a share
1318 ****************************************************************************/
1319 static BOOL check_share_info(int uLevel, char* id)
1321 switch( uLevel ) {
1322 case 0:
1323 if (strcmp(id,"B13") != 0) return False;
1324 break;
1325 case 1:
1326 if (strcmp(id,"B13BWz") != 0) return False;
1327 break;
1328 case 2:
1329 if (strcmp(id,"B13BWzWWWzB9B") != 0) return False;
1330 break;
1331 case 91:
1332 if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) return False;
1333 break;
1334 default: return False;
1336 return True;
1339 static int fill_share_info(connection_struct *conn, int snum, int uLevel,
1340 char** buf, int* buflen,
1341 char** stringbuf, int* stringspace, char* baseaddr)
1343 int struct_len;
1344 char* p;
1345 char* p2;
1346 int l2;
1347 int len;
1349 switch( uLevel ) {
1350 case 0: struct_len = 13; break;
1351 case 1: struct_len = 20; break;
1352 case 2: struct_len = 40; break;
1353 case 91: struct_len = 68; break;
1354 default: return -1;
1358 if (!buf)
1360 len = 0;
1361 if (uLevel > 0) len += StrlenExpanded(conn,snum,lp_comment(snum));
1362 if (uLevel > 1) len += strlen(lp_pathname(snum)) + 1;
1363 if (buflen) *buflen = struct_len;
1364 if (stringspace) *stringspace = len;
1365 return struct_len + len;
1368 len = struct_len;
1369 p = *buf;
1370 if ((*buflen) < struct_len) return -1;
1371 if (stringbuf)
1373 p2 = *stringbuf;
1374 l2 = *stringspace;
1376 else
1378 p2 = p + struct_len;
1379 l2 = (*buflen) - struct_len;
1381 if (!baseaddr) baseaddr = p;
1383 push_ascii(p,lp_servicename(snum),13, STR_TERMINATE);
1385 if (uLevel > 0)
1387 int type;
1388 SCVAL(p,13,0);
1389 type = STYPE_DISKTREE;
1390 if (lp_print_ok(snum)) type = STYPE_PRINTQ;
1391 if (strequal("IPC",lp_fstype(snum))) type = STYPE_IPC;
1392 SSVAL(p,14,type); /* device type */
1393 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1394 len += CopyExpanded(conn,snum,&p2,lp_comment(snum),&l2);
1397 if (uLevel > 1)
1399 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1400 SSVALS(p,22,-1); /* max uses */
1401 SSVAL(p,24,1); /* current uses */
1402 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1403 len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1404 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1407 if (uLevel > 2)
1409 memset(p+40,0,SHPWLEN+2);
1410 SSVAL(p,50,0);
1411 SIVAL(p,52,0);
1412 SSVAL(p,56,0);
1413 SSVAL(p,58,0);
1414 SIVAL(p,60,0);
1415 SSVAL(p,64,0);
1416 SSVAL(p,66,0);
1419 if (stringbuf)
1421 (*buf) = p + struct_len;
1422 (*buflen) -= struct_len;
1423 (*stringbuf) = p2;
1424 (*stringspace) = l2;
1426 else
1428 (*buf) = p2;
1429 (*buflen) -= len;
1431 return len;
1434 static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
1435 int mdrcnt,int mprcnt,
1436 char **rdata,char **rparam,
1437 int *rdata_len,int *rparam_len)
1439 char *str1 = param+2;
1440 char *str2 = skip_string(str1,1);
1441 char *netname = skip_string(str2,1);
1442 char *p = skip_string(netname,1);
1443 int uLevel = SVAL(p,0);
1444 int snum = find_service(netname);
1446 if (snum < 0) return False;
1448 /* check it's a supported varient */
1449 if (!prefix_ok(str1,"zWrLh")) return False;
1450 if (!check_share_info(uLevel,str2)) return False;
1452 *rdata = REALLOC(*rdata,mdrcnt);
1453 p = *rdata;
1454 *rdata_len = fill_share_info(conn,snum,uLevel,&p,&mdrcnt,0,0,0);
1455 if (*rdata_len < 0) return False;
1457 *rparam_len = 6;
1458 *rparam = REALLOC(*rparam,*rparam_len);
1459 SSVAL(*rparam,0,NERR_Success);
1460 SSVAL(*rparam,2,0); /* converter word */
1461 SSVAL(*rparam,4,*rdata_len);
1463 return(True);
1466 /****************************************************************************
1467 View the list of available shares.
1469 This function is the server side of the NetShareEnum() RAP call.
1470 It fills the return buffer with share names and share comments.
1471 Note that the return buffer normally (in all known cases) allows only
1472 twelve byte strings for share names (plus one for a nul terminator).
1473 Share names longer than 12 bytes must be skipped.
1474 ****************************************************************************/
1475 static BOOL api_RNetShareEnum( connection_struct *conn,
1476 uint16 vuid,
1477 char *param,
1478 char *data,
1479 int mdrcnt,
1480 int mprcnt,
1481 char **rdata,
1482 char **rparam,
1483 int *rdata_len,
1484 int *rparam_len )
1486 char *str1 = param+2;
1487 char *str2 = skip_string(str1,1);
1488 char *p = skip_string(str2,1);
1489 int uLevel = SVAL(p,0);
1490 int buf_len = SVAL(p,2);
1491 char *p2;
1492 int count=lp_numservices();
1493 int total=0,counted=0;
1494 BOOL missed = False;
1495 int i;
1496 int data_len, fixed_len, string_len;
1497 int f_len = 0, s_len = 0;
1499 if (!prefix_ok(str1,"WrLeh")) return False;
1500 if (!check_share_info(uLevel,str2)) return False;
1502 data_len = fixed_len = string_len = 0;
1503 for (i=0;i<count;i++) {
1504 fstring servicename_dos;
1505 push_ascii_fstring(servicename_dos, lp_servicename(i));
1506 if( lp_browseable( i )
1507 && lp_snum_ok( i )
1508 && (strlen(servicename_dos) < 13) ) /* Maximum name length. */
1510 total++;
1511 data_len += fill_share_info(conn,i,uLevel,0,&f_len,0,&s_len,0);
1512 if (data_len <= buf_len)
1514 counted++;
1515 fixed_len += f_len;
1516 string_len += s_len;
1518 else
1519 missed = True;
1522 *rdata_len = fixed_len + string_len;
1523 *rdata = REALLOC(*rdata,*rdata_len);
1524 memset(*rdata,0,*rdata_len);
1526 p2 = (*rdata) + fixed_len; /* auxiliary data (strings) will go here */
1527 p = *rdata;
1528 f_len = fixed_len;
1529 s_len = string_len;
1530 for( i = 0; i < count; i++ )
1532 fstring servicename_dos;
1533 push_ascii_fstring(servicename_dos, lp_servicename(i));
1534 if( lp_browseable( i )
1535 && lp_snum_ok( i )
1536 && (strlen(servicename_dos) < 13) )
1538 if( fill_share_info( conn,i,uLevel,&p,&f_len,&p2,&s_len,*rdata ) < 0 )
1539 break;
1543 *rparam_len = 8;
1544 *rparam = REALLOC(*rparam,*rparam_len);
1545 SSVAL(*rparam,0,missed ? ERRmoredata : NERR_Success);
1546 SSVAL(*rparam,2,0);
1547 SSVAL(*rparam,4,counted);
1548 SSVAL(*rparam,6,total);
1550 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1551 counted,total,uLevel,
1552 buf_len,*rdata_len,mdrcnt));
1553 return(True);
1554 } /* api_RNetShareEnum */
1556 /****************************************************************************
1557 Add a share
1558 ****************************************************************************/
1559 static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid, char *param,char *data,
1560 int mdrcnt,int mprcnt,
1561 char **rdata,char **rparam,
1562 int *rdata_len,int *rparam_len)
1564 char *str1 = param+2;
1565 char *str2 = skip_string(str1,1);
1566 char *p = skip_string(str2,1);
1567 int uLevel = SVAL(p,0);
1568 fstring sharename;
1569 fstring comment;
1570 pstring pathname;
1571 char *command, *cmdname;
1572 unsigned int offset;
1573 int snum;
1574 int res = ERRunsup;
1576 /* check it's a supported varient */
1577 if (!prefix_ok(str1,RAP_WShareAdd_REQ)) return False;
1578 if (!check_share_info(uLevel,str2)) return False;
1579 if (uLevel != 2) return False;
1581 pull_ascii_fstring(sharename,data);
1582 snum = find_service(sharename);
1583 if (snum >= 0) { /* already exists */
1584 res = ERRfilexists;
1585 goto error_exit;
1588 /* only support disk share adds */
1589 if (SVAL(data,14)!=STYPE_DISKTREE) return False;
1591 offset = IVAL(data, 16);
1592 if (offset >= mdrcnt) {
1593 res = ERRinvalidparam;
1594 goto error_exit;
1596 pull_ascii_fstring(comment, offset? (data+offset) : "");
1598 offset = IVAL(data, 26);
1599 if (offset >= mdrcnt) {
1600 res = ERRinvalidparam;
1601 goto error_exit;
1603 pull_ascii_pstring(pathname, offset? (data+offset) : "");
1605 string_replace(sharename, '"', ' ');
1606 string_replace(pathname, '"', ' ');
1607 string_replace(comment, '"', ' ');
1609 cmdname = lp_add_share_cmd();
1611 if (!cmdname || *cmdname == '\0') return False;
1613 asprintf(&command, "%s \"%s\" \"%s\" \"%s\" \"%s\"",
1614 lp_add_share_cmd(), dyn_CONFIGFILE, sharename, pathname, comment);
1616 if (command) {
1617 DEBUG(10,("api_RNetShareAdd: Running [%s]\n", command ));
1618 if ((res = smbrun(command, NULL)) != 0) {
1619 DEBUG(1,("api_RNetShareAdd: Running [%s] returned (%d)\n", command, res ));
1620 SAFE_FREE(command);
1621 res = ERRnoaccess;
1622 goto error_exit;
1623 } else {
1624 SAFE_FREE(command);
1625 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
1627 } else return False;
1629 *rparam_len = 6;
1630 *rparam = REALLOC(*rparam,*rparam_len);
1631 SSVAL(*rparam,0,NERR_Success);
1632 SSVAL(*rparam,2,0); /* converter word */
1633 SSVAL(*rparam,4,*rdata_len);
1634 *rdata_len = 0;
1636 return True;
1638 error_exit:
1639 *rparam_len = 4;
1640 *rparam = REALLOC(*rparam,*rparam_len);
1641 *rdata_len = 0;
1642 SSVAL(*rparam,0,res);
1643 SSVAL(*rparam,2,0);
1644 return True;
1648 /****************************************************************************
1649 view list of groups available
1650 ****************************************************************************/
1651 static BOOL api_RNetGroupEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
1652 int mdrcnt,int mprcnt,
1653 char **rdata,char **rparam,
1654 int *rdata_len,int *rparam_len)
1656 int i;
1657 int errflags=0;
1658 int resume_context, cli_buf_size;
1659 char *str1 = param+2;
1660 char *str2 = skip_string(str1,1);
1661 char *p = skip_string(str2,1);
1662 BOOL ret;
1664 GROUP_MAP *group_list;
1665 int num_entries;
1667 if (strcmp(str1,"WrLeh") != 0)
1668 return False;
1670 /* parameters
1671 * W-> resume context (number of users to skip)
1672 * r -> return parameter pointer to receive buffer
1673 * L -> length of receive buffer
1674 * e -> return parameter number of entries
1675 * h -> return parameter total number of users
1677 if (strcmp("B21",str2) != 0)
1678 return False;
1680 /* get list of domain groups SID_DOMAIN_GRP=2 */
1681 become_root();
1682 ret = pdb_enum_group_mapping(SID_NAME_DOM_GRP , &group_list, &num_entries, False);
1683 unbecome_root();
1685 if( !ret ) {
1686 DEBUG(3,("api_RNetGroupEnum:failed to get group list"));
1687 return False;
1690 resume_context = SVAL(p,0);
1691 cli_buf_size=SVAL(p+2,0);
1692 DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: %d\n", resume_context, cli_buf_size));
1694 *rdata_len = cli_buf_size;
1695 *rdata = REALLOC(*rdata,*rdata_len);
1697 p = *rdata;
1699 for(i=resume_context; i<num_entries; i++) {
1700 char* name=group_list[i].nt_name;
1701 if( ((PTR_DIFF(p,*rdata)+21) <= *rdata_len) ) {
1702 /* truncate the name at 21 chars. */
1703 memcpy(p, name, 21);
1704 DEBUG(10,("adding entry %d group %s\n", i, p));
1705 p += 21;
1706 } else {
1707 /* set overflow error */
1708 DEBUG(3,("overflow on entry %d group %s\n", i, name));
1709 errflags=234;
1710 break;
1714 *rdata_len = PTR_DIFF(p,*rdata);
1716 *rparam_len = 8;
1717 *rparam = REALLOC(*rparam,*rparam_len);
1719 SSVAL(*rparam, 0, errflags);
1720 SSVAL(*rparam, 2, 0); /* converter word */
1721 SSVAL(*rparam, 4, i-resume_context); /* is this right?? */
1722 SSVAL(*rparam, 6, num_entries); /* is this right?? */
1724 return(True);
1727 /*******************************************************************
1728 get groups that a user is a member of
1729 ******************************************************************/
1730 static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *param,char *data,
1731 int mdrcnt,int mprcnt,
1732 char **rdata,char **rparam,
1733 int *rdata_len,int *rparam_len)
1735 char *str1 = param+2;
1736 char *str2 = skip_string(str1,1);
1737 char *UserName = skip_string(str2,1);
1738 char *p = skip_string(UserName,1);
1739 int uLevel = SVAL(p,0);
1740 const char *level_string;
1741 int count=0;
1742 SAM_ACCOUNT *sampw = NULL;
1743 BOOL ret = False;
1744 DOM_GID *gids = NULL;
1745 int num_groups = 0;
1746 int i;
1747 fstring grp_domain;
1748 fstring grp_name;
1749 enum SID_NAME_USE grp_type;
1750 DOM_SID sid, dom_sid;
1752 *rparam_len = 8;
1753 *rparam = REALLOC(*rparam,*rparam_len);
1755 /* check it's a supported varient */
1757 if ( strcmp(str1,"zWrLeh") != 0 )
1758 return False;
1760 switch( uLevel ) {
1761 case 0:
1762 level_string = "B21";
1763 break;
1764 default:
1765 return False;
1768 if (strcmp(level_string,str2) != 0)
1769 return False;
1771 *rdata_len = mdrcnt + 1024;
1772 *rdata = REALLOC(*rdata,*rdata_len);
1774 SSVAL(*rparam,0,NERR_Success);
1775 SSVAL(*rparam,2,0); /* converter word */
1777 p = *rdata;
1779 /* Lookup the user information; This should only be one of
1780 our accounts (not remote domains) */
1782 pdb_init_sam( &sampw );
1784 become_root(); /* ROOT BLOCK */
1786 if ( !pdb_getsampwnam(sampw, UserName) )
1787 goto out;
1789 /* this next set of code is horribly inefficient, but since
1790 it is rarely called, I'm going to leave it like this since
1791 it easier to follow --jerry */
1793 /* get the list of group SIDs */
1795 if ( !get_domain_user_groups(conn->mem_ctx, &num_groups, &gids, sampw) ) {
1796 DEBUG(1,("api_NetUserGetGroups: get_domain_user_groups() failed!\n"));
1797 goto out;
1800 /* convert to names (we don't support universal groups so the domain
1801 can only be ours) */
1803 sid_copy( &dom_sid, get_global_sam_sid() );
1804 for (i=0; i<num_groups; i++) {
1806 /* make the DOM_GID into a DOM_SID and then lookup
1807 the name */
1809 sid_copy( &sid, &dom_sid );
1810 sid_append_rid( &sid, gids[i].g_rid );
1812 if ( lookup_sid(&sid, grp_domain, grp_name, &grp_type) ) {
1813 pstrcpy(p, grp_name);
1814 p += 21;
1815 count++;
1819 *rdata_len = PTR_DIFF(p,*rdata);
1821 SSVAL(*rparam,4,count); /* is this right?? */
1822 SSVAL(*rparam,6,count); /* is this right?? */
1824 ret = True;
1826 out:
1827 unbecome_root(); /* END ROOT BLOCK */
1829 pdb_free_sam( &sampw );
1831 return ret;
1834 /*******************************************************************
1835 get all users
1836 ******************************************************************/
1837 static BOOL api_RNetUserEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
1838 int mdrcnt,int mprcnt,
1839 char **rdata,char **rparam,
1840 int *rdata_len,int *rparam_len)
1842 SAM_ACCOUNT *pwd=NULL;
1843 int count_sent=0;
1844 int count_total=0;
1845 int errflags=0;
1846 int resume_context, cli_buf_size;
1848 char *str1 = param+2;
1849 char *str2 = skip_string(str1,1);
1850 char *p = skip_string(str2,1);
1852 if (strcmp(str1,"WrLeh") != 0)
1853 return False;
1854 /* parameters
1855 * W-> resume context (number of users to skip)
1856 * r -> return parameter pointer to receive buffer
1857 * L -> length of receive buffer
1858 * e -> return parameter number of entries
1859 * h -> return parameter total number of users
1862 resume_context = SVAL(p,0);
1863 cli_buf_size=SVAL(p+2,0);
1864 DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n", resume_context, cli_buf_size));
1866 *rparam_len = 8;
1867 *rparam = REALLOC(*rparam,*rparam_len);
1869 /* check it's a supported varient */
1870 if (strcmp("B21",str2) != 0)
1871 return False;
1873 *rdata_len = cli_buf_size;
1874 *rdata = REALLOC(*rdata,*rdata_len);
1876 p = *rdata;
1878 /* to get user list enumerations for NetUserEnum in B21 format */
1879 pdb_init_sam(&pwd);
1881 /* Open the passgrp file - not for update. */
1882 become_root();
1883 if(!pdb_setsampwent(False)) {
1884 DEBUG(0, ("api_RNetUserEnum:unable to open sam database.\n"));
1885 unbecome_root();
1886 return False;
1888 errflags=NERR_Success;
1890 while ( pdb_getsampwent(pwd) ) {
1891 const char *name=pdb_get_username(pwd);
1892 if ((name) && (*(name+strlen(name)-1)!='$')) {
1893 count_total++;
1894 if(count_total>=resume_context) {
1895 if( ((PTR_DIFF(p,*rdata)+21)<=*rdata_len)&&(strlen(name)<=21) ) {
1896 pstrcpy(p,name);
1897 DEBUG(10,("api_RNetUserEnum:adding entry %d username %s\n",count_sent,p));
1898 p += 21;
1899 count_sent++;
1900 } else {
1901 /* set overflow error */
1902 DEBUG(10,("api_RNetUserEnum:overflow on entry %d username %s\n",count_sent,name));
1903 errflags=234;
1904 break;
1910 pdb_endsampwent();
1911 unbecome_root();
1913 pdb_free_sam(&pwd);
1915 *rdata_len = PTR_DIFF(p,*rdata);
1917 SSVAL(*rparam,0,errflags);
1918 SSVAL(*rparam,2,0); /* converter word */
1919 SSVAL(*rparam,4,count_sent); /* is this right?? */
1920 SSVAL(*rparam,6,count_total); /* is this right?? */
1922 return True;
1927 /****************************************************************************
1928 get the time of day info
1929 ****************************************************************************/
1930 static BOOL api_NetRemoteTOD(connection_struct *conn,uint16 vuid, char *param,char *data,
1931 int mdrcnt,int mprcnt,
1932 char **rdata,char **rparam,
1933 int *rdata_len,int *rparam_len)
1935 char *p;
1936 *rparam_len = 4;
1937 *rparam = REALLOC(*rparam,*rparam_len);
1939 *rdata_len = 21;
1940 *rdata = REALLOC(*rdata,*rdata_len);
1942 SSVAL(*rparam,0,NERR_Success);
1943 SSVAL(*rparam,2,0); /* converter word */
1945 p = *rdata;
1948 struct tm *t;
1949 time_t unixdate = time(NULL);
1951 put_dos_date3(p,0,unixdate); /* this is the time that is looked at
1952 by NT in a "net time" operation,
1953 it seems to ignore the one below */
1955 /* the client expects to get localtime, not GMT, in this bit
1956 (I think, this needs testing) */
1957 t = LocalTime(&unixdate);
1959 SIVAL(p,4,0); /* msecs ? */
1960 SCVAL(p,8,t->tm_hour);
1961 SCVAL(p,9,t->tm_min);
1962 SCVAL(p,10,t->tm_sec);
1963 SCVAL(p,11,0); /* hundredths of seconds */
1964 SSVALS(p,12,TimeDiff(unixdate)/60); /* timezone in minutes from GMT */
1965 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
1966 SCVAL(p,16,t->tm_mday);
1967 SCVAL(p,17,t->tm_mon + 1);
1968 SSVAL(p,18,1900+t->tm_year);
1969 SCVAL(p,20,t->tm_wday);
1973 return(True);
1976 /****************************************************************************
1977 Set the user password.
1978 *****************************************************************************/
1980 static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param,char *data,
1981 int mdrcnt,int mprcnt,
1982 char **rdata,char **rparam,
1983 int *rdata_len,int *rparam_len)
1985 char *p = skip_string(param+2,2);
1986 fstring user;
1987 fstring pass1,pass2;
1989 pull_ascii_fstring(user,p);
1991 p = skip_string(p,1);
1993 memset(pass1,'\0',sizeof(pass1));
1994 memset(pass2,'\0',sizeof(pass2));
1995 memcpy(pass1,p,16);
1996 memcpy(pass2,p+16,16);
1998 *rparam_len = 4;
1999 *rparam = REALLOC(*rparam,*rparam_len);
2001 *rdata_len = 0;
2003 SSVAL(*rparam,0,NERR_badpass);
2004 SSVAL(*rparam,2,0); /* converter word */
2006 DEBUG(3,("Set password for <%s>\n",user));
2009 * Attempt to verify the old password against smbpasswd entries
2010 * Win98 clients send old and new password in plaintext for this call.
2014 auth_serversupplied_info *server_info = NULL;
2015 DATA_BLOB password = data_blob(pass1, strlen(pass1)+1);
2017 if (NT_STATUS_IS_OK(check_plaintext_password(user,password,&server_info))) {
2019 become_root();
2020 if (NT_STATUS_IS_OK(change_oem_password(server_info->sam_account, pass1, pass2, False))) {
2021 SSVAL(*rparam,0,NERR_Success);
2023 unbecome_root();
2025 free_server_info(&server_info);
2027 data_blob_clear_free(&password);
2031 * If the plaintext change failed, attempt
2032 * the old encrypted method. NT will generate this
2033 * after trying the samr method. Note that this
2034 * method is done as a last resort as this
2035 * password change method loses the NT password hash
2036 * and cannot change the UNIX password as no plaintext
2037 * is received.
2040 if(SVAL(*rparam,0) != NERR_Success) {
2041 SAM_ACCOUNT *hnd = NULL;
2043 if (check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &hnd)) {
2044 become_root();
2045 if (change_lanman_password(hnd,(uchar *)pass2)) {
2046 SSVAL(*rparam,0,NERR_Success);
2048 unbecome_root();
2049 pdb_free_sam(&hnd);
2053 memset((char *)pass1,'\0',sizeof(fstring));
2054 memset((char *)pass2,'\0',sizeof(fstring));
2056 return(True);
2059 /****************************************************************************
2060 Set the user password (SamOEM version - gets plaintext).
2061 ****************************************************************************/
2063 static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char *param,char *data,
2064 int mdrcnt,int mprcnt,
2065 char **rdata,char **rparam,
2066 int *rdata_len,int *rparam_len)
2068 fstring user;
2069 char *p = param + 2;
2070 *rparam_len = 2;
2071 *rparam = REALLOC(*rparam,*rparam_len);
2073 *rdata_len = 0;
2075 SSVAL(*rparam,0,NERR_badpass);
2078 * Check the parameter definition is correct.
2081 if(!strequal(param + 2, "zsT")) {
2082 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", param + 2));
2083 return False;
2085 p = skip_string(p, 1);
2087 if(!strequal(p, "B516B16")) {
2088 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p));
2089 return False;
2091 p = skip_string(p,1);
2092 p += pull_ascii_fstring(user,p);
2094 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user));
2097 * Pass the user through the NT -> unix user mapping
2098 * function.
2101 (void)map_username(user);
2103 if (NT_STATUS_IS_OK(pass_oem_change(user, (uchar*) data, (uchar *)&data[516], NULL, NULL))) {
2104 SSVAL(*rparam,0,NERR_Success);
2107 return(True);
2110 /****************************************************************************
2111 delete a print job
2112 Form: <W> <>
2113 ****************************************************************************/
2114 static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char *param,char *data,
2115 int mdrcnt,int mprcnt,
2116 char **rdata,char **rparam,
2117 int *rdata_len,int *rparam_len)
2119 int function = SVAL(param,0);
2120 char *str1 = param+2;
2121 char *str2 = skip_string(str1,1);
2122 char *p = skip_string(str2,1);
2123 uint32 jobid;
2124 int snum;
2125 fstring sharename;
2126 int errcode;
2127 extern struct current_user current_user;
2128 WERROR werr = WERR_OK;
2130 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
2131 return False;
2133 /* check it's a supported varient */
2134 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
2135 return(False);
2137 *rparam_len = 4;
2138 *rparam = REALLOC(*rparam,*rparam_len);
2139 *rdata_len = 0;
2141 if (!print_job_exists(sharename, jobid)) {
2142 errcode = NERR_JobNotFound;
2143 goto out;
2146 errcode = NERR_notsupported;
2148 switch (function) {
2149 case 81: /* delete */
2150 if (print_job_delete(&current_user, snum, jobid, &werr))
2151 errcode = NERR_Success;
2152 break;
2153 case 82: /* pause */
2154 if (print_job_pause(&current_user, snum, jobid, &werr))
2155 errcode = NERR_Success;
2156 break;
2157 case 83: /* resume */
2158 if (print_job_resume(&current_user, snum, jobid, &werr))
2159 errcode = NERR_Success;
2160 break;
2163 if (!W_ERROR_IS_OK(werr))
2164 errcode = W_ERROR_V(werr);
2166 out:
2167 SSVAL(*rparam,0,errcode);
2168 SSVAL(*rparam,2,0); /* converter word */
2170 return(True);
2173 /****************************************************************************
2174 Purge a print queue - or pause or resume it.
2175 ****************************************************************************/
2176 static BOOL api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid, char *param,char *data,
2177 int mdrcnt,int mprcnt,
2178 char **rdata,char **rparam,
2179 int *rdata_len,int *rparam_len)
2181 int function = SVAL(param,0);
2182 char *str1 = param+2;
2183 char *str2 = skip_string(str1,1);
2184 char *QueueName = skip_string(str2,1);
2185 int errcode = NERR_notsupported;
2186 int snum;
2187 WERROR werr = WERR_OK;
2188 extern struct current_user current_user;
2190 /* check it's a supported varient */
2191 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
2192 return(False);
2194 *rparam_len = 4;
2195 *rparam = REALLOC(*rparam,*rparam_len);
2196 *rdata_len = 0;
2198 snum = print_queue_snum(QueueName);
2200 if (snum == -1) {
2201 errcode = NERR_JobNotFound;
2202 goto out;
2205 switch (function) {
2206 case 74: /* Pause queue */
2207 if (print_queue_pause(&current_user, snum, &werr)) errcode = NERR_Success;
2208 break;
2209 case 75: /* Resume queue */
2210 if (print_queue_resume(&current_user, snum, &werr)) errcode = NERR_Success;
2211 break;
2212 case 103: /* Purge */
2213 if (print_queue_purge(&current_user, snum, &werr)) errcode = NERR_Success;
2214 break;
2217 if (!W_ERROR_IS_OK(werr)) errcode = W_ERROR_V(werr);
2219 out:
2220 SSVAL(*rparam,0,errcode);
2221 SSVAL(*rparam,2,0); /* converter word */
2223 return(True);
2227 /****************************************************************************
2228 set the property of a print job (undocumented?)
2229 ? function = 0xb -> set name of print job
2230 ? function = 0x6 -> move print job up/down
2231 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
2232 or <WWsTP> <WB21BB16B10zWWzDDz>
2233 ****************************************************************************/
2234 static int check_printjob_info(struct pack_desc* desc,
2235 int uLevel, char* id)
2237 desc->subformat = NULL;
2238 switch( uLevel ) {
2239 case 0: desc->format = "W"; break;
2240 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
2241 case 2: desc->format = "WWzWWDDzz"; break;
2242 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
2243 case 4: desc->format = "WWzWWDDzzzzzDDDDDDD"; break;
2244 default: return False;
2246 if (strcmp(desc->format,id) != 0) return False;
2247 return True;
2250 static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,char *data,
2251 int mdrcnt,int mprcnt,
2252 char **rdata,char **rparam,
2253 int *rdata_len,int *rparam_len)
2255 struct pack_desc desc;
2256 char *str1 = param+2;
2257 char *str2 = skip_string(str1,1);
2258 char *p = skip_string(str2,1);
2259 uint32 jobid;
2260 int snum;
2261 fstring sharename;
2262 int uLevel = SVAL(p,2);
2263 int function = SVAL(p,4);
2264 int place, errcode;
2266 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
2267 return False;
2268 *rparam_len = 4;
2269 *rparam = REALLOC(*rparam,*rparam_len);
2271 *rdata_len = 0;
2273 /* check it's a supported varient */
2274 if ((strcmp(str1,"WWsTP")) ||
2275 (!check_printjob_info(&desc,uLevel,str2)))
2276 return(False);
2278 if (!print_job_exists(sharename, jobid)) {
2279 errcode=NERR_JobNotFound;
2280 goto out;
2283 errcode = NERR_notsupported;
2285 switch (function) {
2286 case 0x6:
2287 /* change job place in the queue,
2288 data gives the new place */
2289 place = SVAL(data,0);
2290 if (print_job_set_place(snum, jobid, place)) {
2291 errcode=NERR_Success;
2293 break;
2295 case 0xb:
2296 /* change print job name, data gives the name */
2297 if (print_job_set_name(snum, jobid, data)) {
2298 errcode=NERR_Success;
2300 break;
2302 default:
2303 return False;
2306 out:
2307 SSVALS(*rparam,0,errcode);
2308 SSVAL(*rparam,2,0); /* converter word */
2310 return(True);
2314 /****************************************************************************
2315 get info about the server
2316 ****************************************************************************/
2317 static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2318 int mdrcnt,int mprcnt,
2319 char **rdata,char **rparam,
2320 int *rdata_len,int *rparam_len)
2322 char *str1 = param+2;
2323 char *str2 = skip_string(str1,1);
2324 char *p = skip_string(str2,1);
2325 int uLevel = SVAL(p,0);
2326 char *p2;
2327 int struct_len;
2329 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
2331 /* check it's a supported varient */
2332 if (!prefix_ok(str1,"WrLh")) return False;
2333 switch( uLevel ) {
2334 case 0:
2335 if (strcmp(str2,"B16") != 0) return False;
2336 struct_len = 16;
2337 break;
2338 case 1:
2339 if (strcmp(str2,"B16BBDz") != 0) return False;
2340 struct_len = 26;
2341 break;
2342 case 2:
2343 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")
2344 != 0) return False;
2345 struct_len = 134;
2346 break;
2347 case 3:
2348 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz")
2349 != 0) return False;
2350 struct_len = 144;
2351 break;
2352 case 20:
2353 if (strcmp(str2,"DN") != 0) return False;
2354 struct_len = 6;
2355 break;
2356 case 50:
2357 if (strcmp(str2,"B16BBDzWWzzz") != 0) return False;
2358 struct_len = 42;
2359 break;
2360 default: return False;
2363 *rdata_len = mdrcnt;
2364 *rdata = REALLOC(*rdata,*rdata_len);
2366 p = *rdata;
2367 p2 = p + struct_len;
2368 if (uLevel != 20) {
2369 srvstr_push(NULL, p,local_machine,16,
2370 STR_ASCII|STR_UPPER|STR_TERMINATE);
2372 p += 16;
2373 if (uLevel > 0)
2375 struct srv_info_struct *servers=NULL;
2376 int i,count;
2377 pstring comment;
2378 uint32 servertype= lp_default_server_announce();
2380 push_ascii(comment,lp_serverstring(), MAX_SERVER_STRING_LENGTH,STR_TERMINATE);
2382 if ((count=get_server_info(SV_TYPE_ALL,&servers,lp_workgroup()))>0) {
2383 for (i=0;i<count;i++) {
2384 if (strequal(servers[i].name,local_machine)) {
2385 servertype = servers[i].type;
2386 push_ascii(comment,servers[i].comment,sizeof(pstring),STR_TERMINATE);
2390 SAFE_FREE(servers);
2392 SCVAL(p,0,lp_major_announce_version());
2393 SCVAL(p,1,lp_minor_announce_version());
2394 SIVAL(p,2,servertype);
2396 if (mdrcnt == struct_len) {
2397 SIVAL(p,6,0);
2398 } else {
2399 SIVAL(p,6,PTR_DIFF(p2,*rdata));
2400 standard_sub_conn(conn,comment,sizeof(comment));
2401 StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
2402 p2 = skip_string(p2,1);
2405 if (uLevel > 1)
2407 return False; /* not yet implemented */
2410 *rdata_len = PTR_DIFF(p2,*rdata);
2412 *rparam_len = 6;
2413 *rparam = REALLOC(*rparam,*rparam_len);
2414 SSVAL(*rparam,0,NERR_Success);
2415 SSVAL(*rparam,2,0); /* converter word */
2416 SSVAL(*rparam,4,*rdata_len);
2418 return(True);
2422 /****************************************************************************
2423 get info about the server
2424 ****************************************************************************/
2425 static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2426 int mdrcnt,int mprcnt,
2427 char **rdata,char **rparam,
2428 int *rdata_len,int *rparam_len)
2430 char *str1 = param+2;
2431 char *str2 = skip_string(str1,1);
2432 char *p = skip_string(str2,1);
2433 char *p2;
2434 extern userdom_struct current_user_info;
2435 int level = SVAL(p,0);
2437 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
2439 *rparam_len = 6;
2440 *rparam = REALLOC(*rparam,*rparam_len);
2442 /* check it's a supported varient */
2443 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz")))
2444 return(False);
2446 *rdata_len = mdrcnt + 1024;
2447 *rdata = REALLOC(*rdata,*rdata_len);
2449 SSVAL(*rparam,0,NERR_Success);
2450 SSVAL(*rparam,2,0); /* converter word */
2452 p = *rdata;
2453 p2 = p + 22;
2456 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
2457 pstrcpy(p2,local_machine);
2458 strupper_m(p2);
2459 p2 = skip_string(p2,1);
2460 p += 4;
2462 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2463 pstrcpy(p2,current_user_info.smb_name);
2464 p2 = skip_string(p2,1);
2465 p += 4;
2467 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
2468 pstrcpy(p2,lp_workgroup());
2469 strupper_m(p2);
2470 p2 = skip_string(p2,1);
2471 p += 4;
2473 SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
2474 SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
2475 p += 2;
2477 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2478 pstrcpy(p2,lp_workgroup()); /* don't know. login domain?? */
2479 p2 = skip_string(p2,1);
2480 p += 4;
2482 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
2483 pstrcpy(p2,"");
2484 p2 = skip_string(p2,1);
2485 p += 4;
2487 *rdata_len = PTR_DIFF(p2,*rdata);
2489 SSVAL(*rparam,4,*rdata_len);
2491 return(True);
2494 /****************************************************************************
2495 get info about a user
2497 struct user_info_11 {
2498 char usri11_name[21]; 0-20
2499 char usri11_pad; 21
2500 char *usri11_comment; 22-25
2501 char *usri11_usr_comment; 26-29
2502 unsigned short usri11_priv; 30-31
2503 unsigned long usri11_auth_flags; 32-35
2504 long usri11_password_age; 36-39
2505 char *usri11_homedir; 40-43
2506 char *usri11_parms; 44-47
2507 long usri11_last_logon; 48-51
2508 long usri11_last_logoff; 52-55
2509 unsigned short usri11_bad_pw_count; 56-57
2510 unsigned short usri11_num_logons; 58-59
2511 char *usri11_logon_server; 60-63
2512 unsigned short usri11_country_code; 64-65
2513 char *usri11_workstations; 66-69
2514 unsigned long usri11_max_storage; 70-73
2515 unsigned short usri11_units_per_week; 74-75
2516 unsigned char *usri11_logon_hours; 76-79
2517 unsigned short usri11_code_page; 80-81
2520 where:
2522 usri11_name specifies the user name for which information is retireved
2524 usri11_pad aligns the next data structure element to a word boundary
2526 usri11_comment is a null terminated ASCII comment
2528 usri11_user_comment is a null terminated ASCII comment about the user
2530 usri11_priv specifies the level of the privilege assigned to the user.
2531 The possible values are:
2533 Name Value Description
2534 USER_PRIV_GUEST 0 Guest privilege
2535 USER_PRIV_USER 1 User privilege
2536 USER_PRV_ADMIN 2 Administrator privilege
2538 usri11_auth_flags specifies the account operator privileges. The
2539 possible values are:
2541 Name Value Description
2542 AF_OP_PRINT 0 Print operator
2545 Leach, Naik [Page 28]
2549 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2552 AF_OP_COMM 1 Communications operator
2553 AF_OP_SERVER 2 Server operator
2554 AF_OP_ACCOUNTS 3 Accounts operator
2557 usri11_password_age specifies how many seconds have elapsed since the
2558 password was last changed.
2560 usri11_home_dir points to a null terminated ASCII string that contains
2561 the path name of the user's home directory.
2563 usri11_parms points to a null terminated ASCII string that is set
2564 aside for use by applications.
2566 usri11_last_logon specifies the time when the user last logged on.
2567 This value is stored as the number of seconds elapsed since
2568 00:00:00, January 1, 1970.
2570 usri11_last_logoff specifies the time when the user last logged off.
2571 This value is stored as the number of seconds elapsed since
2572 00:00:00, January 1, 1970. A value of 0 means the last logoff
2573 time is unknown.
2575 usri11_bad_pw_count specifies the number of incorrect passwords
2576 entered since the last successful logon.
2578 usri11_log1_num_logons specifies the number of times this user has
2579 logged on. A value of -1 means the number of logons is unknown.
2581 usri11_logon_server points to a null terminated ASCII string that
2582 contains the name of the server to which logon requests are sent.
2583 A null string indicates logon requests should be sent to the
2584 domain controller.
2586 usri11_country_code specifies the country code for the user's language
2587 of choice.
2589 usri11_workstations points to a null terminated ASCII string that
2590 contains the names of workstations the user may log on from.
2591 There may be up to 8 workstations, with the names separated by
2592 commas. A null strings indicates there are no restrictions.
2594 usri11_max_storage specifies the maximum amount of disk space the user
2595 can occupy. A value of 0xffffffff indicates there are no
2596 restrictions.
2598 usri11_units_per_week specifies the equal number of time units into
2599 which a week is divided. This value must be equal to 168.
2601 usri11_logon_hours points to a 21 byte (168 bits) string that
2602 specifies the time during which the user can log on. Each bit
2603 represents one unique hour in a week. The first bit (bit 0, word
2604 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
2608 Leach, Naik [Page 29]
2612 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2615 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
2616 are no restrictions.
2618 usri11_code_page specifies the code page for the user's language of
2619 choice
2621 All of the pointers in this data structure need to be treated
2622 specially. The pointer is a 32 bit pointer. The higher 16 bits need
2623 to be ignored. The converter word returned in the parameters section
2624 needs to be subtracted from the lower 16 bits to calculate an offset
2625 into the return buffer where this ASCII string resides.
2627 There is no auxiliary data in the response.
2629 ****************************************************************************/
2631 #define usri11_name 0
2632 #define usri11_pad 21
2633 #define usri11_comment 22
2634 #define usri11_usr_comment 26
2635 #define usri11_full_name 30
2636 #define usri11_priv 34
2637 #define usri11_auth_flags 36
2638 #define usri11_password_age 40
2639 #define usri11_homedir 44
2640 #define usri11_parms 48
2641 #define usri11_last_logon 52
2642 #define usri11_last_logoff 56
2643 #define usri11_bad_pw_count 60
2644 #define usri11_num_logons 62
2645 #define usri11_logon_server 64
2646 #define usri11_country_code 68
2647 #define usri11_workstations 70
2648 #define usri11_max_storage 74
2649 #define usri11_units_per_week 78
2650 #define usri11_logon_hours 80
2651 #define usri11_code_page 84
2652 #define usri11_end 86
2654 #define USER_PRIV_GUEST 0
2655 #define USER_PRIV_USER 1
2656 #define USER_PRIV_ADMIN 2
2658 #define AF_OP_PRINT 0
2659 #define AF_OP_COMM 1
2660 #define AF_OP_SERVER 2
2661 #define AF_OP_ACCOUNTS 3
2664 static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2665 int mdrcnt,int mprcnt,
2666 char **rdata,char **rparam,
2667 int *rdata_len,int *rparam_len)
2669 char *str1 = param+2;
2670 char *str2 = skip_string(str1,1);
2671 char *UserName = skip_string(str2,1);
2672 char *p = skip_string(UserName,1);
2673 int uLevel = SVAL(p,0);
2674 char *p2;
2675 const char *level_string;
2677 /* get NIS home of a previously validated user - simeon */
2678 /* With share level security vuid will always be zero.
2679 Don't depend on vuser being non-null !!. JRA */
2680 user_struct *vuser = get_valid_user_struct(vuid);
2681 if(vuser != NULL)
2682 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid,
2683 vuser->user.unix_name));
2685 *rparam_len = 6;
2686 *rparam = REALLOC(*rparam,*rparam_len);
2688 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
2690 /* check it's a supported variant */
2691 if (strcmp(str1,"zWrLh") != 0) return False;
2692 switch( uLevel )
2694 case 0: level_string = "B21"; break;
2695 case 1: level_string = "B21BB16DWzzWz"; break;
2696 case 2: level_string = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
2697 case 10: level_string = "B21Bzzz"; break;
2698 case 11: level_string = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
2699 default: return False;
2702 if (strcmp(level_string,str2) != 0) return False;
2704 *rdata_len = mdrcnt + 1024;
2705 *rdata = REALLOC(*rdata,*rdata_len);
2707 SSVAL(*rparam,0,NERR_Success);
2708 SSVAL(*rparam,2,0); /* converter word */
2710 p = *rdata;
2711 p2 = p + usri11_end;
2713 memset(p,0,21);
2714 fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
2716 if (uLevel > 0)
2718 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
2719 *p2 = 0;
2721 if (uLevel >= 10)
2723 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
2724 pstrcpy(p2,"Comment");
2725 p2 = skip_string(p2,1);
2727 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
2728 pstrcpy(p2,"UserComment");
2729 p2 = skip_string(p2,1);
2731 /* EEK! the cifsrap.txt doesn't have this in!!!! */
2732 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
2733 pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName));
2734 p2 = skip_string(p2,1);
2737 if (uLevel == 11) /* modelled after NTAS 3.51 reply */
2739 SSVAL(p,usri11_priv,conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2740 SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
2741 SIVALS(p,usri11_password_age,-1); /* password age */
2742 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
2743 pstrcpy(p2, vuser && vuser->homedir ? vuser->homedir : "");
2744 p2 = skip_string(p2,1);
2745 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
2746 pstrcpy(p2,"");
2747 p2 = skip_string(p2,1);
2748 SIVAL(p,usri11_last_logon,0); /* last logon */
2749 SIVAL(p,usri11_last_logoff,0); /* last logoff */
2750 SSVALS(p,usri11_bad_pw_count,-1); /* bad pw counts */
2751 SSVALS(p,usri11_num_logons,-1); /* num logons */
2752 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
2753 pstrcpy(p2,"\\\\*");
2754 p2 = skip_string(p2,1);
2755 SSVAL(p,usri11_country_code,0); /* country code */
2757 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
2758 pstrcpy(p2,"");
2759 p2 = skip_string(p2,1);
2761 SIVALS(p,usri11_max_storage,-1); /* max storage */
2762 SSVAL(p,usri11_units_per_week,168); /* units per week */
2763 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
2765 /* a simple way to get logon hours at all times. */
2766 memset(p2,0xff,21);
2767 SCVAL(p2,21,0); /* fix zero termination */
2768 p2 = skip_string(p2,1);
2770 SSVAL(p,usri11_code_page,0); /* code page */
2772 if (uLevel == 1 || uLevel == 2)
2774 memset(p+22,' ',16); /* password */
2775 SIVALS(p,38,-1); /* password age */
2776 SSVAL(p,42,
2777 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2778 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
2779 pstrcpy(p2, vuser && vuser->homedir ? vuser->homedir : "");
2780 p2 = skip_string(p2,1);
2781 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
2782 *p2++ = 0;
2783 SSVAL(p,52,0); /* flags */
2784 SIVAL(p,54,PTR_DIFF(p2,*rdata)); /* script_path */
2785 pstrcpy(p2,vuser && vuser->logon_script ? vuser->logon_script : "");
2786 p2 = skip_string(p2,1);
2787 if (uLevel == 2)
2789 SIVAL(p,60,0); /* auth_flags */
2790 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
2791 pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName));
2792 p2 = skip_string(p2,1);
2793 SIVAL(p,68,0); /* urs_comment */
2794 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
2795 pstrcpy(p2,"");
2796 p2 = skip_string(p2,1);
2797 SIVAL(p,76,0); /* workstations */
2798 SIVAL(p,80,0); /* last_logon */
2799 SIVAL(p,84,0); /* last_logoff */
2800 SIVALS(p,88,-1); /* acct_expires */
2801 SIVALS(p,92,-1); /* max_storage */
2802 SSVAL(p,96,168); /* units_per_week */
2803 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
2804 memset(p2,-1,21);
2805 p2 += 21;
2806 SSVALS(p,102,-1); /* bad_pw_count */
2807 SSVALS(p,104,-1); /* num_logons */
2808 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
2809 pstrcpy(p2,"\\\\%L");
2810 standard_sub_conn(conn, p2,0);
2811 p2 = skip_string(p2,1);
2812 SSVAL(p,110,49); /* country_code */
2813 SSVAL(p,112,860); /* code page */
2817 *rdata_len = PTR_DIFF(p2,*rdata);
2819 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
2821 return(True);
2824 static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param,char *data,
2825 int mdrcnt,int mprcnt,
2826 char **rdata,char **rparam,
2827 int *rdata_len,int *rparam_len)
2829 char *str1 = param+2;
2830 char *str2 = skip_string(str1,1);
2831 char *p = skip_string(str2,1);
2832 int uLevel;
2833 struct pack_desc desc;
2834 char* name;
2835 /* With share level security vuid will always be zero.
2836 Don't depend on vuser being non-null !!. JRA */
2837 user_struct *vuser = get_valid_user_struct(vuid);
2838 if(vuser != NULL)
2839 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid,
2840 vuser->user.unix_name));
2842 uLevel = SVAL(p,0);
2843 name = p + 2;
2845 memset((char *)&desc,'\0',sizeof(desc));
2847 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
2849 /* check it's a supported varient */
2850 if (strcmp(str1,"OOWb54WrLh") != 0) return False;
2851 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) return False;
2852 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2853 desc.base = *rdata;
2854 desc.buflen = mdrcnt;
2855 desc.subformat = NULL;
2856 desc.format = str2;
2858 if (init_package(&desc,1,0))
2860 PACKI(&desc,"W",0); /* code */
2861 PACKS(&desc,"B21",name); /* eff. name */
2862 PACKS(&desc,"B",""); /* pad */
2863 PACKI(&desc,"W",
2864 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2865 PACKI(&desc,"D",0); /* auth flags XXX */
2866 PACKI(&desc,"W",0); /* num logons */
2867 PACKI(&desc,"W",0); /* bad pw count */
2868 PACKI(&desc,"D",0); /* last logon */
2869 PACKI(&desc,"D",-1); /* last logoff */
2870 PACKI(&desc,"D",-1); /* logoff time */
2871 PACKI(&desc,"D",-1); /* kickoff time */
2872 PACKI(&desc,"D",0); /* password age */
2873 PACKI(&desc,"D",0); /* password can change */
2874 PACKI(&desc,"D",-1); /* password must change */
2876 fstring mypath;
2877 fstrcpy(mypath,"\\\\");
2878 fstrcat(mypath,local_machine);
2879 strupper_m(mypath);
2880 PACKS(&desc,"z",mypath); /* computer */
2882 PACKS(&desc,"z",lp_workgroup());/* domain */
2884 PACKS(&desc,"z", vuser && vuser->logon_script ? vuser->logon_script :""); /* script path */
2886 PACKI(&desc,"D",0x00000000); /* reserved */
2889 *rdata_len = desc.usedlen;
2890 *rparam_len = 6;
2891 *rparam = REALLOC(*rparam,*rparam_len);
2892 SSVALS(*rparam,0,desc.errcode);
2893 SSVAL(*rparam,2,0);
2894 SSVAL(*rparam,4,desc.neededlen);
2896 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
2897 return(True);
2901 /****************************************************************************
2902 api_WAccessGetUserPerms
2903 ****************************************************************************/
2904 static BOOL api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid, char *param,char *data,
2905 int mdrcnt,int mprcnt,
2906 char **rdata,char **rparam,
2907 int *rdata_len,int *rparam_len)
2909 char *str1 = param+2;
2910 char *str2 = skip_string(str1,1);
2911 char *user = skip_string(str2,1);
2912 char *resource = skip_string(user,1);
2914 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
2916 /* check it's a supported varient */
2917 if (strcmp(str1,"zzh") != 0) return False;
2918 if (strcmp(str2,"") != 0) return False;
2920 *rparam_len = 6;
2921 *rparam = REALLOC(*rparam,*rparam_len);
2922 SSVALS(*rparam,0,0); /* errorcode */
2923 SSVAL(*rparam,2,0); /* converter word */
2924 SSVAL(*rparam,4,0x7f); /* permission flags */
2926 return(True);
2929 /****************************************************************************
2930 api_WPrintJobEnumerate
2931 ****************************************************************************/
2932 static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2933 int mdrcnt,int mprcnt,
2934 char **rdata,char **rparam,
2935 int *rdata_len,int *rparam_len)
2937 char *str1 = param+2;
2938 char *str2 = skip_string(str1,1);
2939 char *p = skip_string(str2,1);
2940 int uLevel;
2941 int count;
2942 int i;
2943 int snum;
2944 fstring sharename;
2945 uint32 jobid;
2946 struct pack_desc desc;
2947 print_queue_struct *queue=NULL;
2948 print_status_struct status;
2949 char *tmpdata=NULL;
2951 uLevel = SVAL(p,2);
2953 memset((char *)&desc,'\0',sizeof(desc));
2954 memset((char *)&status,'\0',sizeof(status));
2956 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
2958 /* check it's a supported varient */
2959 if (strcmp(str1,"WWrLh") != 0) return False;
2960 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2962 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
2963 return False;
2965 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2967 count = print_queue_status(snum,&queue,&status);
2968 for (i = 0; i < count; i++) {
2969 if (queue[i].job == jobid) break;
2972 if (mdrcnt > 0) {
2973 *rdata = REALLOC(*rdata,mdrcnt);
2974 desc.base = *rdata;
2975 desc.buflen = mdrcnt;
2976 } else {
2978 * Don't return data but need to get correct length
2979 * init_package will return wrong size if buflen=0
2981 desc.buflen = getlen(desc.format);
2982 desc.base = tmpdata = (char *)malloc ( desc.buflen );
2985 if (init_package(&desc,1,0)) {
2986 if (i < count) {
2987 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
2988 *rdata_len = desc.usedlen;
2990 else {
2991 desc.errcode = NERR_JobNotFound;
2992 *rdata_len = 0;
2996 *rparam_len = 6;
2997 *rparam = REALLOC(*rparam,*rparam_len);
2998 SSVALS(*rparam,0,desc.errcode);
2999 SSVAL(*rparam,2,0);
3000 SSVAL(*rparam,4,desc.neededlen);
3002 SAFE_FREE(queue);
3003 SAFE_FREE(tmpdata);
3005 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
3006 return(True);
3009 static BOOL api_WPrintJobEnumerate(connection_struct *conn,uint16 vuid, char *param,char *data,
3010 int mdrcnt,int mprcnt,
3011 char **rdata,char **rparam,
3012 int *rdata_len,int *rparam_len)
3014 char *str1 = param+2;
3015 char *str2 = skip_string(str1,1);
3016 char *p = skip_string(str2,1);
3017 char* name = p;
3018 int uLevel;
3019 int count;
3020 int i, succnt=0;
3021 int snum;
3022 struct pack_desc desc;
3023 print_queue_struct *queue=NULL;
3024 print_status_struct status;
3026 memset((char *)&desc,'\0',sizeof(desc));
3027 memset((char *)&status,'\0',sizeof(status));
3029 p = skip_string(p,1);
3030 uLevel = SVAL(p,0);
3032 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
3034 /* check it's a supported variant */
3035 if (strcmp(str1,"zWrLeh") != 0) return False;
3036 if (uLevel > 2) return False; /* defined only for uLevel 0,1,2 */
3037 if (!check_printjob_info(&desc,uLevel,str2)) return False;
3039 snum = lp_servicenumber(name);
3040 if (snum < 0 && pcap_printername_ok(name,NULL)) {
3041 int pnum = lp_servicenumber(PRINTERS_NAME);
3042 if (pnum >= 0) {
3043 lp_add_printer(name,pnum);
3044 snum = lp_servicenumber(name);
3048 if (snum < 0 || !VALID_SNUM(snum)) return(False);
3050 count = print_queue_status(snum,&queue,&status);
3051 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3052 desc.base = *rdata;
3053 desc.buflen = mdrcnt;
3055 if (init_package(&desc,count,0)) {
3056 succnt = 0;
3057 for (i = 0; i < count; i++) {
3058 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
3059 if (desc.errcode == NERR_Success) succnt = i+1;
3063 *rdata_len = desc.usedlen;
3065 *rparam_len = 8;
3066 *rparam = REALLOC(*rparam,*rparam_len);
3067 SSVALS(*rparam,0,desc.errcode);
3068 SSVAL(*rparam,2,0);
3069 SSVAL(*rparam,4,succnt);
3070 SSVAL(*rparam,6,count);
3072 SAFE_FREE(queue);
3074 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
3075 return(True);
3078 static int check_printdest_info(struct pack_desc* desc,
3079 int uLevel, char* id)
3081 desc->subformat = NULL;
3082 switch( uLevel ) {
3083 case 0: desc->format = "B9"; break;
3084 case 1: desc->format = "B9B21WWzW"; break;
3085 case 2: desc->format = "z"; break;
3086 case 3: desc->format = "zzzWWzzzWW"; break;
3087 default: return False;
3089 if (strcmp(desc->format,id) != 0) return False;
3090 return True;
3093 static void fill_printdest_info(connection_struct *conn, int snum, int uLevel,
3094 struct pack_desc* desc)
3096 char buf[100];
3097 strncpy(buf,SERVICE(snum),sizeof(buf)-1);
3098 buf[sizeof(buf)-1] = 0;
3099 strupper_m(buf);
3100 if (uLevel <= 1) {
3101 PACKS(desc,"B9",buf); /* szName */
3102 if (uLevel == 1) {
3103 PACKS(desc,"B21",""); /* szUserName */
3104 PACKI(desc,"W",0); /* uJobId */
3105 PACKI(desc,"W",0); /* fsStatus */
3106 PACKS(desc,"z",""); /* pszStatus */
3107 PACKI(desc,"W",0); /* time */
3110 if (uLevel == 2 || uLevel == 3) {
3111 PACKS(desc,"z",buf); /* pszPrinterName */
3112 if (uLevel == 3) {
3113 PACKS(desc,"z",""); /* pszUserName */
3114 PACKS(desc,"z",""); /* pszLogAddr */
3115 PACKI(desc,"W",0); /* uJobId */
3116 PACKI(desc,"W",0); /* fsStatus */
3117 PACKS(desc,"z",""); /* pszStatus */
3118 PACKS(desc,"z",""); /* pszComment */
3119 PACKS(desc,"z","NULL"); /* pszDrivers */
3120 PACKI(desc,"W",0); /* time */
3121 PACKI(desc,"W",0); /* pad1 */
3126 static BOOL api_WPrintDestGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
3127 int mdrcnt,int mprcnt,
3128 char **rdata,char **rparam,
3129 int *rdata_len,int *rparam_len)
3131 char *str1 = param+2;
3132 char *str2 = skip_string(str1,1);
3133 char *p = skip_string(str2,1);
3134 char* PrinterName = p;
3135 int uLevel;
3136 struct pack_desc desc;
3137 int snum;
3138 char *tmpdata=NULL;
3140 memset((char *)&desc,'\0',sizeof(desc));
3142 p = skip_string(p,1);
3143 uLevel = SVAL(p,0);
3145 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
3147 /* check it's a supported varient */
3148 if (strcmp(str1,"zWrLh") != 0) return False;
3149 if (!check_printdest_info(&desc,uLevel,str2)) return False;
3151 snum = lp_servicenumber(PrinterName);
3152 if (snum < 0 && pcap_printername_ok(PrinterName,NULL)) {
3153 int pnum = lp_servicenumber(PRINTERS_NAME);
3154 if (pnum >= 0) {
3155 lp_add_printer(PrinterName,pnum);
3156 snum = lp_servicenumber(PrinterName);
3160 if (snum < 0) {
3161 *rdata_len = 0;
3162 desc.errcode = NERR_DestNotFound;
3163 desc.neededlen = 0;
3165 else {
3166 if (mdrcnt > 0) {
3167 *rdata = REALLOC(*rdata,mdrcnt);
3168 desc.base = *rdata;
3169 desc.buflen = mdrcnt;
3170 } else {
3172 * Don't return data but need to get correct length
3173 * init_package will return wrong size if buflen=0
3175 desc.buflen = getlen(desc.format);
3176 desc.base = tmpdata = (char *)malloc ( desc.buflen );
3178 if (init_package(&desc,1,0)) {
3179 fill_printdest_info(conn,snum,uLevel,&desc);
3181 *rdata_len = desc.usedlen;
3184 *rparam_len = 6;
3185 *rparam = REALLOC(*rparam,*rparam_len);
3186 SSVALS(*rparam,0,desc.errcode);
3187 SSVAL(*rparam,2,0);
3188 SSVAL(*rparam,4,desc.neededlen);
3190 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
3191 SAFE_FREE(tmpdata);
3192 return(True);
3195 static BOOL api_WPrintDestEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3196 int mdrcnt,int mprcnt,
3197 char **rdata,char **rparam,
3198 int *rdata_len,int *rparam_len)
3200 char *str1 = param+2;
3201 char *str2 = skip_string(str1,1);
3202 char *p = skip_string(str2,1);
3203 int uLevel;
3204 int queuecnt;
3205 int i, n, succnt=0;
3206 struct pack_desc desc;
3207 int services = lp_numservices();
3209 memset((char *)&desc,'\0',sizeof(desc));
3211 uLevel = SVAL(p,0);
3213 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
3215 /* check it's a supported varient */
3216 if (strcmp(str1,"WrLeh") != 0) return False;
3217 if (!check_printdest_info(&desc,uLevel,str2)) return False;
3219 queuecnt = 0;
3220 for (i = 0; i < services; i++)
3221 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
3222 queuecnt++;
3224 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3225 desc.base = *rdata;
3226 desc.buflen = mdrcnt;
3227 if (init_package(&desc,queuecnt,0)) {
3228 succnt = 0;
3229 n = 0;
3230 for (i = 0; i < services; i++) {
3231 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
3232 fill_printdest_info(conn,i,uLevel,&desc);
3233 n++;
3234 if (desc.errcode == NERR_Success) succnt = n;
3239 *rdata_len = desc.usedlen;
3241 *rparam_len = 8;
3242 *rparam = REALLOC(*rparam,*rparam_len);
3243 SSVALS(*rparam,0,desc.errcode);
3244 SSVAL(*rparam,2,0);
3245 SSVAL(*rparam,4,succnt);
3246 SSVAL(*rparam,6,queuecnt);
3248 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
3249 return(True);
3252 static BOOL api_WPrintDriverEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3253 int mdrcnt,int mprcnt,
3254 char **rdata,char **rparam,
3255 int *rdata_len,int *rparam_len)
3257 char *str1 = param+2;
3258 char *str2 = skip_string(str1,1);
3259 char *p = skip_string(str2,1);
3260 int uLevel;
3261 int succnt;
3262 struct pack_desc desc;
3264 memset((char *)&desc,'\0',sizeof(desc));
3266 uLevel = SVAL(p,0);
3268 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
3270 /* check it's a supported varient */
3271 if (strcmp(str1,"WrLeh") != 0) return False;
3272 if (uLevel != 0 || strcmp(str2,"B41") != 0) return False;
3274 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3275 desc.base = *rdata;
3276 desc.buflen = mdrcnt;
3277 if (init_package(&desc,1,0)) {
3278 PACKS(&desc,"B41","NULL");
3281 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3283 *rdata_len = desc.usedlen;
3285 *rparam_len = 8;
3286 *rparam = REALLOC(*rparam,*rparam_len);
3287 SSVALS(*rparam,0,desc.errcode);
3288 SSVAL(*rparam,2,0);
3289 SSVAL(*rparam,4,succnt);
3290 SSVAL(*rparam,6,1);
3292 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
3293 return(True);
3296 static BOOL api_WPrintQProcEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3297 int mdrcnt,int mprcnt,
3298 char **rdata,char **rparam,
3299 int *rdata_len,int *rparam_len)
3301 char *str1 = param+2;
3302 char *str2 = skip_string(str1,1);
3303 char *p = skip_string(str2,1);
3304 int uLevel;
3305 int succnt;
3306 struct pack_desc desc;
3308 memset((char *)&desc,'\0',sizeof(desc));
3310 uLevel = SVAL(p,0);
3312 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
3314 /* check it's a supported varient */
3315 if (strcmp(str1,"WrLeh") != 0) return False;
3316 if (uLevel != 0 || strcmp(str2,"B13") != 0) return False;
3318 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3319 desc.base = *rdata;
3320 desc.buflen = mdrcnt;
3321 desc.format = str2;
3322 if (init_package(&desc,1,0)) {
3323 PACKS(&desc,"B13","lpd");
3326 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3328 *rdata_len = desc.usedlen;
3330 *rparam_len = 8;
3331 *rparam = REALLOC(*rparam,*rparam_len);
3332 SSVALS(*rparam,0,desc.errcode);
3333 SSVAL(*rparam,2,0);
3334 SSVAL(*rparam,4,succnt);
3335 SSVAL(*rparam,6,1);
3337 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
3338 return(True);
3341 static BOOL api_WPrintPortEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3342 int mdrcnt,int mprcnt,
3343 char **rdata,char **rparam,
3344 int *rdata_len,int *rparam_len)
3346 char *str1 = param+2;
3347 char *str2 = skip_string(str1,1);
3348 char *p = skip_string(str2,1);
3349 int uLevel;
3350 int succnt;
3351 struct pack_desc desc;
3353 memset((char *)&desc,'\0',sizeof(desc));
3355 uLevel = SVAL(p,0);
3357 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
3359 /* check it's a supported varient */
3360 if (strcmp(str1,"WrLeh") != 0) return False;
3361 if (uLevel != 0 || strcmp(str2,"B9") != 0) return False;
3363 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3364 memset((char *)&desc,'\0',sizeof(desc));
3365 desc.base = *rdata;
3366 desc.buflen = mdrcnt;
3367 desc.format = str2;
3368 if (init_package(&desc,1,0)) {
3369 PACKS(&desc,"B13","lp0");
3372 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3374 *rdata_len = desc.usedlen;
3376 *rparam_len = 8;
3377 *rparam = REALLOC(*rparam,*rparam_len);
3378 SSVALS(*rparam,0,desc.errcode);
3379 SSVAL(*rparam,2,0);
3380 SSVAL(*rparam,4,succnt);
3381 SSVAL(*rparam,6,1);
3383 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
3384 return(True);
3388 /****************************************************************************
3389 List open sessions
3390 ****************************************************************************/
3391 static BOOL api_RNetSessionEnum(connection_struct *conn,uint16 vuid, char *param, char *data,
3392 int mdrcnt,int mprcnt,
3393 char **rdata,char **rparam,
3394 int *rdata_len,int *rparam_len)
3397 char *str1 = param+2;
3398 char *str2 = skip_string(str1,1);
3399 char *p = skip_string(str2,1);
3400 int uLevel;
3401 struct pack_desc desc;
3402 struct sessionid *session_list;
3403 int i, num_sessions;
3405 memset((char *)&desc,'\0',sizeof(desc));
3407 uLevel = SVAL(p,0);
3409 DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel));
3410 DEBUG(7,("RNetSessionEnum req string=%s\n",str1));
3411 DEBUG(7,("RNetSessionEnum ret string=%s\n",str2));
3413 /* check it's a supported varient */
3414 if (strcmp(str1,RAP_NetSessionEnum_REQ) != 0) return False;
3415 if (uLevel != 2 || strcmp(str2,RAP_SESSION_INFO_L2) != 0) return False;
3417 num_sessions = list_sessions(&session_list);
3419 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3420 memset((char *)&desc,'\0',sizeof(desc));
3421 desc.base = *rdata;
3422 desc.buflen = mdrcnt;
3423 desc.format = str2;
3424 if (!init_package(&desc,num_sessions,0)) {
3425 return False;
3428 for(i=0; i<num_sessions; i++) {
3429 PACKS(&desc, "z", session_list[i].remote_machine);
3430 PACKS(&desc, "z", session_list[i].username);
3431 PACKI(&desc, "W", 1); /* num conns */
3432 PACKI(&desc, "W", 0); /* num opens */
3433 PACKI(&desc, "W", 1); /* num users */
3434 PACKI(&desc, "D", 0); /* session time */
3435 PACKI(&desc, "D", 0); /* idle time */
3436 PACKI(&desc, "D", 0); /* flags */
3437 PACKS(&desc, "z", "Unknown Client"); /* client type string */
3440 *rdata_len = desc.usedlen;
3442 *rparam_len = 8;
3443 *rparam = REALLOC(*rparam,*rparam_len);
3444 SSVALS(*rparam,0,desc.errcode);
3445 SSVAL(*rparam,2,0); /* converter */
3446 SSVAL(*rparam,4,num_sessions); /* count */
3448 DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc.errcode));
3449 return True;
3453 /****************************************************************************
3454 The buffer was too small
3455 ****************************************************************************/
3457 static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param,char *data,
3458 int mdrcnt,int mprcnt,
3459 char **rdata,char **rparam,
3460 int *rdata_len,int *rparam_len)
3462 *rparam_len = MIN(*rparam_len,mprcnt);
3463 *rparam = REALLOC(*rparam,*rparam_len);
3465 *rdata_len = 0;
3467 SSVAL(*rparam,0,NERR_BufTooSmall);
3469 DEBUG(3,("Supplied buffer too small in API command\n"));
3471 return(True);
3475 /****************************************************************************
3476 The request is not supported
3477 ****************************************************************************/
3479 static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param,char *data,
3480 int mdrcnt,int mprcnt,
3481 char **rdata,char **rparam,
3482 int *rdata_len,int *rparam_len)
3484 *rparam_len = 4;
3485 *rparam = REALLOC(*rparam,*rparam_len);
3487 *rdata_len = 0;
3489 SSVAL(*rparam,0,NERR_notsupported);
3490 SSVAL(*rparam,2,0); /* converter word */
3492 DEBUG(3,("Unsupported API command\n"));
3494 return(True);
3500 static const struct
3502 const char *name;
3503 int id;
3504 BOOL (*fn)(connection_struct *,uint16,char *,char *,
3505 int,int,char **,char **,int *,int *);
3506 BOOL auth_user; /* Deny anonymous access? */
3507 } api_commands[] = {
3508 {"RNetShareEnum", RAP_WshareEnum, api_RNetShareEnum, True},
3509 {"RNetShareGetInfo", RAP_WshareGetInfo, api_RNetShareGetInfo},
3510 {"RNetShareAdd", RAP_WshareAdd, api_RNetShareAdd},
3511 {"RNetSessionEnum", RAP_WsessionEnum, api_RNetSessionEnum, True},
3512 {"RNetServerGetInfo", RAP_WserverGetInfo, api_RNetServerGetInfo},
3513 {"RNetGroupEnum", RAP_WGroupEnum, api_RNetGroupEnum, True},
3514 {"RNetGroupGetUsers", RAP_WGroupGetUsers, api_RNetGroupGetUsers, True},
3515 {"RNetUserEnum", RAP_WUserEnum, api_RNetUserEnum, True},
3516 {"RNetUserGetInfo", RAP_WUserGetInfo, api_RNetUserGetInfo},
3517 {"NetUserGetGroups", RAP_WUserGetGroups, api_NetUserGetGroups},
3518 {"NetWkstaGetInfo", RAP_WWkstaGetInfo, api_NetWkstaGetInfo},
3519 {"DosPrintQEnum", RAP_WPrintQEnum, api_DosPrintQEnum, True},
3520 {"DosPrintQGetInfo", RAP_WPrintQGetInfo, api_DosPrintQGetInfo},
3521 {"WPrintQueuePause", RAP_WPrintQPause, api_WPrintQueueCtrl},
3522 {"WPrintQueueResume", RAP_WPrintQContinue, api_WPrintQueueCtrl},
3523 {"WPrintJobEnumerate",RAP_WPrintJobEnum, api_WPrintJobEnumerate},
3524 {"WPrintJobGetInfo", RAP_WPrintJobGetInfo, api_WPrintJobGetInfo},
3525 {"RDosPrintJobDel", RAP_WPrintJobDel, api_RDosPrintJobDel},
3526 {"RDosPrintJobPause", RAP_WPrintJobPause, api_RDosPrintJobDel},
3527 {"RDosPrintJobResume",RAP_WPrintJobContinue, api_RDosPrintJobDel},
3528 {"WPrintDestEnum", RAP_WPrintDestEnum, api_WPrintDestEnum},
3529 {"WPrintDestGetInfo", RAP_WPrintDestGetInfo, api_WPrintDestGetInfo},
3530 {"NetRemoteTOD", RAP_NetRemoteTOD, api_NetRemoteTOD},
3531 {"WPrintQueuePurge", RAP_WPrintQPurge, api_WPrintQueueCtrl},
3532 {"NetServerEnum", RAP_NetServerEnum2, api_RNetServerEnum}, /* anon OK */
3533 {"WAccessGetUserPerms",RAP_WAccessGetUserPerms,api_WAccessGetUserPerms},
3534 {"SetUserPassword", RAP_WUserPasswordSet2, api_SetUserPassword},
3535 {"WWkstaUserLogon", RAP_WWkstaUserLogon, api_WWkstaUserLogon},
3536 {"PrintJobInfo", RAP_WPrintJobSetInfo, api_PrintJobInfo},
3537 {"WPrintDriverEnum", RAP_WPrintDriverEnum, api_WPrintDriverEnum},
3538 {"WPrintQProcEnum", RAP_WPrintQProcessorEnum,api_WPrintQProcEnum},
3539 {"WPrintPortEnum", RAP_WPrintPortEnum, api_WPrintPortEnum},
3540 {"SamOEMChangePassword",RAP_SamOEMChgPasswordUser2_P,api_SamOEMChangePassword}, /* anon OK */
3541 {NULL, -1, api_Unsupported}};
3543 /* The following RAP calls are not implemented by Samba:
3545 RAP_WFileEnum2 - anon not OK
3548 /****************************************************************************
3549 Handle remote api calls
3550 ****************************************************************************/
3552 int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data,char *params,
3553 int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
3555 int api_command;
3556 char *rdata = NULL;
3557 char *rparam = NULL;
3558 int rdata_len = 0;
3559 int rparam_len = 0;
3560 BOOL reply=False;
3561 int i;
3563 if (!params) {
3564 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
3565 return 0;
3568 api_command = SVAL(params,0);
3570 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
3571 api_command,
3572 params+2,
3573 skip_string(params+2,1),
3574 tdscnt,tpscnt,mdrcnt,mprcnt));
3576 for (i=0;api_commands[i].name;i++) {
3577 if (api_commands[i].id == api_command && api_commands[i].fn) {
3578 DEBUG(3,("Doing %s\n",api_commands[i].name));
3579 break;
3583 /* Check whether this api call can be done anonymously */
3585 if (api_commands[i].auth_user && lp_restrict_anonymous()) {
3586 user_struct *user = get_valid_user_struct(vuid);
3588 if (!user || user->guest)
3589 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
3592 rdata = (char *)malloc(1024);
3593 if (rdata)
3594 memset(rdata,'\0',1024);
3596 rparam = (char *)malloc(1024);
3597 if (rparam)
3598 memset(rparam,'\0',1024);
3600 if(!rdata || !rparam) {
3601 DEBUG(0,("api_reply: malloc fail !\n"));
3602 return -1;
3605 reply = api_commands[i].fn(conn,vuid,params,data,mdrcnt,mprcnt,
3606 &rdata,&rparam,&rdata_len,&rparam_len);
3609 if (rdata_len > mdrcnt ||
3610 rparam_len > mprcnt) {
3611 reply = api_TooSmall(conn,vuid,params,data,mdrcnt,mprcnt,
3612 &rdata,&rparam,&rdata_len,&rparam_len);
3615 /* if we get False back then it's actually unsupported */
3616 if (!reply)
3617 api_Unsupported(conn,vuid,params,data,mdrcnt,mprcnt,
3618 &rdata,&rparam,&rdata_len,&rparam_len);
3620 send_trans_reply(outbuf, rparam, rparam_len, rdata, rdata_len, False);
3622 SAFE_FREE(rdata);
3623 SAFE_FREE(rparam);
3625 return -1;