Sync to the changes in head ...
[Samba/gbeck.git] / source3 / smbd / lanman.c
blob98857c6d3208f025eb66399fe9ebe163c03ef459
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 if ( !W_ERROR_IS_OK(get_a_printer( NULL, &printer, 2, lp_servicename(snum))) ) {
526 DEBUG(3,("fill_printq_info_52: Failed to lookup printer [%s]\n",
527 lp_servicename(snum)));
528 goto err;
531 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername,
532 "Windows 4.0", 0)) )
534 DEBUG(3,("fill_printq_info_52: Failed to lookup driver [%s]\n",
535 printer->info_2->drivername));
536 goto err;
539 trim_string(driver.info_3->driverpath, "\\print$\\WIN40\\0\\", 0);
540 trim_string(driver.info_3->datafile, "\\print$\\WIN40\\0\\", 0);
541 trim_string(driver.info_3->helpfile, "\\print$\\WIN40\\0\\", 0);
543 PACKI(desc, "W", 0x0400); /* don't know */
544 PACKS(desc, "z", driver.info_3->name); /* long printer name */
545 PACKS(desc, "z", driver.info_3->driverpath); /* Driverfile Name */
546 PACKS(desc, "z", driver.info_3->datafile); /* Datafile name */
547 PACKS(desc, "z", driver.info_3->monitorname); /* language monitor */
549 fstrcpy(location, "\\\\");
550 fstrcat(location, get_called_name());
551 fstrcat(location, "\\print$\\WIN40\\0");
552 PACKS(desc,"z", location); /* share to retrieve files */
554 PACKS(desc,"z", driver.info_3->defaultdatatype); /* default data type */
555 PACKS(desc,"z", driver.info_3->helpfile); /* helpfile name */
556 PACKS(desc,"z", driver.info_3->driverpath); /* driver name */
558 DEBUG(3,("Printer Driver Name: %s:\n",driver.info_3->name));
559 DEBUG(3,("Driver: %s:\n",driver.info_3->driverpath));
560 DEBUG(3,("Data File: %s:\n",driver.info_3->datafile));
561 DEBUG(3,("Language Monitor: %s:\n",driver.info_3->monitorname));
562 DEBUG(3,("Driver Location: %s:\n",location));
563 DEBUG(3,("Data Type: %s:\n",driver.info_3->defaultdatatype));
564 DEBUG(3,("Help File: %s:\n",driver.info_3->helpfile));
565 PACKI(desc,"N",count); /* number of files to copy */
567 for ( i=0; i<count && driver.info_3->dependentfiles && *driver.info_3->dependentfiles[i]; i++)
569 trim_string(driver.info_3->dependentfiles[i], "\\print$\\WIN40\\0\\", 0);
570 PACKS(desc,"z",driver.info_3->dependentfiles[i]); /* driver files to copy */
571 DEBUG(3,("Dependent File: %s:\n",driver.info_3->dependentfiles[i]));
574 /* sanity check */
575 if ( i != count )
576 DEBUG(3,("fill_printq_info_52: file count specified by client [%d] != number of dependent files [%i]\n",
577 count, i));
579 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n", SERVICE(snum),i));
581 desc->errcode=NERR_Success;
582 goto done;
584 err:
585 DEBUG(3,("fill_printq_info: Can't supply driver files\n"));
586 desc->errcode=NERR_notsupported;
588 done:
589 if ( printer )
590 free_a_printer( &printer, 2 );
592 if ( driver.info_3 )
593 free_a_printer_driver( driver, 3 );
597 static void fill_printq_info(connection_struct *conn, int snum, int uLevel,
598 struct pack_desc* desc,
599 int count, print_queue_struct* queue,
600 print_status_struct* status)
602 switch (uLevel) {
603 case 1:
604 case 2:
605 PACKS(desc,"B13",SERVICE(snum));
606 break;
607 case 3:
608 case 4:
609 case 5:
610 PACKS(desc,"z",Expand(conn,snum,SERVICE(snum)));
611 break;
612 case 51:
613 PACKI(desc,"K",printq_status(status->status));
614 break;
617 if (uLevel == 1 || uLevel == 2) {
618 PACKS(desc,"B",""); /* alignment */
619 PACKI(desc,"W",5); /* priority */
620 PACKI(desc,"W",0); /* start time */
621 PACKI(desc,"W",0); /* until time */
622 PACKS(desc,"z",""); /* pSepFile */
623 PACKS(desc,"z","lpd"); /* pPrProc */
624 PACKS(desc,"z",SERVICE(snum)); /* pDestinations */
625 PACKS(desc,"z",""); /* pParms */
626 if (snum < 0) {
627 PACKS(desc,"z","UNKNOWN PRINTER");
628 PACKI(desc,"W",LPSTAT_ERROR);
630 else if (!status || !status->message[0]) {
631 PACKS(desc,"z",Expand(conn,snum,lp_comment(snum)));
632 PACKI(desc,"W",LPSTAT_OK); /* status */
633 } else {
634 PACKS(desc,"z",status->message);
635 PACKI(desc,"W",printq_status(status->status)); /* status */
637 PACKI(desc,(uLevel == 1 ? "W" : "N"),count);
640 if (uLevel == 3 || uLevel == 4) {
641 pstring drivername;
643 PACKI(desc,"W",5); /* uPriority */
644 PACKI(desc,"W",0); /* uStarttime */
645 PACKI(desc,"W",0); /* uUntiltime */
646 PACKI(desc,"W",5); /* pad1 */
647 PACKS(desc,"z",""); /* pszSepFile */
648 PACKS(desc,"z","WinPrint"); /* pszPrProc */
649 PACKS(desc,"z",NULL); /* pszParms */
650 PACKS(desc,"z",NULL); /* pszComment - don't ask.... JRA */
651 /* "don't ask" that it's done this way to fix corrupted
652 Win9X/ME printer comments. */
653 if (!status) {
654 PACKI(desc,"W",LPSTAT_OK); /* fsStatus */
655 } else {
656 PACKI(desc,"W",printq_status(status->status)); /* fsStatus */
658 PACKI(desc,(uLevel == 3 ? "W" : "N"),count); /* cJobs */
659 PACKS(desc,"z",SERVICE(snum)); /* pszPrinters */
660 get_driver_name(snum,drivername);
661 PACKS(desc,"z",drivername); /* pszDriverName */
662 PackDriverData(desc); /* pDriverData */
665 if (uLevel == 2 || uLevel == 4) {
666 int i;
667 for (i=0;i<count;i++)
668 fill_printjob_info(conn,snum,uLevel == 2 ? 1 : 2,desc,&queue[i],i);
671 if (uLevel==52)
672 fill_printq_info_52( conn, snum, desc, count );
675 /* This function returns the number of files for a given driver */
676 static int get_printerdrivernumber(int snum)
678 int result = 0;
679 NT_PRINTER_DRIVER_INFO_LEVEL driver;
680 NT_PRINTER_INFO_LEVEL *printer = NULL;
682 if ( !W_ERROR_IS_OK(get_a_printer( NULL, &printer, 2, lp_servicename(snum))) ) {
683 DEBUG(3,("get_printerdrivernumber: Failed to lookup printer [%s]\n",
684 lp_servicename(snum)));
685 goto done;
688 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername,
689 "Windows 4.0", 0)) )
691 DEBUG(3,("get_printerdrivernumber: Failed to lookup driver [%s]\n",
692 printer->info_2->drivername));
693 goto done;
696 /* count the number of files */
697 while ( driver.info_3->dependentfiles && *driver.info_3->dependentfiles[result] )
698 result++;
700 done:
701 if ( printer )
702 free_a_printer( &printer, 2 );
704 if ( driver.info_3 )
705 free_a_printer_driver( driver, 3 );
707 return result;
710 static BOOL api_DosPrintQGetInfo(connection_struct *conn,
711 uint16 vuid, char *param,char *data,
712 int mdrcnt,int mprcnt,
713 char **rdata,char **rparam,
714 int *rdata_len,int *rparam_len)
716 char *str1 = param+2;
717 char *str2 = skip_string(str1,1);
718 char *p = skip_string(str2,1);
719 char *QueueName = p;
720 int uLevel;
721 int count=0;
722 int snum;
723 char* str3;
724 struct pack_desc desc;
725 print_queue_struct *queue=NULL;
726 print_status_struct status;
727 char* tmpdata=NULL;
729 memset((char *)&status,'\0',sizeof(status));
730 memset((char *)&desc,'\0',sizeof(desc));
732 p = skip_string(p,1);
733 uLevel = SVAL(p,0);
734 str3 = p + 4;
736 /* remove any trailing username */
737 if ((p = strchr_m(QueueName,'%')))
738 *p = 0;
740 DEBUG(3,("api_DosPrintQGetInfo uLevel=%d name=%s\n",uLevel,QueueName));
742 /* check it's a supported varient */
743 if (!prefix_ok(str1,"zWrLh"))
744 return False;
745 if (!check_printq_info(&desc,uLevel,str2,str3)) {
747 * Patch from Scott Moomaw <scott@bridgewater.edu>
748 * to return the 'invalid info level' error if an
749 * unknown level was requested.
751 *rdata_len = 0;
752 *rparam_len = 6;
753 *rparam = REALLOC(*rparam,*rparam_len);
754 SSVALS(*rparam,0,ERRunknownlevel);
755 SSVAL(*rparam,2,0);
756 SSVAL(*rparam,4,0);
757 return(True);
760 snum = lp_servicenumber(QueueName);
761 if (snum < 0 && pcap_printername_ok(QueueName,NULL)) {
762 int pnum = lp_servicenumber(PRINTERS_NAME);
763 if (pnum >= 0) {
764 lp_add_printer(QueueName,pnum);
765 snum = lp_servicenumber(QueueName);
769 if (snum < 0 || !VALID_SNUM(snum))
770 return(False);
772 if (uLevel==52) {
773 count = get_printerdrivernumber(snum);
774 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count));
775 } else {
776 count = print_queue_status(snum, &queue,&status);
779 if (mdrcnt > 0) {
780 *rdata = REALLOC(*rdata,mdrcnt);
781 desc.base = *rdata;
782 desc.buflen = mdrcnt;
783 } else {
785 * Don't return data but need to get correct length
786 * init_package will return wrong size if buflen=0
788 desc.buflen = getlen(desc.format);
789 desc.base = tmpdata = (char *) malloc (desc.buflen);
792 if (init_package(&desc,1,count)) {
793 desc.subcount = count;
794 fill_printq_info(conn,snum,uLevel,&desc,count,queue,&status);
797 *rdata_len = desc.usedlen;
800 * We must set the return code to ERRbuftoosmall
801 * in order to support lanman style printing with Win NT/2k
802 * clients --jerry
804 if (!mdrcnt && lp_disable_spoolss())
805 desc.errcode = ERRbuftoosmall;
807 *rdata_len = desc.usedlen;
808 *rparam_len = 6;
809 *rparam = REALLOC(*rparam,*rparam_len);
810 SSVALS(*rparam,0,desc.errcode);
811 SSVAL(*rparam,2,0);
812 SSVAL(*rparam,4,desc.neededlen);
814 DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode));
816 SAFE_FREE(queue);
817 SAFE_FREE(tmpdata);
819 return(True);
822 /****************************************************************************
823 View list of all print jobs on all queues.
824 ****************************************************************************/
826 static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid, char* param, char* data,
827 int mdrcnt, int mprcnt,
828 char **rdata, char** rparam,
829 int *rdata_len, int *rparam_len)
831 char *param_format = param+2;
832 char *output_format1 = skip_string(param_format,1);
833 char *p = skip_string(output_format1,1);
834 int uLevel = SVAL(p,0);
835 char *output_format2 = p + 4;
836 int services = lp_numservices();
837 int i, n;
838 struct pack_desc desc;
839 print_queue_struct **queue = NULL;
840 print_status_struct *status = NULL;
841 int* subcntarr = NULL;
842 int queuecnt, subcnt=0, succnt=0;
844 memset((char *)&desc,'\0',sizeof(desc));
846 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
848 if (!prefix_ok(param_format,"WrLeh")) return False;
849 if (!check_printq_info(&desc,uLevel,output_format1,output_format2)) {
851 * Patch from Scott Moomaw <scott@bridgewater.edu>
852 * to return the 'invalid info level' error if an
853 * unknown level was requested.
855 *rdata_len = 0;
856 *rparam_len = 6;
857 *rparam = REALLOC(*rparam,*rparam_len);
858 SSVALS(*rparam,0,ERRunknownlevel);
859 SSVAL(*rparam,2,0);
860 SSVAL(*rparam,4,0);
861 return(True);
864 queuecnt = 0;
865 for (i = 0; i < services; i++)
866 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
867 queuecnt++;
868 if (uLevel > 0) {
869 if((queue = (print_queue_struct**)malloc(queuecnt*sizeof(print_queue_struct*))) == NULL) {
870 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
871 return False;
873 memset(queue,0,queuecnt*sizeof(print_queue_struct*));
874 if((status = (print_status_struct*)malloc(queuecnt*sizeof(print_status_struct))) == NULL) {
875 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
876 return False;
878 memset(status,0,queuecnt*sizeof(print_status_struct));
879 if((subcntarr = (int*)malloc(queuecnt*sizeof(int))) == NULL) {
880 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
881 return False;
883 subcnt = 0;
884 n = 0;
885 for (i = 0; i < services; i++)
886 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
887 subcntarr[n] = print_queue_status(i, &queue[n],&status[n]);
888 subcnt += subcntarr[n];
889 n++;
892 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
893 desc.base = *rdata;
894 desc.buflen = mdrcnt;
896 if (init_package(&desc,queuecnt,subcnt)) {
897 n = 0;
898 succnt = 0;
899 for (i = 0; i < services; i++)
900 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
901 fill_printq_info(conn,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]);
902 n++;
903 if (desc.errcode == NERR_Success) succnt = n;
907 SAFE_FREE(subcntarr);
909 *rdata_len = desc.usedlen;
910 *rparam_len = 8;
911 *rparam = REALLOC(*rparam,*rparam_len);
912 SSVALS(*rparam,0,desc.errcode);
913 SSVAL(*rparam,2,0);
914 SSVAL(*rparam,4,succnt);
915 SSVAL(*rparam,6,queuecnt);
917 for (i = 0; i < queuecnt; i++) {
918 if (queue) SAFE_FREE(queue[i]);
921 SAFE_FREE(queue);
922 SAFE_FREE(status);
924 return True;
927 /****************************************************************************
928 get info level for a server list query
929 ****************************************************************************/
930 static BOOL check_server_info(int uLevel, char* id)
932 switch( uLevel ) {
933 case 0:
934 if (strcmp(id,"B16") != 0) return False;
935 break;
936 case 1:
937 if (strcmp(id,"B16BBDz") != 0) return False;
938 break;
939 default:
940 return False;
942 return True;
945 struct srv_info_struct
947 fstring name;
948 uint32 type;
949 fstring comment;
950 fstring domain;
951 BOOL server_added;
955 /*******************************************************************
956 get server info lists from the files saved by nmbd. Return the
957 number of entries
958 ******************************************************************/
959 static int get_server_info(uint32 servertype,
960 struct srv_info_struct **servers,
961 const char *domain)
963 int count=0;
964 int alloced=0;
965 char **lines;
966 BOOL local_list_only;
967 int i;
969 lines = file_lines_load(lock_path(SERVER_LIST), NULL);
970 if (!lines) {
971 DEBUG(4,("Can't open %s - %s\n",lock_path(SERVER_LIST),strerror(errno)));
972 return(0);
975 /* request for everything is code for request all servers */
976 if (servertype == SV_TYPE_ALL)
977 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
979 local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY);
981 DEBUG(4,("Servertype search: %8x\n",servertype));
983 for (i=0;lines[i];i++) {
984 fstring stype;
985 struct srv_info_struct *s;
986 const char *ptr = lines[i];
987 BOOL ok = True;
989 if (!*ptr) continue;
991 if (count == alloced) {
992 struct srv_info_struct *ts;
994 alloced += 10;
995 ts = (struct srv_info_struct *)
996 Realloc(*servers,sizeof(**servers)*alloced);
997 if (!ts) {
998 DEBUG(0,("get_server_info: failed to enlarge servers info struct!\n"));
999 return(0);
1001 else *servers = ts;
1002 memset((char *)((*servers)+count),'\0',sizeof(**servers)*(alloced-count));
1004 s = &(*servers)[count];
1006 if (!next_token(&ptr,s->name , NULL, sizeof(s->name))) continue;
1007 if (!next_token(&ptr,stype , NULL, sizeof(stype))) continue;
1008 if (!next_token(&ptr,s->comment, NULL, sizeof(s->comment))) continue;
1009 if (!next_token(&ptr,s->domain , NULL, sizeof(s->domain))) {
1010 /* this allows us to cope with an old nmbd */
1011 fstrcpy(s->domain,lp_workgroup());
1014 if (sscanf(stype,"%X",&s->type) != 1) {
1015 DEBUG(4,("r:host file "));
1016 ok = False;
1019 /* Filter the servers/domains we return based on what was asked for. */
1021 /* Check to see if we are being asked for a local list only. */
1022 if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) {
1023 DEBUG(4,("r: local list only"));
1024 ok = False;
1027 /* doesn't match up: don't want it */
1028 if (!(servertype & s->type)) {
1029 DEBUG(4,("r:serv type "));
1030 ok = False;
1033 if ((servertype & SV_TYPE_DOMAIN_ENUM) !=
1034 (s->type & SV_TYPE_DOMAIN_ENUM))
1036 DEBUG(4,("s: dom mismatch "));
1037 ok = False;
1040 if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM))
1042 ok = False;
1045 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1046 s->type &= ~SV_TYPE_LOCAL_LIST_ONLY;
1048 if (ok)
1050 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1051 s->name, s->type, s->comment, s->domain));
1053 s->server_added = True;
1054 count++;
1056 else
1058 DEBUG(4,("%20s %8x %25s %15s\n",
1059 s->name, s->type, s->comment, s->domain));
1063 file_lines_free(lines);
1064 return(count);
1068 /*******************************************************************
1069 fill in a server info structure
1070 ******************************************************************/
1071 static int fill_srv_info(struct srv_info_struct *service,
1072 int uLevel, char **buf, int *buflen,
1073 char **stringbuf, int *stringspace, char *baseaddr)
1075 int struct_len;
1076 char* p;
1077 char* p2;
1078 int l2;
1079 int len;
1081 switch (uLevel) {
1082 case 0: struct_len = 16; break;
1083 case 1: struct_len = 26; break;
1084 default: return -1;
1087 if (!buf)
1089 len = 0;
1090 switch (uLevel)
1092 case 1:
1093 len = strlen(service->comment)+1;
1094 break;
1097 if (buflen) *buflen = struct_len;
1098 if (stringspace) *stringspace = len;
1099 return struct_len + len;
1102 len = struct_len;
1103 p = *buf;
1104 if (*buflen < struct_len) return -1;
1105 if (stringbuf)
1107 p2 = *stringbuf;
1108 l2 = *stringspace;
1110 else
1112 p2 = p + struct_len;
1113 l2 = *buflen - struct_len;
1115 if (!baseaddr) baseaddr = p;
1117 switch (uLevel)
1119 case 0:
1120 push_ascii(p,service->name, 15, STR_TERMINATE);
1121 break;
1123 case 1:
1124 push_ascii(p,service->name,15, STR_TERMINATE);
1125 SIVAL(p,18,service->type);
1126 SIVAL(p,22,PTR_DIFF(p2,baseaddr));
1127 len += CopyAndAdvance(&p2,service->comment,&l2);
1128 break;
1131 if (stringbuf)
1133 *buf = p + struct_len;
1134 *buflen -= struct_len;
1135 *stringbuf = p2;
1136 *stringspace = l2;
1138 else
1140 *buf = p2;
1141 *buflen -= len;
1143 return len;
1147 static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
1149 return(strcmp(s1->name,s2->name));
1152 /****************************************************************************
1153 view list of servers available (or possibly domains). The info is
1154 extracted from lists saved by nmbd on the local host
1155 ****************************************************************************/
1156 static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid, char *param, char *data,
1157 int mdrcnt, int mprcnt, char **rdata,
1158 char **rparam, int *rdata_len, int *rparam_len)
1160 char *str1 = param+2;
1161 char *str2 = skip_string(str1,1);
1162 char *p = skip_string(str2,1);
1163 int uLevel = SVAL(p,0);
1164 int buf_len = SVAL(p,2);
1165 uint32 servertype = IVAL(p,4);
1166 char *p2;
1167 int data_len, fixed_len, string_len;
1168 int f_len = 0, s_len = 0;
1169 struct srv_info_struct *servers=NULL;
1170 int counted=0,total=0;
1171 int i,missed;
1172 fstring domain;
1173 BOOL domain_request;
1174 BOOL local_request;
1176 /* If someone sets all the bits they don't really mean to set
1177 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1178 known servers. */
1180 if (servertype == SV_TYPE_ALL)
1181 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1183 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1184 any other bit (they may just set this bit on it's own) they
1185 want all the locally seen servers. However this bit can be
1186 set on its own so set the requested servers to be
1187 ALL - DOMAIN_ENUM. */
1189 if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM))
1190 servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
1192 domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
1193 local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
1195 p += 8;
1197 if (!prefix_ok(str1,"WrLehD")) return False;
1198 if (!check_server_info(uLevel,str2)) return False;
1200 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1201 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1202 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1204 if (strcmp(str1, "WrLehDz") == 0) {
1205 pull_ascii_fstring(domain, p);
1206 } else {
1207 fstrcpy(domain, lp_workgroup());
1210 if (lp_browse_list())
1211 total = get_server_info(servertype,&servers,domain);
1213 data_len = fixed_len = string_len = 0;
1214 missed = 0;
1216 if (total > 0)
1217 qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
1220 char *lastname=NULL;
1222 for (i=0;i<total;i++)
1224 struct srv_info_struct *s = &servers[i];
1225 if (lastname && strequal(lastname,s->name)) continue;
1226 lastname = s->name;
1227 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1228 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1229 s->name, s->type, s->comment, s->domain));
1231 if (data_len <= buf_len) {
1232 counted++;
1233 fixed_len += f_len;
1234 string_len += s_len;
1235 } else {
1236 missed++;
1241 *rdata_len = fixed_len + string_len;
1242 *rdata = REALLOC(*rdata,*rdata_len);
1243 memset(*rdata,'\0',*rdata_len);
1245 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1246 p = *rdata;
1247 f_len = fixed_len;
1248 s_len = string_len;
1251 char *lastname=NULL;
1252 int count2 = counted;
1253 for (i = 0; i < total && count2;i++)
1255 struct srv_info_struct *s = &servers[i];
1256 if (lastname && strequal(lastname,s->name)) continue;
1257 lastname = s->name;
1258 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1259 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1260 s->name, s->type, s->comment, s->domain));
1261 count2--;
1265 *rparam_len = 8;
1266 *rparam = REALLOC(*rparam,*rparam_len);
1267 SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata));
1268 SSVAL(*rparam,2,0);
1269 SSVAL(*rparam,4,counted);
1270 SSVAL(*rparam,6,counted+missed);
1272 SAFE_FREE(servers);
1274 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1275 domain,uLevel,counted,counted+missed));
1277 return(True);
1280 /****************************************************************************
1281 command 0x34 - suspected of being a "Lookup Names" stub api
1282 ****************************************************************************/
1283 static BOOL api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid, char *param, char *data,
1284 int mdrcnt, int mprcnt, char **rdata,
1285 char **rparam, int *rdata_len, int *rparam_len)
1287 char *str1 = param+2;
1288 char *str2 = skip_string(str1,1);
1289 char *p = skip_string(str2,1);
1290 int uLevel = SVAL(p,0);
1291 int buf_len = SVAL(p,2);
1292 int counted=0;
1293 int missed=0;
1295 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1296 str1, str2, p, uLevel, buf_len));
1298 if (!prefix_ok(str1,"zWrLeh")) return False;
1300 *rdata_len = 0;
1302 *rparam_len = 8;
1303 *rparam = REALLOC(*rparam,*rparam_len);
1305 SSVAL(*rparam,0,0x08AC); /* informational warning message */
1306 SSVAL(*rparam,2,0);
1307 SSVAL(*rparam,4,counted);
1308 SSVAL(*rparam,6,counted+missed);
1310 return(True);
1313 /****************************************************************************
1314 get info about a share
1315 ****************************************************************************/
1316 static BOOL check_share_info(int uLevel, char* id)
1318 switch( uLevel ) {
1319 case 0:
1320 if (strcmp(id,"B13") != 0) return False;
1321 break;
1322 case 1:
1323 if (strcmp(id,"B13BWz") != 0) return False;
1324 break;
1325 case 2:
1326 if (strcmp(id,"B13BWzWWWzB9B") != 0) return False;
1327 break;
1328 case 91:
1329 if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) return False;
1330 break;
1331 default: return False;
1333 return True;
1336 static int fill_share_info(connection_struct *conn, int snum, int uLevel,
1337 char** buf, int* buflen,
1338 char** stringbuf, int* stringspace, char* baseaddr)
1340 int struct_len;
1341 char* p;
1342 char* p2;
1343 int l2;
1344 int len;
1346 switch( uLevel ) {
1347 case 0: struct_len = 13; break;
1348 case 1: struct_len = 20; break;
1349 case 2: struct_len = 40; break;
1350 case 91: struct_len = 68; break;
1351 default: return -1;
1355 if (!buf)
1357 len = 0;
1358 if (uLevel > 0) len += StrlenExpanded(conn,snum,lp_comment(snum));
1359 if (uLevel > 1) len += strlen(lp_pathname(snum)) + 1;
1360 if (buflen) *buflen = struct_len;
1361 if (stringspace) *stringspace = len;
1362 return struct_len + len;
1365 len = struct_len;
1366 p = *buf;
1367 if ((*buflen) < struct_len) return -1;
1368 if (stringbuf)
1370 p2 = *stringbuf;
1371 l2 = *stringspace;
1373 else
1375 p2 = p + struct_len;
1376 l2 = (*buflen) - struct_len;
1378 if (!baseaddr) baseaddr = p;
1380 push_ascii(p,lp_servicename(snum),13, STR_TERMINATE);
1382 if (uLevel > 0)
1384 int type;
1385 SCVAL(p,13,0);
1386 type = STYPE_DISKTREE;
1387 if (lp_print_ok(snum)) type = STYPE_PRINTQ;
1388 if (strequal("IPC",lp_fstype(snum))) type = STYPE_IPC;
1389 SSVAL(p,14,type); /* device type */
1390 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1391 len += CopyExpanded(conn,snum,&p2,lp_comment(snum),&l2);
1394 if (uLevel > 1)
1396 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1397 SSVALS(p,22,-1); /* max uses */
1398 SSVAL(p,24,1); /* current uses */
1399 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1400 len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1401 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1404 if (uLevel > 2)
1406 memset(p+40,0,SHPWLEN+2);
1407 SSVAL(p,50,0);
1408 SIVAL(p,52,0);
1409 SSVAL(p,56,0);
1410 SSVAL(p,58,0);
1411 SIVAL(p,60,0);
1412 SSVAL(p,64,0);
1413 SSVAL(p,66,0);
1416 if (stringbuf)
1418 (*buf) = p + struct_len;
1419 (*buflen) -= struct_len;
1420 (*stringbuf) = p2;
1421 (*stringspace) = l2;
1423 else
1425 (*buf) = p2;
1426 (*buflen) -= len;
1428 return len;
1431 static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
1432 int mdrcnt,int mprcnt,
1433 char **rdata,char **rparam,
1434 int *rdata_len,int *rparam_len)
1436 char *str1 = param+2;
1437 char *str2 = skip_string(str1,1);
1438 char *netname = skip_string(str2,1);
1439 char *p = skip_string(netname,1);
1440 int uLevel = SVAL(p,0);
1441 int snum = find_service(netname);
1443 if (snum < 0) return False;
1445 /* check it's a supported varient */
1446 if (!prefix_ok(str1,"zWrLh")) return False;
1447 if (!check_share_info(uLevel,str2)) return False;
1449 *rdata = REALLOC(*rdata,mdrcnt);
1450 p = *rdata;
1451 *rdata_len = fill_share_info(conn,snum,uLevel,&p,&mdrcnt,0,0,0);
1452 if (*rdata_len < 0) return False;
1454 *rparam_len = 6;
1455 *rparam = REALLOC(*rparam,*rparam_len);
1456 SSVAL(*rparam,0,NERR_Success);
1457 SSVAL(*rparam,2,0); /* converter word */
1458 SSVAL(*rparam,4,*rdata_len);
1460 return(True);
1463 /****************************************************************************
1464 view list of shares available
1465 ****************************************************************************/
1466 static BOOL api_RNetShareEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
1467 int mdrcnt,int mprcnt,
1468 char **rdata,char **rparam,
1469 int *rdata_len,int *rparam_len)
1471 char *str1 = param+2;
1472 char *str2 = skip_string(str1,1);
1473 char *p = skip_string(str2,1);
1474 int uLevel = SVAL(p,0);
1475 int buf_len = SVAL(p,2);
1476 char *p2;
1477 int count=lp_numservices();
1478 int total=0,counted=0;
1479 BOOL missed = False;
1480 int i;
1481 int data_len, fixed_len, string_len;
1482 int f_len = 0, s_len = 0;
1484 if (!prefix_ok(str1,"WrLeh")) return False;
1485 if (!check_share_info(uLevel,str2)) return False;
1487 data_len = fixed_len = string_len = 0;
1488 for (i=0;i<count;i++)
1489 if (lp_browseable(i) && lp_snum_ok(i))
1491 total++;
1492 data_len += fill_share_info(conn,i,uLevel,0,&f_len,0,&s_len,0);
1493 if (data_len <= buf_len)
1495 counted++;
1496 fixed_len += f_len;
1497 string_len += s_len;
1499 else
1500 missed = True;
1502 *rdata_len = fixed_len + string_len;
1503 *rdata = REALLOC(*rdata,*rdata_len);
1504 memset(*rdata,0,*rdata_len);
1506 p2 = (*rdata) + fixed_len; /* auxiliary data (strings) will go here */
1507 p = *rdata;
1508 f_len = fixed_len;
1509 s_len = string_len;
1510 for (i = 0; i < count;i++)
1511 if (lp_browseable(i) && lp_snum_ok(i))
1512 if (fill_share_info(conn,i,uLevel,&p,&f_len,&p2,&s_len,*rdata) < 0)
1513 break;
1515 *rparam_len = 8;
1516 *rparam = REALLOC(*rparam,*rparam_len);
1517 SSVAL(*rparam,0,missed ? ERRmoredata : NERR_Success);
1518 SSVAL(*rparam,2,0);
1519 SSVAL(*rparam,4,counted);
1520 SSVAL(*rparam,6,total);
1522 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1523 counted,total,uLevel,
1524 buf_len,*rdata_len,mdrcnt));
1525 return(True);
1528 /****************************************************************************
1529 Add a share
1530 ****************************************************************************/
1531 static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid, char *param,char *data,
1532 int mdrcnt,int mprcnt,
1533 char **rdata,char **rparam,
1534 int *rdata_len,int *rparam_len)
1536 char *str1 = param+2;
1537 char *str2 = skip_string(str1,1);
1538 char *p = skip_string(str2,1);
1539 int uLevel = SVAL(p,0);
1540 fstring sharename;
1541 fstring comment;
1542 pstring pathname;
1543 char *command, *cmdname;
1544 unsigned int offset;
1545 int snum;
1546 int res = ERRunsup;
1548 /* check it's a supported varient */
1549 if (!prefix_ok(str1,RAP_WShareAdd_REQ)) return False;
1550 if (!check_share_info(uLevel,str2)) return False;
1551 if (uLevel != 2) return False;
1553 pull_ascii_fstring(sharename,data);
1554 snum = find_service(sharename);
1555 if (snum >= 0) { /* already exists */
1556 res = ERRfilexists;
1557 goto error_exit;
1560 /* only support disk share adds */
1561 if (SVAL(data,14)!=STYPE_DISKTREE) return False;
1563 offset = IVAL(data, 16);
1564 if (offset >= mdrcnt) {
1565 res = ERRinvalidparam;
1566 goto error_exit;
1568 pull_ascii_fstring(comment, offset? (data+offset) : "");
1570 offset = IVAL(data, 26);
1571 if (offset >= mdrcnt) {
1572 res = ERRinvalidparam;
1573 goto error_exit;
1575 pull_ascii_pstring(pathname, offset? (data+offset) : "");
1577 string_replace(sharename, '"', ' ');
1578 string_replace(pathname, '"', ' ');
1579 string_replace(comment, '"', ' ');
1581 cmdname = lp_add_share_cmd();
1583 if (!cmdname || *cmdname == '\0') return False;
1585 asprintf(&command, "%s \"%s\" \"%s\" \"%s\" \"%s\"",
1586 lp_add_share_cmd(), dyn_CONFIGFILE, sharename, pathname, comment);
1588 if (command) {
1589 DEBUG(10,("api_RNetShareAdd: Running [%s]\n", command ));
1590 if ((res = smbrun(command, NULL)) != 0) {
1591 DEBUG(1,("api_RNetShareAdd: Running [%s] returned (%d)\n", command, res ));
1592 SAFE_FREE(command);
1593 res = ERRnoaccess;
1594 goto error_exit;
1595 } else {
1596 SAFE_FREE(command);
1597 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
1599 } else return False;
1601 *rparam_len = 6;
1602 *rparam = REALLOC(*rparam,*rparam_len);
1603 SSVAL(*rparam,0,NERR_Success);
1604 SSVAL(*rparam,2,0); /* converter word */
1605 SSVAL(*rparam,4,*rdata_len);
1606 *rdata_len = 0;
1608 return True;
1610 error_exit:
1611 *rparam_len = 4;
1612 *rparam = REALLOC(*rparam,*rparam_len);
1613 *rdata_len = 0;
1614 SSVAL(*rparam,0,res);
1615 SSVAL(*rparam,2,0);
1616 return True;
1620 /****************************************************************************
1621 view list of groups available
1622 ****************************************************************************/
1623 static BOOL api_RNetGroupEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
1624 int mdrcnt,int mprcnt,
1625 char **rdata,char **rparam,
1626 int *rdata_len,int *rparam_len)
1628 int i;
1629 int errflags=0;
1630 int resume_context, cli_buf_size;
1631 char *str1 = param+2;
1632 char *str2 = skip_string(str1,1);
1633 char *p = skip_string(str2,1);
1635 GROUP_MAP *group_list;
1636 int num_entries;
1638 if (strcmp(str1,"WrLeh") != 0)
1639 return False;
1641 /* parameters
1642 * W-> resume context (number of users to skip)
1643 * r -> return parameter pointer to receive buffer
1644 * L -> length of receive buffer
1645 * e -> return parameter number of entries
1646 * h -> return parameter total number of users
1648 if (strcmp("B21",str2) != 0)
1649 return False;
1651 /* get list of domain groups SID_DOMAIN_GRP=2 */
1652 if(!pdb_enum_group_mapping(SID_NAME_DOM_GRP , &group_list, &num_entries, False, False)) {
1653 DEBUG(3,("api_RNetGroupEnum:failed to get group list"));
1654 return False;
1657 resume_context = SVAL(p,0);
1658 cli_buf_size=SVAL(p+2,0);
1659 DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: %d\n", resume_context, cli_buf_size));
1661 *rdata_len = cli_buf_size;
1662 *rdata = REALLOC(*rdata,*rdata_len);
1664 p = *rdata;
1666 for(i=resume_context; i<num_entries; i++) {
1667 char* name=group_list[i].nt_name;
1668 if( ((PTR_DIFF(p,*rdata)+21) <= *rdata_len) ) {
1669 /* truncate the name at 21 chars. */
1670 memcpy(p, name, 21);
1671 DEBUG(10,("adding entry %d group %s\n", i, p));
1672 p += 21;
1673 } else {
1674 /* set overflow error */
1675 DEBUG(3,("overflow on entry %d group %s\n", i, name));
1676 errflags=234;
1677 break;
1681 *rdata_len = PTR_DIFF(p,*rdata);
1683 *rparam_len = 8;
1684 *rparam = REALLOC(*rparam,*rparam_len);
1686 SSVAL(*rparam, 0, errflags);
1687 SSVAL(*rparam, 2, 0); /* converter word */
1688 SSVAL(*rparam, 4, i-resume_context); /* is this right?? */
1689 SSVAL(*rparam, 6, num_entries); /* is this right?? */
1691 return(True);
1694 /*******************************************************************
1695 get groups that a user is a member of
1696 ******************************************************************/
1697 static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *param,char *data,
1698 int mdrcnt,int mprcnt,
1699 char **rdata,char **rparam,
1700 int *rdata_len,int *rparam_len)
1702 char *str1 = param+2;
1703 char *str2 = skip_string(str1,1);
1704 char *UserName = skip_string(str2,1);
1705 char *p = skip_string(UserName,1);
1706 int uLevel = SVAL(p,0);
1707 const char *level_string;
1708 int count=0;
1710 *rparam_len = 8;
1711 *rparam = REALLOC(*rparam,*rparam_len);
1713 /* check it's a supported varient */
1714 if (!strcmp(str1,"zWrLeh"))
1715 return False;
1716 switch( uLevel ) {
1717 case 0:
1718 level_string = "B21";
1719 break;
1720 default:
1721 return False;
1724 if (strcmp(level_string,str2) != 0)
1725 return False;
1727 *rdata_len = mdrcnt + 1024;
1728 *rdata = REALLOC(*rdata,*rdata_len);
1730 SSVAL(*rparam,0,NERR_Success);
1731 SSVAL(*rparam,2,0); /* converter word */
1733 p = *rdata;
1735 /* XXXX we need a real SAM database some day */
1736 pstrcpy(p,"Users"); p += 21; count++;
1737 pstrcpy(p,"Domain Users"); p += 21; count++;
1738 pstrcpy(p,"Guests"); p += 21; count++;
1739 pstrcpy(p,"Domain Guests"); p += 21; count++;
1741 *rdata_len = PTR_DIFF(p,*rdata);
1743 SSVAL(*rparam,4,count); /* is this right?? */
1744 SSVAL(*rparam,6,count); /* is this right?? */
1746 return(True);
1749 /*******************************************************************
1750 get all users
1751 ******************************************************************/
1752 static BOOL api_RNetUserEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
1753 int mdrcnt,int mprcnt,
1754 char **rdata,char **rparam,
1755 int *rdata_len,int *rparam_len)
1757 SAM_ACCOUNT *pwd=NULL;
1758 int count_sent=0;
1759 int count_total=0;
1760 int errflags=0;
1761 int resume_context, cli_buf_size;
1763 char *str1 = param+2;
1764 char *str2 = skip_string(str1,1);
1765 char *p = skip_string(str2,1);
1767 if (strcmp(str1,"WrLeh") != 0)
1768 return False;
1769 /* parameters
1770 * W-> resume context (number of users to skip)
1771 * r -> return parameter pointer to receive buffer
1772 * L -> length of receive buffer
1773 * e -> return parameter number of entries
1774 * h -> return parameter total number of users
1777 resume_context = SVAL(p,0);
1778 cli_buf_size=SVAL(p+2,0);
1779 DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n", resume_context, cli_buf_size));
1781 *rparam_len = 8;
1782 *rparam = REALLOC(*rparam,*rparam_len);
1784 /* check it's a supported varient */
1785 if (strcmp("B21",str2) != 0)
1786 return False;
1788 *rdata_len = cli_buf_size;
1789 *rdata = REALLOC(*rdata,*rdata_len);
1791 p = *rdata;
1793 /* to get user list enumerations for NetUserEnum in B21 format */
1794 pdb_init_sam(&pwd);
1796 /* Open the passgrp file - not for update. */
1797 become_root();
1798 if(!pdb_setsampwent(False)) {
1799 DEBUG(0, ("api_RNetUserEnum:unable to open sam database.\n"));
1800 unbecome_root();
1801 return False;
1803 errflags=NERR_Success;
1805 while ( pdb_getsampwent(pwd) ) {
1806 const char *name=pdb_get_username(pwd);
1807 if ((name) && (*(name+strlen(name)-1)!='$')) {
1808 count_total++;
1809 if(count_total>=resume_context) {
1810 if( ((PTR_DIFF(p,*rdata)+21)<=*rdata_len)&&(strlen(name)<=21) ) {
1811 pstrcpy(p,name);
1812 DEBUG(10,("api_RNetUserEnum:adding entry %d username %s\n",count_sent,p));
1813 p += 21;
1814 count_sent++;
1815 } else {
1816 /* set overflow error */
1817 DEBUG(10,("api_RNetUserEnum:overflow on entry %d username %s\n",count_sent,name));
1818 errflags=234;
1819 break;
1825 pdb_endsampwent();
1826 unbecome_root();
1828 pdb_free_sam(&pwd);
1830 *rdata_len = PTR_DIFF(p,*rdata);
1832 SSVAL(*rparam,0,errflags);
1833 SSVAL(*rparam,2,0); /* converter word */
1834 SSVAL(*rparam,4,count_sent); /* is this right?? */
1835 SSVAL(*rparam,6,count_total); /* is this right?? */
1837 return True;
1842 /****************************************************************************
1843 get the time of day info
1844 ****************************************************************************/
1845 static BOOL api_NetRemoteTOD(connection_struct *conn,uint16 vuid, char *param,char *data,
1846 int mdrcnt,int mprcnt,
1847 char **rdata,char **rparam,
1848 int *rdata_len,int *rparam_len)
1850 char *p;
1851 *rparam_len = 4;
1852 *rparam = REALLOC(*rparam,*rparam_len);
1854 *rdata_len = 21;
1855 *rdata = REALLOC(*rdata,*rdata_len);
1857 SSVAL(*rparam,0,NERR_Success);
1858 SSVAL(*rparam,2,0); /* converter word */
1860 p = *rdata;
1863 struct tm *t;
1864 time_t unixdate = time(NULL);
1866 put_dos_date3(p,0,unixdate); /* this is the time that is looked at
1867 by NT in a "net time" operation,
1868 it seems to ignore the one below */
1870 /* the client expects to get localtime, not GMT, in this bit
1871 (I think, this needs testing) */
1872 t = LocalTime(&unixdate);
1874 SIVAL(p,4,0); /* msecs ? */
1875 SCVAL(p,8,t->tm_hour);
1876 SCVAL(p,9,t->tm_min);
1877 SCVAL(p,10,t->tm_sec);
1878 SCVAL(p,11,0); /* hundredths of seconds */
1879 SSVALS(p,12,TimeDiff(unixdate)/60); /* timezone in minutes from GMT */
1880 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
1881 SCVAL(p,16,t->tm_mday);
1882 SCVAL(p,17,t->tm_mon + 1);
1883 SSVAL(p,18,1900+t->tm_year);
1884 SCVAL(p,20,t->tm_wday);
1888 return(True);
1891 /****************************************************************************
1892 Set the user password.
1893 *****************************************************************************/
1895 static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param,char *data,
1896 int mdrcnt,int mprcnt,
1897 char **rdata,char **rparam,
1898 int *rdata_len,int *rparam_len)
1900 char *p = skip_string(param+2,2);
1901 fstring user;
1902 fstring pass1,pass2;
1904 pull_ascii_fstring(user,p);
1906 p = skip_string(p,1);
1908 memset(pass1,'\0',sizeof(pass1));
1909 memset(pass2,'\0',sizeof(pass2));
1910 memcpy(pass1,p,16);
1911 memcpy(pass2,p+16,16);
1913 *rparam_len = 4;
1914 *rparam = REALLOC(*rparam,*rparam_len);
1916 *rdata_len = 0;
1918 SSVAL(*rparam,0,NERR_badpass);
1919 SSVAL(*rparam,2,0); /* converter word */
1921 DEBUG(3,("Set password for <%s>\n",user));
1924 * Attempt to verify the old password against smbpasswd entries
1925 * Win98 clients send old and new password in plaintext for this call.
1929 auth_serversupplied_info *server_info = NULL;
1930 DATA_BLOB password = data_blob(pass1, strlen(pass1)+1);
1931 if (NT_STATUS_IS_OK(check_plaintext_password(user,password,&server_info))) {
1933 if (NT_STATUS_IS_OK(change_oem_password(server_info->sam_account, pass1, pass2)))
1935 SSVAL(*rparam,0,NERR_Success);
1938 free_server_info(&server_info);
1940 data_blob_clear_free(&password);
1944 * If the plaintext change failed, attempt
1945 * the old encrypted method. NT will generate this
1946 * after trying the samr method. Note that this
1947 * method is done as a last resort as this
1948 * password change method loses the NT password hash
1949 * and cannot change the UNIX password as no plaintext
1950 * is received.
1953 if(SVAL(*rparam,0) != NERR_Success)
1955 SAM_ACCOUNT *hnd = NULL;
1957 if (check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &hnd) &&
1958 change_lanman_password(hnd,pass2))
1960 SSVAL(*rparam,0,NERR_Success);
1962 pdb_free_sam(&hnd);
1966 memset((char *)pass1,'\0',sizeof(fstring));
1967 memset((char *)pass2,'\0',sizeof(fstring));
1969 return(True);
1972 /****************************************************************************
1973 Set the user password (SamOEM version - gets plaintext).
1974 ****************************************************************************/
1976 static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char *param,char *data,
1977 int mdrcnt,int mprcnt,
1978 char **rdata,char **rparam,
1979 int *rdata_len,int *rparam_len)
1981 fstring user;
1982 char *p = param + 2;
1983 *rparam_len = 2;
1984 *rparam = REALLOC(*rparam,*rparam_len);
1986 *rdata_len = 0;
1988 SSVAL(*rparam,0,NERR_badpass);
1991 * Check the parameter definition is correct.
1993 if(!strequal(param + 2, "zsT")) {
1994 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", param + 2));
1995 return False;
1997 p = skip_string(p, 1);
1999 if(!strequal(p, "B516B16")) {
2000 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p));
2001 return False;
2003 p = skip_string(p,1);
2005 p += pull_ascii_fstring(user,p);
2007 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user));
2010 * Pass the user through the NT -> unix user mapping
2011 * function.
2014 (void)map_username(user);
2016 if (NT_STATUS_IS_OK(pass_oem_change(user, (uchar*) data, (uchar *)&data[516], NULL, NULL)))
2018 SSVAL(*rparam,0,NERR_Success);
2021 return(True);
2024 /****************************************************************************
2025 delete a print job
2026 Form: <W> <>
2027 ****************************************************************************/
2028 static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char *param,char *data,
2029 int mdrcnt,int mprcnt,
2030 char **rdata,char **rparam,
2031 int *rdata_len,int *rparam_len)
2033 int function = SVAL(param,0);
2034 char *str1 = param+2;
2035 char *str2 = skip_string(str1,1);
2036 char *p = skip_string(str2,1);
2037 uint32 jobid;
2038 int snum;
2039 int errcode;
2040 extern struct current_user current_user;
2041 WERROR werr = WERR_OK;
2043 if(!rap_to_pjobid(SVAL(p,0),&snum,&jobid))
2044 return False;
2046 /* check it's a supported varient */
2047 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
2048 return(False);
2050 *rparam_len = 4;
2051 *rparam = REALLOC(*rparam,*rparam_len);
2052 *rdata_len = 0;
2054 if (!print_job_exists(snum, jobid)) {
2055 errcode = NERR_JobNotFound;
2056 goto out;
2059 errcode = NERR_notsupported;
2061 switch (function) {
2062 case 81: /* delete */
2063 if (print_job_delete(&current_user, snum, jobid, &werr))
2064 errcode = NERR_Success;
2065 break;
2066 case 82: /* pause */
2067 if (print_job_pause(&current_user, snum, jobid, &werr))
2068 errcode = NERR_Success;
2069 break;
2070 case 83: /* resume */
2071 if (print_job_resume(&current_user, snum, jobid, &werr))
2072 errcode = NERR_Success;
2073 break;
2076 if (!W_ERROR_IS_OK(werr))
2077 errcode = W_ERROR_V(werr);
2079 out:
2080 SSVAL(*rparam,0,errcode);
2081 SSVAL(*rparam,2,0); /* converter word */
2083 return(True);
2086 /****************************************************************************
2087 Purge a print queue - or pause or resume it.
2088 ****************************************************************************/
2089 static BOOL api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid, char *param,char *data,
2090 int mdrcnt,int mprcnt,
2091 char **rdata,char **rparam,
2092 int *rdata_len,int *rparam_len)
2094 int function = SVAL(param,0);
2095 char *str1 = param+2;
2096 char *str2 = skip_string(str1,1);
2097 char *QueueName = skip_string(str2,1);
2098 int errcode = NERR_notsupported;
2099 int snum;
2100 WERROR werr = WERR_OK;
2101 extern struct current_user current_user;
2103 /* check it's a supported varient */
2104 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
2105 return(False);
2107 *rparam_len = 4;
2108 *rparam = REALLOC(*rparam,*rparam_len);
2109 *rdata_len = 0;
2111 snum = print_queue_snum(QueueName);
2113 if (snum == -1) {
2114 errcode = NERR_JobNotFound;
2115 goto out;
2118 switch (function) {
2119 case 74: /* Pause queue */
2120 if (print_queue_pause(&current_user, snum, &werr)) errcode = NERR_Success;
2121 break;
2122 case 75: /* Resume queue */
2123 if (print_queue_resume(&current_user, snum, &werr)) errcode = NERR_Success;
2124 break;
2125 case 103: /* Purge */
2126 if (print_queue_purge(&current_user, snum, &werr)) errcode = NERR_Success;
2127 break;
2130 if (!W_ERROR_IS_OK(werr)) errcode = W_ERROR_V(werr);
2132 out:
2133 SSVAL(*rparam,0,errcode);
2134 SSVAL(*rparam,2,0); /* converter word */
2136 return(True);
2140 /****************************************************************************
2141 set the property of a print job (undocumented?)
2142 ? function = 0xb -> set name of print job
2143 ? function = 0x6 -> move print job up/down
2144 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
2145 or <WWsTP> <WB21BB16B10zWWzDDz>
2146 ****************************************************************************/
2147 static int check_printjob_info(struct pack_desc* desc,
2148 int uLevel, char* id)
2150 desc->subformat = NULL;
2151 switch( uLevel ) {
2152 case 0: desc->format = "W"; break;
2153 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
2154 case 2: desc->format = "WWzWWDDzz"; break;
2155 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
2156 case 4: desc->format = "WWzWWDDzzzzzDDDDDDD"; break;
2157 default: return False;
2159 if (strcmp(desc->format,id) != 0) return False;
2160 return True;
2163 static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,char *data,
2164 int mdrcnt,int mprcnt,
2165 char **rdata,char **rparam,
2166 int *rdata_len,int *rparam_len)
2168 struct pack_desc desc;
2169 char *str1 = param+2;
2170 char *str2 = skip_string(str1,1);
2171 char *p = skip_string(str2,1);
2172 uint32 jobid;
2173 int snum;
2174 int uLevel = SVAL(p,2);
2175 int function = SVAL(p,4);
2176 int place, errcode;
2178 if(!rap_to_pjobid(SVAL(p,0),&snum,&jobid))
2179 return False;
2180 *rparam_len = 4;
2181 *rparam = REALLOC(*rparam,*rparam_len);
2183 *rdata_len = 0;
2185 /* check it's a supported varient */
2186 if ((strcmp(str1,"WWsTP")) ||
2187 (!check_printjob_info(&desc,uLevel,str2)))
2188 return(False);
2190 if (!print_job_exists(snum, jobid)) {
2191 errcode=NERR_JobNotFound;
2192 goto out;
2195 errcode = NERR_notsupported;
2197 switch (function) {
2198 case 0x6:
2199 /* change job place in the queue,
2200 data gives the new place */
2201 place = SVAL(data,0);
2202 if (print_job_set_place(snum, jobid, place)) {
2203 errcode=NERR_Success;
2205 break;
2207 case 0xb:
2208 /* change print job name, data gives the name */
2209 if (print_job_set_name(snum, jobid, data)) {
2210 errcode=NERR_Success;
2212 break;
2214 default:
2215 return False;
2218 out:
2219 SSVALS(*rparam,0,errcode);
2220 SSVAL(*rparam,2,0); /* converter word */
2222 return(True);
2226 /****************************************************************************
2227 get info about the server
2228 ****************************************************************************/
2229 static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2230 int mdrcnt,int mprcnt,
2231 char **rdata,char **rparam,
2232 int *rdata_len,int *rparam_len)
2234 char *str1 = param+2;
2235 char *str2 = skip_string(str1,1);
2236 char *p = skip_string(str2,1);
2237 int uLevel = SVAL(p,0);
2238 char *p2;
2239 int struct_len;
2241 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
2243 /* check it's a supported varient */
2244 if (!prefix_ok(str1,"WrLh")) return False;
2245 switch( uLevel ) {
2246 case 0:
2247 if (strcmp(str2,"B16") != 0) return False;
2248 struct_len = 16;
2249 break;
2250 case 1:
2251 if (strcmp(str2,"B16BBDz") != 0) return False;
2252 struct_len = 26;
2253 break;
2254 case 2:
2255 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")
2256 != 0) return False;
2257 struct_len = 134;
2258 break;
2259 case 3:
2260 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz")
2261 != 0) return False;
2262 struct_len = 144;
2263 break;
2264 case 20:
2265 if (strcmp(str2,"DN") != 0) return False;
2266 struct_len = 6;
2267 break;
2268 case 50:
2269 if (strcmp(str2,"B16BBDzWWzzz") != 0) return False;
2270 struct_len = 42;
2271 break;
2272 default: return False;
2275 *rdata_len = mdrcnt;
2276 *rdata = REALLOC(*rdata,*rdata_len);
2278 p = *rdata;
2279 p2 = p + struct_len;
2280 if (uLevel != 20) {
2281 srvstr_push(NULL, p,local_machine,16,
2282 STR_ASCII|STR_UPPER|STR_TERMINATE);
2284 p += 16;
2285 if (uLevel > 0)
2287 struct srv_info_struct *servers=NULL;
2288 int i,count;
2289 pstring comment;
2290 uint32 servertype= lp_default_server_announce();
2292 pstrcpy(comment,string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH));
2294 if ((count=get_server_info(SV_TYPE_ALL,&servers,lp_workgroup()))>0) {
2295 for (i=0;i<count;i++)
2296 if (strequal(servers[i].name,local_machine))
2298 servertype = servers[i].type;
2299 pstrcpy(comment,servers[i].comment);
2302 SAFE_FREE(servers);
2304 SCVAL(p,0,lp_major_announce_version());
2305 SCVAL(p,1,lp_minor_announce_version());
2306 SIVAL(p,2,servertype);
2308 if (mdrcnt == struct_len) {
2309 SIVAL(p,6,0);
2310 } else {
2311 SIVAL(p,6,PTR_DIFF(p2,*rdata));
2312 standard_sub_conn(conn,comment,sizeof(comment));
2313 StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
2314 p2 = skip_string(p2,1);
2317 if (uLevel > 1)
2319 return False; /* not yet implemented */
2322 *rdata_len = PTR_DIFF(p2,*rdata);
2324 *rparam_len = 6;
2325 *rparam = REALLOC(*rparam,*rparam_len);
2326 SSVAL(*rparam,0,NERR_Success);
2327 SSVAL(*rparam,2,0); /* converter word */
2328 SSVAL(*rparam,4,*rdata_len);
2330 return(True);
2334 /****************************************************************************
2335 get info about the server
2336 ****************************************************************************/
2337 static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2338 int mdrcnt,int mprcnt,
2339 char **rdata,char **rparam,
2340 int *rdata_len,int *rparam_len)
2342 char *str1 = param+2;
2343 char *str2 = skip_string(str1,1);
2344 char *p = skip_string(str2,1);
2345 char *p2;
2346 extern userdom_struct current_user_info;
2347 int level = SVAL(p,0);
2349 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
2351 *rparam_len = 6;
2352 *rparam = REALLOC(*rparam,*rparam_len);
2354 /* check it's a supported varient */
2355 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz")))
2356 return(False);
2358 *rdata_len = mdrcnt + 1024;
2359 *rdata = REALLOC(*rdata,*rdata_len);
2361 SSVAL(*rparam,0,NERR_Success);
2362 SSVAL(*rparam,2,0); /* converter word */
2364 p = *rdata;
2365 p2 = p + 22;
2368 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
2369 pstrcpy(p2,local_machine);
2370 strupper(p2);
2371 p2 = skip_string(p2,1);
2372 p += 4;
2374 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2375 pstrcpy(p2,current_user_info.smb_name);
2376 p2 = skip_string(p2,1);
2377 p += 4;
2379 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
2380 pstrcpy(p2,lp_workgroup());
2381 strupper(p2);
2382 p2 = skip_string(p2,1);
2383 p += 4;
2385 SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
2386 SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
2387 p += 2;
2389 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2390 pstrcpy(p2,lp_workgroup()); /* don't know. login domain?? */
2391 p2 = skip_string(p2,1);
2392 p += 4;
2394 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
2395 pstrcpy(p2,"");
2396 p2 = skip_string(p2,1);
2397 p += 4;
2399 *rdata_len = PTR_DIFF(p2,*rdata);
2401 SSVAL(*rparam,4,*rdata_len);
2403 return(True);
2406 /****************************************************************************
2407 get info about a user
2409 struct user_info_11 {
2410 char usri11_name[21]; 0-20
2411 char usri11_pad; 21
2412 char *usri11_comment; 22-25
2413 char *usri11_usr_comment; 26-29
2414 unsigned short usri11_priv; 30-31
2415 unsigned long usri11_auth_flags; 32-35
2416 long usri11_password_age; 36-39
2417 char *usri11_homedir; 40-43
2418 char *usri11_parms; 44-47
2419 long usri11_last_logon; 48-51
2420 long usri11_last_logoff; 52-55
2421 unsigned short usri11_bad_pw_count; 56-57
2422 unsigned short usri11_num_logons; 58-59
2423 char *usri11_logon_server; 60-63
2424 unsigned short usri11_country_code; 64-65
2425 char *usri11_workstations; 66-69
2426 unsigned long usri11_max_storage; 70-73
2427 unsigned short usri11_units_per_week; 74-75
2428 unsigned char *usri11_logon_hours; 76-79
2429 unsigned short usri11_code_page; 80-81
2432 where:
2434 usri11_name specifies the user name for which information is retireved
2436 usri11_pad aligns the next data structure element to a word boundary
2438 usri11_comment is a null terminated ASCII comment
2440 usri11_user_comment is a null terminated ASCII comment about the user
2442 usri11_priv specifies the level of the privilege assigned to the user.
2443 The possible values are:
2445 Name Value Description
2446 USER_PRIV_GUEST 0 Guest privilege
2447 USER_PRIV_USER 1 User privilege
2448 USER_PRV_ADMIN 2 Administrator privilege
2450 usri11_auth_flags specifies the account operator privileges. The
2451 possible values are:
2453 Name Value Description
2454 AF_OP_PRINT 0 Print operator
2457 Leach, Naik [Page 28]
2461 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2464 AF_OP_COMM 1 Communications operator
2465 AF_OP_SERVER 2 Server operator
2466 AF_OP_ACCOUNTS 3 Accounts operator
2469 usri11_password_age specifies how many seconds have elapsed since the
2470 password was last changed.
2472 usri11_home_dir points to a null terminated ASCII string that contains
2473 the path name of the user's home directory.
2475 usri11_parms points to a null terminated ASCII string that is set
2476 aside for use by applications.
2478 usri11_last_logon specifies the time when the user last logged on.
2479 This value is stored as the number of seconds elapsed since
2480 00:00:00, January 1, 1970.
2482 usri11_last_logoff specifies the time when the user last logged off.
2483 This value is stored as the number of seconds elapsed since
2484 00:00:00, January 1, 1970. A value of 0 means the last logoff
2485 time is unknown.
2487 usri11_bad_pw_count specifies the number of incorrect passwords
2488 entered since the last successful logon.
2490 usri11_log1_num_logons specifies the number of times this user has
2491 logged on. A value of -1 means the number of logons is unknown.
2493 usri11_logon_server points to a null terminated ASCII string that
2494 contains the name of the server to which logon requests are sent.
2495 A null string indicates logon requests should be sent to the
2496 domain controller.
2498 usri11_country_code specifies the country code for the user's language
2499 of choice.
2501 usri11_workstations points to a null terminated ASCII string that
2502 contains the names of workstations the user may log on from.
2503 There may be up to 8 workstations, with the names separated by
2504 commas. A null strings indicates there are no restrictions.
2506 usri11_max_storage specifies the maximum amount of disk space the user
2507 can occupy. A value of 0xffffffff indicates there are no
2508 restrictions.
2510 usri11_units_per_week specifies the equal number of time units into
2511 which a week is divided. This value must be equal to 168.
2513 usri11_logon_hours points to a 21 byte (168 bits) string that
2514 specifies the time during which the user can log on. Each bit
2515 represents one unique hour in a week. The first bit (bit 0, word
2516 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
2520 Leach, Naik [Page 29]
2524 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2527 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
2528 are no restrictions.
2530 usri11_code_page specifies the code page for the user's language of
2531 choice
2533 All of the pointers in this data structure need to be treated
2534 specially. The pointer is a 32 bit pointer. The higher 16 bits need
2535 to be ignored. The converter word returned in the parameters section
2536 needs to be subtracted from the lower 16 bits to calculate an offset
2537 into the return buffer where this ASCII string resides.
2539 There is no auxiliary data in the response.
2541 ****************************************************************************/
2543 #define usri11_name 0
2544 #define usri11_pad 21
2545 #define usri11_comment 22
2546 #define usri11_usr_comment 26
2547 #define usri11_full_name 30
2548 #define usri11_priv 34
2549 #define usri11_auth_flags 36
2550 #define usri11_password_age 40
2551 #define usri11_homedir 44
2552 #define usri11_parms 48
2553 #define usri11_last_logon 52
2554 #define usri11_last_logoff 56
2555 #define usri11_bad_pw_count 60
2556 #define usri11_num_logons 62
2557 #define usri11_logon_server 64
2558 #define usri11_country_code 68
2559 #define usri11_workstations 70
2560 #define usri11_max_storage 74
2561 #define usri11_units_per_week 78
2562 #define usri11_logon_hours 80
2563 #define usri11_code_page 84
2564 #define usri11_end 86
2566 #define USER_PRIV_GUEST 0
2567 #define USER_PRIV_USER 1
2568 #define USER_PRIV_ADMIN 2
2570 #define AF_OP_PRINT 0
2571 #define AF_OP_COMM 1
2572 #define AF_OP_SERVER 2
2573 #define AF_OP_ACCOUNTS 3
2576 static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2577 int mdrcnt,int mprcnt,
2578 char **rdata,char **rparam,
2579 int *rdata_len,int *rparam_len)
2581 char *str1 = param+2;
2582 char *str2 = skip_string(str1,1);
2583 char *UserName = skip_string(str2,1);
2584 char *p = skip_string(UserName,1);
2585 int uLevel = SVAL(p,0);
2586 char *p2;
2587 const char *level_string;
2589 /* get NIS home of a previously validated user - simeon */
2590 /* With share level security vuid will always be zero.
2591 Don't depend on vuser being non-null !!. JRA */
2592 user_struct *vuser = get_valid_user_struct(vuid);
2593 if(vuser != NULL)
2594 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid,
2595 vuser->user.unix_name));
2597 *rparam_len = 6;
2598 *rparam = REALLOC(*rparam,*rparam_len);
2600 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
2602 /* check it's a supported variant */
2603 if (strcmp(str1,"zWrLh") != 0) return False;
2604 switch( uLevel )
2606 case 0: level_string = "B21"; break;
2607 case 1: level_string = "B21BB16DWzzWz"; break;
2608 case 2: level_string = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
2609 case 10: level_string = "B21Bzzz"; break;
2610 case 11: level_string = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
2611 default: return False;
2614 if (strcmp(level_string,str2) != 0) return False;
2616 *rdata_len = mdrcnt + 1024;
2617 *rdata = REALLOC(*rdata,*rdata_len);
2619 SSVAL(*rparam,0,NERR_Success);
2620 SSVAL(*rparam,2,0); /* converter word */
2622 p = *rdata;
2623 p2 = p + usri11_end;
2625 memset(p,0,21);
2626 fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
2628 if (uLevel > 0)
2630 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
2631 *p2 = 0;
2633 if (uLevel >= 10)
2635 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
2636 pstrcpy(p2,"Comment");
2637 p2 = skip_string(p2,1);
2639 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
2640 pstrcpy(p2,"UserComment");
2641 p2 = skip_string(p2,1);
2643 /* EEK! the cifsrap.txt doesn't have this in!!!! */
2644 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
2645 pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName));
2646 p2 = skip_string(p2,1);
2649 if (uLevel == 11) /* modelled after NTAS 3.51 reply */
2651 SSVAL(p,usri11_priv,conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2652 SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
2653 SIVALS(p,usri11_password_age,-1); /* password age */
2654 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
2655 pstrcpy(p2, vuser && vuser->homedir ? vuser->homedir : "");
2656 p2 = skip_string(p2,1);
2657 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
2658 pstrcpy(p2,"");
2659 p2 = skip_string(p2,1);
2660 SIVAL(p,usri11_last_logon,0); /* last logon */
2661 SIVAL(p,usri11_last_logoff,0); /* last logoff */
2662 SSVALS(p,usri11_bad_pw_count,-1); /* bad pw counts */
2663 SSVALS(p,usri11_num_logons,-1); /* num logons */
2664 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
2665 pstrcpy(p2,"\\\\*");
2666 p2 = skip_string(p2,1);
2667 SSVAL(p,usri11_country_code,0); /* country code */
2669 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
2670 pstrcpy(p2,"");
2671 p2 = skip_string(p2,1);
2673 SIVALS(p,usri11_max_storage,-1); /* max storage */
2674 SSVAL(p,usri11_units_per_week,168); /* units per week */
2675 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
2677 /* a simple way to get logon hours at all times. */
2678 memset(p2,0xff,21);
2679 SCVAL(p2,21,0); /* fix zero termination */
2680 p2 = skip_string(p2,1);
2682 SSVAL(p,usri11_code_page,0); /* code page */
2684 if (uLevel == 1 || uLevel == 2)
2686 memset(p+22,' ',16); /* password */
2687 SIVALS(p,38,-1); /* password age */
2688 SSVAL(p,42,
2689 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2690 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
2691 pstrcpy(p2, vuser && vuser->homedir ? vuser->homedir : "");
2692 p2 = skip_string(p2,1);
2693 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
2694 *p2++ = 0;
2695 SSVAL(p,52,0); /* flags */
2696 SIVAL(p,54,PTR_DIFF(p2,*rdata)); /* script_path */
2697 pstrcpy(p2,vuser && vuser->logon_script ? vuser->logon_script : "");
2698 p2 = skip_string(p2,1);
2699 if (uLevel == 2)
2701 SIVAL(p,60,0); /* auth_flags */
2702 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
2703 pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName));
2704 p2 = skip_string(p2,1);
2705 SIVAL(p,68,0); /* urs_comment */
2706 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
2707 pstrcpy(p2,"");
2708 p2 = skip_string(p2,1);
2709 SIVAL(p,76,0); /* workstations */
2710 SIVAL(p,80,0); /* last_logon */
2711 SIVAL(p,84,0); /* last_logoff */
2712 SIVALS(p,88,-1); /* acct_expires */
2713 SIVALS(p,92,-1); /* max_storage */
2714 SSVAL(p,96,168); /* units_per_week */
2715 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
2716 memset(p2,-1,21);
2717 p2 += 21;
2718 SSVALS(p,102,-1); /* bad_pw_count */
2719 SSVALS(p,104,-1); /* num_logons */
2720 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
2721 pstrcpy(p2,"\\\\%L");
2722 standard_sub_conn(conn, p2,0);
2723 p2 = skip_string(p2,1);
2724 SSVAL(p,110,49); /* country_code */
2725 SSVAL(p,112,860); /* code page */
2729 *rdata_len = PTR_DIFF(p2,*rdata);
2731 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
2733 return(True);
2736 static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param,char *data,
2737 int mdrcnt,int mprcnt,
2738 char **rdata,char **rparam,
2739 int *rdata_len,int *rparam_len)
2741 char *str1 = param+2;
2742 char *str2 = skip_string(str1,1);
2743 char *p = skip_string(str2,1);
2744 int uLevel;
2745 struct pack_desc desc;
2746 char* name;
2747 /* With share level security vuid will always be zero.
2748 Don't depend on vuser being non-null !!. JRA */
2749 user_struct *vuser = get_valid_user_struct(vuid);
2750 if(vuser != NULL)
2751 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid,
2752 vuser->user.unix_name));
2754 uLevel = SVAL(p,0);
2755 name = p + 2;
2757 memset((char *)&desc,'\0',sizeof(desc));
2759 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
2761 /* check it's a supported varient */
2762 if (strcmp(str1,"OOWb54WrLh") != 0) return False;
2763 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) return False;
2764 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2765 desc.base = *rdata;
2766 desc.buflen = mdrcnt;
2767 desc.subformat = NULL;
2768 desc.format = str2;
2770 if (init_package(&desc,1,0))
2772 PACKI(&desc,"W",0); /* code */
2773 PACKS(&desc,"B21",name); /* eff. name */
2774 PACKS(&desc,"B",""); /* pad */
2775 PACKI(&desc,"W",
2776 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2777 PACKI(&desc,"D",0); /* auth flags XXX */
2778 PACKI(&desc,"W",0); /* num logons */
2779 PACKI(&desc,"W",0); /* bad pw count */
2780 PACKI(&desc,"D",0); /* last logon */
2781 PACKI(&desc,"D",-1); /* last logoff */
2782 PACKI(&desc,"D",-1); /* logoff time */
2783 PACKI(&desc,"D",-1); /* kickoff time */
2784 PACKI(&desc,"D",0); /* password age */
2785 PACKI(&desc,"D",0); /* password can change */
2786 PACKI(&desc,"D",-1); /* password must change */
2788 fstring mypath;
2789 fstrcpy(mypath,"\\\\");
2790 fstrcat(mypath,local_machine);
2791 strupper(mypath);
2792 PACKS(&desc,"z",mypath); /* computer */
2794 PACKS(&desc,"z",lp_workgroup());/* domain */
2796 PACKS(&desc,"z", vuser && vuser->logon_script ? vuser->logon_script :""); /* script path */
2798 PACKI(&desc,"D",0x00000000); /* reserved */
2801 *rdata_len = desc.usedlen;
2802 *rparam_len = 6;
2803 *rparam = REALLOC(*rparam,*rparam_len);
2804 SSVALS(*rparam,0,desc.errcode);
2805 SSVAL(*rparam,2,0);
2806 SSVAL(*rparam,4,desc.neededlen);
2808 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
2809 return(True);
2813 /****************************************************************************
2814 api_WAccessGetUserPerms
2815 ****************************************************************************/
2816 static BOOL api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid, char *param,char *data,
2817 int mdrcnt,int mprcnt,
2818 char **rdata,char **rparam,
2819 int *rdata_len,int *rparam_len)
2821 char *str1 = param+2;
2822 char *str2 = skip_string(str1,1);
2823 char *user = skip_string(str2,1);
2824 char *resource = skip_string(user,1);
2826 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
2828 /* check it's a supported varient */
2829 if (strcmp(str1,"zzh") != 0) return False;
2830 if (strcmp(str2,"") != 0) return False;
2832 *rparam_len = 6;
2833 *rparam = REALLOC(*rparam,*rparam_len);
2834 SSVALS(*rparam,0,0); /* errorcode */
2835 SSVAL(*rparam,2,0); /* converter word */
2836 SSVAL(*rparam,4,0x7f); /* permission flags */
2838 return(True);
2841 /****************************************************************************
2842 api_WPrintJobEnumerate
2843 ****************************************************************************/
2844 static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2845 int mdrcnt,int mprcnt,
2846 char **rdata,char **rparam,
2847 int *rdata_len,int *rparam_len)
2849 char *str1 = param+2;
2850 char *str2 = skip_string(str1,1);
2851 char *p = skip_string(str2,1);
2852 int uLevel;
2853 int count;
2854 int i;
2855 int snum;
2856 uint32 jobid;
2857 struct pack_desc desc;
2858 print_queue_struct *queue=NULL;
2859 print_status_struct status;
2860 char *tmpdata=NULL;
2862 uLevel = SVAL(p,2);
2864 memset((char *)&desc,'\0',sizeof(desc));
2865 memset((char *)&status,'\0',sizeof(status));
2867 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
2869 /* check it's a supported varient */
2870 if (strcmp(str1,"WWrLh") != 0) return False;
2871 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2873 if(!rap_to_pjobid(SVAL(p,0),&snum,&jobid))
2874 return False;
2876 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2878 count = print_queue_status(snum,&queue,&status);
2879 for (i = 0; i < count; i++) {
2880 if (queue[i].job == jobid) break;
2883 if (mdrcnt > 0) {
2884 *rdata = REALLOC(*rdata,mdrcnt);
2885 desc.base = *rdata;
2886 desc.buflen = mdrcnt;
2887 } else {
2889 * Don't return data but need to get correct length
2890 * init_package will return wrong size if buflen=0
2892 desc.buflen = getlen(desc.format);
2893 desc.base = tmpdata = (char *)malloc ( desc.buflen );
2896 if (init_package(&desc,1,0)) {
2897 if (i < count) {
2898 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
2899 *rdata_len = desc.usedlen;
2901 else {
2902 desc.errcode = NERR_JobNotFound;
2903 *rdata_len = 0;
2907 *rparam_len = 6;
2908 *rparam = REALLOC(*rparam,*rparam_len);
2909 SSVALS(*rparam,0,desc.errcode);
2910 SSVAL(*rparam,2,0);
2911 SSVAL(*rparam,4,desc.neededlen);
2913 SAFE_FREE(queue);
2914 SAFE_FREE(tmpdata);
2916 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
2917 return(True);
2920 static BOOL api_WPrintJobEnumerate(connection_struct *conn,uint16 vuid, char *param,char *data,
2921 int mdrcnt,int mprcnt,
2922 char **rdata,char **rparam,
2923 int *rdata_len,int *rparam_len)
2925 char *str1 = param+2;
2926 char *str2 = skip_string(str1,1);
2927 char *p = skip_string(str2,1);
2928 char* name = p;
2929 int uLevel;
2930 int count;
2931 int i, succnt=0;
2932 int snum;
2933 struct pack_desc desc;
2934 print_queue_struct *queue=NULL;
2935 print_status_struct status;
2937 memset((char *)&desc,'\0',sizeof(desc));
2938 memset((char *)&status,'\0',sizeof(status));
2940 p = skip_string(p,1);
2941 uLevel = SVAL(p,0);
2943 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
2945 /* check it's a supported variant */
2946 if (strcmp(str1,"zWrLeh") != 0) return False;
2947 if (uLevel > 2) return False; /* defined only for uLevel 0,1,2 */
2948 if (!check_printjob_info(&desc,uLevel,str2)) return False;
2950 snum = lp_servicenumber(name);
2951 if (snum < 0 && pcap_printername_ok(name,NULL)) {
2952 int pnum = lp_servicenumber(PRINTERS_NAME);
2953 if (pnum >= 0) {
2954 lp_add_printer(name,pnum);
2955 snum = lp_servicenumber(name);
2959 if (snum < 0 || !VALID_SNUM(snum)) return(False);
2961 count = print_queue_status(snum,&queue,&status);
2962 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
2963 desc.base = *rdata;
2964 desc.buflen = mdrcnt;
2966 if (init_package(&desc,count,0)) {
2967 succnt = 0;
2968 for (i = 0; i < count; i++) {
2969 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
2970 if (desc.errcode == NERR_Success) succnt = i+1;
2974 *rdata_len = desc.usedlen;
2976 *rparam_len = 8;
2977 *rparam = REALLOC(*rparam,*rparam_len);
2978 SSVALS(*rparam,0,desc.errcode);
2979 SSVAL(*rparam,2,0);
2980 SSVAL(*rparam,4,succnt);
2981 SSVAL(*rparam,6,count);
2983 SAFE_FREE(queue);
2985 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
2986 return(True);
2989 static int check_printdest_info(struct pack_desc* desc,
2990 int uLevel, char* id)
2992 desc->subformat = NULL;
2993 switch( uLevel ) {
2994 case 0: desc->format = "B9"; break;
2995 case 1: desc->format = "B9B21WWzW"; break;
2996 case 2: desc->format = "z"; break;
2997 case 3: desc->format = "zzzWWzzzWW"; break;
2998 default: return False;
3000 if (strcmp(desc->format,id) != 0) return False;
3001 return True;
3004 static void fill_printdest_info(connection_struct *conn, int snum, int uLevel,
3005 struct pack_desc* desc)
3007 char buf[100];
3008 strncpy(buf,SERVICE(snum),sizeof(buf)-1);
3009 buf[sizeof(buf)-1] = 0;
3010 strupper(buf);
3011 if (uLevel <= 1) {
3012 PACKS(desc,"B9",buf); /* szName */
3013 if (uLevel == 1) {
3014 PACKS(desc,"B21",""); /* szUserName */
3015 PACKI(desc,"W",0); /* uJobId */
3016 PACKI(desc,"W",0); /* fsStatus */
3017 PACKS(desc,"z",""); /* pszStatus */
3018 PACKI(desc,"W",0); /* time */
3021 if (uLevel == 2 || uLevel == 3) {
3022 PACKS(desc,"z",buf); /* pszPrinterName */
3023 if (uLevel == 3) {
3024 PACKS(desc,"z",""); /* pszUserName */
3025 PACKS(desc,"z",""); /* pszLogAddr */
3026 PACKI(desc,"W",0); /* uJobId */
3027 PACKI(desc,"W",0); /* fsStatus */
3028 PACKS(desc,"z",""); /* pszStatus */
3029 PACKS(desc,"z",""); /* pszComment */
3030 PACKS(desc,"z","NULL"); /* pszDrivers */
3031 PACKI(desc,"W",0); /* time */
3032 PACKI(desc,"W",0); /* pad1 */
3037 static BOOL api_WPrintDestGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
3038 int mdrcnt,int mprcnt,
3039 char **rdata,char **rparam,
3040 int *rdata_len,int *rparam_len)
3042 char *str1 = param+2;
3043 char *str2 = skip_string(str1,1);
3044 char *p = skip_string(str2,1);
3045 char* PrinterName = p;
3046 int uLevel;
3047 struct pack_desc desc;
3048 int snum;
3049 char *tmpdata=NULL;
3051 memset((char *)&desc,'\0',sizeof(desc));
3053 p = skip_string(p,1);
3054 uLevel = SVAL(p,0);
3056 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
3058 /* check it's a supported varient */
3059 if (strcmp(str1,"zWrLh") != 0) return False;
3060 if (!check_printdest_info(&desc,uLevel,str2)) return False;
3062 snum = lp_servicenumber(PrinterName);
3063 if (snum < 0 && pcap_printername_ok(PrinterName,NULL)) {
3064 int pnum = lp_servicenumber(PRINTERS_NAME);
3065 if (pnum >= 0) {
3066 lp_add_printer(PrinterName,pnum);
3067 snum = lp_servicenumber(PrinterName);
3071 if (snum < 0) {
3072 *rdata_len = 0;
3073 desc.errcode = NERR_DestNotFound;
3074 desc.neededlen = 0;
3076 else {
3077 if (mdrcnt > 0) {
3078 *rdata = REALLOC(*rdata,mdrcnt);
3079 desc.base = *rdata;
3080 desc.buflen = mdrcnt;
3081 } else {
3083 * Don't return data but need to get correct length
3084 * init_package will return wrong size if buflen=0
3086 desc.buflen = getlen(desc.format);
3087 desc.base = tmpdata = (char *)malloc ( desc.buflen );
3089 if (init_package(&desc,1,0)) {
3090 fill_printdest_info(conn,snum,uLevel,&desc);
3092 *rdata_len = desc.usedlen;
3095 *rparam_len = 6;
3096 *rparam = REALLOC(*rparam,*rparam_len);
3097 SSVALS(*rparam,0,desc.errcode);
3098 SSVAL(*rparam,2,0);
3099 SSVAL(*rparam,4,desc.neededlen);
3101 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
3102 SAFE_FREE(tmpdata);
3103 return(True);
3106 static BOOL api_WPrintDestEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3107 int mdrcnt,int mprcnt,
3108 char **rdata,char **rparam,
3109 int *rdata_len,int *rparam_len)
3111 char *str1 = param+2;
3112 char *str2 = skip_string(str1,1);
3113 char *p = skip_string(str2,1);
3114 int uLevel;
3115 int queuecnt;
3116 int i, n, succnt=0;
3117 struct pack_desc desc;
3118 int services = lp_numservices();
3120 memset((char *)&desc,'\0',sizeof(desc));
3122 uLevel = SVAL(p,0);
3124 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
3126 /* check it's a supported varient */
3127 if (strcmp(str1,"WrLeh") != 0) return False;
3128 if (!check_printdest_info(&desc,uLevel,str2)) return False;
3130 queuecnt = 0;
3131 for (i = 0; i < services; i++)
3132 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
3133 queuecnt++;
3135 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3136 desc.base = *rdata;
3137 desc.buflen = mdrcnt;
3138 if (init_package(&desc,queuecnt,0)) {
3139 succnt = 0;
3140 n = 0;
3141 for (i = 0; i < services; i++) {
3142 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
3143 fill_printdest_info(conn,i,uLevel,&desc);
3144 n++;
3145 if (desc.errcode == NERR_Success) succnt = n;
3150 *rdata_len = desc.usedlen;
3152 *rparam_len = 8;
3153 *rparam = REALLOC(*rparam,*rparam_len);
3154 SSVALS(*rparam,0,desc.errcode);
3155 SSVAL(*rparam,2,0);
3156 SSVAL(*rparam,4,succnt);
3157 SSVAL(*rparam,6,queuecnt);
3159 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
3160 return(True);
3163 static BOOL api_WPrintDriverEnum(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 succnt;
3173 struct pack_desc desc;
3175 memset((char *)&desc,'\0',sizeof(desc));
3177 uLevel = SVAL(p,0);
3179 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
3181 /* check it's a supported varient */
3182 if (strcmp(str1,"WrLeh") != 0) return False;
3183 if (uLevel != 0 || strcmp(str2,"B41") != 0) return False;
3185 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3186 desc.base = *rdata;
3187 desc.buflen = mdrcnt;
3188 if (init_package(&desc,1,0)) {
3189 PACKS(&desc,"B41","NULL");
3192 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3194 *rdata_len = desc.usedlen;
3196 *rparam_len = 8;
3197 *rparam = REALLOC(*rparam,*rparam_len);
3198 SSVALS(*rparam,0,desc.errcode);
3199 SSVAL(*rparam,2,0);
3200 SSVAL(*rparam,4,succnt);
3201 SSVAL(*rparam,6,1);
3203 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
3204 return(True);
3207 static BOOL api_WPrintQProcEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3208 int mdrcnt,int mprcnt,
3209 char **rdata,char **rparam,
3210 int *rdata_len,int *rparam_len)
3212 char *str1 = param+2;
3213 char *str2 = skip_string(str1,1);
3214 char *p = skip_string(str2,1);
3215 int uLevel;
3216 int succnt;
3217 struct pack_desc desc;
3219 memset((char *)&desc,'\0',sizeof(desc));
3221 uLevel = SVAL(p,0);
3223 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
3225 /* check it's a supported varient */
3226 if (strcmp(str1,"WrLeh") != 0) return False;
3227 if (uLevel != 0 || strcmp(str2,"B13") != 0) return False;
3229 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3230 desc.base = *rdata;
3231 desc.buflen = mdrcnt;
3232 desc.format = str2;
3233 if (init_package(&desc,1,0)) {
3234 PACKS(&desc,"B13","lpd");
3237 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3239 *rdata_len = desc.usedlen;
3241 *rparam_len = 8;
3242 *rparam = REALLOC(*rparam,*rparam_len);
3243 SSVALS(*rparam,0,desc.errcode);
3244 SSVAL(*rparam,2,0);
3245 SSVAL(*rparam,4,succnt);
3246 SSVAL(*rparam,6,1);
3248 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
3249 return(True);
3252 static BOOL api_WPrintPortEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3253 int mdrcnt,int mprcnt,
3254 char **rdata,char **rparam,
3255 int *rdata_len,int *rparam_len)
3257 char *str1 = param+2;
3258 char *str2 = skip_string(str1,1);
3259 char *p = skip_string(str2,1);
3260 int uLevel;
3261 int succnt;
3262 struct pack_desc desc;
3264 memset((char *)&desc,'\0',sizeof(desc));
3266 uLevel = SVAL(p,0);
3268 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
3270 /* check it's a supported varient */
3271 if (strcmp(str1,"WrLeh") != 0) return False;
3272 if (uLevel != 0 || strcmp(str2,"B9") != 0) return False;
3274 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3275 memset((char *)&desc,'\0',sizeof(desc));
3276 desc.base = *rdata;
3277 desc.buflen = mdrcnt;
3278 desc.format = str2;
3279 if (init_package(&desc,1,0)) {
3280 PACKS(&desc,"B13","lp0");
3283 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3285 *rdata_len = desc.usedlen;
3287 *rparam_len = 8;
3288 *rparam = REALLOC(*rparam,*rparam_len);
3289 SSVALS(*rparam,0,desc.errcode);
3290 SSVAL(*rparam,2,0);
3291 SSVAL(*rparam,4,succnt);
3292 SSVAL(*rparam,6,1);
3294 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
3295 return(True);
3299 /****************************************************************************
3300 List open sessions
3301 ****************************************************************************/
3302 static BOOL api_RNetSessionEnum(connection_struct *conn,uint16 vuid, char *param, char *data,
3303 int mdrcnt,int mprcnt,
3304 char **rdata,char **rparam,
3305 int *rdata_len,int *rparam_len)
3308 char *str1 = param+2;
3309 char *str2 = skip_string(str1,1);
3310 char *p = skip_string(str2,1);
3311 int uLevel;
3312 struct pack_desc desc;
3313 struct sessionid *session_list;
3314 int i, num_sessions;
3316 memset((char *)&desc,'\0',sizeof(desc));
3318 uLevel = SVAL(p,0);
3320 DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel));
3321 DEBUG(7,("RNetSessionEnum req string=%s\n",str1));
3322 DEBUG(7,("RNetSessionEnum ret string=%s\n",str2));
3324 /* check it's a supported varient */
3325 if (strcmp(str1,RAP_NetSessionEnum_REQ) != 0) return False;
3326 if (uLevel != 2 || strcmp(str2,RAP_SESSION_INFO_L2) != 0) return False;
3328 num_sessions = list_sessions(&session_list);
3330 if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
3331 memset((char *)&desc,'\0',sizeof(desc));
3332 desc.base = *rdata;
3333 desc.buflen = mdrcnt;
3334 desc.format = str2;
3335 if (!init_package(&desc,num_sessions,0)) {
3336 return False;
3339 for(i=0; i<num_sessions; i++) {
3340 PACKS(&desc, "z", session_list[i].remote_machine);
3341 PACKS(&desc, "z", session_list[i].username);
3342 PACKI(&desc, "W", 1); /* num conns */
3343 PACKI(&desc, "W", 0); /* num opens */
3344 PACKI(&desc, "W", 1); /* num users */
3345 PACKI(&desc, "D", 0); /* session time */
3346 PACKI(&desc, "D", 0); /* idle time */
3347 PACKI(&desc, "D", 0); /* flags */
3348 PACKS(&desc, "z", "Unknown Client"); /* client type string */
3351 *rdata_len = desc.usedlen;
3353 *rparam_len = 8;
3354 *rparam = REALLOC(*rparam,*rparam_len);
3355 SSVALS(*rparam,0,desc.errcode);
3356 SSVAL(*rparam,2,0); /* converter */
3357 SSVAL(*rparam,4,num_sessions); /* count */
3359 DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc.errcode));
3360 return True;
3364 /****************************************************************************
3365 The buffer was too small
3366 ****************************************************************************/
3368 static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param,char *data,
3369 int mdrcnt,int mprcnt,
3370 char **rdata,char **rparam,
3371 int *rdata_len,int *rparam_len)
3373 *rparam_len = MIN(*rparam_len,mprcnt);
3374 *rparam = REALLOC(*rparam,*rparam_len);
3376 *rdata_len = 0;
3378 SSVAL(*rparam,0,NERR_BufTooSmall);
3380 DEBUG(3,("Supplied buffer too small in API command\n"));
3382 return(True);
3386 /****************************************************************************
3387 The request is not supported
3388 ****************************************************************************/
3390 static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param,char *data,
3391 int mdrcnt,int mprcnt,
3392 char **rdata,char **rparam,
3393 int *rdata_len,int *rparam_len)
3395 *rparam_len = 4;
3396 *rparam = REALLOC(*rparam,*rparam_len);
3398 *rdata_len = 0;
3400 SSVAL(*rparam,0,NERR_notsupported);
3401 SSVAL(*rparam,2,0); /* converter word */
3403 DEBUG(3,("Unsupported API command\n"));
3405 return(True);
3411 static const struct
3413 const char *name;
3414 int id;
3415 BOOL (*fn)(connection_struct *,uint16,char *,char *,
3416 int,int,char **,char **,int *,int *);
3417 BOOL auth_user; /* Deny anonymous access? */
3418 } api_commands[] = {
3419 {"RNetShareEnum", RAP_WshareEnum, api_RNetShareEnum, True},
3420 {"RNetShareGetInfo", RAP_WshareGetInfo, api_RNetShareGetInfo},
3421 {"RNetShareAdd", RAP_WshareAdd, api_RNetShareAdd},
3422 {"RNetSessionEnum", RAP_WsessionEnum, api_RNetSessionEnum, True},
3423 {"RNetServerGetInfo", RAP_WserverGetInfo, api_RNetServerGetInfo},
3424 {"RNetGroupEnum", RAP_WGroupEnum, api_RNetGroupEnum, True},
3425 {"RNetGroupGetUsers", RAP_WGroupGetUsers, api_RNetGroupGetUsers, True},
3426 {"RNetUserEnum", RAP_WUserEnum, api_RNetUserEnum, True},
3427 {"RNetUserGetInfo", RAP_WUserGetInfo, api_RNetUserGetInfo},
3428 {"NetUserGetGroups", RAP_WUserGetGroups, api_NetUserGetGroups},
3429 {"NetWkstaGetInfo", RAP_WWkstaGetInfo, api_NetWkstaGetInfo},
3430 {"DosPrintQEnum", RAP_WPrintQEnum, api_DosPrintQEnum, True},
3431 {"DosPrintQGetInfo", RAP_WPrintQGetInfo, api_DosPrintQGetInfo},
3432 {"WPrintQueuePause", RAP_WPrintQPause, api_WPrintQueueCtrl},
3433 {"WPrintQueueResume", RAP_WPrintQContinue, api_WPrintQueueCtrl},
3434 {"WPrintJobEnumerate",RAP_WPrintJobEnum, api_WPrintJobEnumerate},
3435 {"WPrintJobGetInfo", RAP_WPrintJobGetInfo, api_WPrintJobGetInfo},
3436 {"RDosPrintJobDel", RAP_WPrintJobDel, api_RDosPrintJobDel},
3437 {"RDosPrintJobPause", RAP_WPrintJobPause, api_RDosPrintJobDel},
3438 {"RDosPrintJobResume",RAP_WPrintJobContinue, api_RDosPrintJobDel},
3439 {"WPrintDestEnum", RAP_WPrintDestEnum, api_WPrintDestEnum},
3440 {"WPrintDestGetInfo", RAP_WPrintDestGetInfo, api_WPrintDestGetInfo},
3441 {"NetRemoteTOD", RAP_NetRemoteTOD, api_NetRemoteTOD},
3442 {"WPrintQueuePurge", RAP_WPrintQPurge, api_WPrintQueueCtrl},
3443 {"NetServerEnum", RAP_NetServerEnum2, api_RNetServerEnum}, /* anon OK */
3444 {"WAccessGetUserPerms",RAP_WAccessGetUserPerms,api_WAccessGetUserPerms},
3445 {"SetUserPassword", RAP_WUserPasswordSet2, api_SetUserPassword},
3446 {"WWkstaUserLogon", RAP_WWkstaUserLogon, api_WWkstaUserLogon},
3447 {"PrintJobInfo", RAP_WPrintJobSetInfo, api_PrintJobInfo},
3448 {"WPrintDriverEnum", RAP_WPrintDriverEnum, api_WPrintDriverEnum},
3449 {"WPrintQProcEnum", RAP_WPrintQProcessorEnum,api_WPrintQProcEnum},
3450 {"WPrintPortEnum", RAP_WPrintPortEnum, api_WPrintPortEnum},
3451 {"SamOEMChangePassword",RAP_SamOEMChgPasswordUser2_P,api_SamOEMChangePassword}, /* anon OK */
3452 {NULL, -1, api_Unsupported}};
3454 /* The following RAP calls are not implemented by Samba:
3456 RAP_WFileEnum2 - anon not OK
3459 /****************************************************************************
3460 Handle remote api calls
3461 ****************************************************************************/
3463 int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data,char *params,
3464 int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
3466 int api_command;
3467 char *rdata = NULL;
3468 char *rparam = NULL;
3469 int rdata_len = 0;
3470 int rparam_len = 0;
3471 BOOL reply=False;
3472 int i;
3474 if (!params) {
3475 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
3476 return 0;
3479 api_command = SVAL(params,0);
3481 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
3482 api_command,
3483 params+2,
3484 skip_string(params+2,1),
3485 tdscnt,tpscnt,mdrcnt,mprcnt));
3487 for (i=0;api_commands[i].name;i++) {
3488 if (api_commands[i].id == api_command && api_commands[i].fn) {
3489 DEBUG(3,("Doing %s\n",api_commands[i].name));
3490 break;
3494 /* Check whether this api call can be done anonymously */
3496 if (api_commands[i].auth_user && lp_restrict_anonymous()) {
3497 user_struct *user = get_valid_user_struct(vuid);
3499 if (!user || user->guest)
3500 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
3503 rdata = (char *)malloc(1024);
3504 if (rdata)
3505 memset(rdata,'\0',1024);
3507 rparam = (char *)malloc(1024);
3508 if (rparam)
3509 memset(rparam,'\0',1024);
3511 if(!rdata || !rparam) {
3512 DEBUG(0,("api_reply: malloc fail !\n"));
3513 return -1;
3516 reply = api_commands[i].fn(conn,vuid,params,data,mdrcnt,mprcnt,
3517 &rdata,&rparam,&rdata_len,&rparam_len);
3520 if (rdata_len > mdrcnt ||
3521 rparam_len > mprcnt) {
3522 reply = api_TooSmall(conn,vuid,params,data,mdrcnt,mprcnt,
3523 &rdata,&rparam,&rdata_len,&rparam_len);
3526 /* if we get False back then it's actually unsupported */
3527 if (!reply)
3528 api_Unsupported(conn,vuid,params,data,mdrcnt,mprcnt,
3529 &rdata,&rparam,&rdata_len,&rparam_len);
3531 send_trans_reply(outbuf, rparam, rparam_len, rdata, rdata_len, False);
3533 SAFE_FREE(rdata);
3534 SAFE_FREE(rparam);
3536 return -1;