r13316: Let the carnage begin....
[Samba/gbeck.git] / source / smbd / lanman.c
blob83dfdf0d8bca3ced02e3182b4ee06af3fb017534
1 /*
2 Unix SMB/CIFS implementation.
3 Inter-process communication and named pipe handling
4 Copyright (C) Andrew Tridgell 1992-1998
6 SMB Version handling
7 Copyright (C) John H Terpstra 1995-1998
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 This file handles the named pipe and mailslot calls
25 in the SMBtrans protocol
28 #include "includes.h"
30 extern struct current_user current_user;
31 extern userdom_struct current_user_info;
33 #ifdef CHECK_TYPES
34 #undef CHECK_TYPES
35 #endif
36 #define CHECK_TYPES 0
38 #define NERR_Success 0
39 #define NERR_badpass 86
40 #define NERR_notsupported 50
42 #define NERR_BASE (2100)
43 #define NERR_BufTooSmall (NERR_BASE+23)
44 #define NERR_JobNotFound (NERR_BASE+51)
45 #define NERR_DestNotFound (NERR_BASE+52)
47 #define ACCESS_READ 0x01
48 #define ACCESS_WRITE 0x02
49 #define ACCESS_CREATE 0x04
51 #define SHPWLEN 8 /* share password length */
53 static BOOL api_Unsupported(connection_struct *conn,uint16 vuid, char *param, char *data,
54 int mdrcnt, int mprcnt,
55 char **rdata, char **rparam,
56 int *rdata_len, int *rparam_len);
57 static BOOL api_TooSmall(connection_struct *conn, uint16 vuid, char *param, char *data,
58 int mdrcnt, int mprcnt,
59 char **rdata, char **rparam,
60 int *rdata_len, int *rparam_len);
63 static int CopyExpanded(connection_struct *conn,
64 int snum, char **dst, char *src, int *n)
66 pstring buf;
67 int l;
69 if (!src || !dst || !n || !(*dst)) {
70 return 0;
73 StrnCpy(buf,src,sizeof(buf)/2);
74 pstring_sub(buf,"%S",lp_servicename(snum));
75 standard_sub_conn(conn,buf,sizeof(buf));
76 l = push_ascii(*dst,buf,*n, STR_TERMINATE);
77 (*dst) += l;
78 (*n) -= l;
79 return l;
82 static int CopyAndAdvance(char **dst, char *src, int *n)
84 int l;
85 if (!src || !dst || !n || !(*dst)) {
86 return 0;
88 l = push_ascii(*dst,src,*n, STR_TERMINATE);
89 (*dst) += l;
90 (*n) -= l;
91 return l;
94 static int StrlenExpanded(connection_struct *conn, int snum, char *s)
96 pstring buf;
97 if (!s) {
98 return 0;
100 StrnCpy(buf,s,sizeof(buf)/2);
101 pstring_sub(buf,"%S",lp_servicename(snum));
102 standard_sub_conn(conn,buf,sizeof(buf));
103 return strlen(buf) + 1;
106 static char *Expand(connection_struct *conn, int snum, char *s)
108 static pstring buf;
109 if (!s) {
110 return NULL;
112 StrnCpy(buf,s,sizeof(buf)/2);
113 pstring_sub(buf,"%S",lp_servicename(snum));
114 standard_sub_conn(conn,buf,sizeof(buf));
115 return &buf[0];
118 /*******************************************************************
119 Check a API string for validity when we only need to check the prefix.
120 ******************************************************************/
122 static BOOL prefix_ok(const char *str, const char *prefix)
124 return(strncmp(str,prefix,strlen(prefix)) == 0);
127 struct pack_desc {
128 const char *format; /* formatstring for structure */
129 const char *subformat; /* subformat for structure */
130 char *base; /* baseaddress of buffer */
131 int buflen; /* remaining size for fixed part; on init: length of base */
132 int subcount; /* count of substructures */
133 char *structbuf; /* pointer into buffer for remaining fixed part */
134 int stringlen; /* remaining size for variable part */
135 char *stringbuf; /* pointer into buffer for remaining variable part */
136 int neededlen; /* total needed size */
137 int usedlen; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
138 const char *curpos; /* current position; pointer into format or subformat */
139 int errcode;
142 static int get_counter(const char **p)
144 int i, n;
145 if (!p || !(*p)) {
146 return 1;
148 if (!isdigit((int)**p)) {
149 return 1;
151 for (n = 0;;) {
152 i = **p;
153 if (isdigit(i)) {
154 n = 10 * n + (i - '0');
155 } else {
156 return n;
158 (*p)++;
162 static int getlen(const char *p)
164 int n = 0;
165 if (!p) {
166 return 0;
169 while (*p) {
170 switch( *p++ ) {
171 case 'W': /* word (2 byte) */
172 n += 2;
173 break;
174 case 'K': /* status word? (2 byte) */
175 n += 2;
176 break;
177 case 'N': /* count of substructures (word) at end */
178 n += 2;
179 break;
180 case 'D': /* double word (4 byte) */
181 case 'z': /* offset to zero terminated string (4 byte) */
182 case 'l': /* offset to user data (4 byte) */
183 n += 4;
184 break;
185 case 'b': /* offset to data (with counter) (4 byte) */
186 n += 4;
187 get_counter(&p);
188 break;
189 case 'B': /* byte (with optional counter) */
190 n += get_counter(&p);
191 break;
194 return n;
197 static BOOL init_package(struct pack_desc *p, int count, int subcount)
199 int n = p->buflen;
200 int i;
202 if (!p->format || !p->base) {
203 return False;
206 i = count * getlen(p->format);
207 if (p->subformat) {
208 i += subcount * getlen(p->subformat);
210 p->structbuf = p->base;
211 p->neededlen = 0;
212 p->usedlen = 0;
213 p->subcount = 0;
214 p->curpos = p->format;
215 if (i > n) {
216 p->neededlen = i;
217 i = n = 0;
218 #if 0
220 * This is the old error code we used. Aparently
221 * WinNT/2k systems return ERRbuftoosmall (2123) and
222 * OS/2 needs this. I'm leaving this here so we can revert
223 * if needed. JRA.
225 p->errcode = ERRmoredata;
226 #else
227 p->errcode = ERRbuftoosmall;
228 #endif
229 } else {
230 p->errcode = NERR_Success;
232 p->buflen = i;
233 n -= i;
234 p->stringbuf = p->base + i;
235 p->stringlen = n;
236 return (p->errcode == NERR_Success);
239 static int package(struct pack_desc *p, ...)
241 va_list args;
242 int needed=0, stringneeded;
243 const char *str=NULL;
244 int is_string=0, stringused;
245 int32 temp;
247 va_start(args,p);
249 if (!*p->curpos) {
250 if (!p->subcount) {
251 p->curpos = p->format;
252 } else {
253 p->curpos = p->subformat;
254 p->subcount--;
257 #if CHECK_TYPES
258 str = va_arg(args,char*);
259 SMB_ASSERT(strncmp(str,p->curpos,strlen(str)) == 0);
260 #endif
261 stringneeded = -1;
263 if (!p->curpos) {
264 va_end(args);
265 return 0;
268 switch( *p->curpos++ ) {
269 case 'W': /* word (2 byte) */
270 needed = 2;
271 temp = va_arg(args,int);
272 if (p->buflen >= needed) {
273 SSVAL(p->structbuf,0,temp);
275 break;
276 case 'K': /* status word? (2 byte) */
277 needed = 2;
278 temp = va_arg(args,int);
279 if (p->buflen >= needed) {
280 SSVAL(p->structbuf,0,temp);
282 break;
283 case 'N': /* count of substructures (word) at end */
284 needed = 2;
285 p->subcount = va_arg(args,int);
286 if (p->buflen >= needed) {
287 SSVAL(p->structbuf,0,p->subcount);
289 break;
290 case 'D': /* double word (4 byte) */
291 needed = 4;
292 temp = va_arg(args,int);
293 if (p->buflen >= needed) {
294 SIVAL(p->structbuf,0,temp);
296 break;
297 case 'B': /* byte (with optional counter) */
298 needed = get_counter(&p->curpos);
300 char *s = va_arg(args,char*);
301 if (p->buflen >= needed) {
302 StrnCpy(p->structbuf,s?s:"",needed-1);
305 break;
306 case 'z': /* offset to zero terminated string (4 byte) */
307 str = va_arg(args,char*);
308 stringneeded = (str ? strlen(str)+1 : 0);
309 is_string = 1;
310 break;
311 case 'l': /* offset to user data (4 byte) */
312 str = va_arg(args,char*);
313 stringneeded = va_arg(args,int);
314 is_string = 0;
315 break;
316 case 'b': /* offset to data (with counter) (4 byte) */
317 str = va_arg(args,char*);
318 stringneeded = get_counter(&p->curpos);
319 is_string = 0;
320 break;
323 va_end(args);
324 if (stringneeded >= 0) {
325 needed = 4;
326 if (p->buflen >= needed) {
327 stringused = stringneeded;
328 if (stringused > p->stringlen) {
329 stringused = (is_string ? p->stringlen : 0);
330 if (p->errcode == NERR_Success) {
331 p->errcode = ERRmoredata;
334 if (!stringused) {
335 SIVAL(p->structbuf,0,0);
336 } else {
337 SIVAL(p->structbuf,0,PTR_DIFF(p->stringbuf,p->base));
338 memcpy(p->stringbuf,str?str:"",stringused);
339 if (is_string) {
340 p->stringbuf[stringused-1] = '\0';
342 p->stringbuf += stringused;
343 p->stringlen -= stringused;
344 p->usedlen += stringused;
347 p->neededlen += stringneeded;
350 p->neededlen += needed;
351 if (p->buflen >= needed) {
352 p->structbuf += needed;
353 p->buflen -= needed;
354 p->usedlen += needed;
355 } else {
356 if (p->errcode == NERR_Success) {
357 p->errcode = ERRmoredata;
360 return 1;
363 #if CHECK_TYPES
364 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
365 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
366 #else
367 #define PACK(desc,t,v) package(desc,v)
368 #define PACKl(desc,t,v,l) package(desc,v,l)
369 #endif
371 static void PACKI(struct pack_desc* desc, const char *t,int v)
373 PACK(desc,t,v);
376 static void PACKS(struct pack_desc* desc,const char *t,const char *v)
378 PACK(desc,t,v);
381 /****************************************************************************
382 Get a print queue.
383 ****************************************************************************/
385 static void PackDriverData(struct pack_desc* desc)
387 char drivdata[4+4+32];
388 SIVAL(drivdata,0,sizeof drivdata); /* cb */
389 SIVAL(drivdata,4,1000); /* lVersion */
390 memset(drivdata+8,0,32); /* szDeviceName */
391 push_ascii(drivdata+8,"NULL",-1, STR_TERMINATE);
392 PACKl(desc,"l",drivdata,sizeof drivdata); /* pDriverData */
395 static int check_printq_info(struct pack_desc* desc,
396 unsigned int uLevel, char *id1, char *id2)
398 desc->subformat = NULL;
399 switch( uLevel ) {
400 case 0:
401 desc->format = "B13";
402 break;
403 case 1:
404 desc->format = "B13BWWWzzzzzWW";
405 break;
406 case 2:
407 desc->format = "B13BWWWzzzzzWN";
408 desc->subformat = "WB21BB16B10zWWzDDz";
409 break;
410 case 3:
411 desc->format = "zWWWWzzzzWWzzl";
412 break;
413 case 4:
414 desc->format = "zWWWWzzzzWNzzl";
415 desc->subformat = "WWzWWDDzz";
416 break;
417 case 5:
418 desc->format = "z";
419 break;
420 case 51:
421 desc->format = "K";
422 break;
423 case 52:
424 desc->format = "WzzzzzzzzN";
425 desc->subformat = "z";
426 break;
427 default:
428 return False;
430 if (strcmp(desc->format,id1) != 0) {
431 return False;
433 if (desc->subformat && strcmp(desc->subformat,id2) != 0) {
434 return False;
436 return True;
440 #define RAP_JOB_STATUS_QUEUED 0
441 #define RAP_JOB_STATUS_PAUSED 1
442 #define RAP_JOB_STATUS_SPOOLING 2
443 #define RAP_JOB_STATUS_PRINTING 3
444 #define RAP_JOB_STATUS_PRINTED 4
446 #define RAP_QUEUE_STATUS_PAUSED 1
447 #define RAP_QUEUE_STATUS_ERROR 2
449 /* turn a print job status into a on the wire status
451 static int printj_status(int v)
453 switch (v) {
454 case LPQ_QUEUED:
455 return RAP_JOB_STATUS_QUEUED;
456 case LPQ_PAUSED:
457 return RAP_JOB_STATUS_PAUSED;
458 case LPQ_SPOOLING:
459 return RAP_JOB_STATUS_SPOOLING;
460 case LPQ_PRINTING:
461 return RAP_JOB_STATUS_PRINTING;
463 return 0;
466 /* turn a print queue status into a on the wire status
468 static int printq_status(int v)
470 switch (v) {
471 case LPQ_QUEUED:
472 return 0;
473 case LPQ_PAUSED:
474 return RAP_QUEUE_STATUS_PAUSED;
476 return RAP_QUEUE_STATUS_ERROR;
479 static void fill_printjob_info(connection_struct *conn, int snum, int uLevel,
480 struct pack_desc *desc,
481 print_queue_struct *queue, int n)
483 time_t t = queue->time;
485 /* the client expects localtime */
486 t -= get_time_zone(t);
488 PACKI(desc,"W",pjobid_to_rap(lp_const_servicename(snum),queue->job)); /* uJobId */
489 if (uLevel == 1) {
490 PACKS(desc,"B21",queue->fs_user); /* szUserName */
491 PACKS(desc,"B",""); /* pad */
492 PACKS(desc,"B16",""); /* szNotifyName */
493 PACKS(desc,"B10","PM_Q_RAW"); /* szDataType */
494 PACKS(desc,"z",""); /* pszParms */
495 PACKI(desc,"W",n+1); /* uPosition */
496 PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */
497 PACKS(desc,"z",""); /* pszStatus */
498 PACKI(desc,"D",t); /* ulSubmitted */
499 PACKI(desc,"D",queue->size); /* ulSize */
500 PACKS(desc,"z",queue->fs_file); /* pszComment */
502 if (uLevel == 2 || uLevel == 3 || uLevel == 4) {
503 PACKI(desc,"W",queue->priority); /* uPriority */
504 PACKS(desc,"z",queue->fs_user); /* pszUserName */
505 PACKI(desc,"W",n+1); /* uPosition */
506 PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */
507 PACKI(desc,"D",t); /* ulSubmitted */
508 PACKI(desc,"D",queue->size); /* ulSize */
509 PACKS(desc,"z","Samba"); /* pszComment */
510 PACKS(desc,"z",queue->fs_file); /* pszDocument */
511 if (uLevel == 3) {
512 PACKS(desc,"z",""); /* pszNotifyName */
513 PACKS(desc,"z","PM_Q_RAW"); /* pszDataType */
514 PACKS(desc,"z",""); /* pszParms */
515 PACKS(desc,"z",""); /* pszStatus */
516 PACKS(desc,"z",SERVICE(snum)); /* pszQueue */
517 PACKS(desc,"z","lpd"); /* pszQProcName */
518 PACKS(desc,"z",""); /* pszQProcParms */
519 PACKS(desc,"z","NULL"); /* pszDriverName */
520 PackDriverData(desc); /* pDriverData */
521 PACKS(desc,"z",""); /* pszPrinterName */
522 } else if (uLevel == 4) { /* OS2 */
523 PACKS(desc,"z",""); /* pszSpoolFileName */
524 PACKS(desc,"z",""); /* pszPortName */
525 PACKS(desc,"z",""); /* pszStatus */
526 PACKI(desc,"D",0); /* ulPagesSpooled */
527 PACKI(desc,"D",0); /* ulPagesSent */
528 PACKI(desc,"D",0); /* ulPagesPrinted */
529 PACKI(desc,"D",0); /* ulTimePrinted */
530 PACKI(desc,"D",0); /* ulExtendJobStatus */
531 PACKI(desc,"D",0); /* ulStartPage */
532 PACKI(desc,"D",0); /* ulEndPage */
537 /********************************************************************
538 Return a driver name given an snum.
539 Returns True if from tdb, False otherwise.
540 ********************************************************************/
542 static BOOL get_driver_name(int snum, pstring drivername)
544 NT_PRINTER_INFO_LEVEL *info = NULL;
545 BOOL in_tdb = False;
547 get_a_printer (NULL, &info, 2, lp_servicename(snum));
548 if (info != NULL) {
549 pstrcpy( drivername, info->info_2->drivername);
550 in_tdb = True;
551 free_a_printer(&info, 2);
554 return in_tdb;
557 /********************************************************************
558 Respond to the DosPrintQInfo command with a level of 52
559 This is used to get printer driver information for Win9x clients
560 ********************************************************************/
561 static void fill_printq_info_52(connection_struct *conn, int snum,
562 struct pack_desc* desc, int count )
564 int i;
565 fstring location;
566 NT_PRINTER_DRIVER_INFO_LEVEL driver;
567 NT_PRINTER_INFO_LEVEL *printer = NULL;
569 ZERO_STRUCT(driver);
571 if ( !W_ERROR_IS_OK(get_a_printer( NULL, &printer, 2, lp_servicename(snum))) ) {
572 DEBUG(3,("fill_printq_info_52: Failed to lookup printer [%s]\n",
573 lp_servicename(snum)));
574 goto err;
577 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername,
578 "Windows 4.0", 0)) )
580 DEBUG(3,("fill_printq_info_52: Failed to lookup driver [%s]\n",
581 printer->info_2->drivername));
582 goto err;
585 trim_string(driver.info_3->driverpath, "\\print$\\WIN40\\0\\", 0);
586 trim_string(driver.info_3->datafile, "\\print$\\WIN40\\0\\", 0);
587 trim_string(driver.info_3->helpfile, "\\print$\\WIN40\\0\\", 0);
589 PACKI(desc, "W", 0x0400); /* don't know */
590 PACKS(desc, "z", driver.info_3->name); /* long printer name */
591 PACKS(desc, "z", driver.info_3->driverpath); /* Driverfile Name */
592 PACKS(desc, "z", driver.info_3->datafile); /* Datafile name */
593 PACKS(desc, "z", driver.info_3->monitorname); /* language monitor */
595 fstrcpy(location, "\\\\%L\\print$\\WIN40\\0");
596 standard_sub_basic( "", location, sizeof(location)-1 );
597 PACKS(desc,"z", location); /* share to retrieve files */
599 PACKS(desc,"z", driver.info_3->defaultdatatype); /* default data type */
600 PACKS(desc,"z", driver.info_3->helpfile); /* helpfile name */
601 PACKS(desc,"z", driver.info_3->driverpath); /* driver name */
603 DEBUG(3,("Printer Driver Name: %s:\n",driver.info_3->name));
604 DEBUG(3,("Driver: %s:\n",driver.info_3->driverpath));
605 DEBUG(3,("Data File: %s:\n",driver.info_3->datafile));
606 DEBUG(3,("Language Monitor: %s:\n",driver.info_3->monitorname));
607 DEBUG(3,("Driver Location: %s:\n",location));
608 DEBUG(3,("Data Type: %s:\n",driver.info_3->defaultdatatype));
609 DEBUG(3,("Help File: %s:\n",driver.info_3->helpfile));
610 PACKI(desc,"N",count); /* number of files to copy */
612 for ( i=0; i<count && driver.info_3->dependentfiles && *driver.info_3->dependentfiles[i]; i++)
614 trim_string(driver.info_3->dependentfiles[i], "\\print$\\WIN40\\0\\", 0);
615 PACKS(desc,"z",driver.info_3->dependentfiles[i]); /* driver files to copy */
616 DEBUG(3,("Dependent File: %s:\n",driver.info_3->dependentfiles[i]));
619 /* sanity check */
620 if ( i != count )
621 DEBUG(3,("fill_printq_info_52: file count specified by client [%d] != number of dependent files [%i]\n",
622 count, i));
624 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n", SERVICE(snum),i));
626 desc->errcode=NERR_Success;
627 goto done;
629 err:
630 DEBUG(3,("fill_printq_info: Can't supply driver files\n"));
631 desc->errcode=NERR_notsupported;
633 done:
634 if ( printer )
635 free_a_printer( &printer, 2 );
637 if ( driver.info_3 )
638 free_a_printer_driver( driver, 3 );
642 static void fill_printq_info(connection_struct *conn, int snum, int uLevel,
643 struct pack_desc* desc,
644 int count, print_queue_struct* queue,
645 print_status_struct* status)
647 switch (uLevel) {
648 case 1:
649 case 2:
650 PACKS(desc,"B13",SERVICE(snum));
651 break;
652 case 3:
653 case 4:
654 case 5:
655 PACKS(desc,"z",Expand(conn,snum,SERVICE(snum)));
656 break;
657 case 51:
658 PACKI(desc,"K",printq_status(status->status));
659 break;
662 if (uLevel == 1 || uLevel == 2) {
663 PACKS(desc,"B",""); /* alignment */
664 PACKI(desc,"W",5); /* priority */
665 PACKI(desc,"W",0); /* start time */
666 PACKI(desc,"W",0); /* until time */
667 PACKS(desc,"z",""); /* pSepFile */
668 PACKS(desc,"z","lpd"); /* pPrProc */
669 PACKS(desc,"z",SERVICE(snum)); /* pDestinations */
670 PACKS(desc,"z",""); /* pParms */
671 if (snum < 0) {
672 PACKS(desc,"z","UNKNOWN PRINTER");
673 PACKI(desc,"W",LPSTAT_ERROR);
675 else if (!status || !status->message[0]) {
676 PACKS(desc,"z",Expand(conn,snum,lp_comment(snum)));
677 PACKI(desc,"W",LPSTAT_OK); /* status */
678 } else {
679 PACKS(desc,"z",status->message);
680 PACKI(desc,"W",printq_status(status->status)); /* status */
682 PACKI(desc,(uLevel == 1 ? "W" : "N"),count);
685 if (uLevel == 3 || uLevel == 4) {
686 pstring drivername;
688 PACKI(desc,"W",5); /* uPriority */
689 PACKI(desc,"W",0); /* uStarttime */
690 PACKI(desc,"W",0); /* uUntiltime */
691 PACKI(desc,"W",5); /* pad1 */
692 PACKS(desc,"z",""); /* pszSepFile */
693 PACKS(desc,"z","WinPrint"); /* pszPrProc */
694 PACKS(desc,"z",NULL); /* pszParms */
695 PACKS(desc,"z",NULL); /* pszComment - don't ask.... JRA */
696 /* "don't ask" that it's done this way to fix corrupted
697 Win9X/ME printer comments. */
698 if (!status) {
699 PACKI(desc,"W",LPSTAT_OK); /* fsStatus */
700 } else {
701 PACKI(desc,"W",printq_status(status->status)); /* fsStatus */
703 PACKI(desc,(uLevel == 3 ? "W" : "N"),count); /* cJobs */
704 PACKS(desc,"z",SERVICE(snum)); /* pszPrinters */
705 get_driver_name(snum,drivername);
706 PACKS(desc,"z",drivername); /* pszDriverName */
707 PackDriverData(desc); /* pDriverData */
710 if (uLevel == 2 || uLevel == 4) {
711 int i;
712 for (i=0;i<count;i++)
713 fill_printjob_info(conn,snum,uLevel == 2 ? 1 : 2,desc,&queue[i],i);
716 if (uLevel==52)
717 fill_printq_info_52( conn, snum, desc, count );
720 /* This function returns the number of files for a given driver */
721 static int get_printerdrivernumber(int snum)
723 int result = 0;
724 NT_PRINTER_DRIVER_INFO_LEVEL driver;
725 NT_PRINTER_INFO_LEVEL *printer = NULL;
727 ZERO_STRUCT(driver);
729 if ( !W_ERROR_IS_OK(get_a_printer( NULL, &printer, 2, lp_servicename(snum))) ) {
730 DEBUG(3,("get_printerdrivernumber: Failed to lookup printer [%s]\n",
731 lp_servicename(snum)));
732 goto done;
735 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername,
736 "Windows 4.0", 0)) )
738 DEBUG(3,("get_printerdrivernumber: Failed to lookup driver [%s]\n",
739 printer->info_2->drivername));
740 goto done;
743 /* count the number of files */
744 while ( driver.info_3->dependentfiles && *driver.info_3->dependentfiles[result] )
745 result++;
747 done:
748 if ( printer )
749 free_a_printer( &printer, 2 );
751 if ( driver.info_3 )
752 free_a_printer_driver( driver, 3 );
754 return result;
757 static BOOL api_DosPrintQGetInfo(connection_struct *conn,
758 uint16 vuid, char *param,char *data,
759 int mdrcnt,int mprcnt,
760 char **rdata,char **rparam,
761 int *rdata_len,int *rparam_len)
763 char *str1 = param+2;
764 char *str2 = skip_string(str1,1);
765 char *p = skip_string(str2,1);
766 char *QueueName = p;
767 unsigned int uLevel;
768 int count=0;
769 int snum;
770 char* str3;
771 struct pack_desc desc;
772 print_queue_struct *queue=NULL;
773 print_status_struct status;
774 char* tmpdata=NULL;
776 memset((char *)&status,'\0',sizeof(status));
777 memset((char *)&desc,'\0',sizeof(desc));
779 p = skip_string(p,1);
780 uLevel = SVAL(p,0);
781 str3 = p + 4;
783 /* remove any trailing username */
784 if ((p = strchr_m(QueueName,'%')))
785 *p = 0;
787 DEBUG(3,("api_DosPrintQGetInfo uLevel=%d name=%s\n",uLevel,QueueName));
789 /* check it's a supported varient */
790 if (!prefix_ok(str1,"zWrLh"))
791 return False;
792 if (!check_printq_info(&desc,uLevel,str2,str3)) {
794 * Patch from Scott Moomaw <scott@bridgewater.edu>
795 * to return the 'invalid info level' error if an
796 * unknown level was requested.
798 *rdata_len = 0;
799 *rparam_len = 6;
800 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
801 SSVALS(*rparam,0,ERRunknownlevel);
802 SSVAL(*rparam,2,0);
803 SSVAL(*rparam,4,0);
804 return(True);
807 snum = find_service(QueueName);
808 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
809 return False;
811 if (uLevel==52) {
812 count = get_printerdrivernumber(snum);
813 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count));
814 } else {
815 count = print_queue_status(snum, &queue,&status);
818 if (mdrcnt > 0) {
819 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
820 desc.base = *rdata;
821 desc.buflen = mdrcnt;
822 } else {
824 * Don't return data but need to get correct length
825 * init_package will return wrong size if buflen=0
827 desc.buflen = getlen(desc.format);
828 desc.base = tmpdata = (char *) SMB_MALLOC (desc.buflen);
831 if (init_package(&desc,1,count)) {
832 desc.subcount = count;
833 fill_printq_info(conn,snum,uLevel,&desc,count,queue,&status);
836 *rdata_len = desc.usedlen;
839 * We must set the return code to ERRbuftoosmall
840 * in order to support lanman style printing with Win NT/2k
841 * clients --jerry
843 if (!mdrcnt && lp_disable_spoolss())
844 desc.errcode = ERRbuftoosmall;
846 *rdata_len = desc.usedlen;
847 *rparam_len = 6;
848 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
849 SSVALS(*rparam,0,desc.errcode);
850 SSVAL(*rparam,2,0);
851 SSVAL(*rparam,4,desc.neededlen);
853 DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode));
855 SAFE_FREE(queue);
856 SAFE_FREE(tmpdata);
858 return(True);
861 /****************************************************************************
862 View list of all print jobs on all queues.
863 ****************************************************************************/
865 static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid, char* param, char* data,
866 int mdrcnt, int mprcnt,
867 char **rdata, char** rparam,
868 int *rdata_len, int *rparam_len)
870 char *param_format = param+2;
871 char *output_format1 = skip_string(param_format,1);
872 char *p = skip_string(output_format1,1);
873 unsigned int uLevel = SVAL(p,0);
874 char *output_format2 = p + 4;
875 int services = lp_numservices();
876 int i, n;
877 struct pack_desc desc;
878 print_queue_struct **queue = NULL;
879 print_status_struct *status = NULL;
880 int *subcntarr = NULL;
881 int queuecnt = 0, subcnt = 0, succnt = 0;
883 memset((char *)&desc,'\0',sizeof(desc));
885 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
887 if (!prefix_ok(param_format,"WrLeh")) {
888 return False;
890 if (!check_printq_info(&desc,uLevel,output_format1,output_format2)) {
892 * Patch from Scott Moomaw <scott@bridgewater.edu>
893 * to return the 'invalid info level' error if an
894 * unknown level was requested.
896 *rdata_len = 0;
897 *rparam_len = 6;
898 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
899 SSVALS(*rparam,0,ERRunknownlevel);
900 SSVAL(*rparam,2,0);
901 SSVAL(*rparam,4,0);
902 return(True);
905 for (i = 0; i < services; i++) {
906 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
907 queuecnt++;
911 if((queue = SMB_MALLOC_ARRAY(print_queue_struct*, queuecnt)) == NULL) {
912 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
913 goto err;
915 memset(queue,0,queuecnt*sizeof(print_queue_struct*));
916 if((status = SMB_MALLOC_ARRAY(print_status_struct,queuecnt)) == NULL) {
917 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
918 goto err;
920 memset(status,0,queuecnt*sizeof(print_status_struct));
921 if((subcntarr = SMB_MALLOC_ARRAY(int,queuecnt)) == NULL) {
922 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
923 goto err;
926 subcnt = 0;
927 n = 0;
928 for (i = 0; i < services; i++) {
929 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
930 subcntarr[n] = print_queue_status(i, &queue[n],&status[n]);
931 subcnt += subcntarr[n];
932 n++;
936 if (mdrcnt > 0) {
937 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
938 if (!*rdata) {
939 goto err;
942 desc.base = *rdata;
943 desc.buflen = mdrcnt;
945 if (init_package(&desc,queuecnt,subcnt)) {
946 n = 0;
947 succnt = 0;
948 for (i = 0; i < services; i++) {
949 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
950 fill_printq_info(conn,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]);
951 n++;
952 if (desc.errcode == NERR_Success) {
953 succnt = n;
959 SAFE_FREE(subcntarr);
961 *rdata_len = desc.usedlen;
962 *rparam_len = 8;
963 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
964 if (!*rparam) {
965 goto err;
967 SSVALS(*rparam,0,desc.errcode);
968 SSVAL(*rparam,2,0);
969 SSVAL(*rparam,4,succnt);
970 SSVAL(*rparam,6,queuecnt);
972 for (i = 0; i < queuecnt; i++) {
973 if (queue) {
974 SAFE_FREE(queue[i]);
978 SAFE_FREE(queue);
979 SAFE_FREE(status);
981 return True;
983 err:
985 SAFE_FREE(subcntarr);
986 for (i = 0; i < queuecnt; i++) {
987 if (queue) {
988 SAFE_FREE(queue[i]);
991 SAFE_FREE(queue);
992 SAFE_FREE(status);
994 return False;
997 /****************************************************************************
998 Get info level for a server list query.
999 ****************************************************************************/
1001 static BOOL check_server_info(int uLevel, char* id)
1003 switch( uLevel ) {
1004 case 0:
1005 if (strcmp(id,"B16") != 0) {
1006 return False;
1008 break;
1009 case 1:
1010 if (strcmp(id,"B16BBDz") != 0) {
1011 return False;
1013 break;
1014 default:
1015 return False;
1017 return True;
1020 struct srv_info_struct {
1021 fstring name;
1022 uint32 type;
1023 fstring comment;
1024 fstring domain;
1025 BOOL server_added;
1028 /*******************************************************************
1029 Get server info lists from the files saved by nmbd. Return the
1030 number of entries.
1031 ******************************************************************/
1033 static int get_server_info(uint32 servertype,
1034 struct srv_info_struct **servers,
1035 const char *domain)
1037 int count=0;
1038 int alloced=0;
1039 char **lines;
1040 BOOL local_list_only;
1041 int i;
1043 lines = file_lines_load(lock_path(SERVER_LIST), NULL, 0);
1044 if (!lines) {
1045 DEBUG(4,("Can't open %s - %s\n",lock_path(SERVER_LIST),strerror(errno)));
1046 return 0;
1049 /* request for everything is code for request all servers */
1050 if (servertype == SV_TYPE_ALL) {
1051 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1054 local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY);
1056 DEBUG(4,("Servertype search: %8x\n",servertype));
1058 for (i=0;lines[i];i++) {
1059 fstring stype;
1060 struct srv_info_struct *s;
1061 const char *ptr = lines[i];
1062 BOOL ok = True;
1064 if (!*ptr) {
1065 continue;
1068 if (count == alloced) {
1069 struct srv_info_struct *ts;
1071 alloced += 10;
1072 ts = SMB_REALLOC_ARRAY(*servers,struct srv_info_struct, alloced);
1073 if (!ts) {
1074 DEBUG(0,("get_server_info: failed to enlarge servers info struct!\n"));
1075 return 0;
1076 } else {
1077 *servers = ts;
1079 memset((char *)((*servers)+count),'\0',sizeof(**servers)*(alloced-count));
1081 s = &(*servers)[count];
1083 if (!next_token(&ptr,s->name, NULL, sizeof(s->name))) {
1084 continue;
1086 if (!next_token(&ptr,stype, NULL, sizeof(stype))) {
1087 continue;
1089 if (!next_token(&ptr,s->comment, NULL, sizeof(s->comment))) {
1090 continue;
1092 if (!next_token(&ptr,s->domain, NULL, sizeof(s->domain))) {
1093 /* this allows us to cope with an old nmbd */
1094 fstrcpy(s->domain,lp_workgroup());
1097 if (sscanf(stype,"%X",&s->type) != 1) {
1098 DEBUG(4,("r:host file "));
1099 ok = False;
1102 /* Filter the servers/domains we return based on what was asked for. */
1104 /* Check to see if we are being asked for a local list only. */
1105 if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) {
1106 DEBUG(4,("r: local list only"));
1107 ok = False;
1110 /* doesn't match up: don't want it */
1111 if (!(servertype & s->type)) {
1112 DEBUG(4,("r:serv type "));
1113 ok = False;
1116 if ((servertype & SV_TYPE_DOMAIN_ENUM) !=
1117 (s->type & SV_TYPE_DOMAIN_ENUM)) {
1118 DEBUG(4,("s: dom mismatch "));
1119 ok = False;
1122 if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM)) {
1123 ok = False;
1126 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1127 s->type &= ~SV_TYPE_LOCAL_LIST_ONLY;
1129 if (ok) {
1130 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1131 s->name, s->type, s->comment, s->domain));
1132 s->server_added = True;
1133 count++;
1134 } else {
1135 DEBUG(4,("%20s %8x %25s %15s\n",
1136 s->name, s->type, s->comment, s->domain));
1140 file_lines_free(lines);
1141 return count;
1144 /*******************************************************************
1145 Fill in a server info structure.
1146 ******************************************************************/
1148 static int fill_srv_info(struct srv_info_struct *service,
1149 int uLevel, char **buf, int *buflen,
1150 char **stringbuf, int *stringspace, char *baseaddr)
1152 int struct_len;
1153 char* p;
1154 char* p2;
1155 int l2;
1156 int len;
1158 switch (uLevel) {
1159 case 0:
1160 struct_len = 16;
1161 break;
1162 case 1:
1163 struct_len = 26;
1164 break;
1165 default:
1166 return -1;
1169 if (!buf) {
1170 len = 0;
1171 switch (uLevel) {
1172 case 1:
1173 len = strlen(service->comment)+1;
1174 break;
1177 if (buflen) {
1178 *buflen = struct_len;
1180 if (stringspace) {
1181 *stringspace = len;
1183 return struct_len + len;
1186 len = struct_len;
1187 p = *buf;
1188 if (*buflen < struct_len) {
1189 return -1;
1191 if (stringbuf) {
1192 p2 = *stringbuf;
1193 l2 = *stringspace;
1194 } else {
1195 p2 = p + struct_len;
1196 l2 = *buflen - struct_len;
1198 if (!baseaddr) {
1199 baseaddr = p;
1202 switch (uLevel) {
1203 case 0:
1204 push_ascii(p,service->name, MAX_NETBIOSNAME_LEN, STR_TERMINATE);
1205 break;
1207 case 1:
1208 push_ascii(p,service->name,MAX_NETBIOSNAME_LEN, STR_TERMINATE);
1209 SIVAL(p,18,service->type);
1210 SIVAL(p,22,PTR_DIFF(p2,baseaddr));
1211 len += CopyAndAdvance(&p2,service->comment,&l2);
1212 break;
1215 if (stringbuf) {
1216 *buf = p + struct_len;
1217 *buflen -= struct_len;
1218 *stringbuf = p2;
1219 *stringspace = l2;
1220 } else {
1221 *buf = p2;
1222 *buflen -= len;
1224 return len;
1228 static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
1230 return(strcmp(s1->name,s2->name));
1233 /****************************************************************************
1234 View list of servers available (or possibly domains). The info is
1235 extracted from lists saved by nmbd on the local host.
1236 ****************************************************************************/
1238 static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid, char *param, char *data,
1239 int mdrcnt, int mprcnt, char **rdata,
1240 char **rparam, int *rdata_len, int *rparam_len)
1242 char *str1 = param+2;
1243 char *str2 = skip_string(str1,1);
1244 char *p = skip_string(str2,1);
1245 int uLevel = SVAL(p,0);
1246 int buf_len = SVAL(p,2);
1247 uint32 servertype = IVAL(p,4);
1248 char *p2;
1249 int data_len, fixed_len, string_len;
1250 int f_len = 0, s_len = 0;
1251 struct srv_info_struct *servers=NULL;
1252 int counted=0,total=0;
1253 int i,missed;
1254 fstring domain;
1255 BOOL domain_request;
1256 BOOL local_request;
1258 /* If someone sets all the bits they don't really mean to set
1259 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1260 known servers. */
1262 if (servertype == SV_TYPE_ALL) {
1263 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1266 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1267 any other bit (they may just set this bit on it's own) they
1268 want all the locally seen servers. However this bit can be
1269 set on its own so set the requested servers to be
1270 ALL - DOMAIN_ENUM. */
1272 if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM)) {
1273 servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
1276 domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
1277 local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
1279 p += 8;
1281 if (!prefix_ok(str1,"WrLehD")) {
1282 return False;
1284 if (!check_server_info(uLevel,str2)) {
1285 return False;
1288 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1289 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1290 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1292 if (strcmp(str1, "WrLehDz") == 0) {
1293 pull_ascii_fstring(domain, p);
1294 } else {
1295 fstrcpy(domain, lp_workgroup());
1298 if (lp_browse_list()) {
1299 total = get_server_info(servertype,&servers,domain);
1302 data_len = fixed_len = string_len = 0;
1303 missed = 0;
1305 if (total > 0) {
1306 qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
1310 char *lastname=NULL;
1312 for (i=0;i<total;i++) {
1313 struct srv_info_struct *s = &servers[i];
1315 if (lastname && strequal(lastname,s->name)) {
1316 continue;
1318 lastname = s->name;
1319 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1320 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1321 s->name, s->type, s->comment, s->domain));
1323 if (data_len <= buf_len) {
1324 counted++;
1325 fixed_len += f_len;
1326 string_len += s_len;
1327 } else {
1328 missed++;
1333 *rdata_len = fixed_len + string_len;
1334 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
1335 memset(*rdata,'\0',*rdata_len);
1337 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1338 p = *rdata;
1339 f_len = fixed_len;
1340 s_len = string_len;
1343 char *lastname=NULL;
1344 int count2 = counted;
1346 for (i = 0; i < total && count2;i++) {
1347 struct srv_info_struct *s = &servers[i];
1349 if (lastname && strequal(lastname,s->name)) {
1350 continue;
1352 lastname = s->name;
1353 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1354 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1355 s->name, s->type, s->comment, s->domain));
1356 count2--;
1360 *rparam_len = 8;
1361 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1362 SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata));
1363 SSVAL(*rparam,2,0);
1364 SSVAL(*rparam,4,counted);
1365 SSVAL(*rparam,6,counted+missed);
1367 SAFE_FREE(servers);
1369 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1370 domain,uLevel,counted,counted+missed));
1372 return True;
1375 /****************************************************************************
1376 command 0x34 - suspected of being a "Lookup Names" stub api
1377 ****************************************************************************/
1379 static BOOL api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid, char *param, char *data,
1380 int mdrcnt, int mprcnt, char **rdata,
1381 char **rparam, int *rdata_len, int *rparam_len)
1383 char *str1 = param+2;
1384 char *str2 = skip_string(str1,1);
1385 char *p = skip_string(str2,1);
1386 int uLevel = SVAL(p,0);
1387 int buf_len = SVAL(p,2);
1388 int counted=0;
1389 int missed=0;
1391 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1392 str1, str2, p, uLevel, buf_len));
1394 if (!prefix_ok(str1,"zWrLeh")) {
1395 return False;
1398 *rdata_len = 0;
1400 *rparam_len = 8;
1401 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1403 SSVAL(*rparam,0,0x08AC); /* informational warning message */
1404 SSVAL(*rparam,2,0);
1405 SSVAL(*rparam,4,counted);
1406 SSVAL(*rparam,6,counted+missed);
1408 return True;
1411 /****************************************************************************
1412 get info about a share
1413 ****************************************************************************/
1415 static BOOL check_share_info(int uLevel, char* id)
1417 switch( uLevel ) {
1418 case 0:
1419 if (strcmp(id,"B13") != 0) {
1420 return False;
1422 break;
1423 case 1:
1424 if (strcmp(id,"B13BWz") != 0) {
1425 return False;
1427 break;
1428 case 2:
1429 if (strcmp(id,"B13BWzWWWzB9B") != 0) {
1430 return False;
1432 break;
1433 case 91:
1434 if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) {
1435 return False;
1437 break;
1438 default:
1439 return False;
1441 return True;
1444 static int fill_share_info(connection_struct *conn, int snum, int uLevel,
1445 char** buf, int* buflen,
1446 char** stringbuf, int* stringspace, char* baseaddr)
1448 int struct_len;
1449 char* p;
1450 char* p2;
1451 int l2;
1452 int len;
1454 switch( uLevel ) {
1455 case 0:
1456 struct_len = 13;
1457 break;
1458 case 1:
1459 struct_len = 20;
1460 break;
1461 case 2:
1462 struct_len = 40;
1463 break;
1464 case 91:
1465 struct_len = 68;
1466 break;
1467 default:
1468 return -1;
1472 if (!buf) {
1473 len = 0;
1475 if (uLevel > 0) {
1476 len += StrlenExpanded(conn,snum,lp_comment(snum));
1478 if (uLevel > 1) {
1479 len += strlen(lp_pathname(snum)) + 1;
1481 if (buflen) {
1482 *buflen = struct_len;
1484 if (stringspace) {
1485 *stringspace = len;
1487 return struct_len + len;
1490 len = struct_len;
1491 p = *buf;
1492 if ((*buflen) < struct_len) {
1493 return -1;
1496 if (stringbuf) {
1497 p2 = *stringbuf;
1498 l2 = *stringspace;
1499 } else {
1500 p2 = p + struct_len;
1501 l2 = (*buflen) - struct_len;
1504 if (!baseaddr) {
1505 baseaddr = p;
1508 push_ascii(p,lp_servicename(snum),13, STR_TERMINATE);
1510 if (uLevel > 0) {
1511 int type;
1513 SCVAL(p,13,0);
1514 type = STYPE_DISKTREE;
1515 if (lp_print_ok(snum)) {
1516 type = STYPE_PRINTQ;
1518 if (strequal("IPC",lp_fstype(snum))) {
1519 type = STYPE_IPC;
1521 SSVAL(p,14,type); /* device type */
1522 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1523 len += CopyExpanded(conn,snum,&p2,lp_comment(snum),&l2);
1526 if (uLevel > 1) {
1527 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1528 SSVALS(p,22,-1); /* max uses */
1529 SSVAL(p,24,1); /* current uses */
1530 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1531 len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1532 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1535 if (uLevel > 2) {
1536 memset(p+40,0,SHPWLEN+2);
1537 SSVAL(p,50,0);
1538 SIVAL(p,52,0);
1539 SSVAL(p,56,0);
1540 SSVAL(p,58,0);
1541 SIVAL(p,60,0);
1542 SSVAL(p,64,0);
1543 SSVAL(p,66,0);
1546 if (stringbuf) {
1547 (*buf) = p + struct_len;
1548 (*buflen) -= struct_len;
1549 (*stringbuf) = p2;
1550 (*stringspace) = l2;
1551 } else {
1552 (*buf) = p2;
1553 (*buflen) -= len;
1556 return len;
1559 static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
1560 int mdrcnt,int mprcnt,
1561 char **rdata,char **rparam,
1562 int *rdata_len,int *rparam_len)
1564 char *str1 = param+2;
1565 char *str2 = skip_string(str1,1);
1566 char *netname = skip_string(str2,1);
1567 char *p = skip_string(netname,1);
1568 int uLevel = SVAL(p,0);
1569 int snum = find_service(netname);
1571 if (snum < 0) {
1572 return False;
1575 /* check it's a supported varient */
1576 if (!prefix_ok(str1,"zWrLh")) {
1577 return False;
1579 if (!check_share_info(uLevel,str2)) {
1580 return False;
1583 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
1584 p = *rdata;
1585 *rdata_len = fill_share_info(conn,snum,uLevel,&p,&mdrcnt,0,0,0);
1586 if (*rdata_len < 0) {
1587 return False;
1590 *rparam_len = 6;
1591 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1592 SSVAL(*rparam,0,NERR_Success);
1593 SSVAL(*rparam,2,0); /* converter word */
1594 SSVAL(*rparam,4,*rdata_len);
1596 return True;
1599 /****************************************************************************
1600 View the list of available shares.
1602 This function is the server side of the NetShareEnum() RAP call.
1603 It fills the return buffer with share names and share comments.
1604 Note that the return buffer normally (in all known cases) allows only
1605 twelve byte strings for share names (plus one for a nul terminator).
1606 Share names longer than 12 bytes must be skipped.
1607 ****************************************************************************/
1609 static BOOL api_RNetShareEnum( connection_struct *conn,
1610 uint16 vuid,
1611 char *param,
1612 char *data,
1613 int mdrcnt,
1614 int mprcnt,
1615 char **rdata,
1616 char **rparam,
1617 int *rdata_len,
1618 int *rparam_len )
1620 char *str1 = param+2;
1621 char *str2 = skip_string(str1,1);
1622 char *p = skip_string(str2,1);
1623 int uLevel = SVAL(p,0);
1624 int buf_len = SVAL(p,2);
1625 char *p2;
1626 int count = 0;
1627 int total=0,counted=0;
1628 BOOL missed = False;
1629 int i;
1630 int data_len, fixed_len, string_len;
1631 int f_len = 0, s_len = 0;
1633 if (!prefix_ok(str1,"WrLeh")) {
1634 return False;
1636 if (!check_share_info(uLevel,str2)) {
1637 return False;
1640 /* Ensure all the usershares are loaded. */
1641 become_root();
1642 count = load_usershare_shares();
1643 unbecome_root();
1645 data_len = fixed_len = string_len = 0;
1646 for (i=0;i<count;i++) {
1647 fstring servicename_dos;
1648 if (!(lp_browseable(i) && lp_snum_ok(i))) {
1649 continue;
1651 push_ascii_fstring(servicename_dos, lp_servicename(i));
1652 /* Maximum name length = 13. */
1653 if( lp_browseable( i ) && lp_snum_ok( i ) && (strlen(servicename_dos) < 13)) {
1654 total++;
1655 data_len += fill_share_info(conn,i,uLevel,0,&f_len,0,&s_len,0);
1656 if (data_len <= buf_len) {
1657 counted++;
1658 fixed_len += f_len;
1659 string_len += s_len;
1660 } else {
1661 missed = True;
1666 *rdata_len = fixed_len + string_len;
1667 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
1668 memset(*rdata,0,*rdata_len);
1670 p2 = (*rdata) + fixed_len; /* auxiliary data (strings) will go here */
1671 p = *rdata;
1672 f_len = fixed_len;
1673 s_len = string_len;
1675 for( i = 0; i < count; i++ ) {
1676 fstring servicename_dos;
1677 if (!(lp_browseable(i) && lp_snum_ok(i))) {
1678 continue;
1681 push_ascii_fstring(servicename_dos, lp_servicename(i));
1682 if (lp_browseable(i) && lp_snum_ok(i) && (strlen(servicename_dos) < 13)) {
1683 if (fill_share_info( conn,i,uLevel,&p,&f_len,&p2,&s_len,*rdata ) < 0) {
1684 break;
1689 *rparam_len = 8;
1690 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1691 SSVAL(*rparam,0,missed ? ERRmoredata : NERR_Success);
1692 SSVAL(*rparam,2,0);
1693 SSVAL(*rparam,4,counted);
1694 SSVAL(*rparam,6,total);
1696 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1697 counted,total,uLevel,
1698 buf_len,*rdata_len,mdrcnt));
1700 return True;
1703 /****************************************************************************
1704 Add a share
1705 ****************************************************************************/
1707 static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid, char *param,char *data,
1708 int mdrcnt,int mprcnt,
1709 char **rdata,char **rparam,
1710 int *rdata_len,int *rparam_len)
1712 char *str1 = param+2;
1713 char *str2 = skip_string(str1,1);
1714 char *p = skip_string(str2,1);
1715 int uLevel = SVAL(p,0);
1716 fstring sharename;
1717 fstring comment;
1718 pstring pathname;
1719 char *command, *cmdname;
1720 unsigned int offset;
1721 int snum;
1722 int res = ERRunsup;
1724 /* check it's a supported varient */
1725 if (!prefix_ok(str1,RAP_WShareAdd_REQ)) {
1726 return False;
1728 if (!check_share_info(uLevel,str2)) {
1729 return False;
1731 if (uLevel != 2) {
1732 return False;
1735 pull_ascii_fstring(sharename,data);
1736 snum = find_service(sharename);
1737 if (snum >= 0) { /* already exists */
1738 res = ERRfilexists;
1739 goto error_exit;
1742 /* only support disk share adds */
1743 if (SVAL(data,14)!=STYPE_DISKTREE) {
1744 return False;
1747 offset = IVAL(data, 16);
1748 if (offset >= mdrcnt) {
1749 res = ERRinvalidparam;
1750 goto error_exit;
1753 pull_ascii_fstring(comment, offset? (data+offset) : "");
1755 offset = IVAL(data, 26);
1757 if (offset >= mdrcnt) {
1758 res = ERRinvalidparam;
1759 goto error_exit;
1762 pull_ascii_pstring(pathname, offset? (data+offset) : "");
1764 string_replace(sharename, '"', ' ');
1765 string_replace(pathname, '"', ' ');
1766 string_replace(comment, '"', ' ');
1768 cmdname = lp_add_share_cmd();
1770 if (!cmdname || *cmdname == '\0') {
1771 return False;
1774 asprintf(&command, "%s \"%s\" \"%s\" \"%s\" \"%s\"",
1775 lp_add_share_cmd(), dyn_CONFIGFILE, sharename, pathname, comment);
1777 if (command) {
1778 DEBUG(10,("api_RNetShareAdd: Running [%s]\n", command ));
1780 if ((res = smbrun(command, NULL)) != 0) {
1781 DEBUG(1,("api_RNetShareAdd: Running [%s] returned (%d)\n", command, res ));
1782 SAFE_FREE(command);
1783 res = ERRnoaccess;
1784 goto error_exit;
1785 } else {
1786 SAFE_FREE(command);
1787 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
1789 } else {
1790 return False;
1793 *rparam_len = 6;
1794 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1795 SSVAL(*rparam,0,NERR_Success);
1796 SSVAL(*rparam,2,0); /* converter word */
1797 SSVAL(*rparam,4,*rdata_len);
1798 *rdata_len = 0;
1800 return True;
1802 error_exit:
1804 *rparam_len = 4;
1805 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1806 *rdata_len = 0;
1807 SSVAL(*rparam,0,res);
1808 SSVAL(*rparam,2,0);
1809 return True;
1812 /****************************************************************************
1813 view list of groups available
1814 ****************************************************************************/
1816 static BOOL api_RNetGroupEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
1817 int mdrcnt,int mprcnt,
1818 char **rdata,char **rparam,
1819 int *rdata_len,int *rparam_len)
1821 int i;
1822 int errflags=0;
1823 int resume_context, cli_buf_size;
1824 char *str1 = param+2;
1825 char *str2 = skip_string(str1,1);
1826 char *p = skip_string(str2,1);
1828 struct pdb_search *search;
1829 struct samr_displayentry *entries;
1831 int num_entries;
1833 if (strcmp(str1,"WrLeh") != 0) {
1834 return False;
1837 /* parameters
1838 * W-> resume context (number of users to skip)
1839 * r -> return parameter pointer to receive buffer
1840 * L -> length of receive buffer
1841 * e -> return parameter number of entries
1842 * h -> return parameter total number of users
1845 if (strcmp("B21",str2) != 0) {
1846 return False;
1849 /* get list of domain groups SID_DOMAIN_GRP=2 */
1850 become_root();
1851 search = pdb_search_groups();
1852 unbecome_root();
1854 if (search == NULL) {
1855 DEBUG(3,("api_RNetGroupEnum:failed to get group list"));
1856 return False;
1859 resume_context = SVAL(p,0);
1860 cli_buf_size=SVAL(p+2,0);
1861 DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: "
1862 "%d\n", resume_context, cli_buf_size));
1864 become_root();
1865 num_entries = pdb_search_entries(search, resume_context, 0xffffffff,
1866 &entries);
1867 unbecome_root();
1869 *rdata_len = cli_buf_size;
1870 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
1872 p = *rdata;
1874 for(i=0; i<num_entries; i++) {
1875 fstring name;
1876 fstrcpy(name, entries[i].account_name);
1877 if( ((PTR_DIFF(p,*rdata)+21) <= *rdata_len) ) {
1878 /* truncate the name at 21 chars. */
1879 memcpy(p, name, 21);
1880 DEBUG(10,("adding entry %d group %s\n", i, p));
1881 p += 21;
1882 p += 5; /* Both NT4 and W2k3SP1 do padding here.
1883 No idea why... */
1884 } else {
1885 /* set overflow error */
1886 DEBUG(3,("overflow on entry %d group %s\n", i, name));
1887 errflags=234;
1888 break;
1892 pdb_search_destroy(search);
1894 *rdata_len = PTR_DIFF(p,*rdata);
1896 *rparam_len = 8;
1897 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1899 SSVAL(*rparam, 0, errflags);
1900 SSVAL(*rparam, 2, 0); /* converter word */
1901 SSVAL(*rparam, 4, i); /* is this right?? */
1902 SSVAL(*rparam, 6, resume_context+num_entries); /* is this right?? */
1904 return(True);
1907 /*******************************************************************
1908 Get groups that a user is a member of.
1909 ******************************************************************/
1911 static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *param,char *data,
1912 int mdrcnt,int mprcnt,
1913 char **rdata,char **rparam,
1914 int *rdata_len,int *rparam_len)
1916 char *str1 = param+2;
1917 char *str2 = skip_string(str1,1);
1918 char *UserName = skip_string(str2,1);
1919 char *p = skip_string(UserName,1);
1920 int uLevel = SVAL(p,0);
1921 const char *level_string;
1922 int count=0;
1923 SAM_ACCOUNT *sampw = NULL;
1924 BOOL ret = False;
1925 DOM_SID *sids;
1926 gid_t *gids;
1927 size_t num_groups;
1928 size_t i;
1929 NTSTATUS result;
1930 DOM_SID user_sid;
1931 enum SID_NAME_USE type;
1932 TALLOC_CTX *mem_ctx;
1934 *rparam_len = 8;
1935 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1937 /* check it's a supported varient */
1939 if ( strcmp(str1,"zWrLeh") != 0 )
1940 return False;
1942 switch( uLevel ) {
1943 case 0:
1944 level_string = "B21";
1945 break;
1946 default:
1947 return False;
1950 if (strcmp(level_string,str2) != 0)
1951 return False;
1953 *rdata_len = mdrcnt + 1024;
1954 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
1956 SSVAL(*rparam,0,NERR_Success);
1957 SSVAL(*rparam,2,0); /* converter word */
1959 p = *rdata;
1961 mem_ctx = talloc_new(NULL);
1962 if (mem_ctx == NULL) {
1963 DEBUG(0, ("talloc_new failed\n"));
1964 return False;
1967 /* Lookup the user information; This should only be one of
1968 our accounts (not remote domains) */
1970 become_root(); /* ROOT BLOCK */
1972 if (!lookup_name(mem_ctx, UserName, LOOKUP_NAME_ALL,
1973 NULL, NULL, &user_sid, &type)) {
1974 DEBUG(10, ("lookup_name(%s) failed\n", UserName));
1975 goto done;
1978 if (type != SID_NAME_USER) {
1979 DEBUG(10, ("%s is a %s, not a user\n", UserName,
1980 sid_type_lookup(type)));
1981 goto done;
1984 if (!NT_STATUS_IS_OK(pdb_init_sam_talloc(mem_ctx, &sampw))) {
1985 DEBUG(10, ("pdb_init_sam_talloc failed\n"));
1986 goto done;
1989 if ( !pdb_getsampwsid(sampw, &user_sid) ) {
1990 DEBUG(10, ("pdb_getsampwsid(%s) failed for user %s\n",
1991 sid_string_static(&user_sid), UserName));
1992 goto done;
1995 gids = NULL;
1996 sids = NULL;
1997 num_groups = 0;
1999 result = pdb_enum_group_memberships(mem_ctx, sampw,
2000 &sids, &gids, &num_groups);
2002 if (!NT_STATUS_IS_OK(result)) {
2003 DEBUG(10, ("pdb_enum_group_memberships failed for %s\n",
2004 UserName));
2005 goto done;
2008 for (i=0; i<num_groups; i++) {
2010 const char *grp_name;
2012 if ( lookup_sid(mem_ctx, &sids[i], NULL, &grp_name, NULL) ) {
2013 pstrcpy(p, grp_name);
2014 p += 21;
2015 count++;
2019 *rdata_len = PTR_DIFF(p,*rdata);
2021 SSVAL(*rparam,4,count); /* is this right?? */
2022 SSVAL(*rparam,6,count); /* is this right?? */
2024 ret = True;
2026 done:
2027 unbecome_root(); /* END ROOT BLOCK */
2029 talloc_free(mem_ctx);
2031 return ret;
2034 /*******************************************************************
2035 Get all users.
2036 ******************************************************************/
2038 static BOOL api_RNetUserEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
2039 int mdrcnt,int mprcnt,
2040 char **rdata,char **rparam,
2041 int *rdata_len,int *rparam_len)
2043 int count_sent=0;
2044 int num_users=0;
2045 int errflags=0;
2046 int i, resume_context, cli_buf_size;
2047 struct pdb_search *search;
2048 struct samr_displayentry *users;
2050 char *str1 = param+2;
2051 char *str2 = skip_string(str1,1);
2052 char *p = skip_string(str2,1);
2054 if (strcmp(str1,"WrLeh") != 0)
2055 return False;
2056 /* parameters
2057 * W-> resume context (number of users to skip)
2058 * r -> return parameter pointer to receive buffer
2059 * L -> length of receive buffer
2060 * e -> return parameter number of entries
2061 * h -> return parameter total number of users
2064 resume_context = SVAL(p,0);
2065 cli_buf_size=SVAL(p+2,0);
2066 DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n",
2067 resume_context, cli_buf_size));
2069 *rparam_len = 8;
2070 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2072 /* check it's a supported varient */
2073 if (strcmp("B21",str2) != 0)
2074 return False;
2076 *rdata_len = cli_buf_size;
2077 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
2079 p = *rdata;
2081 become_root();
2082 search = pdb_search_users(ACB_NORMAL);
2083 unbecome_root();
2084 if (search == NULL) {
2085 DEBUG(0, ("api_RNetUserEnum:unable to open sam database.\n"));
2086 return False;
2089 become_root();
2090 num_users = pdb_search_entries(search, resume_context, 0xffffffff,
2091 &users);
2092 unbecome_root();
2094 errflags=NERR_Success;
2096 for (i=0; i<num_users; i++) {
2097 const char *name = users[i].account_name;
2099 if(((PTR_DIFF(p,*rdata)+21)<=*rdata_len)&&(strlen(name)<=21)) {
2100 pstrcpy(p,name);
2101 DEBUG(10,("api_RNetUserEnum:adding entry %d username "
2102 "%s\n",count_sent,p));
2103 p += 21;
2104 count_sent++;
2105 } else {
2106 /* set overflow error */
2107 DEBUG(10,("api_RNetUserEnum:overflow on entry %d "
2108 "username %s\n",count_sent,name));
2109 errflags=234;
2110 break;
2114 pdb_search_destroy(search);
2116 *rdata_len = PTR_DIFF(p,*rdata);
2118 SSVAL(*rparam,0,errflags);
2119 SSVAL(*rparam,2,0); /* converter word */
2120 SSVAL(*rparam,4,count_sent); /* is this right?? */
2121 SSVAL(*rparam,6,num_users); /* is this right?? */
2123 return True;
2126 /****************************************************************************
2127 Get the time of day info.
2128 ****************************************************************************/
2130 static BOOL api_NetRemoteTOD(connection_struct *conn,uint16 vuid, char *param,char *data,
2131 int mdrcnt,int mprcnt,
2132 char **rdata,char **rparam,
2133 int *rdata_len,int *rparam_len)
2135 struct tm *t;
2136 time_t unixdate = time(NULL);
2137 char *p;
2139 *rparam_len = 4;
2140 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2142 *rdata_len = 21;
2143 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
2145 SSVAL(*rparam,0,NERR_Success);
2146 SSVAL(*rparam,2,0); /* converter word */
2148 p = *rdata;
2150 srv_put_dos_date3(p,0,unixdate); /* this is the time that is looked at
2151 by NT in a "net time" operation,
2152 it seems to ignore the one below */
2154 /* the client expects to get localtime, not GMT, in this bit
2155 (I think, this needs testing) */
2156 t = localtime(&unixdate);
2158 SIVAL(p,4,0); /* msecs ? */
2159 SCVAL(p,8,t->tm_hour);
2160 SCVAL(p,9,t->tm_min);
2161 SCVAL(p,10,t->tm_sec);
2162 SCVAL(p,11,0); /* hundredths of seconds */
2163 SSVALS(p,12,get_time_zone(unixdate)/60); /* timezone in minutes from GMT */
2164 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
2165 SCVAL(p,16,t->tm_mday);
2166 SCVAL(p,17,t->tm_mon + 1);
2167 SSVAL(p,18,1900+t->tm_year);
2168 SCVAL(p,20,t->tm_wday);
2170 return True;
2173 /****************************************************************************
2174 Set the user password.
2175 *****************************************************************************/
2177 static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param,char *data,
2178 int mdrcnt,int mprcnt,
2179 char **rdata,char **rparam,
2180 int *rdata_len,int *rparam_len)
2182 char *p = skip_string(param+2,2);
2183 fstring user;
2184 fstring pass1,pass2;
2186 pull_ascii_fstring(user,p);
2188 p = skip_string(p,1);
2190 memset(pass1,'\0',sizeof(pass1));
2191 memset(pass2,'\0',sizeof(pass2));
2192 memcpy(pass1,p,16);
2193 memcpy(pass2,p+16,16);
2195 *rparam_len = 4;
2196 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2198 *rdata_len = 0;
2200 SSVAL(*rparam,0,NERR_badpass);
2201 SSVAL(*rparam,2,0); /* converter word */
2203 DEBUG(3,("Set password for <%s>\n",user));
2206 * Attempt to verify the old password against smbpasswd entries
2207 * Win98 clients send old and new password in plaintext for this call.
2211 auth_serversupplied_info *server_info = NULL;
2212 DATA_BLOB password = data_blob(pass1, strlen(pass1)+1);
2214 if (NT_STATUS_IS_OK(check_plaintext_password(user,password,&server_info))) {
2216 become_root();
2217 if (NT_STATUS_IS_OK(change_oem_password(server_info->sam_account, pass1, pass2, False))) {
2218 SSVAL(*rparam,0,NERR_Success);
2220 unbecome_root();
2222 talloc_free(server_info);
2224 data_blob_clear_free(&password);
2228 * If the plaintext change failed, attempt
2229 * the old encrypted method. NT will generate this
2230 * after trying the samr method. Note that this
2231 * method is done as a last resort as this
2232 * password change method loses the NT password hash
2233 * and cannot change the UNIX password as no plaintext
2234 * is received.
2237 if(SVAL(*rparam,0) != NERR_Success) {
2238 SAM_ACCOUNT *hnd = NULL;
2240 if (check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &hnd)) {
2241 become_root();
2242 if (change_lanman_password(hnd,(uchar *)pass2)) {
2243 SSVAL(*rparam,0,NERR_Success);
2245 unbecome_root();
2246 pdb_free_sam(&hnd);
2250 memset((char *)pass1,'\0',sizeof(fstring));
2251 memset((char *)pass2,'\0',sizeof(fstring));
2253 return(True);
2256 /****************************************************************************
2257 Set the user password (SamOEM version - gets plaintext).
2258 ****************************************************************************/
2260 static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char *param,char *data,
2261 int mdrcnt,int mprcnt,
2262 char **rdata,char **rparam,
2263 int *rdata_len,int *rparam_len)
2265 fstring user;
2266 char *p = param + 2;
2267 *rparam_len = 2;
2268 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2270 *rdata_len = 0;
2272 SSVAL(*rparam,0,NERR_badpass);
2275 * Check the parameter definition is correct.
2278 if(!strequal(param + 2, "zsT")) {
2279 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", param + 2));
2280 return False;
2282 p = skip_string(p, 1);
2284 if(!strequal(p, "B516B16")) {
2285 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p));
2286 return False;
2288 p = skip_string(p,1);
2289 p += pull_ascii_fstring(user,p);
2291 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user));
2294 * Pass the user through the NT -> unix user mapping
2295 * function.
2298 (void)map_username(user);
2300 if (NT_STATUS_IS_OK(pass_oem_change(user, (uchar*) data, (uchar *)&data[516], NULL, NULL))) {
2301 SSVAL(*rparam,0,NERR_Success);
2304 return(True);
2307 /****************************************************************************
2308 delete a print job
2309 Form: <W> <>
2310 ****************************************************************************/
2312 static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char *param,char *data,
2313 int mdrcnt,int mprcnt,
2314 char **rdata,char **rparam,
2315 int *rdata_len,int *rparam_len)
2317 int function = SVAL(param,0);
2318 char *str1 = param+2;
2319 char *str2 = skip_string(str1,1);
2320 char *p = skip_string(str2,1);
2321 uint32 jobid;
2322 int snum;
2323 fstring sharename;
2324 int errcode;
2325 WERROR werr = WERR_OK;
2327 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
2328 return False;
2330 /* check it's a supported varient */
2331 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
2332 return(False);
2334 *rparam_len = 4;
2335 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2336 *rdata_len = 0;
2338 if (!print_job_exists(sharename, jobid)) {
2339 errcode = NERR_JobNotFound;
2340 goto out;
2343 snum = lp_servicenumber( sharename);
2344 if (snum == -1) {
2345 errcode = NERR_DestNotFound;
2346 goto out;
2349 errcode = NERR_notsupported;
2351 switch (function) {
2352 case 81: /* delete */
2353 if (print_job_delete(&current_user, snum, jobid, &werr))
2354 errcode = NERR_Success;
2355 break;
2356 case 82: /* pause */
2357 if (print_job_pause(&current_user, snum, jobid, &werr))
2358 errcode = NERR_Success;
2359 break;
2360 case 83: /* resume */
2361 if (print_job_resume(&current_user, snum, jobid, &werr))
2362 errcode = NERR_Success;
2363 break;
2366 if (!W_ERROR_IS_OK(werr))
2367 errcode = W_ERROR_V(werr);
2369 out:
2370 SSVAL(*rparam,0,errcode);
2371 SSVAL(*rparam,2,0); /* converter word */
2373 return(True);
2376 /****************************************************************************
2377 Purge a print queue - or pause or resume it.
2378 ****************************************************************************/
2380 static BOOL api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid, char *param,char *data,
2381 int mdrcnt,int mprcnt,
2382 char **rdata,char **rparam,
2383 int *rdata_len,int *rparam_len)
2385 int function = SVAL(param,0);
2386 char *str1 = param+2;
2387 char *str2 = skip_string(str1,1);
2388 char *QueueName = skip_string(str2,1);
2389 int errcode = NERR_notsupported;
2390 int snum;
2391 WERROR werr = WERR_OK;
2393 /* check it's a supported varient */
2394 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
2395 return(False);
2397 *rparam_len = 4;
2398 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2399 *rdata_len = 0;
2401 snum = print_queue_snum(QueueName);
2403 if (snum == -1) {
2404 errcode = NERR_JobNotFound;
2405 goto out;
2408 switch (function) {
2409 case 74: /* Pause queue */
2410 if (print_queue_pause(&current_user, snum, &werr)) errcode = NERR_Success;
2411 break;
2412 case 75: /* Resume queue */
2413 if (print_queue_resume(&current_user, snum, &werr)) errcode = NERR_Success;
2414 break;
2415 case 103: /* Purge */
2416 if (print_queue_purge(&current_user, snum, &werr)) errcode = NERR_Success;
2417 break;
2420 if (!W_ERROR_IS_OK(werr)) errcode = W_ERROR_V(werr);
2422 out:
2423 SSVAL(*rparam,0,errcode);
2424 SSVAL(*rparam,2,0); /* converter word */
2426 return(True);
2429 /****************************************************************************
2430 set the property of a print job (undocumented?)
2431 ? function = 0xb -> set name of print job
2432 ? function = 0x6 -> move print job up/down
2433 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
2434 or <WWsTP> <WB21BB16B10zWWzDDz>
2435 ****************************************************************************/
2437 static int check_printjob_info(struct pack_desc* desc,
2438 int uLevel, char* id)
2440 desc->subformat = NULL;
2441 switch( uLevel ) {
2442 case 0: desc->format = "W"; break;
2443 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
2444 case 2: desc->format = "WWzWWDDzz"; break;
2445 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
2446 case 4: desc->format = "WWzWWDDzzzzzDDDDDDD"; break;
2447 default: return False;
2449 if (strcmp(desc->format,id) != 0) return False;
2450 return True;
2453 static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,char *data,
2454 int mdrcnt,int mprcnt,
2455 char **rdata,char **rparam,
2456 int *rdata_len,int *rparam_len)
2458 struct pack_desc desc;
2459 char *str1 = param+2;
2460 char *str2 = skip_string(str1,1);
2461 char *p = skip_string(str2,1);
2462 uint32 jobid;
2463 int snum;
2464 fstring sharename;
2465 int uLevel = SVAL(p,2);
2466 int function = SVAL(p,4);
2467 int place, errcode;
2469 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
2470 return False;
2471 *rparam_len = 4;
2472 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2474 if ( (snum = lp_servicenumber(sharename)) == -1 ) {
2475 DEBUG(0,("api_PrintJobInfo: unable to get service number from sharename [%s]\n",
2476 sharename));
2477 return False;
2480 *rdata_len = 0;
2482 /* check it's a supported varient */
2483 if ((strcmp(str1,"WWsTP")) ||
2484 (!check_printjob_info(&desc,uLevel,str2)))
2485 return(False);
2487 if (!print_job_exists(sharename, jobid)) {
2488 errcode=NERR_JobNotFound;
2489 goto out;
2492 errcode = NERR_notsupported;
2494 switch (function) {
2495 case 0x6:
2496 /* change job place in the queue,
2497 data gives the new place */
2498 place = SVAL(data,0);
2499 if (print_job_set_place(snum, jobid, place)) {
2500 errcode=NERR_Success;
2502 break;
2504 case 0xb:
2505 /* change print job name, data gives the name */
2506 if (print_job_set_name(snum, jobid, data)) {
2507 errcode=NERR_Success;
2509 break;
2511 default:
2512 return False;
2515 out:
2516 SSVALS(*rparam,0,errcode);
2517 SSVAL(*rparam,2,0); /* converter word */
2519 return(True);
2523 /****************************************************************************
2524 Get info about the server.
2525 ****************************************************************************/
2527 static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2528 int mdrcnt,int mprcnt,
2529 char **rdata,char **rparam,
2530 int *rdata_len,int *rparam_len)
2532 char *str1 = param+2;
2533 char *str2 = skip_string(str1,1);
2534 char *p = skip_string(str2,1);
2535 int uLevel = SVAL(p,0);
2536 char *p2;
2537 int struct_len;
2539 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
2541 /* check it's a supported varient */
2542 if (!prefix_ok(str1,"WrLh")) {
2543 return False;
2546 switch( uLevel ) {
2547 case 0:
2548 if (strcmp(str2,"B16") != 0) {
2549 return False;
2551 struct_len = 16;
2552 break;
2553 case 1:
2554 if (strcmp(str2,"B16BBDz") != 0) {
2555 return False;
2557 struct_len = 26;
2558 break;
2559 case 2:
2560 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")!= 0) {
2561 return False;
2563 struct_len = 134;
2564 break;
2565 case 3:
2566 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz") != 0) {
2567 return False;
2569 struct_len = 144;
2570 break;
2571 case 20:
2572 if (strcmp(str2,"DN") != 0) {
2573 return False;
2575 struct_len = 6;
2576 break;
2577 case 50:
2578 if (strcmp(str2,"B16BBDzWWzzz") != 0) {
2579 return False;
2581 struct_len = 42;
2582 break;
2583 default:
2584 return False;
2587 *rdata_len = mdrcnt;
2588 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
2590 p = *rdata;
2591 p2 = p + struct_len;
2592 if (uLevel != 20) {
2593 srvstr_push(NULL, p,get_local_machine_name(),16,
2594 STR_ASCII|STR_UPPER|STR_TERMINATE);
2596 p += 16;
2597 if (uLevel > 0) {
2598 struct srv_info_struct *servers=NULL;
2599 int i,count;
2600 pstring comment;
2601 uint32 servertype= lp_default_server_announce();
2603 push_ascii(comment,lp_serverstring(), MAX_SERVER_STRING_LENGTH,STR_TERMINATE);
2605 if ((count=get_server_info(SV_TYPE_ALL,&servers,lp_workgroup()))>0) {
2606 for (i=0;i<count;i++) {
2607 if (strequal(servers[i].name,get_local_machine_name())) {
2608 servertype = servers[i].type;
2609 push_ascii(comment,servers[i].comment,sizeof(pstring),STR_TERMINATE);
2614 SAFE_FREE(servers);
2616 SCVAL(p,0,lp_major_announce_version());
2617 SCVAL(p,1,lp_minor_announce_version());
2618 SIVAL(p,2,servertype);
2620 if (mdrcnt == struct_len) {
2621 SIVAL(p,6,0);
2622 } else {
2623 SIVAL(p,6,PTR_DIFF(p2,*rdata));
2624 standard_sub_conn(conn,comment,sizeof(comment));
2625 StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
2626 p2 = skip_string(p2,1);
2630 if (uLevel > 1) {
2631 return False; /* not yet implemented */
2634 *rdata_len = PTR_DIFF(p2,*rdata);
2636 *rparam_len = 6;
2637 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2638 SSVAL(*rparam,0,NERR_Success);
2639 SSVAL(*rparam,2,0); /* converter word */
2640 SSVAL(*rparam,4,*rdata_len);
2642 return True;
2645 /****************************************************************************
2646 Get info about the server.
2647 ****************************************************************************/
2649 static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2650 int mdrcnt,int mprcnt,
2651 char **rdata,char **rparam,
2652 int *rdata_len,int *rparam_len)
2654 char *str1 = param+2;
2655 char *str2 = skip_string(str1,1);
2656 char *p = skip_string(str2,1);
2657 char *p2;
2658 int level = SVAL(p,0);
2660 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
2662 *rparam_len = 6;
2663 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2665 /* check it's a supported varient */
2666 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz"))) {
2667 return False;
2670 *rdata_len = mdrcnt + 1024;
2671 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
2673 SSVAL(*rparam,0,NERR_Success);
2674 SSVAL(*rparam,2,0); /* converter word */
2676 p = *rdata;
2677 p2 = p + 22;
2679 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
2680 pstrcpy(p2,get_local_machine_name());
2681 strupper_m(p2);
2682 p2 = skip_string(p2,1);
2683 p += 4;
2685 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2686 pstrcpy(p2,current_user_info.smb_name);
2687 p2 = skip_string(p2,1);
2688 p += 4;
2690 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
2691 pstrcpy(p2,lp_workgroup());
2692 strupper_m(p2);
2693 p2 = skip_string(p2,1);
2694 p += 4;
2696 SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
2697 SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
2698 p += 2;
2700 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2701 pstrcpy(p2,lp_workgroup()); /* don't know. login domain?? */
2702 p2 = skip_string(p2,1);
2703 p += 4;
2705 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
2706 pstrcpy(p2,"");
2707 p2 = skip_string(p2,1);
2708 p += 4;
2710 *rdata_len = PTR_DIFF(p2,*rdata);
2712 SSVAL(*rparam,4,*rdata_len);
2714 return True;
2717 /****************************************************************************
2718 get info about a user
2720 struct user_info_11 {
2721 char usri11_name[21]; 0-20
2722 char usri11_pad; 21
2723 char *usri11_comment; 22-25
2724 char *usri11_usr_comment; 26-29
2725 unsigned short usri11_priv; 30-31
2726 unsigned long usri11_auth_flags; 32-35
2727 long usri11_password_age; 36-39
2728 char *usri11_homedir; 40-43
2729 char *usri11_parms; 44-47
2730 long usri11_last_logon; 48-51
2731 long usri11_last_logoff; 52-55
2732 unsigned short usri11_bad_pw_count; 56-57
2733 unsigned short usri11_num_logons; 58-59
2734 char *usri11_logon_server; 60-63
2735 unsigned short usri11_country_code; 64-65
2736 char *usri11_workstations; 66-69
2737 unsigned long usri11_max_storage; 70-73
2738 unsigned short usri11_units_per_week; 74-75
2739 unsigned char *usri11_logon_hours; 76-79
2740 unsigned short usri11_code_page; 80-81
2743 where:
2745 usri11_name specifies the user name for which information is retireved
2747 usri11_pad aligns the next data structure element to a word boundary
2749 usri11_comment is a null terminated ASCII comment
2751 usri11_user_comment is a null terminated ASCII comment about the user
2753 usri11_priv specifies the level of the privilege assigned to the user.
2754 The possible values are:
2756 Name Value Description
2757 USER_PRIV_GUEST 0 Guest privilege
2758 USER_PRIV_USER 1 User privilege
2759 USER_PRV_ADMIN 2 Administrator privilege
2761 usri11_auth_flags specifies the account operator privileges. The
2762 possible values are:
2764 Name Value Description
2765 AF_OP_PRINT 0 Print operator
2768 Leach, Naik [Page 28]
2772 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2775 AF_OP_COMM 1 Communications operator
2776 AF_OP_SERVER 2 Server operator
2777 AF_OP_ACCOUNTS 3 Accounts operator
2780 usri11_password_age specifies how many seconds have elapsed since the
2781 password was last changed.
2783 usri11_home_dir points to a null terminated ASCII string that contains
2784 the path name of the user's home directory.
2786 usri11_parms points to a null terminated ASCII string that is set
2787 aside for use by applications.
2789 usri11_last_logon specifies the time when the user last logged on.
2790 This value is stored as the number of seconds elapsed since
2791 00:00:00, January 1, 1970.
2793 usri11_last_logoff specifies the time when the user last logged off.
2794 This value is stored as the number of seconds elapsed since
2795 00:00:00, January 1, 1970. A value of 0 means the last logoff
2796 time is unknown.
2798 usri11_bad_pw_count specifies the number of incorrect passwords
2799 entered since the last successful logon.
2801 usri11_log1_num_logons specifies the number of times this user has
2802 logged on. A value of -1 means the number of logons is unknown.
2804 usri11_logon_server points to a null terminated ASCII string that
2805 contains the name of the server to which logon requests are sent.
2806 A null string indicates logon requests should be sent to the
2807 domain controller.
2809 usri11_country_code specifies the country code for the user's language
2810 of choice.
2812 usri11_workstations points to a null terminated ASCII string that
2813 contains the names of workstations the user may log on from.
2814 There may be up to 8 workstations, with the names separated by
2815 commas. A null strings indicates there are no restrictions.
2817 usri11_max_storage specifies the maximum amount of disk space the user
2818 can occupy. A value of 0xffffffff indicates there are no
2819 restrictions.
2821 usri11_units_per_week specifies the equal number of time units into
2822 which a week is divided. This value must be equal to 168.
2824 usri11_logon_hours points to a 21 byte (168 bits) string that
2825 specifies the time during which the user can log on. Each bit
2826 represents one unique hour in a week. The first bit (bit 0, word
2827 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
2831 Leach, Naik [Page 29]
2835 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2838 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
2839 are no restrictions.
2841 usri11_code_page specifies the code page for the user's language of
2842 choice
2844 All of the pointers in this data structure need to be treated
2845 specially. The pointer is a 32 bit pointer. The higher 16 bits need
2846 to be ignored. The converter word returned in the parameters section
2847 needs to be subtracted from the lower 16 bits to calculate an offset
2848 into the return buffer where this ASCII string resides.
2850 There is no auxiliary data in the response.
2852 ****************************************************************************/
2854 #define usri11_name 0
2855 #define usri11_pad 21
2856 #define usri11_comment 22
2857 #define usri11_usr_comment 26
2858 #define usri11_full_name 30
2859 #define usri11_priv 34
2860 #define usri11_auth_flags 36
2861 #define usri11_password_age 40
2862 #define usri11_homedir 44
2863 #define usri11_parms 48
2864 #define usri11_last_logon 52
2865 #define usri11_last_logoff 56
2866 #define usri11_bad_pw_count 60
2867 #define usri11_num_logons 62
2868 #define usri11_logon_server 64
2869 #define usri11_country_code 68
2870 #define usri11_workstations 70
2871 #define usri11_max_storage 74
2872 #define usri11_units_per_week 78
2873 #define usri11_logon_hours 80
2874 #define usri11_code_page 84
2875 #define usri11_end 86
2877 #define USER_PRIV_GUEST 0
2878 #define USER_PRIV_USER 1
2879 #define USER_PRIV_ADMIN 2
2881 #define AF_OP_PRINT 0
2882 #define AF_OP_COMM 1
2883 #define AF_OP_SERVER 2
2884 #define AF_OP_ACCOUNTS 3
2887 static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2888 int mdrcnt,int mprcnt,
2889 char **rdata,char **rparam,
2890 int *rdata_len,int *rparam_len)
2892 char *str1 = param+2;
2893 char *str2 = skip_string(str1,1);
2894 char *UserName = skip_string(str2,1);
2895 char *p = skip_string(UserName,1);
2896 int uLevel = SVAL(p,0);
2897 char *p2;
2898 const char *level_string;
2900 /* get NIS home of a previously validated user - simeon */
2901 /* With share level security vuid will always be zero.
2902 Don't depend on vuser being non-null !!. JRA */
2903 user_struct *vuser = get_valid_user_struct(vuid);
2904 if(vuser != NULL) {
2905 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid,
2906 vuser->user.unix_name));
2909 *rparam_len = 6;
2910 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2912 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
2914 /* check it's a supported variant */
2915 if (strcmp(str1,"zWrLh") != 0) {
2916 return False;
2918 switch( uLevel ) {
2919 case 0: level_string = "B21"; break;
2920 case 1: level_string = "B21BB16DWzzWz"; break;
2921 case 2: level_string = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
2922 case 10: level_string = "B21Bzzz"; break;
2923 case 11: level_string = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
2924 default: return False;
2927 if (strcmp(level_string,str2) != 0) {
2928 return False;
2931 *rdata_len = mdrcnt + 1024;
2932 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
2934 SSVAL(*rparam,0,NERR_Success);
2935 SSVAL(*rparam,2,0); /* converter word */
2937 p = *rdata;
2938 p2 = p + usri11_end;
2940 memset(p,0,21);
2941 fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
2943 if (uLevel > 0) {
2944 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
2945 *p2 = 0;
2948 if (uLevel >= 10) {
2949 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
2950 pstrcpy(p2,"Comment");
2951 p2 = skip_string(p2,1);
2953 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
2954 pstrcpy(p2,"UserComment");
2955 p2 = skip_string(p2,1);
2957 /* EEK! the cifsrap.txt doesn't have this in!!!! */
2958 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
2959 pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName));
2960 p2 = skip_string(p2,1);
2963 if (uLevel == 11) {
2964 /* modelled after NTAS 3.51 reply */
2965 SSVAL(p,usri11_priv,conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
2966 SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
2967 SIVALS(p,usri11_password_age,-1); /* password age */
2968 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
2969 pstrcpy(p2, vuser && vuser->homedir ? vuser->homedir : "");
2970 p2 = skip_string(p2,1);
2971 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
2972 pstrcpy(p2,"");
2973 p2 = skip_string(p2,1);
2974 SIVAL(p,usri11_last_logon,0); /* last logon */
2975 SIVAL(p,usri11_last_logoff,0); /* last logoff */
2976 SSVALS(p,usri11_bad_pw_count,-1); /* bad pw counts */
2977 SSVALS(p,usri11_num_logons,-1); /* num logons */
2978 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
2979 pstrcpy(p2,"\\\\*");
2980 p2 = skip_string(p2,1);
2981 SSVAL(p,usri11_country_code,0); /* country code */
2983 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
2984 pstrcpy(p2,"");
2985 p2 = skip_string(p2,1);
2987 SIVALS(p,usri11_max_storage,-1); /* max storage */
2988 SSVAL(p,usri11_units_per_week,168); /* units per week */
2989 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
2991 /* a simple way to get logon hours at all times. */
2992 memset(p2,0xff,21);
2993 SCVAL(p2,21,0); /* fix zero termination */
2994 p2 = skip_string(p2,1);
2996 SSVAL(p,usri11_code_page,0); /* code page */
2999 if (uLevel == 1 || uLevel == 2) {
3000 memset(p+22,' ',16); /* password */
3001 SIVALS(p,38,-1); /* password age */
3002 SSVAL(p,42,
3003 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
3004 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
3005 pstrcpy(p2, vuser && vuser->homedir ? vuser->homedir : "");
3006 p2 = skip_string(p2,1);
3007 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
3008 *p2++ = 0;
3009 SSVAL(p,52,0); /* flags */
3010 SIVAL(p,54,PTR_DIFF(p2,*rdata)); /* script_path */
3011 pstrcpy(p2,vuser && vuser->logon_script ? vuser->logon_script : "");
3012 p2 = skip_string(p2,1);
3013 if (uLevel == 2) {
3014 SIVAL(p,60,0); /* auth_flags */
3015 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
3016 pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName));
3017 p2 = skip_string(p2,1);
3018 SIVAL(p,68,0); /* urs_comment */
3019 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
3020 pstrcpy(p2,"");
3021 p2 = skip_string(p2,1);
3022 SIVAL(p,76,0); /* workstations */
3023 SIVAL(p,80,0); /* last_logon */
3024 SIVAL(p,84,0); /* last_logoff */
3025 SIVALS(p,88,-1); /* acct_expires */
3026 SIVALS(p,92,-1); /* max_storage */
3027 SSVAL(p,96,168); /* units_per_week */
3028 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
3029 memset(p2,-1,21);
3030 p2 += 21;
3031 SSVALS(p,102,-1); /* bad_pw_count */
3032 SSVALS(p,104,-1); /* num_logons */
3033 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
3034 pstrcpy(p2,"\\\\%L");
3035 standard_sub_conn(conn, p2,0);
3036 p2 = skip_string(p2,1);
3037 SSVAL(p,110,49); /* country_code */
3038 SSVAL(p,112,860); /* code page */
3042 *rdata_len = PTR_DIFF(p2,*rdata);
3044 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
3046 return(True);
3049 static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param,char *data,
3050 int mdrcnt,int mprcnt,
3051 char **rdata,char **rparam,
3052 int *rdata_len,int *rparam_len)
3054 char *str1 = param+2;
3055 char *str2 = skip_string(str1,1);
3056 char *p = skip_string(str2,1);
3057 int uLevel;
3058 struct pack_desc desc;
3059 char* name;
3060 /* With share level security vuid will always be zero.
3061 Don't depend on vuser being non-null !!. JRA */
3062 user_struct *vuser = get_valid_user_struct(vuid);
3064 if(vuser != NULL) {
3065 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid,
3066 vuser->user.unix_name));
3069 uLevel = SVAL(p,0);
3070 name = p + 2;
3072 memset((char *)&desc,'\0',sizeof(desc));
3074 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
3076 /* check it's a supported varient */
3077 if (strcmp(str1,"OOWb54WrLh") != 0) {
3078 return False;
3080 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) {
3081 return False;
3083 if (mdrcnt > 0) {
3084 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3087 desc.base = *rdata;
3088 desc.buflen = mdrcnt;
3089 desc.subformat = NULL;
3090 desc.format = str2;
3092 if (init_package(&desc,1,0)) {
3093 PACKI(&desc,"W",0); /* code */
3094 PACKS(&desc,"B21",name); /* eff. name */
3095 PACKS(&desc,"B",""); /* pad */
3096 PACKI(&desc,"W", conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
3097 PACKI(&desc,"D",0); /* auth flags XXX */
3098 PACKI(&desc,"W",0); /* num logons */
3099 PACKI(&desc,"W",0); /* bad pw count */
3100 PACKI(&desc,"D",0); /* last logon */
3101 PACKI(&desc,"D",-1); /* last logoff */
3102 PACKI(&desc,"D",-1); /* logoff time */
3103 PACKI(&desc,"D",-1); /* kickoff time */
3104 PACKI(&desc,"D",0); /* password age */
3105 PACKI(&desc,"D",0); /* password can change */
3106 PACKI(&desc,"D",-1); /* password must change */
3109 fstring mypath;
3110 fstrcpy(mypath,"\\\\");
3111 fstrcat(mypath,get_local_machine_name());
3112 strupper_m(mypath);
3113 PACKS(&desc,"z",mypath); /* computer */
3116 PACKS(&desc,"z",lp_workgroup());/* domain */
3117 PACKS(&desc,"z", vuser && vuser->logon_script ? vuser->logon_script :""); /* script path */
3118 PACKI(&desc,"D",0x00000000); /* reserved */
3121 *rdata_len = desc.usedlen;
3122 *rparam_len = 6;
3123 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3124 SSVALS(*rparam,0,desc.errcode);
3125 SSVAL(*rparam,2,0);
3126 SSVAL(*rparam,4,desc.neededlen);
3128 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
3130 return True;
3133 /****************************************************************************
3134 api_WAccessGetUserPerms
3135 ****************************************************************************/
3137 static BOOL api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid, char *param,char *data,
3138 int mdrcnt,int mprcnt,
3139 char **rdata,char **rparam,
3140 int *rdata_len,int *rparam_len)
3142 char *str1 = param+2;
3143 char *str2 = skip_string(str1,1);
3144 char *user = skip_string(str2,1);
3145 char *resource = skip_string(user,1);
3147 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
3149 /* check it's a supported varient */
3150 if (strcmp(str1,"zzh") != 0) {
3151 return False;
3153 if (strcmp(str2,"") != 0) {
3154 return False;
3157 *rparam_len = 6;
3158 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3159 SSVALS(*rparam,0,0); /* errorcode */
3160 SSVAL(*rparam,2,0); /* converter word */
3161 SSVAL(*rparam,4,0x7f); /* permission flags */
3163 return True;
3166 /****************************************************************************
3167 api_WPrintJobEnumerate
3168 ****************************************************************************/
3170 static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
3171 int mdrcnt,int mprcnt,
3172 char **rdata,char **rparam,
3173 int *rdata_len,int *rparam_len)
3175 char *str1 = param+2;
3176 char *str2 = skip_string(str1,1);
3177 char *p = skip_string(str2,1);
3178 int uLevel;
3179 int count;
3180 int i;
3181 int snum;
3182 fstring sharename;
3183 uint32 jobid;
3184 struct pack_desc desc;
3185 print_queue_struct *queue=NULL;
3186 print_status_struct status;
3187 char *tmpdata=NULL;
3189 uLevel = SVAL(p,2);
3191 memset((char *)&desc,'\0',sizeof(desc));
3192 memset((char *)&status,'\0',sizeof(status));
3194 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
3196 /* check it's a supported varient */
3197 if (strcmp(str1,"WWrLh") != 0) {
3198 return False;
3200 if (!check_printjob_info(&desc,uLevel,str2)) {
3201 return False;
3204 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid)) {
3205 return False;
3208 snum = lp_servicenumber( sharename);
3209 if (snum < 0 || !VALID_SNUM(snum)) {
3210 return(False);
3213 count = print_queue_status(snum,&queue,&status);
3214 for (i = 0; i < count; i++) {
3215 if (queue[i].job == jobid) {
3216 break;
3220 if (mdrcnt > 0) {
3221 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3222 desc.base = *rdata;
3223 desc.buflen = mdrcnt;
3224 } else {
3226 * Don't return data but need to get correct length
3227 * init_package will return wrong size if buflen=0
3229 desc.buflen = getlen(desc.format);
3230 desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen );
3233 if (init_package(&desc,1,0)) {
3234 if (i < count) {
3235 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
3236 *rdata_len = desc.usedlen;
3237 } else {
3238 desc.errcode = NERR_JobNotFound;
3239 *rdata_len = 0;
3243 *rparam_len = 6;
3244 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3245 SSVALS(*rparam,0,desc.errcode);
3246 SSVAL(*rparam,2,0);
3247 SSVAL(*rparam,4,desc.neededlen);
3249 SAFE_FREE(queue);
3250 SAFE_FREE(tmpdata);
3252 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
3254 return True;
3257 static BOOL api_WPrintJobEnumerate(connection_struct *conn,uint16 vuid, char *param,char *data,
3258 int mdrcnt,int mprcnt,
3259 char **rdata,char **rparam,
3260 int *rdata_len,int *rparam_len)
3262 char *str1 = param+2;
3263 char *str2 = skip_string(str1,1);
3264 char *p = skip_string(str2,1);
3265 char* name = p;
3266 int uLevel;
3267 int count;
3268 int i, succnt=0;
3269 int snum;
3270 struct pack_desc desc;
3271 print_queue_struct *queue=NULL;
3272 print_status_struct status;
3274 memset((char *)&desc,'\0',sizeof(desc));
3275 memset((char *)&status,'\0',sizeof(status));
3277 p = skip_string(p,1);
3278 uLevel = SVAL(p,0);
3280 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
3282 /* check it's a supported variant */
3283 if (strcmp(str1,"zWrLeh") != 0) {
3284 return False;
3287 if (uLevel > 2) {
3288 return False; /* defined only for uLevel 0,1,2 */
3291 if (!check_printjob_info(&desc,uLevel,str2)) {
3292 return False;
3295 snum = find_service(name);
3296 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) ) {
3297 return False;
3300 count = print_queue_status(snum,&queue,&status);
3301 if (mdrcnt > 0) {
3302 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3304 desc.base = *rdata;
3305 desc.buflen = mdrcnt;
3307 if (init_package(&desc,count,0)) {
3308 succnt = 0;
3309 for (i = 0; i < count; i++) {
3310 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
3311 if (desc.errcode == NERR_Success) {
3312 succnt = i+1;
3317 *rdata_len = desc.usedlen;
3319 *rparam_len = 8;
3320 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3321 SSVALS(*rparam,0,desc.errcode);
3322 SSVAL(*rparam,2,0);
3323 SSVAL(*rparam,4,succnt);
3324 SSVAL(*rparam,6,count);
3326 SAFE_FREE(queue);
3328 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
3330 return True;
3333 static int check_printdest_info(struct pack_desc* desc,
3334 int uLevel, char* id)
3336 desc->subformat = NULL;
3337 switch( uLevel ) {
3338 case 0:
3339 desc->format = "B9";
3340 break;
3341 case 1:
3342 desc->format = "B9B21WWzW";
3343 break;
3344 case 2:
3345 desc->format = "z";
3346 break;
3347 case 3:
3348 desc->format = "zzzWWzzzWW";
3349 break;
3350 default:
3351 return False;
3353 if (strcmp(desc->format,id) != 0) {
3354 return False;
3356 return True;
3359 static void fill_printdest_info(connection_struct *conn, int snum, int uLevel,
3360 struct pack_desc* desc)
3362 char buf[100];
3364 strncpy(buf,SERVICE(snum),sizeof(buf)-1);
3365 buf[sizeof(buf)-1] = 0;
3366 strupper_m(buf);
3368 if (uLevel <= 1) {
3369 PACKS(desc,"B9",buf); /* szName */
3370 if (uLevel == 1) {
3371 PACKS(desc,"B21",""); /* szUserName */
3372 PACKI(desc,"W",0); /* uJobId */
3373 PACKI(desc,"W",0); /* fsStatus */
3374 PACKS(desc,"z",""); /* pszStatus */
3375 PACKI(desc,"W",0); /* time */
3379 if (uLevel == 2 || uLevel == 3) {
3380 PACKS(desc,"z",buf); /* pszPrinterName */
3381 if (uLevel == 3) {
3382 PACKS(desc,"z",""); /* pszUserName */
3383 PACKS(desc,"z",""); /* pszLogAddr */
3384 PACKI(desc,"W",0); /* uJobId */
3385 PACKI(desc,"W",0); /* fsStatus */
3386 PACKS(desc,"z",""); /* pszStatus */
3387 PACKS(desc,"z",""); /* pszComment */
3388 PACKS(desc,"z","NULL"); /* pszDrivers */
3389 PACKI(desc,"W",0); /* time */
3390 PACKI(desc,"W",0); /* pad1 */
3395 static BOOL api_WPrintDestGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
3396 int mdrcnt,int mprcnt,
3397 char **rdata,char **rparam,
3398 int *rdata_len,int *rparam_len)
3400 char *str1 = param+2;
3401 char *str2 = skip_string(str1,1);
3402 char *p = skip_string(str2,1);
3403 char* PrinterName = p;
3404 int uLevel;
3405 struct pack_desc desc;
3406 int snum;
3407 char *tmpdata=NULL;
3409 memset((char *)&desc,'\0',sizeof(desc));
3411 p = skip_string(p,1);
3412 uLevel = SVAL(p,0);
3414 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
3416 /* check it's a supported varient */
3417 if (strcmp(str1,"zWrLh") != 0) {
3418 return False;
3420 if (!check_printdest_info(&desc,uLevel,str2)) {
3421 return False;
3424 snum = find_service(PrinterName);
3425 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) ) {
3426 *rdata_len = 0;
3427 desc.errcode = NERR_DestNotFound;
3428 desc.neededlen = 0;
3429 } else {
3430 if (mdrcnt > 0) {
3431 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3432 desc.base = *rdata;
3433 desc.buflen = mdrcnt;
3434 } else {
3436 * Don't return data but need to get correct length
3437 * init_package will return wrong size if buflen=0
3439 desc.buflen = getlen(desc.format);
3440 desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen );
3442 if (init_package(&desc,1,0)) {
3443 fill_printdest_info(conn,snum,uLevel,&desc);
3445 *rdata_len = desc.usedlen;
3448 *rparam_len = 6;
3449 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3450 SSVALS(*rparam,0,desc.errcode);
3451 SSVAL(*rparam,2,0);
3452 SSVAL(*rparam,4,desc.neededlen);
3454 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
3455 SAFE_FREE(tmpdata);
3457 return True;
3460 static BOOL api_WPrintDestEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3461 int mdrcnt,int mprcnt,
3462 char **rdata,char **rparam,
3463 int *rdata_len,int *rparam_len)
3465 char *str1 = param+2;
3466 char *str2 = skip_string(str1,1);
3467 char *p = skip_string(str2,1);
3468 int uLevel;
3469 int queuecnt;
3470 int i, n, succnt=0;
3471 struct pack_desc desc;
3472 int services = lp_numservices();
3474 memset((char *)&desc,'\0',sizeof(desc));
3476 uLevel = SVAL(p,0);
3478 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
3480 /* check it's a supported varient */
3481 if (strcmp(str1,"WrLeh") != 0) {
3482 return False;
3484 if (!check_printdest_info(&desc,uLevel,str2)) {
3485 return False;
3488 queuecnt = 0;
3489 for (i = 0; i < services; i++) {
3490 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
3491 queuecnt++;
3495 if (mdrcnt > 0) {
3496 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3499 desc.base = *rdata;
3500 desc.buflen = mdrcnt;
3501 if (init_package(&desc,queuecnt,0)) {
3502 succnt = 0;
3503 n = 0;
3504 for (i = 0; i < services; i++) {
3505 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
3506 fill_printdest_info(conn,i,uLevel,&desc);
3507 n++;
3508 if (desc.errcode == NERR_Success) {
3509 succnt = n;
3515 *rdata_len = desc.usedlen;
3517 *rparam_len = 8;
3518 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3519 SSVALS(*rparam,0,desc.errcode);
3520 SSVAL(*rparam,2,0);
3521 SSVAL(*rparam,4,succnt);
3522 SSVAL(*rparam,6,queuecnt);
3524 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
3526 return True;
3529 static BOOL api_WPrintDriverEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3530 int mdrcnt,int mprcnt,
3531 char **rdata,char **rparam,
3532 int *rdata_len,int *rparam_len)
3534 char *str1 = param+2;
3535 char *str2 = skip_string(str1,1);
3536 char *p = skip_string(str2,1);
3537 int uLevel;
3538 int succnt;
3539 struct pack_desc desc;
3541 memset((char *)&desc,'\0',sizeof(desc));
3543 uLevel = SVAL(p,0);
3545 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
3547 /* check it's a supported varient */
3548 if (strcmp(str1,"WrLeh") != 0) {
3549 return False;
3551 if (uLevel != 0 || strcmp(str2,"B41") != 0) {
3552 return False;
3555 if (mdrcnt > 0) {
3556 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3558 desc.base = *rdata;
3559 desc.buflen = mdrcnt;
3560 if (init_package(&desc,1,0)) {
3561 PACKS(&desc,"B41","NULL");
3564 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3566 *rdata_len = desc.usedlen;
3568 *rparam_len = 8;
3569 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3570 SSVALS(*rparam,0,desc.errcode);
3571 SSVAL(*rparam,2,0);
3572 SSVAL(*rparam,4,succnt);
3573 SSVAL(*rparam,6,1);
3575 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
3577 return True;
3580 static BOOL api_WPrintQProcEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3581 int mdrcnt,int mprcnt,
3582 char **rdata,char **rparam,
3583 int *rdata_len,int *rparam_len)
3585 char *str1 = param+2;
3586 char *str2 = skip_string(str1,1);
3587 char *p = skip_string(str2,1);
3588 int uLevel;
3589 int succnt;
3590 struct pack_desc desc;
3592 memset((char *)&desc,'\0',sizeof(desc));
3594 uLevel = SVAL(p,0);
3596 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
3598 /* check it's a supported varient */
3599 if (strcmp(str1,"WrLeh") != 0) {
3600 return False;
3602 if (uLevel != 0 || strcmp(str2,"B13") != 0) {
3603 return False;
3606 if (mdrcnt > 0) {
3607 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3609 desc.base = *rdata;
3610 desc.buflen = mdrcnt;
3611 desc.format = str2;
3612 if (init_package(&desc,1,0)) {
3613 PACKS(&desc,"B13","lpd");
3616 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3618 *rdata_len = desc.usedlen;
3620 *rparam_len = 8;
3621 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3622 SSVALS(*rparam,0,desc.errcode);
3623 SSVAL(*rparam,2,0);
3624 SSVAL(*rparam,4,succnt);
3625 SSVAL(*rparam,6,1);
3627 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
3629 return True;
3632 static BOOL api_WPrintPortEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3633 int mdrcnt,int mprcnt,
3634 char **rdata,char **rparam,
3635 int *rdata_len,int *rparam_len)
3637 char *str1 = param+2;
3638 char *str2 = skip_string(str1,1);
3639 char *p = skip_string(str2,1);
3640 int uLevel;
3641 int succnt;
3642 struct pack_desc desc;
3644 memset((char *)&desc,'\0',sizeof(desc));
3646 uLevel = SVAL(p,0);
3648 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
3650 /* check it's a supported varient */
3651 if (strcmp(str1,"WrLeh") != 0) {
3652 return False;
3654 if (uLevel != 0 || strcmp(str2,"B9") != 0) {
3655 return False;
3658 if (mdrcnt > 0) {
3659 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3661 memset((char *)&desc,'\0',sizeof(desc));
3662 desc.base = *rdata;
3663 desc.buflen = mdrcnt;
3664 desc.format = str2;
3665 if (init_package(&desc,1,0)) {
3666 PACKS(&desc,"B13","lp0");
3669 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3671 *rdata_len = desc.usedlen;
3673 *rparam_len = 8;
3674 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3675 SSVALS(*rparam,0,desc.errcode);
3676 SSVAL(*rparam,2,0);
3677 SSVAL(*rparam,4,succnt);
3678 SSVAL(*rparam,6,1);
3680 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
3682 return True;
3686 /****************************************************************************
3687 List open sessions
3688 ****************************************************************************/
3689 static BOOL api_RNetSessionEnum(connection_struct *conn,uint16 vuid, char *param, char *data,
3690 int mdrcnt,int mprcnt,
3691 char **rdata,char **rparam,
3692 int *rdata_len,int *rparam_len)
3695 char *str1 = param+2;
3696 char *str2 = skip_string(str1,1);
3697 char *p = skip_string(str2,1);
3698 int uLevel;
3699 struct pack_desc desc;
3700 struct sessionid *session_list;
3701 int i, num_sessions;
3703 memset((char *)&desc,'\0',sizeof(desc));
3705 uLevel = SVAL(p,0);
3707 DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel));
3708 DEBUG(7,("RNetSessionEnum req string=%s\n",str1));
3709 DEBUG(7,("RNetSessionEnum ret string=%s\n",str2));
3711 /* check it's a supported varient */
3712 if (strcmp(str1,RAP_NetSessionEnum_REQ) != 0) {
3713 return False;
3715 if (uLevel != 2 || strcmp(str2,RAP_SESSION_INFO_L2) != 0) {
3716 return False;
3719 num_sessions = list_sessions(&session_list);
3721 if (mdrcnt > 0) {
3722 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3724 memset((char *)&desc,'\0',sizeof(desc));
3725 desc.base = *rdata;
3726 desc.buflen = mdrcnt;
3727 desc.format = str2;
3728 if (!init_package(&desc,num_sessions,0)) {
3729 return False;
3732 for(i=0; i<num_sessions; i++) {
3733 PACKS(&desc, "z", session_list[i].remote_machine);
3734 PACKS(&desc, "z", session_list[i].username);
3735 PACKI(&desc, "W", 1); /* num conns */
3736 PACKI(&desc, "W", 0); /* num opens */
3737 PACKI(&desc, "W", 1); /* num users */
3738 PACKI(&desc, "D", 0); /* session time */
3739 PACKI(&desc, "D", 0); /* idle time */
3740 PACKI(&desc, "D", 0); /* flags */
3741 PACKS(&desc, "z", "Unknown Client"); /* client type string */
3744 *rdata_len = desc.usedlen;
3746 *rparam_len = 8;
3747 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3748 SSVALS(*rparam,0,desc.errcode);
3749 SSVAL(*rparam,2,0); /* converter */
3750 SSVAL(*rparam,4,num_sessions); /* count */
3752 DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc.errcode));
3754 return True;
3758 /****************************************************************************
3759 The buffer was too small.
3760 ****************************************************************************/
3762 static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param, char *data,
3763 int mdrcnt, int mprcnt,
3764 char **rdata, char **rparam,
3765 int *rdata_len, int *rparam_len)
3767 *rparam_len = MIN(*rparam_len,mprcnt);
3768 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3770 *rdata_len = 0;
3772 SSVAL(*rparam,0,NERR_BufTooSmall);
3774 DEBUG(3,("Supplied buffer too small in API command\n"));
3776 return True;
3779 /****************************************************************************
3780 The request is not supported.
3781 ****************************************************************************/
3783 static BOOL api_Unsupported(connection_struct *conn, uint16 vuid, char *param, char *data,
3784 int mdrcnt, int mprcnt,
3785 char **rdata, char **rparam,
3786 int *rdata_len, int *rparam_len)
3788 *rparam_len = 4;
3789 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3791 *rdata_len = 0;
3793 SSVAL(*rparam,0,NERR_notsupported);
3794 SSVAL(*rparam,2,0); /* converter word */
3796 DEBUG(3,("Unsupported API command\n"));
3798 return True;
3801 static const struct {
3802 const char *name;
3803 int id;
3804 BOOL (*fn)(connection_struct *,uint16,char *,char *,
3805 int,int,char **,char **,int *,int *);
3806 BOOL auth_user; /* Deny anonymous access? */
3807 } api_commands[] = {
3808 {"RNetShareEnum", RAP_WshareEnum, api_RNetShareEnum, True},
3809 {"RNetShareGetInfo", RAP_WshareGetInfo, api_RNetShareGetInfo},
3810 {"RNetShareAdd", RAP_WshareAdd, api_RNetShareAdd},
3811 {"RNetSessionEnum", RAP_WsessionEnum, api_RNetSessionEnum, True},
3812 {"RNetServerGetInfo", RAP_WserverGetInfo, api_RNetServerGetInfo},
3813 {"RNetGroupEnum", RAP_WGroupEnum, api_RNetGroupEnum, True},
3814 {"RNetGroupGetUsers", RAP_WGroupGetUsers, api_RNetGroupGetUsers, True},
3815 {"RNetUserEnum", RAP_WUserEnum, api_RNetUserEnum, True},
3816 {"RNetUserGetInfo", RAP_WUserGetInfo, api_RNetUserGetInfo},
3817 {"NetUserGetGroups", RAP_WUserGetGroups, api_NetUserGetGroups},
3818 {"NetWkstaGetInfo", RAP_WWkstaGetInfo, api_NetWkstaGetInfo},
3819 {"DosPrintQEnum", RAP_WPrintQEnum, api_DosPrintQEnum, True},
3820 {"DosPrintQGetInfo", RAP_WPrintQGetInfo, api_DosPrintQGetInfo},
3821 {"WPrintQueuePause", RAP_WPrintQPause, api_WPrintQueueCtrl},
3822 {"WPrintQueueResume", RAP_WPrintQContinue, api_WPrintQueueCtrl},
3823 {"WPrintJobEnumerate",RAP_WPrintJobEnum, api_WPrintJobEnumerate},
3824 {"WPrintJobGetInfo", RAP_WPrintJobGetInfo, api_WPrintJobGetInfo},
3825 {"RDosPrintJobDel", RAP_WPrintJobDel, api_RDosPrintJobDel},
3826 {"RDosPrintJobPause", RAP_WPrintJobPause, api_RDosPrintJobDel},
3827 {"RDosPrintJobResume",RAP_WPrintJobContinue, api_RDosPrintJobDel},
3828 {"WPrintDestEnum", RAP_WPrintDestEnum, api_WPrintDestEnum},
3829 {"WPrintDestGetInfo", RAP_WPrintDestGetInfo, api_WPrintDestGetInfo},
3830 {"NetRemoteTOD", RAP_NetRemoteTOD, api_NetRemoteTOD},
3831 {"WPrintQueuePurge", RAP_WPrintQPurge, api_WPrintQueueCtrl},
3832 {"NetServerEnum", RAP_NetServerEnum2, api_RNetServerEnum}, /* anon OK */
3833 {"WAccessGetUserPerms",RAP_WAccessGetUserPerms,api_WAccessGetUserPerms},
3834 {"SetUserPassword", RAP_WUserPasswordSet2, api_SetUserPassword},
3835 {"WWkstaUserLogon", RAP_WWkstaUserLogon, api_WWkstaUserLogon},
3836 {"PrintJobInfo", RAP_WPrintJobSetInfo, api_PrintJobInfo},
3837 {"WPrintDriverEnum", RAP_WPrintDriverEnum, api_WPrintDriverEnum},
3838 {"WPrintQProcEnum", RAP_WPrintQProcessorEnum,api_WPrintQProcEnum},
3839 {"WPrintPortEnum", RAP_WPrintPortEnum, api_WPrintPortEnum},
3840 {"SamOEMChangePassword",RAP_SamOEMChgPasswordUser2_P,api_SamOEMChangePassword}, /* anon OK */
3841 {NULL, -1, api_Unsupported}
3842 /* The following RAP calls are not implemented by Samba:
3844 RAP_WFileEnum2 - anon not OK
3849 /****************************************************************************
3850 Handle remote api calls
3851 ****************************************************************************/
3853 int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data,char *params,
3854 int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
3856 int api_command;
3857 char *rdata = NULL;
3858 char *rparam = NULL;
3859 int rdata_len = 0;
3860 int rparam_len = 0;
3861 BOOL reply=False;
3862 int i;
3864 if (!params) {
3865 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
3866 return 0;
3869 api_command = SVAL(params,0);
3871 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
3872 api_command,
3873 params+2,
3874 skip_string(params+2,1),
3875 tdscnt,tpscnt,mdrcnt,mprcnt));
3877 for (i=0;api_commands[i].name;i++) {
3878 if (api_commands[i].id == api_command && api_commands[i].fn) {
3879 DEBUG(3,("Doing %s\n",api_commands[i].name));
3880 break;
3884 /* Check whether this api call can be done anonymously */
3886 if (api_commands[i].auth_user && lp_restrict_anonymous()) {
3887 user_struct *user = get_valid_user_struct(vuid);
3889 if (!user || user->guest) {
3890 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
3894 rdata = (char *)SMB_MALLOC(1024);
3895 if (rdata) {
3896 memset(rdata,'\0',1024);
3899 rparam = (char *)SMB_MALLOC(1024);
3900 if (rparam) {
3901 memset(rparam,'\0',1024);
3904 if(!rdata || !rparam) {
3905 DEBUG(0,("api_reply: malloc fail !\n"));
3906 SAFE_FREE(rdata);
3907 SAFE_FREE(rparam);
3908 return -1;
3911 reply = api_commands[i].fn(conn,vuid,params,data,mdrcnt,mprcnt,
3912 &rdata,&rparam,&rdata_len,&rparam_len);
3915 if (rdata_len > mdrcnt || rparam_len > mprcnt) {
3916 reply = api_TooSmall(conn,vuid,params,data,mdrcnt,mprcnt,
3917 &rdata,&rparam,&rdata_len,&rparam_len);
3920 /* if we get False back then it's actually unsupported */
3921 if (!reply) {
3922 api_Unsupported(conn,vuid,params,data,mdrcnt,mprcnt,
3923 &rdata,&rparam,&rdata_len,&rparam_len);
3926 send_trans_reply(outbuf, rparam, rparam_len, rdata, rdata_len, False);
3928 SAFE_FREE(rdata);
3929 SAFE_FREE(rparam);
3930 return -1;