Minor comment updates ...
[Samba/gebeck_regimport.git] / source3 / smbd / lanman.c
blob3ea6ab483be4226faf999b960e3ef11152a06125
1 /*
2 Unix SMB/CIFS implementation.
3 Inter-process communication and named pipe handling
4 Copyright (C) Andrew Tridgell 1992-1998
6 SMB Version handling
7 Copyright (C) John H Terpstra 1995-1998
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 This file handles the named pipe and mailslot calls
25 in the SMBtrans protocol
28 #include "includes.h"
30 #ifdef CHECK_TYPES
31 #undef CHECK_TYPES
32 #endif
33 #define CHECK_TYPES 0
35 extern fstring local_machine;
37 #define NERR_Success 0
38 #define NERR_badpass 86
39 #define NERR_notsupported 50
41 #define NERR_BASE (2100)
42 #define NERR_BufTooSmall (NERR_BASE+23)
43 #define NERR_JobNotFound (NERR_BASE+51)
44 #define NERR_DestNotFound (NERR_BASE+52)
46 #define ACCESS_READ 0x01
47 #define ACCESS_WRITE 0x02
48 #define ACCESS_CREATE 0x04
50 #define SHPWLEN 8 /* share password length */
52 static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param,char *data,
53 int mdrcnt,int mprcnt,
54 char **rdata,char **rparam,
55 int *rdata_len,int *rparam_len);
56 static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param,char *data,
57 int mdrcnt,int mprcnt,
58 char **rdata,char **rparam,
59 int *rdata_len,int *rparam_len);
62 static int CopyExpanded(connection_struct *conn,
63 int snum, char** dst, char* src, int* n)
65 pstring buf;
66 int l;
68 if (!src || !dst || !n || !(*dst)) return(0);
70 StrnCpy(buf,src,sizeof(buf)/2);
71 pstring_sub(buf,"%S",lp_servicename(snum));
72 standard_sub_conn(conn,buf,sizeof(buf));
73 l = push_ascii(*dst,buf,*n, STR_TERMINATE);
74 (*dst) += l;
75 (*n) -= l;
76 return l;
79 static int CopyAndAdvance(char** dst, char* src, int* n)
81 int l;
82 if (!src || !dst || !n || !(*dst)) return(0);
83 l = push_ascii(*dst,src,*n, STR_TERMINATE);
84 (*dst) += l;
85 (*n) -= l;
86 return l;
89 static int StrlenExpanded(connection_struct *conn, int snum, char* s)
91 pstring buf;
92 if (!s) return(0);
93 StrnCpy(buf,s,sizeof(buf)/2);
94 pstring_sub(buf,"%S",lp_servicename(snum));
95 standard_sub_conn(conn,buf,sizeof(buf));
96 return strlen(buf) + 1;
99 static char* Expand(connection_struct *conn, int snum, char* s)
101 static pstring buf;
102 if (!s) return(NULL);
103 StrnCpy(buf,s,sizeof(buf)/2);
104 pstring_sub(buf,"%S",lp_servicename(snum));
105 standard_sub_conn(conn,buf,sizeof(buf));
106 return &buf[0];
109 /*******************************************************************
110 check a API string for validity when we only need to check the prefix
111 ******************************************************************/
112 static BOOL prefix_ok(const char *str, const char *prefix)
114 return(strncmp(str,prefix,strlen(prefix)) == 0);
117 struct pack_desc {
118 const char* format; /* formatstring for structure */
119 const char* subformat; /* subformat for structure */
120 char* base; /* baseaddress of buffer */
121 int buflen; /* remaining size for fixed part; on init: length of base */
122 int subcount; /* count of substructures */
123 char* structbuf; /* pointer into buffer for remaining fixed part */
124 int stringlen; /* remaining size for variable part */
125 char* stringbuf; /* pointer into buffer for remaining variable part */
126 int neededlen; /* total needed size */
127 int usedlen; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
128 const char* curpos; /* current position; pointer into format or subformat */
129 int errcode;
132 static int get_counter(const char** p)
134 int i, n;
135 if (!p || !(*p)) return(1);
136 if (!isdigit((int)**p)) return 1;
137 for (n = 0;;) {
138 i = **p;
139 if (isdigit(i))
140 n = 10 * n + (i - '0');
141 else
142 return n;
143 (*p)++;
147 static int getlen(const char* p)
149 int n = 0;
150 if (!p) return(0);
151 while (*p) {
152 switch( *p++ ) {
153 case 'W': /* word (2 byte) */
154 n += 2;
155 break;
156 case 'K': /* status word? (2 byte) */
157 n += 2;
158 break;
159 case 'N': /* count of substructures (word) at end */
160 n += 2;
161 break;
162 case 'D': /* double word (4 byte) */
163 case 'z': /* offset to zero terminated string (4 byte) */
164 case 'l': /* offset to user data (4 byte) */
165 n += 4;
166 break;
167 case 'b': /* offset to data (with counter) (4 byte) */
168 n += 4;
169 get_counter(&p);
170 break;
171 case 'B': /* byte (with optional counter) */
172 n += get_counter(&p);
173 break;
176 return n;
179 static BOOL init_package(struct pack_desc* p, int count, int subcount)
181 int n = p->buflen;
182 int i;
184 if (!p->format || !p->base) return(False);
186 i = count * getlen(p->format);
187 if (p->subformat) i += subcount * getlen(p->subformat);
188 p->structbuf = p->base;
189 p->neededlen = 0;
190 p->usedlen = 0;
191 p->subcount = 0;
192 p->curpos = p->format;
193 if (i > n) {
194 p->neededlen = i;
195 i = n = 0;
196 #if 0
198 * This is the old error code we used. Aparently
199 * WinNT/2k systems return ERRbuftoosmall (2123) and
200 * OS/2 needs this. I'm leaving this here so we can revert
201 * if needed. JRA.
203 p->errcode = ERRmoredata;
204 #else
205 p->errcode = ERRbuftoosmall;
206 #endif
208 else
209 p->errcode = NERR_Success;
210 p->buflen = i;
211 n -= i;
212 p->stringbuf = p->base + i;
213 p->stringlen = n;
214 return(p->errcode == NERR_Success);
217 static int package(struct pack_desc* p, ...)
219 va_list args;
220 int needed=0, stringneeded;
221 const char* str=NULL;
222 int is_string=0, stringused;
223 int32 temp;
225 va_start(args,p);
227 if (!*p->curpos) {
228 if (!p->subcount)
229 p->curpos = p->format;
230 else {
231 p->curpos = p->subformat;
232 p->subcount--;
235 #if CHECK_TYPES
236 str = va_arg(args,char*);
237 SMB_ASSERT(strncmp(str,p->curpos,strlen(str)) == 0);
238 #endif
239 stringneeded = -1;
241 if (!p->curpos) {
242 va_end(args);
243 return(0);
246 switch( *p->curpos++ ) {
247 case 'W': /* word (2 byte) */
248 needed = 2;
249 temp = va_arg(args,int);
250 if (p->buflen >= needed) SSVAL(p->structbuf,0,temp);
251 break;
252 case 'K': /* status word? (2 byte) */
253 needed = 2;
254 temp = va_arg(args,int);
255 if (p->buflen >= needed) SSVAL(p->structbuf,0,temp);
256 break;
257 case 'N': /* count of substructures (word) at end */
258 needed = 2;
259 p->subcount = va_arg(args,int);
260 if (p->buflen >= needed) SSVAL(p->structbuf,0,p->subcount);
261 break;
262 case 'D': /* double word (4 byte) */
263 needed = 4;
264 temp = va_arg(args,int);
265 if (p->buflen >= needed) SIVAL(p->structbuf,0,temp);
266 break;
267 case 'B': /* byte (with optional counter) */
268 needed = get_counter(&p->curpos);
270 char *s = va_arg(args,char*);
271 if (p->buflen >= needed) StrnCpy(p->structbuf,s?s:"",needed-1);
273 break;
274 case 'z': /* offset to zero terminated string (4 byte) */
275 str = va_arg(args,char*);
276 stringneeded = (str ? strlen(str)+1 : 0);
277 is_string = 1;
278 break;
279 case 'l': /* offset to user data (4 byte) */
280 str = va_arg(args,char*);
281 stringneeded = va_arg(args,int);
282 is_string = 0;
283 break;
284 case 'b': /* offset to data (with counter) (4 byte) */
285 str = va_arg(args,char*);
286 stringneeded = get_counter(&p->curpos);
287 is_string = 0;
288 break;
290 va_end(args);
291 if (stringneeded >= 0) {
292 needed = 4;
293 if (p->buflen >= needed) {
294 stringused = stringneeded;
295 if (stringused > p->stringlen) {
296 stringused = (is_string ? p->stringlen : 0);
297 if (p->errcode == NERR_Success) p->errcode = ERRmoredata;
299 if (!stringused)
300 SIVAL(p->structbuf,0,0);
301 else {
302 SIVAL(p->structbuf,0,PTR_DIFF(p->stringbuf,p->base));
303 memcpy(p->stringbuf,str?str:"",stringused);
304 if (is_string) p->stringbuf[stringused-1] = '\0';
305 p->stringbuf += stringused;
306 p->stringlen -= stringused;
307 p->usedlen += stringused;
310 p->neededlen += stringneeded;
312 p->neededlen += needed;
313 if (p->buflen >= needed) {
314 p->structbuf += needed;
315 p->buflen -= needed;
316 p->usedlen += needed;
318 else {
319 if (p->errcode == NERR_Success) p->errcode = ERRmoredata;
321 return 1;
324 #if CHECK_TYPES
325 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
326 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
327 #else
328 #define PACK(desc,t,v) package(desc,v)
329 #define PACKl(desc,t,v,l) package(desc,v,l)
330 #endif
332 static void PACKI(struct pack_desc* desc, const char *t,int v)
334 PACK(desc,t,v);
337 static void PACKS(struct pack_desc* desc,const char *t,const char *v)
339 PACK(desc,t,v);
343 /****************************************************************************
344 get a print queue
345 ****************************************************************************/
346 static void PackDriverData(struct pack_desc* desc)
348 char drivdata[4+4+32];
349 SIVAL(drivdata,0,sizeof drivdata); /* cb */
350 SIVAL(drivdata,4,1000); /* lVersion */
351 memset(drivdata+8,0,32); /* szDeviceName */
352 push_ascii(drivdata+8,"NULL",-1, STR_TERMINATE);
353 PACKl(desc,"l",drivdata,sizeof drivdata); /* pDriverData */
356 static int check_printq_info(struct pack_desc* desc,
357 int uLevel, char *id1, char *id2)
359 desc->subformat = NULL;
360 switch( uLevel ) {
361 case 0:
362 desc->format = "B13";
363 break;
364 case 1:
365 desc->format = "B13BWWWzzzzzWW";
366 break;
367 case 2:
368 desc->format = "B13BWWWzzzzzWN";
369 desc->subformat = "WB21BB16B10zWWzDDz";
370 break;
371 case 3:
372 desc->format = "zWWWWzzzzWWzzl";
373 break;
374 case 4:
375 desc->format = "zWWWWzzzzWNzzl";
376 desc->subformat = "WWzWWDDzz";
377 break;
378 case 5:
379 desc->format = "z";
380 break;
381 case 51:
382 desc->format = "K";
383 break;
384 case 52:
385 desc->format = "WzzzzzzzzN";
386 desc->subformat = "z";
387 break;
388 default: return False;
390 if (strcmp(desc->format,id1) != 0) return False;
391 if (desc->subformat && strcmp(desc->subformat,id2) != 0) return False;
392 return True;
396 #define RAP_JOB_STATUS_QUEUED 0
397 #define RAP_JOB_STATUS_PAUSED 1
398 #define RAP_JOB_STATUS_SPOOLING 2
399 #define RAP_JOB_STATUS_PRINTING 3
400 #define RAP_JOB_STATUS_PRINTED 4
402 #define RAP_QUEUE_STATUS_PAUSED 1
403 #define RAP_QUEUE_STATUS_ERROR 2
405 /* turn a print job status into a on the wire status
407 static int printj_status(int v)
409 switch (v) {
410 case LPQ_QUEUED:
411 return RAP_JOB_STATUS_QUEUED;
412 case LPQ_PAUSED:
413 return RAP_JOB_STATUS_PAUSED;
414 case LPQ_SPOOLING:
415 return RAP_JOB_STATUS_SPOOLING;
416 case LPQ_PRINTING:
417 return RAP_JOB_STATUS_PRINTING;
419 return 0;
422 /* turn a print queue status into a on the wire status
424 static int printq_status(int v)
426 switch (v) {
427 case LPQ_QUEUED:
428 return 0;
429 case LPQ_PAUSED:
430 return RAP_QUEUE_STATUS_PAUSED;
432 return RAP_QUEUE_STATUS_ERROR;
435 static void fill_printjob_info(connection_struct *conn, int snum, int uLevel,
436 struct pack_desc* desc,
437 print_queue_struct* queue, int n)
439 time_t t = queue->time;
441 /* the client expects localtime */
442 t -= TimeDiff(t);
444 PACKI(desc,"W",pjobid_to_rap(snum,queue->job)); /* uJobId */
445 if (uLevel == 1) {
446 PACKS(desc,"B21",queue->fs_user); /* szUserName */
447 PACKS(desc,"B",""); /* pad */
448 PACKS(desc,"B16",""); /* szNotifyName */
449 PACKS(desc,"B10","PM_Q_RAW"); /* szDataType */
450 PACKS(desc,"z",""); /* pszParms */
451 PACKI(desc,"W",n+1); /* uPosition */
452 PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */
453 PACKS(desc,"z",""); /* pszStatus */
454 PACKI(desc,"D",t); /* ulSubmitted */
455 PACKI(desc,"D",queue->size); /* ulSize */
456 PACKS(desc,"z",queue->fs_file); /* pszComment */
458 if (uLevel == 2 || uLevel == 3 || uLevel == 4) {
459 PACKI(desc,"W",queue->priority); /* uPriority */
460 PACKS(desc,"z",queue->fs_user); /* pszUserName */
461 PACKI(desc,"W",n+1); /* uPosition */
462 PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */
463 PACKI(desc,"D",t); /* ulSubmitted */
464 PACKI(desc,"D",queue->size); /* ulSize */
465 PACKS(desc,"z","Samba"); /* pszComment */
466 PACKS(desc,"z",queue->fs_file); /* pszDocument */
467 if (uLevel == 3) {
468 PACKS(desc,"z",""); /* pszNotifyName */
469 PACKS(desc,"z","PM_Q_RAW"); /* pszDataType */
470 PACKS(desc,"z",""); /* pszParms */
471 PACKS(desc,"z",""); /* pszStatus */
472 PACKS(desc,"z",SERVICE(snum)); /* pszQueue */
473 PACKS(desc,"z","lpd"); /* pszQProcName */
474 PACKS(desc,"z",""); /* pszQProcParms */
475 PACKS(desc,"z","NULL"); /* pszDriverName */
476 PackDriverData(desc); /* pDriverData */
477 PACKS(desc,"z",""); /* pszPrinterName */
478 } else if (uLevel == 4) { /* OS2 */
479 PACKS(desc,"z",""); /* pszSpoolFileName */
480 PACKS(desc,"z",""); /* pszPortName */
481 PACKS(desc,"z",""); /* pszStatus */
482 PACKI(desc,"D",0); /* ulPagesSpooled */
483 PACKI(desc,"D",0); /* ulPagesSent */
484 PACKI(desc,"D",0); /* ulPagesPrinted */
485 PACKI(desc,"D",0); /* ulTimePrinted */
486 PACKI(desc,"D",0); /* ulExtendJobStatus */
487 PACKI(desc,"D",0); /* ulStartPage */
488 PACKI(desc,"D",0); /* ulEndPage */
493 /********************************************************************
494 Return a driver name given an snum.
495 Returns True if from tdb, False otherwise.
496 ********************************************************************/
498 static BOOL get_driver_name(int snum, pstring drivername)
500 NT_PRINTER_INFO_LEVEL *info = NULL;
501 BOOL in_tdb = False;
503 get_a_printer (NULL, &info, 2, lp_servicename(snum));
504 if (info != NULL) {
505 pstrcpy( drivername, info->info_2->drivername);
506 in_tdb = True;
507 free_a_printer(&info, 2);
510 return in_tdb;
513 /********************************************************************
514 Respond to the DosPrintQInfo command with a level of 52
515 This is used to get printer driver information for Win9x clients
516 ********************************************************************/
517 static void fill_printq_info_52(connection_struct *conn, int snum,
518 struct pack_desc* desc, int count )
520 int i;
521 fstring location;
522 NT_PRINTER_DRIVER_INFO_LEVEL driver;
523 NT_PRINTER_INFO_LEVEL *printer = NULL;
525 ZERO_STRUCT(driver);
527 if ( !W_ERROR_IS_OK(get_a_printer( NULL, &printer, 2, lp_servicename(snum))) ) {
528 DEBUG(3,("fill_printq_info_52: Failed to lookup printer [%s]\n",
529 lp_servicename(snum)));
530 goto err;
533 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername,
534 "Windows 4.0", 0)) )
536 DEBUG(3,("fill_printq_info_52: Failed to lookup driver [%s]\n",
537 printer->info_2->drivername));
538 goto err;
541 trim_string(driver.info_3->driverpath, "\\print$\\WIN40\\0\\", 0);
542 trim_string(driver.info_3->datafile, "\\print$\\WIN40\\0\\", 0);
543 trim_string(driver.info_3->helpfile, "\\print$\\WIN40\\0\\", 0);
545 PACKI(desc, "W", 0x0400); /* don't know */
546 PACKS(desc, "z", driver.info_3->name); /* long printer name */
547 PACKS(desc, "z", driver.info_3->driverpath); /* Driverfile Name */
548 PACKS(desc, "z", driver.info_3->datafile); /* Datafile name */
549 PACKS(desc, "z", driver.info_3->monitorname); /* language monitor */
551 fstrcpy(location, "\\\\");
552 fstrcat(location, get_called_name());
553 fstrcat(location, "\\print$\\WIN40\\0");
554 PACKS(desc,"z", location); /* share to retrieve files */
556 PACKS(desc,"z", driver.info_3->defaultdatatype); /* default data type */
557 PACKS(desc,"z", driver.info_3->helpfile); /* helpfile name */
558 PACKS(desc,"z", driver.info_3->driverpath); /* driver name */
560 DEBUG(3,("Printer Driver Name: %s:\n",driver.info_3->name));
561 DEBUG(3,("Driver: %s:\n",driver.info_3->driverpath));
562 DEBUG(3,("Data File: %s:\n",driver.info_3->datafile));
563 DEBUG(3,("Language Monitor: %s:\n",driver.info_3->monitorname));
564 DEBUG(3,("Driver Location: %s:\n",location));
565 DEBUG(3,("Data Type: %s:\n",driver.info_3->defaultdatatype));
566 DEBUG(3,("Help File: %s:\n",driver.info_3->helpfile));
567 PACKI(desc,"N",count); /* number of files to copy */
569 for ( i=0; i<count && driver.info_3->dependentfiles && *driver.info_3->dependentfiles[i]; i++)
571 trim_string(driver.info_3->dependentfiles[i], "\\print$\\WIN40\\0\\", 0);
572 PACKS(desc,"z",driver.info_3->dependentfiles[i]); /* driver files to copy */
573 DEBUG(3,("Dependent File: %s:\n",driver.info_3->dependentfiles[i]));
576 /* sanity check */
577 if ( i != count )
578 DEBUG(3,("fill_printq_info_52: file count specified by client [%d] != number of dependent files [%i]\n",
579 count, i));
581 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n", SERVICE(snum),i));
583 desc->errcode=NERR_Success;
584 goto done;
586 err:
587 DEBUG(3,("fill_printq_info: Can't supply driver files\n"));
588 desc->errcode=NERR_notsupported;
590 done:
591 if ( printer )
592 free_a_printer( &printer, 2 );
594 if ( driver.info_3 )
595 free_a_printer_driver( driver, 3 );
599 static void fill_printq_info(connection_struct *conn, int snum, int uLevel,
600 struct pack_desc* desc,
601 int count, print_queue_struct* queue,
602 print_status_struct* status)
604 switch (uLevel) {
605 case 1:
606 case 2:
607 PACKS(desc,"B13",SERVICE(snum));
608 break;
609 case 3:
610 case 4:
611 case 5:
612 PACKS(desc,"z",Expand(conn,snum,SERVICE(snum)));
613 break;
614 case 51:
615 PACKI(desc,"K",printq_status(status->status));
616 break;
619 if (uLevel == 1 || uLevel == 2) {
620 PACKS(desc,"B",""); /* alignment */
621 PACKI(desc,"W",5); /* priority */
622 PACKI(desc,"W",0); /* start time */
623 PACKI(desc,"W",0); /* until time */
624 PACKS(desc,"z",""); /* pSepFile */
625 PACKS(desc,"z","lpd"); /* pPrProc */
626 PACKS(desc,"z",SERVICE(snum)); /* pDestinations */
627 PACKS(desc,"z",""); /* pParms */
628 if (snum < 0) {
629 PACKS(desc,"z","UNKNOWN PRINTER");
630 PACKI(desc,"W",LPSTAT_ERROR);
632 else if (!status || !status->message[0]) {
633 PACKS(desc,"z",Expand(conn,snum,lp_comment(snum)));
634 PACKI(desc,"W",LPSTAT_OK); /* status */
635 } else {
636 PACKS(desc,"z",status->message);
637 PACKI(desc,"W",printq_status(status->status)); /* status */
639 PACKI(desc,(uLevel == 1 ? "W" : "N"),count);
642 if (uLevel == 3 || uLevel == 4) {
643 pstring drivername;
645 PACKI(desc,"W",5); /* uPriority */
646 PACKI(desc,"W",0); /* uStarttime */
647 PACKI(desc,"W",0); /* uUntiltime */
648 PACKI(desc,"W",5); /* pad1 */
649 PACKS(desc,"z",""); /* pszSepFile */
650 PACKS(desc,"z","WinPrint"); /* pszPrProc */
651 PACKS(desc,"z",NULL); /* pszParms */
652 PACKS(desc,"z",NULL); /* pszComment - don't ask.... JRA */
653 /* "don't ask" that it's done this way to fix corrupted
654 Win9X/ME printer comments. */
655 if (!status) {
656 PACKI(desc,"W",LPSTAT_OK); /* fsStatus */
657 } else {
658 PACKI(desc,"W",printq_status(status->status)); /* fsStatus */
660 PACKI(desc,(uLevel == 3 ? "W" : "N"),count); /* cJobs */
661 PACKS(desc,"z",SERVICE(snum)); /* pszPrinters */
662 get_driver_name(snum,drivername);
663 PACKS(desc,"z",drivername); /* pszDriverName */
664 PackDriverData(desc); /* pDriverData */
667 if (uLevel == 2 || uLevel == 4) {
668 int i;
669 for (i=0;i<count;i++)
670 fill_printjob_info(conn,snum,uLevel == 2 ? 1 : 2,desc,&queue[i],i);
673 if (uLevel==52)
674 fill_printq_info_52( conn, snum, desc, count );
677 /* This function returns the number of files for a given driver */
678 static int get_printerdrivernumber(int snum)
680 int result = 0;
681 NT_PRINTER_DRIVER_INFO_LEVEL driver;
682 NT_PRINTER_INFO_LEVEL *printer = NULL;
684 ZERO_STRUCT(driver);
686 if ( !W_ERROR_IS_OK(get_a_printer( NULL, &printer, 2, lp_servicename(snum))) ) {
687 DEBUG(3,("get_printerdrivernumber: Failed to lookup printer [%s]\n",
688 lp_servicename(snum)));
689 goto done;
692 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername,
693 "Windows 4.0", 0)) )
695 DEBUG(3,("get_printerdrivernumber: Failed to lookup driver [%s]\n",
696 printer->info_2->drivername));
697 goto done;
700 /* count the number of files */
701 while ( driver.info_3->dependentfiles && *driver.info_3->dependentfiles[result] )
702 result++;
704 done:
705 if ( printer )
706 free_a_printer( &printer, 2 );
708 if ( driver.info_3 )
709 free_a_printer_driver( driver, 3 );
711 return result;
714 static BOOL api_DosPrintQGetInfo(connection_struct *conn,
715 uint16 vuid, char *param,char *data,
716 int mdrcnt,int mprcnt,
717 char **rdata,char **rparam,
718 int *rdata_len,int *rparam_len)
720 char *str1 = param+2;
721 char *str2 = skip_string(str1,1);
722 char *p = skip_string(str2,1);
723 char *QueueName = p;
724 int uLevel;
725 int count=0;
726 int snum;
727 char* str3;
728 struct pack_desc desc;
729 print_queue_struct *queue=NULL;
730 print_status_struct status;
731 char* tmpdata=NULL;
733 memset((char *)&status,'\0',sizeof(status));
734 memset((char *)&desc,'\0',sizeof(desc));
736 p = skip_string(p,1);
737 uLevel = SVAL(p,0);
738 str3 = p + 4;
740 /* remove any trailing username */
741 if ((p = strchr_m(QueueName,'%')))
742 *p = 0;
744 DEBUG(3,("api_DosPrintQGetInfo uLevel=%d name=%s\n",uLevel,QueueName));
746 /* check it's a supported varient */
747 if (!prefix_ok(str1,"zWrLh"))
748 return False;
749 if (!check_printq_info(&desc,uLevel,str2,str3)) {
751 * Patch from Scott Moomaw <scott@bridgewater.edu>
752 * to return the 'invalid info level' error if an
753 * unknown level was requested.
755 *rdata_len = 0;
756 *rparam_len = 6;
757 *rparam = REALLOC(*rparam,*rparam_len);
758 SSVALS(*rparam,0,ERRunknownlevel);
759 SSVAL(*rparam,2,0);
760 SSVAL(*rparam,4,0);
761 return(True);
764 snum = lp_servicenumber(QueueName);
765 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
766 int pnum = lp_servicenumber(PRINTERS_NAME);
767 if (pnum >= 0) {
768 lp_add_printer(QueueName,pnum);
769 snum = lp_servicenumber(QueueName);
773 if (snum < 0 || !VALID_SNUM(snum))
774 return(False);
776 if (uLevel==52) {
777 count = get_printerdrivernumber(snum);
778 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count));
779 } else {
780 count = print_queue_status(snum, &queue,&status);
783 if (mdrcnt > 0) {
784 *rdata = REALLOC(*rdata,mdrcnt);
785 desc.base = *rdata;
786 desc.buflen = mdrcnt;
787 } else {
789 * Don't return data but need to get correct length
790 * init_package will return wrong size if buflen=0
792 desc.buflen = getlen(desc.format);
793 desc.base = tmpdata = (char *) malloc (desc.buflen);
796 if (init_package(&desc,1,count)) {
797 desc.subcount = count;
798 fill_printq_info(conn,snum,uLevel,&desc,count,queue,&status);
801 *rdata_len = desc.usedlen;
804 * We must set the return code to ERRbuftoosmall
805 * in order to support lanman style printing with Win NT/2k
806 * clients --jerry
808 if (!mdrcnt && lp_disable_spoolss())
809 desc.errcode = ERRbuftoosmall;
811 *rdata_len = desc.usedlen;
812 *rparam_len = 6;
813 *rparam = REALLOC(*rparam,*rparam_len);
814 SSVALS(*rparam,0,desc.errcode);
815 SSVAL(*rparam,2,0);
816 SSVAL(*rparam,4,desc.neededlen);
818 DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode));
820 SAFE_FREE(queue);
821 SAFE_FREE(tmpdata);
823 return(True);
826 /****************************************************************************
827 View list of all print jobs on all queues.
828 ****************************************************************************/
830 static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid, char* param, char* data,
831 int mdrcnt, int mprcnt,
832 char **rdata, char** rparam,
833 int *rdata_len, int *rparam_len)
835 char *param_format = param+2;
836 char *output_format1 = skip_string(param_format,1);
837 char *p = skip_string(output_format1,1);
838 int uLevel = SVAL(p,0);
839 char *output_format2 = p + 4;
840 int services = lp_numservices();
841 int i, n;
842 struct pack_desc desc;
843 print_queue_struct **queue = NULL;
844 print_status_struct *status = NULL;
845 int* subcntarr = NULL;
846 int queuecnt, subcnt=0, succnt=0;
848 memset((char *)&desc,'\0',sizeof(desc));
850 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
852 if (!prefix_ok(param_format,"WrLeh")) return False;
853 if (!check_printq_info(&desc,uLevel,output_format1,output_format2)) {
855 * Patch from Scott Moomaw <scott@bridgewater.edu>
856 * to return the 'invalid info level' error if an
857 * unknown level was requested.
859 *rdata_len = 0;
860 *rparam_len = 6;
861 *rparam = REALLOC(*rparam,*rparam_len);
862 SSVALS(*rparam,0,ERRunknownlevel);
863 SSVAL(*rparam,2,0);
864 SSVAL(*rparam,4,0);
865 return(True);
868 queuecnt = 0;
869 for (i = 0; i < services; i++)
870 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
871 queuecnt++;
872 if (uLevel > 0) {
873 if((queue = (print_queue_struct**)malloc(queuecnt*sizeof(print_queue_struct*))) == NULL) {
874 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
875 return False;
877 memset(queue,0,queuecnt*sizeof(print_queue_struct*));
878 if((status = (print_status_struct*)malloc(queuecnt*sizeof(print_status_struct))) == NULL) {
879 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
880 return False;
882 memset(status,0,queuecnt*sizeof(print_status_struct));
883 if((subcntarr = (int*)malloc(queuecnt*sizeof(int))) == NULL) {
884 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
885 return False;
887 subcnt = 0;
888 n = 0;
889 for (i = 0; i < services; i++)
890 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
891 subcntarr[n] = print_queue_status(i, &queue[n],&status[n]);
892 subcnt += subcntarr[n];
893 n++;
896 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
897 desc.base = *rdata;
898 desc.buflen = mdrcnt;
900 if (init_package(&desc,queuecnt,subcnt)) {
901 n = 0;
902 succnt = 0;
903 for (i = 0; i < services; i++)
904 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
905 fill_printq_info(conn,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]);
906 n++;
907 if (desc.errcode == NERR_Success) succnt = n;
911 SAFE_FREE(subcntarr);
913 *rdata_len = desc.usedlen;
914 *rparam_len = 8;
915 *rparam = REALLOC(*rparam,*rparam_len);
916 SSVALS(*rparam,0,desc.errcode);
917 SSVAL(*rparam,2,0);
918 SSVAL(*rparam,4,succnt);
919 SSVAL(*rparam,6,queuecnt);
921 for (i = 0; i < queuecnt; i++) {
922 if (queue) SAFE_FREE(queue[i]);
925 SAFE_FREE(queue);
926 SAFE_FREE(status);
928 return True;
931 /****************************************************************************
932 get info level for a server list query
933 ****************************************************************************/
934 static BOOL check_server_info(int uLevel, char* id)
936 switch( uLevel ) {
937 case 0:
938 if (strcmp(id,"B16") != 0) return False;
939 break;
940 case 1:
941 if (strcmp(id,"B16BBDz") != 0) return False;
942 break;
943 default:
944 return False;
946 return True;
949 struct srv_info_struct
951 fstring name;
952 uint32 type;
953 fstring comment;
954 fstring domain;
955 BOOL server_added;
959 /*******************************************************************
960 get server info lists from the files saved by nmbd. Return the
961 number of entries
962 ******************************************************************/
963 static int get_server_info(uint32 servertype,
964 struct srv_info_struct **servers,
965 const char *domain)
967 int count=0;
968 int alloced=0;
969 char **lines;
970 BOOL local_list_only;
971 int i;
973 lines = file_lines_load(lock_path(SERVER_LIST), NULL);
974 if (!lines) {
975 DEBUG(4,("Can't open %s - %s\n",lock_path(SERVER_LIST),strerror(errno)));
976 return(0);
979 /* request for everything is code for request all servers */
980 if (servertype == SV_TYPE_ALL)
981 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
983 local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY);
985 DEBUG(4,("Servertype search: %8x\n",servertype));
987 for (i=0;lines[i];i++) {
988 fstring stype;
989 struct srv_info_struct *s;
990 const char *ptr = lines[i];
991 BOOL ok = True;
993 if (!*ptr) continue;
995 if (count == alloced) {
996 struct srv_info_struct *ts;
998 alloced += 10;
999 ts = (struct srv_info_struct *)
1000 Realloc(*servers,sizeof(**servers)*alloced);
1001 if (!ts) {
1002 DEBUG(0,("get_server_info: failed to enlarge servers info struct!\n"));
1003 return(0);
1005 else *servers = ts;
1006 memset((char *)((*servers)+count),'\0',sizeof(**servers)*(alloced-count));
1008 s = &(*servers)[count];
1010 if (!next_token(&ptr,s->name , NULL, sizeof(s->name))) continue;
1011 if (!next_token(&ptr,stype , NULL, sizeof(stype))) continue;
1012 if (!next_token(&ptr,s->comment, NULL, sizeof(s->comment))) continue;
1013 if (!next_token(&ptr,s->domain , NULL, sizeof(s->domain))) {
1014 /* this allows us to cope with an old nmbd */
1015 fstrcpy(s->domain,lp_workgroup());
1018 if (sscanf(stype,"%X",&s->type) != 1) {
1019 DEBUG(4,("r:host file "));
1020 ok = False;
1023 /* Filter the servers/domains we return based on what was asked for. */
1025 /* Check to see if we are being asked for a local list only. */
1026 if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) {
1027 DEBUG(4,("r: local list only"));
1028 ok = False;
1031 /* doesn't match up: don't want it */
1032 if (!(servertype & s->type)) {
1033 DEBUG(4,("r:serv type "));
1034 ok = False;
1037 if ((servertype & SV_TYPE_DOMAIN_ENUM) !=
1038 (s->type & SV_TYPE_DOMAIN_ENUM))
1040 DEBUG(4,("s: dom mismatch "));
1041 ok = False;
1044 if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM))
1046 ok = False;
1049 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1050 s->type &= ~SV_TYPE_LOCAL_LIST_ONLY;
1052 if (ok)
1054 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1055 s->name, s->type, s->comment, s->domain));
1057 s->server_added = True;
1058 count++;
1060 else
1062 DEBUG(4,("%20s %8x %25s %15s\n",
1063 s->name, s->type, s->comment, s->domain));
1067 file_lines_free(lines);
1068 return(count);
1072 /*******************************************************************
1073 fill in a server info structure
1074 ******************************************************************/
1075 static int fill_srv_info(struct srv_info_struct *service,
1076 int uLevel, char **buf, int *buflen,
1077 char **stringbuf, int *stringspace, char *baseaddr)
1079 int struct_len;
1080 char* p;
1081 char* p2;
1082 int l2;
1083 int len;
1085 switch (uLevel) {
1086 case 0: struct_len = 16; break;
1087 case 1: struct_len = 26; break;
1088 default: return -1;
1091 if (!buf)
1093 len = 0;
1094 switch (uLevel)
1096 case 1:
1097 len = strlen(service->comment)+1;
1098 break;
1101 if (buflen) *buflen = struct_len;
1102 if (stringspace) *stringspace = len;
1103 return struct_len + len;
1106 len = struct_len;
1107 p = *buf;
1108 if (*buflen < struct_len) return -1;
1109 if (stringbuf)
1111 p2 = *stringbuf;
1112 l2 = *stringspace;
1114 else
1116 p2 = p + struct_len;
1117 l2 = *buflen - struct_len;
1119 if (!baseaddr) baseaddr = p;
1121 switch (uLevel)
1123 case 0:
1124 push_ascii(p,service->name, 15, STR_TERMINATE);
1125 break;
1127 case 1:
1128 push_ascii(p,service->name,15, STR_TERMINATE);
1129 SIVAL(p,18,service->type);
1130 SIVAL(p,22,PTR_DIFF(p2,baseaddr));
1131 len += CopyAndAdvance(&p2,service->comment,&l2);
1132 break;
1135 if (stringbuf)
1137 *buf = p + struct_len;
1138 *buflen -= struct_len;
1139 *stringbuf = p2;
1140 *stringspace = l2;
1142 else
1144 *buf = p2;
1145 *buflen -= len;
1147 return len;
1151 static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
1153 return(strcmp(s1->name,s2->name));
1156 /****************************************************************************
1157 view list of servers available (or possibly domains). The info is
1158 extracted from lists saved by nmbd on the local host
1159 ****************************************************************************/
1160 static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid, char *param, char *data,
1161 int mdrcnt, int mprcnt, char **rdata,
1162 char **rparam, int *rdata_len, int *rparam_len)
1164 char *str1 = param+2;
1165 char *str2 = skip_string(str1,1);
1166 char *p = skip_string(str2,1);
1167 int uLevel = SVAL(p,0);
1168 int buf_len = SVAL(p,2);
1169 uint32 servertype = IVAL(p,4);
1170 char *p2;
1171 int data_len, fixed_len, string_len;
1172 int f_len = 0, s_len = 0;
1173 struct srv_info_struct *servers=NULL;
1174 int counted=0,total=0;
1175 int i,missed;
1176 fstring domain;
1177 BOOL domain_request;
1178 BOOL local_request;
1180 /* If someone sets all the bits they don't really mean to set
1181 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1182 known servers. */
1184 if (servertype == SV_TYPE_ALL)
1185 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1187 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1188 any other bit (they may just set this bit on it's own) they
1189 want all the locally seen servers. However this bit can be
1190 set on its own so set the requested servers to be
1191 ALL - DOMAIN_ENUM. */
1193 if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM))
1194 servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
1196 domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
1197 local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
1199 p += 8;
1201 if (!prefix_ok(str1,"WrLehD")) return False;
1202 if (!check_server_info(uLevel,str2)) return False;
1204 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1205 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1206 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1208 if (strcmp(str1, "WrLehDz") == 0) {
1209 pull_ascii_fstring(domain, p);
1210 } else {
1211 fstrcpy(domain, lp_workgroup());
1214 if (lp_browse_list())
1215 total = get_server_info(servertype,&servers,domain);
1217 data_len = fixed_len = string_len = 0;
1218 missed = 0;
1220 if (total > 0)
1221 qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
1224 char *lastname=NULL;
1226 for (i=0;i<total;i++)
1228 struct srv_info_struct *s = &servers[i];
1229 if (lastname && strequal(lastname,s->name)) continue;
1230 lastname = s->name;
1231 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1232 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1233 s->name, s->type, s->comment, s->domain));
1235 if (data_len <= buf_len) {
1236 counted++;
1237 fixed_len += f_len;
1238 string_len += s_len;
1239 } else {
1240 missed++;
1245 *rdata_len = fixed_len + string_len;
1246 *rdata = REALLOC(*rdata,*rdata_len);
1247 memset(*rdata,'\0',*rdata_len);
1249 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1250 p = *rdata;
1251 f_len = fixed_len;
1252 s_len = string_len;
1255 char *lastname=NULL;
1256 int count2 = counted;
1257 for (i = 0; i < total && count2;i++)
1259 struct srv_info_struct *s = &servers[i];
1260 if (lastname && strequal(lastname,s->name)) continue;
1261 lastname = s->name;
1262 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1263 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1264 s->name, s->type, s->comment, s->domain));
1265 count2--;
1269 *rparam_len = 8;
1270 *rparam = REALLOC(*rparam,*rparam_len);
1271 SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata));
1272 SSVAL(*rparam,2,0);
1273 SSVAL(*rparam,4,counted);
1274 SSVAL(*rparam,6,counted+missed);
1276 SAFE_FREE(servers);
1278 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1279 domain,uLevel,counted,counted+missed));
1281 return(True);
1284 /****************************************************************************
1285 command 0x34 - suspected of being a "Lookup Names" stub api
1286 ****************************************************************************/
1287 static BOOL api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid, char *param, char *data,
1288 int mdrcnt, int mprcnt, char **rdata,
1289 char **rparam, int *rdata_len, int *rparam_len)
1291 char *str1 = param+2;
1292 char *str2 = skip_string(str1,1);
1293 char *p = skip_string(str2,1);
1294 int uLevel = SVAL(p,0);
1295 int buf_len = SVAL(p,2);
1296 int counted=0;
1297 int missed=0;
1299 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1300 str1, str2, p, uLevel, buf_len));
1302 if (!prefix_ok(str1,"zWrLeh")) return False;
1304 *rdata_len = 0;
1306 *rparam_len = 8;
1307 *rparam = REALLOC(*rparam,*rparam_len);
1309 SSVAL(*rparam,0,0x08AC); /* informational warning message */
1310 SSVAL(*rparam,2,0);
1311 SSVAL(*rparam,4,counted);
1312 SSVAL(*rparam,6,counted+missed);
1314 return(True);
1317 /****************************************************************************
1318 get info about a share
1319 ****************************************************************************/
1320 static BOOL check_share_info(int uLevel, char* id)
1322 switch( uLevel ) {
1323 case 0:
1324 if (strcmp(id,"B13") != 0) return False;
1325 break;
1326 case 1:
1327 if (strcmp(id,"B13BWz") != 0) return False;
1328 break;
1329 case 2:
1330 if (strcmp(id,"B13BWzWWWzB9B") != 0) return False;
1331 break;
1332 case 91:
1333 if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) return False;
1334 break;
1335 default: return False;
1337 return True;
1340 static int fill_share_info(connection_struct *conn, int snum, int uLevel,
1341 char** buf, int* buflen,
1342 char** stringbuf, int* stringspace, char* baseaddr)
1344 int struct_len;
1345 char* p;
1346 char* p2;
1347 int l2;
1348 int len;
1350 switch( uLevel ) {
1351 case 0: struct_len = 13; break;
1352 case 1: struct_len = 20; break;
1353 case 2: struct_len = 40; break;
1354 case 91: struct_len = 68; break;
1355 default: return -1;
1359 if (!buf)
1361 len = 0;
1362 if (uLevel > 0) len += StrlenExpanded(conn,snum,lp_comment(snum));
1363 if (uLevel > 1) len += strlen(lp_pathname(snum)) + 1;
1364 if (buflen) *buflen = struct_len;
1365 if (stringspace) *stringspace = len;
1366 return struct_len + len;
1369 len = struct_len;
1370 p = *buf;
1371 if ((*buflen) < struct_len) return -1;
1372 if (stringbuf)
1374 p2 = *stringbuf;
1375 l2 = *stringspace;
1377 else
1379 p2 = p + struct_len;
1380 l2 = (*buflen) - struct_len;
1382 if (!baseaddr) baseaddr = p;
1384 push_ascii(p,lp_servicename(snum),13, STR_TERMINATE);
1386 if (uLevel > 0)
1388 int type;
1389 SCVAL(p,13,0);
1390 type = STYPE_DISKTREE;
1391 if (lp_print_ok(snum)) type = STYPE_PRINTQ;
1392 if (strequal("IPC",lp_fstype(snum))) type = STYPE_IPC;
1393 SSVAL(p,14,type); /* device type */
1394 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1395 len += CopyExpanded(conn,snum,&p2,lp_comment(snum),&l2);
1398 if (uLevel > 1)
1400 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1401 SSVALS(p,22,-1); /* max uses */
1402 SSVAL(p,24,1); /* current uses */
1403 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1404 len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1405 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1408 if (uLevel > 2)
1410 memset(p+40,0,SHPWLEN+2);
1411 SSVAL(p,50,0);
1412 SIVAL(p,52,0);
1413 SSVAL(p,56,0);
1414 SSVAL(p,58,0);
1415 SIVAL(p,60,0);
1416 SSVAL(p,64,0);
1417 SSVAL(p,66,0);
1420 if (stringbuf)
1422 (*buf) = p + struct_len;
1423 (*buflen) -= struct_len;
1424 (*stringbuf) = p2;
1425 (*stringspace) = l2;
1427 else
1429 (*buf) = p2;
1430 (*buflen) -= len;
1432 return len;
1435 static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
1436 int mdrcnt,int mprcnt,
1437 char **rdata,char **rparam,
1438 int *rdata_len,int *rparam_len)
1440 char *str1 = param+2;
1441 char *str2 = skip_string(str1,1);
1442 char *netname = skip_string(str2,1);
1443 char *p = skip_string(netname,1);
1444 int uLevel = SVAL(p,0);
1445 int snum = find_service(netname);
1447 if (snum < 0) return False;
1449 /* check it's a supported varient */
1450 if (!prefix_ok(str1,"zWrLh")) return False;
1451 if (!check_share_info(uLevel,str2)) return False;
1453 *rdata = REALLOC(*rdata,mdrcnt);
1454 p = *rdata;
1455 *rdata_len = fill_share_info(conn,snum,uLevel,&p,&mdrcnt,0,0,0);
1456 if (*rdata_len < 0) return False;
1458 *rparam_len = 6;
1459 *rparam = REALLOC(*rparam,*rparam_len);
1460 SSVAL(*rparam,0,NERR_Success);
1461 SSVAL(*rparam,2,0); /* converter word */
1462 SSVAL(*rparam,4,*rdata_len);
1464 return(True);
1467 /****************************************************************************
1468 view list of shares available
1469 ****************************************************************************/
1470 static BOOL api_RNetShareEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
1471 int mdrcnt,int mprcnt,
1472 char **rdata,char **rparam,
1473 int *rdata_len,int *rparam_len)
1475 char *str1 = param+2;
1476 char *str2 = skip_string(str1,1);
1477 char *p = skip_string(str2,1);
1478 int uLevel = SVAL(p,0);
1479 int buf_len = SVAL(p,2);
1480 char *p2;
1481 int count=lp_numservices();
1482 int total=0,counted=0;
1483 BOOL missed = False;
1484 int i;
1485 int data_len, fixed_len, string_len;
1486 int f_len = 0, s_len = 0;
1488 if (!prefix_ok(str1,"WrLeh")) return False;
1489 if (!check_share_info(uLevel,str2)) return False;
1491 data_len = fixed_len = string_len = 0;
1492 for (i=0;i<count;i++)
1493 if (lp_browseable(i) && lp_snum_ok(i))
1495 total++;
1496 data_len += fill_share_info(conn,i,uLevel,0,&f_len,0,&s_len,0);
1497 if (data_len <= buf_len)
1499 counted++;
1500 fixed_len += f_len;
1501 string_len += s_len;
1503 else
1504 missed = True;
1506 *rdata_len = fixed_len + string_len;
1507 *rdata = REALLOC(*rdata,*rdata_len);
1508 memset(*rdata,0,*rdata_len);
1510 p2 = (*rdata) + fixed_len; /* auxiliary data (strings) will go here */
1511 p = *rdata;
1512 f_len = fixed_len;
1513 s_len = string_len;
1514 for (i = 0; i < count;i++)
1515 if (lp_browseable(i) && lp_snum_ok(i))
1516 if (fill_share_info(conn,i,uLevel,&p,&f_len,&p2,&s_len,*rdata) < 0)
1517 break;
1519 *rparam_len = 8;
1520 *rparam = REALLOC(*rparam,*rparam_len);
1521 SSVAL(*rparam,0,missed ? ERRmoredata : NERR_Success);
1522 SSVAL(*rparam,2,0);
1523 SSVAL(*rparam,4,counted);
1524 SSVAL(*rparam,6,total);
1526 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1527 counted,total,uLevel,
1528 buf_len,*rdata_len,mdrcnt));
1529 return(True);
1532 /****************************************************************************
1533 Add a share
1534 ****************************************************************************/
1535 static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid, char *param,char *data,
1536 int mdrcnt,int mprcnt,
1537 char **rdata,char **rparam,
1538 int *rdata_len,int *rparam_len)
1540 char *str1 = param+2;
1541 char *str2 = skip_string(str1,1);
1542 char *p = skip_string(str2,1);
1543 int uLevel = SVAL(p,0);
1544 fstring sharename;
1545 fstring comment;
1546 pstring pathname;
1547 char *command, *cmdname;
1548 unsigned int offset;
1549 int snum;
1550 int res = ERRunsup;
1552 /* check it's a supported varient */
1553 if (!prefix_ok(str1,RAP_WShareAdd_REQ)) return False;
1554 if (!check_share_info(uLevel,str2)) return False;
1555 if (uLevel != 2) return False;
1557 pull_ascii_fstring(sharename,data);
1558 snum = find_service(sharename);
1559 if (snum >= 0) { /* already exists */
1560 res = ERRfilexists;
1561 goto error_exit;
1564 /* only support disk share adds */
1565 if (SVAL(data,14)!=STYPE_DISKTREE) return False;
1567 offset = IVAL(data, 16);
1568 if (offset >= mdrcnt) {
1569 res = ERRinvalidparam;
1570 goto error_exit;
1572 pull_ascii_fstring(comment, offset? (data+offset) : "");
1574 offset = IVAL(data, 26);
1575 if (offset >= mdrcnt) {
1576 res = ERRinvalidparam;
1577 goto error_exit;
1579 pull_ascii_pstring(pathname, offset? (data+offset) : "");
1581 string_replace(sharename, '"', ' ');
1582 string_replace(pathname, '"', ' ');
1583 string_replace(comment, '"', ' ');
1585 cmdname = lp_add_share_cmd();
1587 if (!cmdname || *cmdname == '\0') return False;
1589 asprintf(&command, "%s \"%s\" \"%s\" \"%s\" \"%s\"",
1590 lp_add_share_cmd(), dyn_CONFIGFILE, sharename, pathname, comment);
1592 if (command) {
1593 DEBUG(10,("api_RNetShareAdd: Running [%s]\n", command ));
1594 if ((res = smbrun(command, NULL)) != 0) {
1595 DEBUG(1,("api_RNetShareAdd: Running [%s] returned (%d)\n", command, res ));
1596 SAFE_FREE(command);
1597 res = ERRnoaccess;
1598 goto error_exit;
1599 } else {
1600 SAFE_FREE(command);
1601 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
1603 } else return False;
1605 *rparam_len = 6;
1606 *rparam = REALLOC(*rparam,*rparam_len);
1607 SSVAL(*rparam,0,NERR_Success);
1608 SSVAL(*rparam,2,0); /* converter word */
1609 SSVAL(*rparam,4,*rdata_len);
1610 *rdata_len = 0;
1612 return True;
1614 error_exit:
1615 *rparam_len = 4;
1616 *rparam = REALLOC(*rparam,*rparam_len);
1617 *rdata_len = 0;
1618 SSVAL(*rparam,0,res);
1619 SSVAL(*rparam,2,0);
1620 return True;
1624 /****************************************************************************
1625 view list of groups available
1626 ****************************************************************************/
1627 static BOOL api_RNetGroupEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
1628 int mdrcnt,int mprcnt,
1629 char **rdata,char **rparam,
1630 int *rdata_len,int *rparam_len)
1632 int i;
1633 int errflags=0;
1634 int resume_context, cli_buf_size;
1635 char *str1 = param+2;
1636 char *str2 = skip_string(str1,1);
1637 char *p = skip_string(str2,1);
1639 GROUP_MAP *group_list;
1640 int num_entries;
1642 if (strcmp(str1,"WrLeh") != 0)
1643 return False;
1645 /* parameters
1646 * W-> resume context (number of users to skip)
1647 * r -> return parameter pointer to receive buffer
1648 * L -> length of receive buffer
1649 * e -> return parameter number of entries
1650 * h -> return parameter total number of users
1652 if (strcmp("B21",str2) != 0)
1653 return False;
1655 /* get list of domain groups SID_DOMAIN_GRP=2 */
1656 if(!pdb_enum_group_mapping(SID_NAME_DOM_GRP , &group_list, &num_entries, False)) {
1657 DEBUG(3,("api_RNetGroupEnum:failed to get group list"));
1658 return False;
1661 resume_context = SVAL(p,0);
1662 cli_buf_size=SVAL(p+2,0);
1663 DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: %d\n", resume_context, cli_buf_size));
1665 *rdata_len = cli_buf_size;
1666 *rdata = REALLOC(*rdata,*rdata_len);
1668 p = *rdata;
1670 for(i=resume_context; i<num_entries; i++) {
1671 char* name=group_list[i].nt_name;
1672 if( ((PTR_DIFF(p,*rdata)+21) <= *rdata_len) ) {
1673 /* truncate the name at 21 chars. */
1674 memcpy(p, name, 21);
1675 DEBUG(10,("adding entry %d group %s\n", i, p));
1676 p += 21;
1677 } else {
1678 /* set overflow error */
1679 DEBUG(3,("overflow on entry %d group %s\n", i, name));
1680 errflags=234;
1681 break;
1685 *rdata_len = PTR_DIFF(p,*rdata);
1687 *rparam_len = 8;
1688 *rparam = REALLOC(*rparam,*rparam_len);
1690 SSVAL(*rparam, 0, errflags);
1691 SSVAL(*rparam, 2, 0); /* converter word */
1692 SSVAL(*rparam, 4, i-resume_context); /* is this right?? */
1693 SSVAL(*rparam, 6, num_entries); /* is this right?? */
1695 return(True);
1698 /*******************************************************************
1699 get groups that a user is a member of
1700 ******************************************************************/
1701 static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *param,char *data,
1702 int mdrcnt,int mprcnt,
1703 char **rdata,char **rparam,
1704 int *rdata_len,int *rparam_len)
1706 char *str1 = param+2;
1707 char *str2 = skip_string(str1,1);
1708 char *UserName = skip_string(str2,1);
1709 char *p = skip_string(UserName,1);
1710 int uLevel = SVAL(p,0);
1711 const char *level_string;
1712 int count=0;
1713 SAM_ACCOUNT *sampw = NULL;
1714 BOOL ret = False;
1715 DOM_GID *gids = NULL;
1716 int num_groups = 0;
1717 int i;
1718 fstring grp_domain;
1719 fstring grp_name;
1720 enum SID_NAME_USE grp_type;
1721 DOM_SID sid, dom_sid;
1723 *rparam_len = 8;
1724 *rparam = REALLOC(*rparam,*rparam_len);
1726 /* check it's a supported varient */
1728 if ( strcmp(str1,"zWrLeh") != 0 )
1729 return False;
1731 switch( uLevel ) {
1732 case 0:
1733 level_string = "B21";
1734 break;
1735 default:
1736 return False;
1739 if (strcmp(level_string,str2) != 0)
1740 return False;
1742 *rdata_len = mdrcnt + 1024;
1743 *rdata = REALLOC(*rdata,*rdata_len);
1745 SSVAL(*rparam,0,NERR_Success);
1746 SSVAL(*rparam,2,0); /* converter word */
1748 p = *rdata;
1750 /* Lookup the user information; This should only be one of
1751 our accounts (not remote domains) */
1753 pdb_init_sam( &sampw );
1755 become_root(); /* ROOT BLOCK */
1757 if ( !pdb_getsampwnam(sampw, UserName) )
1758 goto out;
1760 /* this next set of code is horribly inefficient, but since
1761 it is rarely called, I'm going to leave it like this since
1762 it easier to follow --jerry */
1764 /* get the list of group SIDs */
1766 if ( !get_domain_user_groups(conn->mem_ctx, &num_groups, &gids, sampw) ) {
1767 DEBUG(1,("api_NetUserGetGroups: get_domain_user_groups() failed!\n"));
1768 goto out;
1771 /* convert to names (we don't support universal groups so the domain
1772 can only be ours) */
1774 sid_copy( &dom_sid, get_global_sam_sid() );
1775 for (i=0; i<num_groups; i++) {
1777 /* make the DOM_GID into a DOM_SID and then lookup
1778 the name */
1780 sid_copy( &sid, &dom_sid );
1781 sid_append_rid( &sid, gids[i].g_rid );
1783 if ( lookup_sid(&sid, grp_domain, grp_name, &grp_type) ) {
1784 pstrcpy(p, grp_name);
1785 p += 21;
1786 count++;
1790 *rdata_len = PTR_DIFF(p,*rdata);
1792 SSVAL(*rparam,4,count); /* is this right?? */
1793 SSVAL(*rparam,6,count); /* is this right?? */
1795 ret = True;
1797 out:
1798 unbecome_root(); /* END ROOT BLOCK */
1800 pdb_free_sam( &sampw );
1802 return ret;
1805 /*******************************************************************
1806 get all users
1807 ******************************************************************/
1808 static BOOL api_RNetUserEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
1809 int mdrcnt,int mprcnt,
1810 char **rdata,char **rparam,
1811 int *rdata_len,int *rparam_len)
1813 SAM_ACCOUNT *pwd=NULL;
1814 int count_sent=0;
1815 int count_total=0;
1816 int errflags=0;
1817 int resume_context, cli_buf_size;
1819 char *str1 = param+2;
1820 char *str2 = skip_string(str1,1);
1821 char *p = skip_string(str2,1);
1823 if (strcmp(str1,"WrLeh") != 0)
1824 return False;
1825 /* parameters
1826 * W-> resume context (number of users to skip)
1827 * r -> return parameter pointer to receive buffer
1828 * L -> length of receive buffer
1829 * e -> return parameter number of entries
1830 * h -> return parameter total number of users
1833 resume_context = SVAL(p,0);
1834 cli_buf_size=SVAL(p+2,0);
1835 DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n", resume_context, cli_buf_size));
1837 *rparam_len = 8;
1838 *rparam = REALLOC(*rparam,*rparam_len);
1840 /* check it's a supported varient */
1841 if (strcmp("B21",str2) != 0)
1842 return False;
1844 *rdata_len = cli_buf_size;
1845 *rdata = REALLOC(*rdata,*rdata_len);
1847 p = *rdata;
1849 /* to get user list enumerations for NetUserEnum in B21 format */
1850 pdb_init_sam(&pwd);
1852 /* Open the passgrp file - not for update. */
1853 become_root();
1854 if(!pdb_setsampwent(False)) {
1855 DEBUG(0, ("api_RNetUserEnum:unable to open sam database.\n"));
1856 unbecome_root();
1857 return False;
1859 errflags=NERR_Success;
1861 while ( pdb_getsampwent(pwd) ) {
1862 const char *name=pdb_get_username(pwd);
1863 if ((name) && (*(name+strlen(name)-1)!='$')) {
1864 count_total++;
1865 if(count_total>=resume_context) {
1866 if( ((PTR_DIFF(p,*rdata)+21)<=*rdata_len)&&(strlen(name)<=21) ) {
1867 pstrcpy(p,name);
1868 DEBUG(10,("api_RNetUserEnum:adding entry %d username %s\n",count_sent,p));
1869 p += 21;
1870 count_sent++;
1871 } else {
1872 /* set overflow error */
1873 DEBUG(10,("api_RNetUserEnum:overflow on entry %d username %s\n",count_sent,name));
1874 errflags=234;
1875 break;
1881 pdb_endsampwent();
1882 unbecome_root();
1884 pdb_free_sam(&pwd);
1886 *rdata_len = PTR_DIFF(p,*rdata);
1888 SSVAL(*rparam,0,errflags);
1889 SSVAL(*rparam,2,0); /* converter word */
1890 SSVAL(*rparam,4,count_sent); /* is this right?? */
1891 SSVAL(*rparam,6,count_total); /* is this right?? */
1893 return True;
1898 /****************************************************************************
1899 get the time of day info
1900 ****************************************************************************/
1901 static BOOL api_NetRemoteTOD(connection_struct *conn,uint16 vuid, char *param,char *data,
1902 int mdrcnt,int mprcnt,
1903 char **rdata,char **rparam,
1904 int *rdata_len,int *rparam_len)
1906 char *p;
1907 *rparam_len = 4;
1908 *rparam = REALLOC(*rparam,*rparam_len);
1910 *rdata_len = 21;
1911 *rdata = REALLOC(*rdata,*rdata_len);
1913 SSVAL(*rparam,0,NERR_Success);
1914 SSVAL(*rparam,2,0); /* converter word */
1916 p = *rdata;
1919 struct tm *t;
1920 time_t unixdate = time(NULL);
1922 put_dos_date3(p,0,unixdate); /* this is the time that is looked at
1923 by NT in a "net time" operation,
1924 it seems to ignore the one below */
1926 /* the client expects to get localtime, not GMT, in this bit
1927 (I think, this needs testing) */
1928 t = LocalTime(&unixdate);
1930 SIVAL(p,4,0); /* msecs ? */
1931 SCVAL(p,8,t->tm_hour);
1932 SCVAL(p,9,t->tm_min);
1933 SCVAL(p,10,t->tm_sec);
1934 SCVAL(p,11,0); /* hundredths of seconds */
1935 SSVALS(p,12,TimeDiff(unixdate)/60); /* timezone in minutes from GMT */
1936 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
1937 SCVAL(p,16,t->tm_mday);
1938 SCVAL(p,17,t->tm_mon + 1);
1939 SSVAL(p,18,1900+t->tm_year);
1940 SCVAL(p,20,t->tm_wday);
1944 return(True);
1947 /****************************************************************************
1948 Set the user password.
1949 *****************************************************************************/
1951 static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param,char *data,
1952 int mdrcnt,int mprcnt,
1953 char **rdata,char **rparam,
1954 int *rdata_len,int *rparam_len)
1956 char *p = skip_string(param+2,2);
1957 fstring user;
1958 fstring pass1,pass2;
1960 pull_ascii_fstring(user,p);
1962 p = skip_string(p,1);
1964 memset(pass1,'\0',sizeof(pass1));
1965 memset(pass2,'\0',sizeof(pass2));
1966 memcpy(pass1,p,16);
1967 memcpy(pass2,p+16,16);
1969 *rparam_len = 4;
1970 *rparam = REALLOC(*rparam,*rparam_len);
1972 *rdata_len = 0;
1974 SSVAL(*rparam,0,NERR_badpass);
1975 SSVAL(*rparam,2,0); /* converter word */
1977 DEBUG(3,("Set password for <%s>\n",user));
1980 * Attempt to verify the old password against smbpasswd entries
1981 * Win98 clients send old and new password in plaintext for this call.
1985 auth_serversupplied_info *server_info = NULL;
1986 DATA_BLOB password = data_blob(pass1, strlen(pass1)+1);
1988 if (NT_STATUS_IS_OK(check_plaintext_password(user,password,&server_info))) {
1990 become_root();
1991 if (NT_STATUS_IS_OK(change_oem_password(server_info->sam_account, pass1, pass2, False))) {
1992 SSVAL(*rparam,0,NERR_Success);
1994 unbecome_root();
1996 free_server_info(&server_info);
1998 data_blob_clear_free(&password);
2002 * If the plaintext change failed, attempt
2003 * the old encrypted method. NT will generate this
2004 * after trying the samr method. Note that this
2005 * method is done as a last resort as this
2006 * password change method loses the NT password hash
2007 * and cannot change the UNIX password as no plaintext
2008 * is received.
2011 if(SVAL(*rparam,0) != NERR_Success) {
2012 SAM_ACCOUNT *hnd = NULL;
2014 if (check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &hnd)) {
2015 become_root();
2016 if (change_lanman_password(hnd,(uchar *)pass2)) {
2017 SSVAL(*rparam,0,NERR_Success);
2019 unbecome_root();
2020 pdb_free_sam(&hnd);
2024 memset((char *)pass1,'\0',sizeof(fstring));
2025 memset((char *)pass2,'\0',sizeof(fstring));
2027 return(True);
2030 /****************************************************************************
2031 Set the user password (SamOEM version - gets plaintext).
2032 ****************************************************************************/
2034 static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char *param,char *data,
2035 int mdrcnt,int mprcnt,
2036 char **rdata,char **rparam,
2037 int *rdata_len,int *rparam_len)
2039 fstring user;
2040 char *p = param + 2;
2041 *rparam_len = 2;
2042 *rparam = REALLOC(*rparam,*rparam_len);
2044 *rdata_len = 0;
2046 SSVAL(*rparam,0,NERR_badpass);
2049 * Check the parameter definition is correct.
2052 if(!strequal(param + 2, "zsT")) {
2053 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", param + 2));
2054 return False;
2056 p = skip_string(p, 1);
2058 if(!strequal(p, "B516B16")) {
2059 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p));
2060 return False;
2062 p = skip_string(p,1);
2063 p += pull_ascii_fstring(user,p);
2065 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user));
2068 * Pass the user through the NT -> unix user mapping
2069 * function.
2072 (void)map_username(user);
2074 if (NT_STATUS_IS_OK(pass_oem_change(user, (uchar*) data, (uchar *)&data[516], NULL, NULL))) {
2075 SSVAL(*rparam,0,NERR_Success);
2078 return(True);
2081 /****************************************************************************
2082 delete a print job
2083 Form: <W> <>
2084 ****************************************************************************/
2085 static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char *param,char *data,
2086 int mdrcnt,int mprcnt,
2087 char **rdata,char **rparam,
2088 int *rdata_len,int *rparam_len)
2090 int function = SVAL(param,0);
2091 char *str1 = param+2;
2092 char *str2 = skip_string(str1,1);
2093 char *p = skip_string(str2,1);
2094 uint32 jobid;
2095 int snum;
2096 int errcode;
2097 extern struct current_user current_user;
2098 WERROR werr = WERR_OK;
2100 if(!rap_to_pjobid(SVAL(p,0),&snum,&jobid))
2101 return False;
2103 /* check it's a supported varient */
2104 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
2105 return(False);
2107 *rparam_len = 4;
2108 *rparam = REALLOC(*rparam,*rparam_len);
2109 *rdata_len = 0;
2111 if (!print_job_exists(snum, jobid)) {
2112 errcode = NERR_JobNotFound;
2113 goto out;
2116 errcode = NERR_notsupported;
2118 switch (function) {
2119 case 81: /* delete */
2120 if (print_job_delete(&current_user, snum, jobid, &werr))
2121 errcode = NERR_Success;
2122 break;
2123 case 82: /* pause */
2124 if (print_job_pause(&current_user, snum, jobid, &werr))
2125 errcode = NERR_Success;
2126 break;
2127 case 83: /* resume */
2128 if (print_job_resume(&current_user, snum, jobid, &werr))
2129 errcode = NERR_Success;
2130 break;
2133 if (!W_ERROR_IS_OK(werr))
2134 errcode = W_ERROR_V(werr);
2136 out:
2137 SSVAL(*rparam,0,errcode);
2138 SSVAL(*rparam,2,0); /* converter word */
2140 return(True);
2143 /****************************************************************************
2144 Purge a print queue - or pause or resume it.
2145 ****************************************************************************/
2146 static BOOL api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid, char *param,char *data,
2147 int mdrcnt,int mprcnt,
2148 char **rdata,char **rparam,
2149 int *rdata_len,int *rparam_len)
2151 int function = SVAL(param,0);
2152 char *str1 = param+2;
2153 char *str2 = skip_string(str1,1);
2154 char *QueueName = skip_string(str2,1);
2155 int errcode = NERR_notsupported;
2156 int snum;
2157 WERROR werr = WERR_OK;
2158 extern struct current_user current_user;
2160 /* check it's a supported varient */
2161 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
2162 return(False);
2164 *rparam_len = 4;
2165 *rparam = REALLOC(*rparam,*rparam_len);
2166 *rdata_len = 0;
2168 snum = print_queue_snum(QueueName);
2170 if (snum == -1) {
2171 errcode = NERR_JobNotFound;
2172 goto out;
2175 switch (function) {
2176 case 74: /* Pause queue */
2177 if (print_queue_pause(&current_user, snum, &werr)) errcode = NERR_Success;
2178 break;
2179 case 75: /* Resume queue */
2180 if (print_queue_resume(&current_user, snum, &werr)) errcode = NERR_Success;
2181 break;
2182 case 103: /* Purge */
2183 if (print_queue_purge(&current_user, snum, &werr)) errcode = NERR_Success;
2184 break;
2187 if (!W_ERROR_IS_OK(werr)) errcode = W_ERROR_V(werr);
2189 out:
2190 SSVAL(*rparam,0,errcode);
2191 SSVAL(*rparam,2,0); /* converter word */
2193 return(True);
2197 /****************************************************************************
2198 set the property of a print job (undocumented?)
2199 ? function = 0xb -> set name of print job
2200 ? function = 0x6 -> move print job up/down
2201 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
2202 or <WWsTP> <WB21BB16B10zWWzDDz>
2203 ****************************************************************************/
2204 static int check_printjob_info(struct pack_desc* desc,
2205 int uLevel, char* id)
2207 desc->subformat = NULL;
2208 switch( uLevel ) {
2209 case 0: desc->format = "W"; break;
2210 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
2211 case 2: desc->format = "WWzWWDDzz"; break;
2212 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
2213 case 4: desc->format = "WWzWWDDzzzzzDDDDDDD"; break;
2214 default: return False;
2216 if (strcmp(desc->format,id) != 0) return False;
2217 return True;
2220 static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,char *data,
2221 int mdrcnt,int mprcnt,
2222 char **rdata,char **rparam,
2223 int *rdata_len,int *rparam_len)
2225 struct pack_desc desc;
2226 char *str1 = param+2;
2227 char *str2 = skip_string(str1,1);
2228 char *p = skip_string(str2,1);
2229 uint32 jobid;
2230 int snum;
2231 int uLevel = SVAL(p,2);
2232 int function = SVAL(p,4);
2233 int place, errcode;
2235 if(!rap_to_pjobid(SVAL(p,0),&snum,&jobid))
2236 return False;
2237 *rparam_len = 4;
2238 *rparam = REALLOC(*rparam,*rparam_len);
2240 *rdata_len = 0;
2242 /* check it's a supported varient */
2243 if ((strcmp(str1,"WWsTP")) ||
2244 (!check_printjob_info(&desc,uLevel,str2)))
2245 return(False);
2247 if (!print_job_exists(snum, jobid)) {
2248 errcode=NERR_JobNotFound;
2249 goto out;
2252 errcode = NERR_notsupported;
2254 switch (function) {
2255 case 0x6:
2256 /* change job place in the queue,
2257 data gives the new place */
2258 place = SVAL(data,0);
2259 if (print_job_set_place(snum, jobid, place)) {
2260 errcode=NERR_Success;
2262 break;
2264 case 0xb:
2265 /* change print job name, data gives the name */
2266 if (print_job_set_name(snum, jobid, data)) {
2267 errcode=NERR_Success;
2269 break;
2271 default:
2272 return False;
2275 out:
2276 SSVALS(*rparam,0,errcode);
2277 SSVAL(*rparam,2,0); /* converter word */
2279 return(True);
2283 /****************************************************************************
2284 get info about the server
2285 ****************************************************************************/
2286 static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2287 int mdrcnt,int mprcnt,
2288 char **rdata,char **rparam,
2289 int *rdata_len,int *rparam_len)
2291 char *str1 = param+2;
2292 char *str2 = skip_string(str1,1);
2293 char *p = skip_string(str2,1);
2294 int uLevel = SVAL(p,0);
2295 char *p2;
2296 int struct_len;
2298 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
2300 /* check it's a supported varient */
2301 if (!prefix_ok(str1,"WrLh")) return False;
2302 switch( uLevel ) {
2303 case 0:
2304 if (strcmp(str2,"B16") != 0) return False;
2305 struct_len = 16;
2306 break;
2307 case 1:
2308 if (strcmp(str2,"B16BBDz") != 0) return False;
2309 struct_len = 26;
2310 break;
2311 case 2:
2312 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")
2313 != 0) return False;
2314 struct_len = 134;
2315 break;
2316 case 3:
2317 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz")
2318 != 0) return False;
2319 struct_len = 144;
2320 break;
2321 case 20:
2322 if (strcmp(str2,"DN") != 0) return False;
2323 struct_len = 6;
2324 break;
2325 case 50:
2326 if (strcmp(str2,"B16BBDzWWzzz") != 0) return False;
2327 struct_len = 42;
2328 break;
2329 default: return False;
2332 *rdata_len = mdrcnt;
2333 *rdata = REALLOC(*rdata,*rdata_len);
2335 p = *rdata;
2336 p2 = p + struct_len;
2337 if (uLevel != 20) {
2338 srvstr_push(NULL, p,local_machine,16,
2339 STR_ASCII|STR_UPPER|STR_TERMINATE);
2341 p += 16;
2342 if (uLevel > 0)
2344 struct srv_info_struct *servers=NULL;
2345 int i,count;
2346 pstring comment;
2347 uint32 servertype= lp_default_server_announce();
2349 push_ascii(comment,lp_serverstring(), MAX_SERVER_STRING_LENGTH,STR_TERMINATE);
2351 if ((count=get_server_info(SV_TYPE_ALL,&servers,lp_workgroup()))>0) {
2352 for (i=0;i<count;i++) {
2353 if (strequal(servers[i].name,local_machine)) {
2354 servertype = servers[i].type;
2355 push_ascii(comment,servers[i].comment,sizeof(pstring),STR_TERMINATE);
2359 SAFE_FREE(servers);
2361 SCVAL(p,0,lp_major_announce_version());
2362 SCVAL(p,1,lp_minor_announce_version());
2363 SIVAL(p,2,servertype);
2365 if (mdrcnt == struct_len) {
2366 SIVAL(p,6,0);
2367 } else {
2368 SIVAL(p,6,PTR_DIFF(p2,*rdata));
2369 standard_sub_conn(conn,comment,sizeof(comment));
2370 StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
2371 p2 = skip_string(p2,1);
2374 if (uLevel > 1)
2376 return False; /* not yet implemented */
2379 *rdata_len = PTR_DIFF(p2,*rdata);
2381 *rparam_len = 6;
2382 *rparam = REALLOC(*rparam,*rparam_len);
2383 SSVAL(*rparam,0,NERR_Success);
2384 SSVAL(*rparam,2,0); /* converter word */
2385 SSVAL(*rparam,4,*rdata_len);
2387 return(True);
2391 /****************************************************************************
2392 get info about the server
2393 ****************************************************************************/
2394 static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2395 int mdrcnt,int mprcnt,
2396 char **rdata,char **rparam,
2397 int *rdata_len,int *rparam_len)
2399 char *str1 = param+2;
2400 char *str2 = skip_string(str1,1);
2401 char *p = skip_string(str2,1);
2402 char *p2;
2403 extern userdom_struct current_user_info;
2404 int level = SVAL(p,0);
2406 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
2408 *rparam_len = 6;
2409 *rparam = REALLOC(*rparam,*rparam_len);
2411 /* check it's a supported varient */
2412 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz")))
2413 return(False);
2415 *rdata_len = mdrcnt + 1024;
2416 *rdata = REALLOC(*rdata,*rdata_len);
2418 SSVAL(*rparam,0,NERR_Success);
2419 SSVAL(*rparam,2,0); /* converter word */
2421 p = *rdata;
2422 p2 = p + 22;
2425 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
2426 pstrcpy(p2,local_machine);
2427 strupper_m(p2);
2428 p2 = skip_string(p2,1);
2429 p += 4;
2431 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2432 pstrcpy(p2,current_user_info.smb_name);
2433 p2 = skip_string(p2,1);
2434 p += 4;
2436 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
2437 pstrcpy(p2,lp_workgroup());
2438 strupper_m(p2);
2439 p2 = skip_string(p2,1);
2440 p += 4;
2442 SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
2443 SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
2444 p += 2;
2446 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2447 pstrcpy(p2,lp_workgroup()); /* don't know. login domain?? */
2448 p2 = skip_string(p2,1);
2449 p += 4;
2451 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
2452 pstrcpy(p2,"");
2453 p2 = skip_string(p2,1);
2454 p += 4;
2456 *rdata_len = PTR_DIFF(p2,*rdata);
2458 SSVAL(*rparam,4,*rdata_len);
2460 return(True);
2463 /****************************************************************************
2464 get info about a user
2466 struct user_info_11 {
2467 char usri11_name[21]; 0-20
2468 char usri11_pad; 21
2469 char *usri11_comment; 22-25
2470 char *usri11_usr_comment; 26-29
2471 unsigned short usri11_priv; 30-31
2472 unsigned long usri11_auth_flags; 32-35
2473 long usri11_password_age; 36-39
2474 char *usri11_homedir; 40-43
2475 char *usri11_parms; 44-47
2476 long usri11_last_logon; 48-51
2477 long usri11_last_logoff; 52-55
2478 unsigned short usri11_bad_pw_count; 56-57
2479 unsigned short usri11_num_logons; 58-59
2480 char *usri11_logon_server; 60-63
2481 unsigned short usri11_country_code; 64-65
2482 char *usri11_workstations; 66-69
2483 unsigned long usri11_max_storage; 70-73
2484 unsigned short usri11_units_per_week; 74-75
2485 unsigned char *usri11_logon_hours; 76-79
2486 unsigned short usri11_code_page; 80-81
2489 where:
2491 usri11_name specifies the user name for which information is retireved
2493 usri11_pad aligns the next data structure element to a word boundary
2495 usri11_comment is a null terminated ASCII comment
2497 usri11_user_comment is a null terminated ASCII comment about the user
2499 usri11_priv specifies the level of the privilege assigned to the user.
2500 The possible values are:
2502 Name Value Description
2503 USER_PRIV_GUEST 0 Guest privilege
2504 USER_PRIV_USER 1 User privilege
2505 USER_PRV_ADMIN 2 Administrator privilege
2507 usri11_auth_flags specifies the account operator privileges. The
2508 possible values are:
2510 Name Value Description
2511 AF_OP_PRINT 0 Print operator
2514 Leach, Naik [Page 28]
2518 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2521 AF_OP_COMM 1 Communications operator
2522 AF_OP_SERVER 2 Server operator
2523 AF_OP_ACCOUNTS 3 Accounts operator
2526 usri11_password_age specifies how many seconds have elapsed since the
2527 password was last changed.
2529 usri11_home_dir points to a null terminated ASCII string that contains
2530 the path name of the user's home directory.
2532 usri11_parms points to a null terminated ASCII string that is set
2533 aside for use by applications.
2535 usri11_last_logon specifies the time when the user last logged on.
2536 This value is stored as the number of seconds elapsed since
2537 00:00:00, January 1, 1970.
2539 usri11_last_logoff specifies the time when the user last logged off.
2540 This value is stored as the number of seconds elapsed since
2541 00:00:00, January 1, 1970. A value of 0 means the last logoff
2542 time is unknown.
2544 usri11_bad_pw_count specifies the number of incorrect passwords
2545 entered since the last successful logon.
2547 usri11_log1_num_logons specifies the number of times this user has
2548 logged on. A value of -1 means the number of logons is unknown.
2550 usri11_logon_server points to a null terminated ASCII string that
2551 contains the name of the server to which logon requests are sent.
2552 A null string indicates logon requests should be sent to the
2553 domain controller.
2555 usri11_country_code specifies the country code for the user's language
2556 of choice.
2558 usri11_workstations points to a null terminated ASCII string that
2559 contains the names of workstations the user may log on from.
2560 There may be up to 8 workstations, with the names separated by
2561 commas. A null strings indicates there are no restrictions.
2563 usri11_max_storage specifies the maximum amount of disk space the user
2564 can occupy. A value of 0xffffffff indicates there are no
2565 restrictions.
2567 usri11_units_per_week specifies the equal number of time units into
2568 which a week is divided. This value must be equal to 168.
2570 usri11_logon_hours points to a 21 byte (168 bits) string that
2571 specifies the time during which the user can log on. Each bit
2572 represents one unique hour in a week. The first bit (bit 0, word
2573 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
2577 Leach, Naik [Page 29]
2581 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2584 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
2585 are no restrictions.
2587 usri11_code_page specifies the code page for the user's language of
2588 choice
2590 All of the pointers in this data structure need to be treated
2591 specially. The pointer is a 32 bit pointer. The higher 16 bits need
2592 to be ignored. The converter word returned in the parameters section
2593 needs to be subtracted from the lower 16 bits to calculate an offset
2594 into the return buffer where this ASCII string resides.
2596 There is no auxiliary data in the response.
2598 ****************************************************************************/
2600 #define usri11_name 0
2601 #define usri11_pad 21
2602 #define usri11_comment 22
2603 #define usri11_usr_comment 26
2604 #define usri11_full_name 30
2605 #define usri11_priv 34
2606 #define usri11_auth_flags 36
2607 #define usri11_password_age 40
2608 #define usri11_homedir 44
2609 #define usri11_parms 48
2610 #define usri11_last_logon 52
2611 #define usri11_last_logoff 56
2612 #define usri11_bad_pw_count 60
2613 #define usri11_num_logons 62
2614 #define usri11_logon_server 64
2615 #define usri11_country_code 68
2616 #define usri11_workstations 70
2617 #define usri11_max_storage 74
2618 #define usri11_units_per_week 78
2619 #define usri11_logon_hours 80
2620 #define usri11_code_page 84
2621 #define usri11_end 86
2623 #define USER_PRIV_GUEST 0
2624 #define USER_PRIV_USER 1
2625 #define USER_PRIV_ADMIN 2
2627 #define AF_OP_PRINT 0
2628 #define AF_OP_COMM 1
2629 #define AF_OP_SERVER 2
2630 #define AF_OP_ACCOUNTS 3
2633 static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2634 int mdrcnt,int mprcnt,
2635 char **rdata,char **rparam,
2636 int *rdata_len,int *rparam_len)
2638 char *str1 = param+2;
2639 char *str2 = skip_string(str1,1);
2640 char *UserName = skip_string(str2,1);
2641 char *p = skip_string(UserName,1);
2642 int uLevel = SVAL(p,0);
2643 char *p2;
2644 const char *level_string;
2646 /* get NIS home of a previously validated user - simeon */
2647 /* With share level security vuid will always be zero.
2648 Don't depend on vuser being non-null !!. JRA */
2649 user_struct *vuser = get_valid_user_struct(vuid);
2650 if(vuser != NULL)
2651 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid,
2652 vuser->user.unix_name));
2654 *rparam_len = 6;
2655 *rparam = REALLOC(*rparam,*rparam_len);
2657 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
2659 /* check it's a supported variant */
2660 if (strcmp(str1,"zWrLh") != 0) return False;
2661 switch( uLevel )
2663 case 0: level_string = "B21"; break;
2664 case 1: level_string = "B21BB16DWzzWz"; break;
2665 case 2: level_string = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
2666 case 10: level_string = "B21Bzzz"; break;
2667 case 11: level_string = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
2668 default: return False;
2671 if (strcmp(level_string,str2) != 0) return False;
2673 *rdata_len = mdrcnt + 1024;
2674 *rdata = REALLOC(*rdata,*rdata_len);
2676 SSVAL(*rparam,0,NERR_Success);
2677 SSVAL(*rparam,2,0); /* converter word */
2679 p = *rdata;
2680 p2 = p + usri11_end;
2682 memset(p,0,21);
2683 fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
2685 if (uLevel > 0)
2687 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
2688 *p2 = 0;
2690 if (uLevel >= 10)
2692 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
2693 pstrcpy(p2,"Comment");
2694 p2 = skip_string(p2,1);
2696 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
2697 pstrcpy(p2,"UserComment");
2698 p2 = skip_string(p2,1);
2700 /* EEK! the cifsrap.txt doesn't have this in!!!! */
2701 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
2702 pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName));
2703 p2 = skip_string(p2,1);
2706 if (uLevel == 11) /* modelled after NTAS 3.51 reply */
2708 SSVAL(p,usri11_priv,conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2709 SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
2710 SIVALS(p,usri11_password_age,-1); /* password age */
2711 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
2712 pstrcpy(p2, vuser && vuser->homedir ? vuser->homedir : "");
2713 p2 = skip_string(p2,1);
2714 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
2715 pstrcpy(p2,"");
2716 p2 = skip_string(p2,1);
2717 SIVAL(p,usri11_last_logon,0); /* last logon */
2718 SIVAL(p,usri11_last_logoff,0); /* last logoff */
2719 SSVALS(p,usri11_bad_pw_count,-1); /* bad pw counts */
2720 SSVALS(p,usri11_num_logons,-1); /* num logons */
2721 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
2722 pstrcpy(p2,"\\\\*");
2723 p2 = skip_string(p2,1);
2724 SSVAL(p,usri11_country_code,0); /* country code */
2726 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
2727 pstrcpy(p2,"");
2728 p2 = skip_string(p2,1);
2730 SIVALS(p,usri11_max_storage,-1); /* max storage */
2731 SSVAL(p,usri11_units_per_week,168); /* units per week */
2732 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
2734 /* a simple way to get logon hours at all times. */
2735 memset(p2,0xff,21);
2736 SCVAL(p2,21,0); /* fix zero termination */
2737 p2 = skip_string(p2,1);
2739 SSVAL(p,usri11_code_page,0); /* code page */
2741 if (uLevel == 1 || uLevel == 2)
2743 memset(p+22,' ',16); /* password */
2744 SIVALS(p,38,-1); /* password age */
2745 SSVAL(p,42,
2746 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2747 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
2748 pstrcpy(p2, vuser && vuser->homedir ? vuser->homedir : "");
2749 p2 = skip_string(p2,1);
2750 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
2751 *p2++ = 0;
2752 SSVAL(p,52,0); /* flags */
2753 SIVAL(p,54,PTR_DIFF(p2,*rdata)); /* script_path */
2754 pstrcpy(p2,vuser && vuser->logon_script ? vuser->logon_script : "");
2755 p2 = skip_string(p2,1);
2756 if (uLevel == 2)
2758 SIVAL(p,60,0); /* auth_flags */
2759 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
2760 pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName));
2761 p2 = skip_string(p2,1);
2762 SIVAL(p,68,0); /* urs_comment */
2763 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
2764 pstrcpy(p2,"");
2765 p2 = skip_string(p2,1);
2766 SIVAL(p,76,0); /* workstations */
2767 SIVAL(p,80,0); /* last_logon */
2768 SIVAL(p,84,0); /* last_logoff */
2769 SIVALS(p,88,-1); /* acct_expires */
2770 SIVALS(p,92,-1); /* max_storage */
2771 SSVAL(p,96,168); /* units_per_week */
2772 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
2773 memset(p2,-1,21);
2774 p2 += 21;
2775 SSVALS(p,102,-1); /* bad_pw_count */
2776 SSVALS(p,104,-1); /* num_logons */
2777 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
2778 pstrcpy(p2,"\\\\%L");
2779 standard_sub_conn(conn, p2,0);
2780 p2 = skip_string(p2,1);
2781 SSVAL(p,110,49); /* country_code */
2782 SSVAL(p,112,860); /* code page */
2786 *rdata_len = PTR_DIFF(p2,*rdata);
2788 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
2790 return(True);
2793 static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param,char *data,
2794 int mdrcnt,int mprcnt,
2795 char **rdata,char **rparam,
2796 int *rdata_len,int *rparam_len)
2798 char *str1 = param+2;
2799 char *str2 = skip_string(str1,1);
2800 char *p = skip_string(str2,1);
2801 int uLevel;
2802 struct pack_desc desc;
2803 char* name;
2804 /* With share level security vuid will always be zero.
2805 Don't depend on vuser being non-null !!. JRA */
2806 user_struct *vuser = get_valid_user_struct(vuid);
2807 if(vuser != NULL)
2808 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid,
2809 vuser->user.unix_name));
2811 uLevel = SVAL(p,0);
2812 name = p + 2;
2814 memset((char *)&desc,'\0',sizeof(desc));
2816 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
2818 /* check it's a supported varient */
2819 if (strcmp(str1,"OOWb54WrLh") != 0) return False;
2820 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) return False;
2821 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2822 desc.base = *rdata;
2823 desc.buflen = mdrcnt;
2824 desc.subformat = NULL;
2825 desc.format = str2;
2827 if (init_package(&desc,1,0))
2829 PACKI(&desc,"W",0); /* code */
2830 PACKS(&desc,"B21",name); /* eff. name */
2831 PACKS(&desc,"B",""); /* pad */
2832 PACKI(&desc,"W",
2833 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2834 PACKI(&desc,"D",0); /* auth flags XXX */
2835 PACKI(&desc,"W",0); /* num logons */
2836 PACKI(&desc,"W",0); /* bad pw count */
2837 PACKI(&desc,"D",0); /* last logon */
2838 PACKI(&desc,"D",-1); /* last logoff */
2839 PACKI(&desc,"D",-1); /* logoff time */
2840 PACKI(&desc,"D",-1); /* kickoff time */
2841 PACKI(&desc,"D",0); /* password age */
2842 PACKI(&desc,"D",0); /* password can change */
2843 PACKI(&desc,"D",-1); /* password must change */
2845 fstring mypath;
2846 fstrcpy(mypath,"\\\\");
2847 fstrcat(mypath,local_machine);
2848 strupper_m(mypath);
2849 PACKS(&desc,"z",mypath); /* computer */
2851 PACKS(&desc,"z",lp_workgroup());/* domain */
2853 PACKS(&desc,"z", vuser && vuser->logon_script ? vuser->logon_script :""); /* script path */
2855 PACKI(&desc,"D",0x00000000); /* reserved */
2858 *rdata_len = desc.usedlen;
2859 *rparam_len = 6;
2860 *rparam = REALLOC(*rparam,*rparam_len);
2861 SSVALS(*rparam,0,desc.errcode);
2862 SSVAL(*rparam,2,0);
2863 SSVAL(*rparam,4,desc.neededlen);
2865 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
2866 return(True);
2870 /****************************************************************************
2871 api_WAccessGetUserPerms
2872 ****************************************************************************/
2873 static BOOL api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid, char *param,char *data,
2874 int mdrcnt,int mprcnt,
2875 char **rdata,char **rparam,
2876 int *rdata_len,int *rparam_len)
2878 char *str1 = param+2;
2879 char *str2 = skip_string(str1,1);
2880 char *user = skip_string(str2,1);
2881 char *resource = skip_string(user,1);
2883 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
2885 /* check it's a supported varient */
2886 if (strcmp(str1,"zzh") != 0) return False;
2887 if (strcmp(str2,"") != 0) return False;
2889 *rparam_len = 6;
2890 *rparam = REALLOC(*rparam,*rparam_len);
2891 SSVALS(*rparam,0,0); /* errorcode */
2892 SSVAL(*rparam,2,0); /* converter word */
2893 SSVAL(*rparam,4,0x7f); /* permission flags */
2895 return(True);
2898 /****************************************************************************
2899 api_WPrintJobEnumerate
2900 ****************************************************************************/
2901 static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2902 int mdrcnt,int mprcnt,
2903 char **rdata,char **rparam,
2904 int *rdata_len,int *rparam_len)
2906 char *str1 = param+2;
2907 char *str2 = skip_string(str1,1);
2908 char *p = skip_string(str2,1);
2909 int uLevel;
2910 int count;
2911 int i;
2912 int snum;
2913 uint32 jobid;
2914 struct pack_desc desc;
2915 print_queue_struct *queue=NULL;
2916 print_status_struct status;
2917 char *tmpdata=NULL;
2919 uLevel = SVAL(p,2);
2921 memset((char *)&desc,'\0',sizeof(desc));
2922 memset((char *)&status,'\0',sizeof(status));
2924 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
2926 /* check it's a supported varient */
2927 if (strcmp(str1,"WWrLh") != 0) return False;
2928 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2930 if(!rap_to_pjobid(SVAL(p,0),&snum,&jobid))
2931 return False;
2933 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2935 count = print_queue_status(snum,&queue,&status);
2936 for (i = 0; i < count; i++) {
2937 if (queue[i].job == jobid) break;
2940 if (mdrcnt > 0) {
2941 *rdata = REALLOC(*rdata,mdrcnt);
2942 desc.base = *rdata;
2943 desc.buflen = mdrcnt;
2944 } else {
2946 * Don't return data but need to get correct length
2947 * init_package will return wrong size if buflen=0
2949 desc.buflen = getlen(desc.format);
2950 desc.base = tmpdata = (char *)malloc ( desc.buflen );
2953 if (init_package(&desc,1,0)) {
2954 if (i < count) {
2955 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
2956 *rdata_len = desc.usedlen;
2958 else {
2959 desc.errcode = NERR_JobNotFound;
2960 *rdata_len = 0;
2964 *rparam_len = 6;
2965 *rparam = REALLOC(*rparam,*rparam_len);
2966 SSVALS(*rparam,0,desc.errcode);
2967 SSVAL(*rparam,2,0);
2968 SSVAL(*rparam,4,desc.neededlen);
2970 SAFE_FREE(queue);
2971 SAFE_FREE(tmpdata);
2973 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
2974 return(True);
2977 static BOOL api_WPrintJobEnumerate(connection_struct *conn,uint16 vuid, char *param,char *data,
2978 int mdrcnt,int mprcnt,
2979 char **rdata,char **rparam,
2980 int *rdata_len,int *rparam_len)
2982 char *str1 = param+2;
2983 char *str2 = skip_string(str1,1);
2984 char *p = skip_string(str2,1);
2985 char* name = p;
2986 int uLevel;
2987 int count;
2988 int i, succnt=0;
2989 int snum;
2990 struct pack_desc desc;
2991 print_queue_struct *queue=NULL;
2992 print_status_struct status;
2994 memset((char *)&desc,'\0',sizeof(desc));
2995 memset((char *)&status,'\0',sizeof(status));
2997 p = skip_string(p,1);
2998 uLevel = SVAL(p,0);
3000 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
3002 /* check it's a supported variant */
3003 if (strcmp(str1,"zWrLeh") != 0) return False;
3004 if (uLevel > 2) return False; /* defined only for uLevel 0,1,2 */
3005 if (!check_printjob_info(&desc,uLevel,str2)) return False;
3007 snum = lp_servicenumber(name);
3008 if (snum < 0 && pcap_printername_ok(name,NULL)) {
3009 int pnum = lp_servicenumber(PRINTERS_NAME);
3010 if (pnum >= 0) {
3011 lp_add_printer(name,pnum);
3012 snum = lp_servicenumber(name);
3016 if (snum < 0 || !VALID_SNUM(snum)) return(False);
3018 count = print_queue_status(snum,&queue,&status);
3019 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3020 desc.base = *rdata;
3021 desc.buflen = mdrcnt;
3023 if (init_package(&desc,count,0)) {
3024 succnt = 0;
3025 for (i = 0; i < count; i++) {
3026 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
3027 if (desc.errcode == NERR_Success) succnt = i+1;
3031 *rdata_len = desc.usedlen;
3033 *rparam_len = 8;
3034 *rparam = REALLOC(*rparam,*rparam_len);
3035 SSVALS(*rparam,0,desc.errcode);
3036 SSVAL(*rparam,2,0);
3037 SSVAL(*rparam,4,succnt);
3038 SSVAL(*rparam,6,count);
3040 SAFE_FREE(queue);
3042 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
3043 return(True);
3046 static int check_printdest_info(struct pack_desc* desc,
3047 int uLevel, char* id)
3049 desc->subformat = NULL;
3050 switch( uLevel ) {
3051 case 0: desc->format = "B9"; break;
3052 case 1: desc->format = "B9B21WWzW"; break;
3053 case 2: desc->format = "z"; break;
3054 case 3: desc->format = "zzzWWzzzWW"; break;
3055 default: return False;
3057 if (strcmp(desc->format,id) != 0) return False;
3058 return True;
3061 static void fill_printdest_info(connection_struct *conn, int snum, int uLevel,
3062 struct pack_desc* desc)
3064 char buf[100];
3065 strncpy(buf,SERVICE(snum),sizeof(buf)-1);
3066 buf[sizeof(buf)-1] = 0;
3067 strupper_m(buf);
3068 if (uLevel <= 1) {
3069 PACKS(desc,"B9",buf); /* szName */
3070 if (uLevel == 1) {
3071 PACKS(desc,"B21",""); /* szUserName */
3072 PACKI(desc,"W",0); /* uJobId */
3073 PACKI(desc,"W",0); /* fsStatus */
3074 PACKS(desc,"z",""); /* pszStatus */
3075 PACKI(desc,"W",0); /* time */
3078 if (uLevel == 2 || uLevel == 3) {
3079 PACKS(desc,"z",buf); /* pszPrinterName */
3080 if (uLevel == 3) {
3081 PACKS(desc,"z",""); /* pszUserName */
3082 PACKS(desc,"z",""); /* pszLogAddr */
3083 PACKI(desc,"W",0); /* uJobId */
3084 PACKI(desc,"W",0); /* fsStatus */
3085 PACKS(desc,"z",""); /* pszStatus */
3086 PACKS(desc,"z",""); /* pszComment */
3087 PACKS(desc,"z","NULL"); /* pszDrivers */
3088 PACKI(desc,"W",0); /* time */
3089 PACKI(desc,"W",0); /* pad1 */
3094 static BOOL api_WPrintDestGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
3095 int mdrcnt,int mprcnt,
3096 char **rdata,char **rparam,
3097 int *rdata_len,int *rparam_len)
3099 char *str1 = param+2;
3100 char *str2 = skip_string(str1,1);
3101 char *p = skip_string(str2,1);
3102 char* PrinterName = p;
3103 int uLevel;
3104 struct pack_desc desc;
3105 int snum;
3106 char *tmpdata=NULL;
3108 memset((char *)&desc,'\0',sizeof(desc));
3110 p = skip_string(p,1);
3111 uLevel = SVAL(p,0);
3113 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
3115 /* check it's a supported varient */
3116 if (strcmp(str1,"zWrLh") != 0) return False;
3117 if (!check_printdest_info(&desc,uLevel,str2)) return False;
3119 snum = lp_servicenumber(PrinterName);
3120 if (snum < 0 && pcap_printername_ok(PrinterName,NULL)) {
3121 int pnum = lp_servicenumber(PRINTERS_NAME);
3122 if (pnum >= 0) {
3123 lp_add_printer(PrinterName,pnum);
3124 snum = lp_servicenumber(PrinterName);
3128 if (snum < 0) {
3129 *rdata_len = 0;
3130 desc.errcode = NERR_DestNotFound;
3131 desc.neededlen = 0;
3133 else {
3134 if (mdrcnt > 0) {
3135 *rdata = REALLOC(*rdata,mdrcnt);
3136 desc.base = *rdata;
3137 desc.buflen = mdrcnt;
3138 } else {
3140 * Don't return data but need to get correct length
3141 * init_package will return wrong size if buflen=0
3143 desc.buflen = getlen(desc.format);
3144 desc.base = tmpdata = (char *)malloc ( desc.buflen );
3146 if (init_package(&desc,1,0)) {
3147 fill_printdest_info(conn,snum,uLevel,&desc);
3149 *rdata_len = desc.usedlen;
3152 *rparam_len = 6;
3153 *rparam = REALLOC(*rparam,*rparam_len);
3154 SSVALS(*rparam,0,desc.errcode);
3155 SSVAL(*rparam,2,0);
3156 SSVAL(*rparam,4,desc.neededlen);
3158 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
3159 SAFE_FREE(tmpdata);
3160 return(True);
3163 static BOOL api_WPrintDestEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3164 int mdrcnt,int mprcnt,
3165 char **rdata,char **rparam,
3166 int *rdata_len,int *rparam_len)
3168 char *str1 = param+2;
3169 char *str2 = skip_string(str1,1);
3170 char *p = skip_string(str2,1);
3171 int uLevel;
3172 int queuecnt;
3173 int i, n, succnt=0;
3174 struct pack_desc desc;
3175 int services = lp_numservices();
3177 memset((char *)&desc,'\0',sizeof(desc));
3179 uLevel = SVAL(p,0);
3181 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
3183 /* check it's a supported varient */
3184 if (strcmp(str1,"WrLeh") != 0) return False;
3185 if (!check_printdest_info(&desc,uLevel,str2)) return False;
3187 queuecnt = 0;
3188 for (i = 0; i < services; i++)
3189 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
3190 queuecnt++;
3192 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3193 desc.base = *rdata;
3194 desc.buflen = mdrcnt;
3195 if (init_package(&desc,queuecnt,0)) {
3196 succnt = 0;
3197 n = 0;
3198 for (i = 0; i < services; i++) {
3199 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
3200 fill_printdest_info(conn,i,uLevel,&desc);
3201 n++;
3202 if (desc.errcode == NERR_Success) succnt = n;
3207 *rdata_len = desc.usedlen;
3209 *rparam_len = 8;
3210 *rparam = REALLOC(*rparam,*rparam_len);
3211 SSVALS(*rparam,0,desc.errcode);
3212 SSVAL(*rparam,2,0);
3213 SSVAL(*rparam,4,succnt);
3214 SSVAL(*rparam,6,queuecnt);
3216 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
3217 return(True);
3220 static BOOL api_WPrintDriverEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3221 int mdrcnt,int mprcnt,
3222 char **rdata,char **rparam,
3223 int *rdata_len,int *rparam_len)
3225 char *str1 = param+2;
3226 char *str2 = skip_string(str1,1);
3227 char *p = skip_string(str2,1);
3228 int uLevel;
3229 int succnt;
3230 struct pack_desc desc;
3232 memset((char *)&desc,'\0',sizeof(desc));
3234 uLevel = SVAL(p,0);
3236 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
3238 /* check it's a supported varient */
3239 if (strcmp(str1,"WrLeh") != 0) return False;
3240 if (uLevel != 0 || strcmp(str2,"B41") != 0) return False;
3242 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3243 desc.base = *rdata;
3244 desc.buflen = mdrcnt;
3245 if (init_package(&desc,1,0)) {
3246 PACKS(&desc,"B41","NULL");
3249 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3251 *rdata_len = desc.usedlen;
3253 *rparam_len = 8;
3254 *rparam = REALLOC(*rparam,*rparam_len);
3255 SSVALS(*rparam,0,desc.errcode);
3256 SSVAL(*rparam,2,0);
3257 SSVAL(*rparam,4,succnt);
3258 SSVAL(*rparam,6,1);
3260 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
3261 return(True);
3264 static BOOL api_WPrintQProcEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3265 int mdrcnt,int mprcnt,
3266 char **rdata,char **rparam,
3267 int *rdata_len,int *rparam_len)
3269 char *str1 = param+2;
3270 char *str2 = skip_string(str1,1);
3271 char *p = skip_string(str2,1);
3272 int uLevel;
3273 int succnt;
3274 struct pack_desc desc;
3276 memset((char *)&desc,'\0',sizeof(desc));
3278 uLevel = SVAL(p,0);
3280 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
3282 /* check it's a supported varient */
3283 if (strcmp(str1,"WrLeh") != 0) return False;
3284 if (uLevel != 0 || strcmp(str2,"B13") != 0) return False;
3286 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3287 desc.base = *rdata;
3288 desc.buflen = mdrcnt;
3289 desc.format = str2;
3290 if (init_package(&desc,1,0)) {
3291 PACKS(&desc,"B13","lpd");
3294 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3296 *rdata_len = desc.usedlen;
3298 *rparam_len = 8;
3299 *rparam = REALLOC(*rparam,*rparam_len);
3300 SSVALS(*rparam,0,desc.errcode);
3301 SSVAL(*rparam,2,0);
3302 SSVAL(*rparam,4,succnt);
3303 SSVAL(*rparam,6,1);
3305 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
3306 return(True);
3309 static BOOL api_WPrintPortEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3310 int mdrcnt,int mprcnt,
3311 char **rdata,char **rparam,
3312 int *rdata_len,int *rparam_len)
3314 char *str1 = param+2;
3315 char *str2 = skip_string(str1,1);
3316 char *p = skip_string(str2,1);
3317 int uLevel;
3318 int succnt;
3319 struct pack_desc desc;
3321 memset((char *)&desc,'\0',sizeof(desc));
3323 uLevel = SVAL(p,0);
3325 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
3327 /* check it's a supported varient */
3328 if (strcmp(str1,"WrLeh") != 0) return False;
3329 if (uLevel != 0 || strcmp(str2,"B9") != 0) return False;
3331 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3332 memset((char *)&desc,'\0',sizeof(desc));
3333 desc.base = *rdata;
3334 desc.buflen = mdrcnt;
3335 desc.format = str2;
3336 if (init_package(&desc,1,0)) {
3337 PACKS(&desc,"B13","lp0");
3340 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3342 *rdata_len = desc.usedlen;
3344 *rparam_len = 8;
3345 *rparam = REALLOC(*rparam,*rparam_len);
3346 SSVALS(*rparam,0,desc.errcode);
3347 SSVAL(*rparam,2,0);
3348 SSVAL(*rparam,4,succnt);
3349 SSVAL(*rparam,6,1);
3351 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
3352 return(True);
3356 /****************************************************************************
3357 List open sessions
3358 ****************************************************************************/
3359 static BOOL api_RNetSessionEnum(connection_struct *conn,uint16 vuid, char *param, char *data,
3360 int mdrcnt,int mprcnt,
3361 char **rdata,char **rparam,
3362 int *rdata_len,int *rparam_len)
3365 char *str1 = param+2;
3366 char *str2 = skip_string(str1,1);
3367 char *p = skip_string(str2,1);
3368 int uLevel;
3369 struct pack_desc desc;
3370 struct sessionid *session_list;
3371 int i, num_sessions;
3373 memset((char *)&desc,'\0',sizeof(desc));
3375 uLevel = SVAL(p,0);
3377 DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel));
3378 DEBUG(7,("RNetSessionEnum req string=%s\n",str1));
3379 DEBUG(7,("RNetSessionEnum ret string=%s\n",str2));
3381 /* check it's a supported varient */
3382 if (strcmp(str1,RAP_NetSessionEnum_REQ) != 0) return False;
3383 if (uLevel != 2 || strcmp(str2,RAP_SESSION_INFO_L2) != 0) return False;
3385 num_sessions = list_sessions(&session_list);
3387 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3388 memset((char *)&desc,'\0',sizeof(desc));
3389 desc.base = *rdata;
3390 desc.buflen = mdrcnt;
3391 desc.format = str2;
3392 if (!init_package(&desc,num_sessions,0)) {
3393 return False;
3396 for(i=0; i<num_sessions; i++) {
3397 PACKS(&desc, "z", session_list[i].remote_machine);
3398 PACKS(&desc, "z", session_list[i].username);
3399 PACKI(&desc, "W", 1); /* num conns */
3400 PACKI(&desc, "W", 0); /* num opens */
3401 PACKI(&desc, "W", 1); /* num users */
3402 PACKI(&desc, "D", 0); /* session time */
3403 PACKI(&desc, "D", 0); /* idle time */
3404 PACKI(&desc, "D", 0); /* flags */
3405 PACKS(&desc, "z", "Unknown Client"); /* client type string */
3408 *rdata_len = desc.usedlen;
3410 *rparam_len = 8;
3411 *rparam = REALLOC(*rparam,*rparam_len);
3412 SSVALS(*rparam,0,desc.errcode);
3413 SSVAL(*rparam,2,0); /* converter */
3414 SSVAL(*rparam,4,num_sessions); /* count */
3416 DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc.errcode));
3417 return True;
3421 /****************************************************************************
3422 The buffer was too small
3423 ****************************************************************************/
3425 static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param,char *data,
3426 int mdrcnt,int mprcnt,
3427 char **rdata,char **rparam,
3428 int *rdata_len,int *rparam_len)
3430 *rparam_len = MIN(*rparam_len,mprcnt);
3431 *rparam = REALLOC(*rparam,*rparam_len);
3433 *rdata_len = 0;
3435 SSVAL(*rparam,0,NERR_BufTooSmall);
3437 DEBUG(3,("Supplied buffer too small in API command\n"));
3439 return(True);
3443 /****************************************************************************
3444 The request is not supported
3445 ****************************************************************************/
3447 static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param,char *data,
3448 int mdrcnt,int mprcnt,
3449 char **rdata,char **rparam,
3450 int *rdata_len,int *rparam_len)
3452 *rparam_len = 4;
3453 *rparam = REALLOC(*rparam,*rparam_len);
3455 *rdata_len = 0;
3457 SSVAL(*rparam,0,NERR_notsupported);
3458 SSVAL(*rparam,2,0); /* converter word */
3460 DEBUG(3,("Unsupported API command\n"));
3462 return(True);
3468 static const struct
3470 const char *name;
3471 int id;
3472 BOOL (*fn)(connection_struct *,uint16,char *,char *,
3473 int,int,char **,char **,int *,int *);
3474 BOOL auth_user; /* Deny anonymous access? */
3475 } api_commands[] = {
3476 {"RNetShareEnum", RAP_WshareEnum, api_RNetShareEnum, True},
3477 {"RNetShareGetInfo", RAP_WshareGetInfo, api_RNetShareGetInfo},
3478 {"RNetShareAdd", RAP_WshareAdd, api_RNetShareAdd},
3479 {"RNetSessionEnum", RAP_WsessionEnum, api_RNetSessionEnum, True},
3480 {"RNetServerGetInfo", RAP_WserverGetInfo, api_RNetServerGetInfo},
3481 {"RNetGroupEnum", RAP_WGroupEnum, api_RNetGroupEnum, True},
3482 {"RNetGroupGetUsers", RAP_WGroupGetUsers, api_RNetGroupGetUsers, True},
3483 {"RNetUserEnum", RAP_WUserEnum, api_RNetUserEnum, True},
3484 {"RNetUserGetInfo", RAP_WUserGetInfo, api_RNetUserGetInfo},
3485 {"NetUserGetGroups", RAP_WUserGetGroups, api_NetUserGetGroups},
3486 {"NetWkstaGetInfo", RAP_WWkstaGetInfo, api_NetWkstaGetInfo},
3487 {"DosPrintQEnum", RAP_WPrintQEnum, api_DosPrintQEnum, True},
3488 {"DosPrintQGetInfo", RAP_WPrintQGetInfo, api_DosPrintQGetInfo},
3489 {"WPrintQueuePause", RAP_WPrintQPause, api_WPrintQueueCtrl},
3490 {"WPrintQueueResume", RAP_WPrintQContinue, api_WPrintQueueCtrl},
3491 {"WPrintJobEnumerate",RAP_WPrintJobEnum, api_WPrintJobEnumerate},
3492 {"WPrintJobGetInfo", RAP_WPrintJobGetInfo, api_WPrintJobGetInfo},
3493 {"RDosPrintJobDel", RAP_WPrintJobDel, api_RDosPrintJobDel},
3494 {"RDosPrintJobPause", RAP_WPrintJobPause, api_RDosPrintJobDel},
3495 {"RDosPrintJobResume",RAP_WPrintJobContinue, api_RDosPrintJobDel},
3496 {"WPrintDestEnum", RAP_WPrintDestEnum, api_WPrintDestEnum},
3497 {"WPrintDestGetInfo", RAP_WPrintDestGetInfo, api_WPrintDestGetInfo},
3498 {"NetRemoteTOD", RAP_NetRemoteTOD, api_NetRemoteTOD},
3499 {"WPrintQueuePurge", RAP_WPrintQPurge, api_WPrintQueueCtrl},
3500 {"NetServerEnum", RAP_NetServerEnum2, api_RNetServerEnum}, /* anon OK */
3501 {"WAccessGetUserPerms",RAP_WAccessGetUserPerms,api_WAccessGetUserPerms},
3502 {"SetUserPassword", RAP_WUserPasswordSet2, api_SetUserPassword},
3503 {"WWkstaUserLogon", RAP_WWkstaUserLogon, api_WWkstaUserLogon},
3504 {"PrintJobInfo", RAP_WPrintJobSetInfo, api_PrintJobInfo},
3505 {"WPrintDriverEnum", RAP_WPrintDriverEnum, api_WPrintDriverEnum},
3506 {"WPrintQProcEnum", RAP_WPrintQProcessorEnum,api_WPrintQProcEnum},
3507 {"WPrintPortEnum", RAP_WPrintPortEnum, api_WPrintPortEnum},
3508 {"SamOEMChangePassword",RAP_SamOEMChgPasswordUser2_P,api_SamOEMChangePassword}, /* anon OK */
3509 {NULL, -1, api_Unsupported}};
3511 /* The following RAP calls are not implemented by Samba:
3513 RAP_WFileEnum2 - anon not OK
3516 /****************************************************************************
3517 Handle remote api calls
3518 ****************************************************************************/
3520 int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data,char *params,
3521 int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
3523 int api_command;
3524 char *rdata = NULL;
3525 char *rparam = NULL;
3526 int rdata_len = 0;
3527 int rparam_len = 0;
3528 BOOL reply=False;
3529 int i;
3531 if (!params) {
3532 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
3533 return 0;
3536 api_command = SVAL(params,0);
3538 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
3539 api_command,
3540 params+2,
3541 skip_string(params+2,1),
3542 tdscnt,tpscnt,mdrcnt,mprcnt));
3544 for (i=0;api_commands[i].name;i++) {
3545 if (api_commands[i].id == api_command && api_commands[i].fn) {
3546 DEBUG(3,("Doing %s\n",api_commands[i].name));
3547 break;
3551 /* Check whether this api call can be done anonymously */
3553 if (api_commands[i].auth_user && lp_restrict_anonymous()) {
3554 user_struct *user = get_valid_user_struct(vuid);
3556 if (!user || user->guest)
3557 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
3560 rdata = (char *)malloc(1024);
3561 if (rdata)
3562 memset(rdata,'\0',1024);
3564 rparam = (char *)malloc(1024);
3565 if (rparam)
3566 memset(rparam,'\0',1024);
3568 if(!rdata || !rparam) {
3569 DEBUG(0,("api_reply: malloc fail !\n"));
3570 return -1;
3573 reply = api_commands[i].fn(conn,vuid,params,data,mdrcnt,mprcnt,
3574 &rdata,&rparam,&rdata_len,&rparam_len);
3577 if (rdata_len > mdrcnt ||
3578 rparam_len > mprcnt) {
3579 reply = api_TooSmall(conn,vuid,params,data,mdrcnt,mprcnt,
3580 &rdata,&rparam,&rdata_len,&rparam_len);
3583 /* if we get False back then it's actually unsupported */
3584 if (!reply)
3585 api_Unsupported(conn,vuid,params,data,mdrcnt,mprcnt,
3586 &rdata,&rparam,&rdata_len,&rparam_len);
3588 send_trans_reply(outbuf, rparam, rparam_len, rdata, rdata_len, False);
3590 SAFE_FREE(rdata);
3591 SAFE_FREE(rparam);
3593 return -1;