r16344: Allow to set passwords directly when creating users via "net rpc user
[Samba.git] / source / smbd / lanman.c
blobe4531d8ae980f8d56ab991713fd38a62cad5e61a
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 if (!*rparam) {
802 return False;
804 SSVALS(*rparam,0,ERRunknownlevel);
805 SSVAL(*rparam,2,0);
806 SSVAL(*rparam,4,0);
807 return(True);
810 snum = find_service(QueueName);
811 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
812 return False;
814 if (uLevel==52) {
815 count = get_printerdrivernumber(snum);
816 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count));
817 } else {
818 count = print_queue_status(snum, &queue,&status);
821 if (mdrcnt > 0) {
822 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
823 if (!*rdata) {
824 return False;
826 desc.base = *rdata;
827 desc.buflen = mdrcnt;
828 } else {
830 * Don't return data but need to get correct length
831 * init_package will return wrong size if buflen=0
833 desc.buflen = getlen(desc.format);
834 desc.base = tmpdata = (char *) SMB_MALLOC (desc.buflen);
837 if (init_package(&desc,1,count)) {
838 desc.subcount = count;
839 fill_printq_info(conn,snum,uLevel,&desc,count,queue,&status);
842 *rdata_len = desc.usedlen;
845 * We must set the return code to ERRbuftoosmall
846 * in order to support lanman style printing with Win NT/2k
847 * clients --jerry
849 if (!mdrcnt && lp_disable_spoolss())
850 desc.errcode = ERRbuftoosmall;
852 *rdata_len = desc.usedlen;
853 *rparam_len = 6;
854 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
855 if (!*rparam) {
856 return False;
858 SSVALS(*rparam,0,desc.errcode);
859 SSVAL(*rparam,2,0);
860 SSVAL(*rparam,4,desc.neededlen);
862 DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode));
864 SAFE_FREE(queue);
865 SAFE_FREE(tmpdata);
867 return(True);
870 /****************************************************************************
871 View list of all print jobs on all queues.
872 ****************************************************************************/
874 static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid, char* param, char* data,
875 int mdrcnt, int mprcnt,
876 char **rdata, char** rparam,
877 int *rdata_len, int *rparam_len)
879 char *param_format = param+2;
880 char *output_format1 = skip_string(param_format,1);
881 char *p = skip_string(output_format1,1);
882 unsigned int uLevel = SVAL(p,0);
883 char *output_format2 = p + 4;
884 int services = lp_numservices();
885 int i, n;
886 struct pack_desc desc;
887 print_queue_struct **queue = NULL;
888 print_status_struct *status = NULL;
889 int *subcntarr = NULL;
890 int queuecnt = 0, subcnt = 0, succnt = 0;
892 memset((char *)&desc,'\0',sizeof(desc));
894 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
896 if (!prefix_ok(param_format,"WrLeh")) {
897 return False;
899 if (!check_printq_info(&desc,uLevel,output_format1,output_format2)) {
901 * Patch from Scott Moomaw <scott@bridgewater.edu>
902 * to return the 'invalid info level' error if an
903 * unknown level was requested.
905 *rdata_len = 0;
906 *rparam_len = 6;
907 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
908 if (!*rparam) {
909 return False;
911 SSVALS(*rparam,0,ERRunknownlevel);
912 SSVAL(*rparam,2,0);
913 SSVAL(*rparam,4,0);
914 return(True);
917 for (i = 0; i < services; i++) {
918 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
919 queuecnt++;
923 if((queue = SMB_MALLOC_ARRAY(print_queue_struct*, queuecnt)) == NULL) {
924 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
925 goto err;
927 memset(queue,0,queuecnt*sizeof(print_queue_struct*));
928 if((status = SMB_MALLOC_ARRAY(print_status_struct,queuecnt)) == NULL) {
929 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
930 goto err;
932 memset(status,0,queuecnt*sizeof(print_status_struct));
933 if((subcntarr = SMB_MALLOC_ARRAY(int,queuecnt)) == NULL) {
934 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
935 goto err;
938 subcnt = 0;
939 n = 0;
940 for (i = 0; i < services; i++) {
941 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
942 subcntarr[n] = print_queue_status(i, &queue[n],&status[n]);
943 subcnt += subcntarr[n];
944 n++;
948 if (mdrcnt > 0) {
949 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
950 if (!*rdata) {
951 goto err;
954 desc.base = *rdata;
955 desc.buflen = mdrcnt;
957 if (init_package(&desc,queuecnt,subcnt)) {
958 n = 0;
959 succnt = 0;
960 for (i = 0; i < services; i++) {
961 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
962 fill_printq_info(conn,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]);
963 n++;
964 if (desc.errcode == NERR_Success) {
965 succnt = n;
971 SAFE_FREE(subcntarr);
973 *rdata_len = desc.usedlen;
974 *rparam_len = 8;
975 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
976 if (!*rparam) {
977 goto err;
979 SSVALS(*rparam,0,desc.errcode);
980 SSVAL(*rparam,2,0);
981 SSVAL(*rparam,4,succnt);
982 SSVAL(*rparam,6,queuecnt);
984 for (i = 0; i < queuecnt; i++) {
985 if (queue) {
986 SAFE_FREE(queue[i]);
990 SAFE_FREE(queue);
991 SAFE_FREE(status);
993 return True;
995 err:
997 SAFE_FREE(subcntarr);
998 for (i = 0; i < queuecnt; i++) {
999 if (queue) {
1000 SAFE_FREE(queue[i]);
1003 SAFE_FREE(queue);
1004 SAFE_FREE(status);
1006 return False;
1009 /****************************************************************************
1010 Get info level for a server list query.
1011 ****************************************************************************/
1013 static BOOL check_server_info(int uLevel, char* id)
1015 switch( uLevel ) {
1016 case 0:
1017 if (strcmp(id,"B16") != 0) {
1018 return False;
1020 break;
1021 case 1:
1022 if (strcmp(id,"B16BBDz") != 0) {
1023 return False;
1025 break;
1026 default:
1027 return False;
1029 return True;
1032 struct srv_info_struct {
1033 fstring name;
1034 uint32 type;
1035 fstring comment;
1036 fstring domain;
1037 BOOL server_added;
1040 /*******************************************************************
1041 Get server info lists from the files saved by nmbd. Return the
1042 number of entries.
1043 ******************************************************************/
1045 static int get_server_info(uint32 servertype,
1046 struct srv_info_struct **servers,
1047 const char *domain)
1049 int count=0;
1050 int alloced=0;
1051 char **lines;
1052 BOOL local_list_only;
1053 int i;
1055 lines = file_lines_load(lock_path(SERVER_LIST), NULL, 0);
1056 if (!lines) {
1057 DEBUG(4,("Can't open %s - %s\n",lock_path(SERVER_LIST),strerror(errno)));
1058 return 0;
1061 /* request for everything is code for request all servers */
1062 if (servertype == SV_TYPE_ALL) {
1063 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1066 local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY);
1068 DEBUG(4,("Servertype search: %8x\n",servertype));
1070 for (i=0;lines[i];i++) {
1071 fstring stype;
1072 struct srv_info_struct *s;
1073 const char *ptr = lines[i];
1074 BOOL ok = True;
1076 if (!*ptr) {
1077 continue;
1080 if (count == alloced) {
1081 alloced += 10;
1082 *servers = SMB_REALLOC_ARRAY(*servers,struct srv_info_struct, alloced);
1083 if (!*servers) {
1084 DEBUG(0,("get_server_info: failed to enlarge servers info struct!\n"));
1085 file_lines_free(lines);
1086 return 0;
1088 memset((char *)((*servers)+count),'\0',sizeof(**servers)*(alloced-count));
1090 s = &(*servers)[count];
1092 if (!next_token(&ptr,s->name, NULL, sizeof(s->name))) {
1093 continue;
1095 if (!next_token(&ptr,stype, NULL, sizeof(stype))) {
1096 continue;
1098 if (!next_token(&ptr,s->comment, NULL, sizeof(s->comment))) {
1099 continue;
1101 if (!next_token(&ptr,s->domain, NULL, sizeof(s->domain))) {
1102 /* this allows us to cope with an old nmbd */
1103 fstrcpy(s->domain,lp_workgroup());
1106 if (sscanf(stype,"%X",&s->type) != 1) {
1107 DEBUG(4,("r:host file "));
1108 ok = False;
1111 /* Filter the servers/domains we return based on what was asked for. */
1113 /* Check to see if we are being asked for a local list only. */
1114 if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) {
1115 DEBUG(4,("r: local list only"));
1116 ok = False;
1119 /* doesn't match up: don't want it */
1120 if (!(servertype & s->type)) {
1121 DEBUG(4,("r:serv type "));
1122 ok = False;
1125 if ((servertype & SV_TYPE_DOMAIN_ENUM) !=
1126 (s->type & SV_TYPE_DOMAIN_ENUM)) {
1127 DEBUG(4,("s: dom mismatch "));
1128 ok = False;
1131 if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM)) {
1132 ok = False;
1135 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1136 s->type &= ~SV_TYPE_LOCAL_LIST_ONLY;
1138 if (ok) {
1139 DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1140 s->name, s->type, s->comment, s->domain));
1141 s->server_added = True;
1142 count++;
1143 } else {
1144 DEBUG(4,("%20s %8x %25s %15s\n",
1145 s->name, s->type, s->comment, s->domain));
1149 file_lines_free(lines);
1150 return count;
1153 /*******************************************************************
1154 Fill in a server info structure.
1155 ******************************************************************/
1157 static int fill_srv_info(struct srv_info_struct *service,
1158 int uLevel, char **buf, int *buflen,
1159 char **stringbuf, int *stringspace, char *baseaddr)
1161 int struct_len;
1162 char* p;
1163 char* p2;
1164 int l2;
1165 int len;
1167 switch (uLevel) {
1168 case 0:
1169 struct_len = 16;
1170 break;
1171 case 1:
1172 struct_len = 26;
1173 break;
1174 default:
1175 return -1;
1178 if (!buf) {
1179 len = 0;
1180 switch (uLevel) {
1181 case 1:
1182 len = strlen(service->comment)+1;
1183 break;
1186 if (buflen) {
1187 *buflen = struct_len;
1189 if (stringspace) {
1190 *stringspace = len;
1192 return struct_len + len;
1195 len = struct_len;
1196 p = *buf;
1197 if (*buflen < struct_len) {
1198 return -1;
1200 if (stringbuf) {
1201 p2 = *stringbuf;
1202 l2 = *stringspace;
1203 } else {
1204 p2 = p + struct_len;
1205 l2 = *buflen - struct_len;
1207 if (!baseaddr) {
1208 baseaddr = p;
1211 switch (uLevel) {
1212 case 0:
1213 push_ascii(p,service->name, MAX_NETBIOSNAME_LEN, STR_TERMINATE);
1214 break;
1216 case 1:
1217 push_ascii(p,service->name,MAX_NETBIOSNAME_LEN, STR_TERMINATE);
1218 SIVAL(p,18,service->type);
1219 SIVAL(p,22,PTR_DIFF(p2,baseaddr));
1220 len += CopyAndAdvance(&p2,service->comment,&l2);
1221 break;
1224 if (stringbuf) {
1225 *buf = p + struct_len;
1226 *buflen -= struct_len;
1227 *stringbuf = p2;
1228 *stringspace = l2;
1229 } else {
1230 *buf = p2;
1231 *buflen -= len;
1233 return len;
1237 static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
1239 return(strcmp(s1->name,s2->name));
1242 /****************************************************************************
1243 View list of servers available (or possibly domains). The info is
1244 extracted from lists saved by nmbd on the local host.
1245 ****************************************************************************/
1247 static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid, char *param, char *data,
1248 int mdrcnt, int mprcnt, char **rdata,
1249 char **rparam, int *rdata_len, int *rparam_len)
1251 char *str1 = param+2;
1252 char *str2 = skip_string(str1,1);
1253 char *p = skip_string(str2,1);
1254 int uLevel = SVAL(p,0);
1255 int buf_len = SVAL(p,2);
1256 uint32 servertype = IVAL(p,4);
1257 char *p2;
1258 int data_len, fixed_len, string_len;
1259 int f_len = 0, s_len = 0;
1260 struct srv_info_struct *servers=NULL;
1261 int counted=0,total=0;
1262 int i,missed;
1263 fstring domain;
1264 BOOL domain_request;
1265 BOOL local_request;
1267 /* If someone sets all the bits they don't really mean to set
1268 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1269 known servers. */
1271 if (servertype == SV_TYPE_ALL) {
1272 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1275 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1276 any other bit (they may just set this bit on it's own) they
1277 want all the locally seen servers. However this bit can be
1278 set on its own so set the requested servers to be
1279 ALL - DOMAIN_ENUM. */
1281 if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM)) {
1282 servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
1285 domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
1286 local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
1288 p += 8;
1290 if (!prefix_ok(str1,"WrLehD")) {
1291 return False;
1293 if (!check_server_info(uLevel,str2)) {
1294 return False;
1297 DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1298 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1299 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1301 if (strcmp(str1, "WrLehDz") == 0) {
1302 pull_ascii_fstring(domain, p);
1303 } else {
1304 fstrcpy(domain, lp_workgroup());
1307 if (lp_browse_list()) {
1308 total = get_server_info(servertype,&servers,domain);
1311 data_len = fixed_len = string_len = 0;
1312 missed = 0;
1314 if (total > 0) {
1315 qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
1319 char *lastname=NULL;
1321 for (i=0;i<total;i++) {
1322 struct srv_info_struct *s = &servers[i];
1324 if (lastname && strequal(lastname,s->name)) {
1325 continue;
1327 lastname = s->name;
1328 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1329 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1330 s->name, s->type, s->comment, s->domain));
1332 if (data_len <= buf_len) {
1333 counted++;
1334 fixed_len += f_len;
1335 string_len += s_len;
1336 } else {
1337 missed++;
1342 *rdata_len = fixed_len + string_len;
1343 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
1344 if (!*rdata) {
1345 return False;
1347 memset(*rdata,'\0',*rdata_len);
1349 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1350 p = *rdata;
1351 f_len = fixed_len;
1352 s_len = string_len;
1355 char *lastname=NULL;
1356 int count2 = counted;
1358 for (i = 0; i < total && count2;i++) {
1359 struct srv_info_struct *s = &servers[i];
1361 if (lastname && strequal(lastname,s->name)) {
1362 continue;
1364 lastname = s->name;
1365 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1366 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
1367 s->name, s->type, s->comment, s->domain));
1368 count2--;
1372 *rparam_len = 8;
1373 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1374 if (!*rparam) {
1375 return False;
1377 SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata));
1378 SSVAL(*rparam,2,0);
1379 SSVAL(*rparam,4,counted);
1380 SSVAL(*rparam,6,counted+missed);
1382 SAFE_FREE(servers);
1384 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
1385 domain,uLevel,counted,counted+missed));
1387 return True;
1390 /****************************************************************************
1391 command 0x34 - suspected of being a "Lookup Names" stub api
1392 ****************************************************************************/
1394 static BOOL api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid, char *param, char *data,
1395 int mdrcnt, int mprcnt, char **rdata,
1396 char **rparam, int *rdata_len, int *rparam_len)
1398 char *str1 = param+2;
1399 char *str2 = skip_string(str1,1);
1400 char *p = skip_string(str2,1);
1401 int uLevel = SVAL(p,0);
1402 int buf_len = SVAL(p,2);
1403 int counted=0;
1404 int missed=0;
1406 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1407 str1, str2, p, uLevel, buf_len));
1409 if (!prefix_ok(str1,"zWrLeh")) {
1410 return False;
1413 *rdata_len = 0;
1415 *rparam_len = 8;
1416 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1417 if (!*rparam) {
1418 return False;
1421 SSVAL(*rparam,0,0x08AC); /* informational warning message */
1422 SSVAL(*rparam,2,0);
1423 SSVAL(*rparam,4,counted);
1424 SSVAL(*rparam,6,counted+missed);
1426 return True;
1429 /****************************************************************************
1430 get info about a share
1431 ****************************************************************************/
1433 static BOOL check_share_info(int uLevel, char* id)
1435 switch( uLevel ) {
1436 case 0:
1437 if (strcmp(id,"B13") != 0) {
1438 return False;
1440 break;
1441 case 1:
1442 if (strcmp(id,"B13BWz") != 0) {
1443 return False;
1445 break;
1446 case 2:
1447 if (strcmp(id,"B13BWzWWWzB9B") != 0) {
1448 return False;
1450 break;
1451 case 91:
1452 if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) {
1453 return False;
1455 break;
1456 default:
1457 return False;
1459 return True;
1462 static int fill_share_info(connection_struct *conn, int snum, int uLevel,
1463 char** buf, int* buflen,
1464 char** stringbuf, int* stringspace, char* baseaddr)
1466 int struct_len;
1467 char* p;
1468 char* p2;
1469 int l2;
1470 int len;
1472 switch( uLevel ) {
1473 case 0:
1474 struct_len = 13;
1475 break;
1476 case 1:
1477 struct_len = 20;
1478 break;
1479 case 2:
1480 struct_len = 40;
1481 break;
1482 case 91:
1483 struct_len = 68;
1484 break;
1485 default:
1486 return -1;
1490 if (!buf) {
1491 len = 0;
1493 if (uLevel > 0) {
1494 len += StrlenExpanded(conn,snum,lp_comment(snum));
1496 if (uLevel > 1) {
1497 len += strlen(lp_pathname(snum)) + 1;
1499 if (buflen) {
1500 *buflen = struct_len;
1502 if (stringspace) {
1503 *stringspace = len;
1505 return struct_len + len;
1508 len = struct_len;
1509 p = *buf;
1510 if ((*buflen) < struct_len) {
1511 return -1;
1514 if (stringbuf) {
1515 p2 = *stringbuf;
1516 l2 = *stringspace;
1517 } else {
1518 p2 = p + struct_len;
1519 l2 = (*buflen) - struct_len;
1522 if (!baseaddr) {
1523 baseaddr = p;
1526 push_ascii(p,lp_servicename(snum),13, STR_TERMINATE);
1528 if (uLevel > 0) {
1529 int type;
1531 SCVAL(p,13,0);
1532 type = STYPE_DISKTREE;
1533 if (lp_print_ok(snum)) {
1534 type = STYPE_PRINTQ;
1536 if (strequal("IPC",lp_fstype(snum))) {
1537 type = STYPE_IPC;
1539 SSVAL(p,14,type); /* device type */
1540 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1541 len += CopyExpanded(conn,snum,&p2,lp_comment(snum),&l2);
1544 if (uLevel > 1) {
1545 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1546 SSVALS(p,22,-1); /* max uses */
1547 SSVAL(p,24,1); /* current uses */
1548 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1549 len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1550 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1553 if (uLevel > 2) {
1554 memset(p+40,0,SHPWLEN+2);
1555 SSVAL(p,50,0);
1556 SIVAL(p,52,0);
1557 SSVAL(p,56,0);
1558 SSVAL(p,58,0);
1559 SIVAL(p,60,0);
1560 SSVAL(p,64,0);
1561 SSVAL(p,66,0);
1564 if (stringbuf) {
1565 (*buf) = p + struct_len;
1566 (*buflen) -= struct_len;
1567 (*stringbuf) = p2;
1568 (*stringspace) = l2;
1569 } else {
1570 (*buf) = p2;
1571 (*buflen) -= len;
1574 return len;
1577 static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
1578 int mdrcnt,int mprcnt,
1579 char **rdata,char **rparam,
1580 int *rdata_len,int *rparam_len)
1582 char *str1 = param+2;
1583 char *str2 = skip_string(str1,1);
1584 char *netname = skip_string(str2,1);
1585 char *p = skip_string(netname,1);
1586 int uLevel = SVAL(p,0);
1587 int snum = find_service(netname);
1589 if (snum < 0) {
1590 return False;
1593 /* check it's a supported varient */
1594 if (!prefix_ok(str1,"zWrLh")) {
1595 return False;
1597 if (!check_share_info(uLevel,str2)) {
1598 return False;
1601 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
1602 if (!*rdata) {
1603 return False;
1605 p = *rdata;
1606 *rdata_len = fill_share_info(conn,snum,uLevel,&p,&mdrcnt,0,0,0);
1607 if (*rdata_len < 0) {
1608 return False;
1611 *rparam_len = 6;
1612 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1613 if (!*rparam) {
1614 return False;
1616 SSVAL(*rparam,0,NERR_Success);
1617 SSVAL(*rparam,2,0); /* converter word */
1618 SSVAL(*rparam,4,*rdata_len);
1620 return True;
1623 /****************************************************************************
1624 View the list of available shares.
1626 This function is the server side of the NetShareEnum() RAP call.
1627 It fills the return buffer with share names and share comments.
1628 Note that the return buffer normally (in all known cases) allows only
1629 twelve byte strings for share names (plus one for a nul terminator).
1630 Share names longer than 12 bytes must be skipped.
1631 ****************************************************************************/
1633 static BOOL api_RNetShareEnum( connection_struct *conn,
1634 uint16 vuid,
1635 char *param,
1636 char *data,
1637 int mdrcnt,
1638 int mprcnt,
1639 char **rdata,
1640 char **rparam,
1641 int *rdata_len,
1642 int *rparam_len )
1644 char *str1 = param+2;
1645 char *str2 = skip_string(str1,1);
1646 char *p = skip_string(str2,1);
1647 int uLevel = SVAL(p,0);
1648 int buf_len = SVAL(p,2);
1649 char *p2;
1650 int count = 0;
1651 int total=0,counted=0;
1652 BOOL missed = False;
1653 int i;
1654 int data_len, fixed_len, string_len;
1655 int f_len = 0, s_len = 0;
1657 if (!prefix_ok(str1,"WrLeh")) {
1658 return False;
1660 if (!check_share_info(uLevel,str2)) {
1661 return False;
1664 /* Ensure all the usershares are loaded. */
1665 become_root();
1666 count = load_usershare_shares();
1667 unbecome_root();
1669 data_len = fixed_len = string_len = 0;
1670 for (i=0;i<count;i++) {
1671 fstring servicename_dos;
1672 if (!(lp_browseable(i) && lp_snum_ok(i))) {
1673 continue;
1675 push_ascii_fstring(servicename_dos, lp_servicename(i));
1676 /* Maximum name length = 13. */
1677 if( lp_browseable( i ) && lp_snum_ok( i ) && (strlen(servicename_dos) < 13)) {
1678 total++;
1679 data_len += fill_share_info(conn,i,uLevel,0,&f_len,0,&s_len,0);
1680 if (data_len <= buf_len) {
1681 counted++;
1682 fixed_len += f_len;
1683 string_len += s_len;
1684 } else {
1685 missed = True;
1690 *rdata_len = fixed_len + string_len;
1691 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
1692 if (!*rdata) {
1693 return False;
1695 memset(*rdata,0,*rdata_len);
1697 p2 = (*rdata) + fixed_len; /* auxiliary data (strings) will go here */
1698 p = *rdata;
1699 f_len = fixed_len;
1700 s_len = string_len;
1702 for( i = 0; i < count; i++ ) {
1703 fstring servicename_dos;
1704 if (!(lp_browseable(i) && lp_snum_ok(i))) {
1705 continue;
1708 push_ascii_fstring(servicename_dos, lp_servicename(i));
1709 if (lp_browseable(i) && lp_snum_ok(i) && (strlen(servicename_dos) < 13)) {
1710 if (fill_share_info( conn,i,uLevel,&p,&f_len,&p2,&s_len,*rdata ) < 0) {
1711 break;
1716 *rparam_len = 8;
1717 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1718 if (!*rparam) {
1719 return False;
1721 SSVAL(*rparam,0,missed ? ERRmoredata : NERR_Success);
1722 SSVAL(*rparam,2,0);
1723 SSVAL(*rparam,4,counted);
1724 SSVAL(*rparam,6,total);
1726 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
1727 counted,total,uLevel,
1728 buf_len,*rdata_len,mdrcnt));
1730 return True;
1733 /****************************************************************************
1734 Add a share
1735 ****************************************************************************/
1737 static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid, char *param,char *data,
1738 int mdrcnt,int mprcnt,
1739 char **rdata,char **rparam,
1740 int *rdata_len,int *rparam_len)
1742 char *str1 = param+2;
1743 char *str2 = skip_string(str1,1);
1744 char *p = skip_string(str2,1);
1745 int uLevel = SVAL(p,0);
1746 fstring sharename;
1747 fstring comment;
1748 pstring pathname;
1749 char *command, *cmdname;
1750 unsigned int offset;
1751 int snum;
1752 int res = ERRunsup;
1754 /* check it's a supported varient */
1755 if (!prefix_ok(str1,RAP_WShareAdd_REQ)) {
1756 return False;
1758 if (!check_share_info(uLevel,str2)) {
1759 return False;
1761 if (uLevel != 2) {
1762 return False;
1765 pull_ascii_fstring(sharename,data);
1766 snum = find_service(sharename);
1767 if (snum >= 0) { /* already exists */
1768 res = ERRfilexists;
1769 goto error_exit;
1772 /* only support disk share adds */
1773 if (SVAL(data,14)!=STYPE_DISKTREE) {
1774 return False;
1777 offset = IVAL(data, 16);
1778 if (offset >= mdrcnt) {
1779 res = ERRinvalidparam;
1780 goto error_exit;
1783 pull_ascii_fstring(comment, offset? (data+offset) : "");
1785 offset = IVAL(data, 26);
1787 if (offset >= mdrcnt) {
1788 res = ERRinvalidparam;
1789 goto error_exit;
1792 pull_ascii_pstring(pathname, offset? (data+offset) : "");
1794 string_replace(sharename, '"', ' ');
1795 string_replace(pathname, '"', ' ');
1796 string_replace(comment, '"', ' ');
1798 cmdname = lp_add_share_cmd();
1800 if (!cmdname || *cmdname == '\0') {
1801 return False;
1804 asprintf(&command, "%s \"%s\" \"%s\" \"%s\" \"%s\"",
1805 lp_add_share_cmd(), dyn_CONFIGFILE, sharename, pathname, comment);
1807 if (command) {
1808 DEBUG(10,("api_RNetShareAdd: Running [%s]\n", command ));
1810 if ((res = smbrun(command, NULL)) != 0) {
1811 DEBUG(1,("api_RNetShareAdd: Running [%s] returned (%d)\n", command, res ));
1812 SAFE_FREE(command);
1813 res = ERRnoaccess;
1814 goto error_exit;
1815 } else {
1816 SAFE_FREE(command);
1817 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
1819 } else {
1820 return False;
1823 *rparam_len = 6;
1824 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1825 if (!*rparam) {
1826 return False;
1828 SSVAL(*rparam,0,NERR_Success);
1829 SSVAL(*rparam,2,0); /* converter word */
1830 SSVAL(*rparam,4,*rdata_len);
1831 *rdata_len = 0;
1833 return True;
1835 error_exit:
1837 *rparam_len = 4;
1838 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1839 if (!*rparam) {
1840 return False;
1842 *rdata_len = 0;
1843 SSVAL(*rparam,0,res);
1844 SSVAL(*rparam,2,0);
1845 return True;
1848 /****************************************************************************
1849 view list of groups available
1850 ****************************************************************************/
1852 static BOOL api_RNetGroupEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
1853 int mdrcnt,int mprcnt,
1854 char **rdata,char **rparam,
1855 int *rdata_len,int *rparam_len)
1857 int i;
1858 int errflags=0;
1859 int resume_context, cli_buf_size;
1860 char *str1 = param+2;
1861 char *str2 = skip_string(str1,1);
1862 char *p = skip_string(str2,1);
1864 struct pdb_search *search;
1865 struct samr_displayentry *entries;
1867 int num_entries;
1869 if (strcmp(str1,"WrLeh") != 0) {
1870 return False;
1873 /* parameters
1874 * W-> resume context (number of users to skip)
1875 * r -> return parameter pointer to receive buffer
1876 * L -> length of receive buffer
1877 * e -> return parameter number of entries
1878 * h -> return parameter total number of users
1881 if (strcmp("B21",str2) != 0) {
1882 return False;
1885 /* get list of domain groups SID_DOMAIN_GRP=2 */
1886 become_root();
1887 search = pdb_search_groups();
1888 unbecome_root();
1890 if (search == NULL) {
1891 DEBUG(3,("api_RNetGroupEnum:failed to get group list"));
1892 return False;
1895 resume_context = SVAL(p,0);
1896 cli_buf_size=SVAL(p+2,0);
1897 DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: "
1898 "%d\n", resume_context, cli_buf_size));
1900 become_root();
1901 num_entries = pdb_search_entries(search, resume_context, 0xffffffff,
1902 &entries);
1903 unbecome_root();
1905 *rdata_len = cli_buf_size;
1906 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
1907 if (!*rdata) {
1908 return False;
1911 p = *rdata;
1913 for(i=0; i<num_entries; i++) {
1914 fstring name;
1915 fstrcpy(name, entries[i].account_name);
1916 if( ((PTR_DIFF(p,*rdata)+21) <= *rdata_len) ) {
1917 /* truncate the name at 21 chars. */
1918 memcpy(p, name, 21);
1919 DEBUG(10,("adding entry %d group %s\n", i, p));
1920 p += 21;
1921 p += 5; /* Both NT4 and W2k3SP1 do padding here.
1922 No idea why... */
1923 } else {
1924 /* set overflow error */
1925 DEBUG(3,("overflow on entry %d group %s\n", i, name));
1926 errflags=234;
1927 break;
1931 pdb_search_destroy(search);
1933 *rdata_len = PTR_DIFF(p,*rdata);
1935 *rparam_len = 8;
1936 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1937 if (!*rparam) {
1938 return False;
1940 SSVAL(*rparam, 0, errflags);
1941 SSVAL(*rparam, 2, 0); /* converter word */
1942 SSVAL(*rparam, 4, i); /* is this right?? */
1943 SSVAL(*rparam, 6, resume_context+num_entries); /* is this right?? */
1945 return(True);
1948 /*******************************************************************
1949 Get groups that a user is a member of.
1950 ******************************************************************/
1952 static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *param,char *data,
1953 int mdrcnt,int mprcnt,
1954 char **rdata,char **rparam,
1955 int *rdata_len,int *rparam_len)
1957 char *str1 = param+2;
1958 char *str2 = skip_string(str1,1);
1959 char *UserName = skip_string(str2,1);
1960 char *p = skip_string(UserName,1);
1961 int uLevel = SVAL(p,0);
1962 const char *level_string;
1963 int count=0;
1964 struct samu *sampw = NULL;
1965 BOOL ret = False;
1966 DOM_SID *sids;
1967 gid_t *gids;
1968 size_t num_groups;
1969 size_t i;
1970 NTSTATUS result;
1971 DOM_SID user_sid;
1972 enum SID_NAME_USE type;
1973 TALLOC_CTX *mem_ctx;
1975 *rparam_len = 8;
1976 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
1977 if (!*rparam) {
1978 return False;
1981 /* check it's a supported varient */
1983 if ( strcmp(str1,"zWrLeh") != 0 )
1984 return False;
1986 switch( uLevel ) {
1987 case 0:
1988 level_string = "B21";
1989 break;
1990 default:
1991 return False;
1994 if (strcmp(level_string,str2) != 0)
1995 return False;
1997 *rdata_len = mdrcnt + 1024;
1998 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
1999 if (!*rdata) {
2000 return False;
2002 SSVAL(*rparam,0,NERR_Success);
2003 SSVAL(*rparam,2,0); /* converter word */
2005 p = *rdata;
2007 mem_ctx = talloc_new(NULL);
2008 if (mem_ctx == NULL) {
2009 DEBUG(0, ("talloc_new failed\n"));
2010 return False;
2013 if ( !(sampw = samu_new(mem_ctx)) ) {
2014 DEBUG(0, ("samu_new() failed!\n"));
2015 TALLOC_FREE(mem_ctx);
2016 return False;
2019 /* Lookup the user information; This should only be one of
2020 our accounts (not remote domains) */
2022 become_root(); /* ROOT BLOCK */
2024 if (!lookup_name(mem_ctx, UserName, LOOKUP_NAME_ALL,
2025 NULL, NULL, &user_sid, &type)) {
2026 DEBUG(10, ("lookup_name(%s) failed\n", UserName));
2027 goto done;
2030 if (type != SID_NAME_USER) {
2031 DEBUG(10, ("%s is a %s, not a user\n", UserName,
2032 sid_type_lookup(type)));
2033 goto done;
2036 if ( !pdb_getsampwsid(sampw, &user_sid) ) {
2037 DEBUG(10, ("pdb_getsampwsid(%s) failed for user %s\n",
2038 sid_string_static(&user_sid), UserName));
2039 goto done;
2042 gids = NULL;
2043 sids = NULL;
2044 num_groups = 0;
2046 result = pdb_enum_group_memberships(mem_ctx, sampw,
2047 &sids, &gids, &num_groups);
2049 if (!NT_STATUS_IS_OK(result)) {
2050 DEBUG(10, ("pdb_enum_group_memberships failed for %s\n",
2051 UserName));
2052 goto done;
2055 for (i=0; i<num_groups; i++) {
2057 const char *grp_name;
2059 if ( lookup_sid(mem_ctx, &sids[i], NULL, &grp_name, NULL) ) {
2060 pstrcpy(p, grp_name);
2061 p += 21;
2062 count++;
2066 *rdata_len = PTR_DIFF(p,*rdata);
2068 SSVAL(*rparam,4,count); /* is this right?? */
2069 SSVAL(*rparam,6,count); /* is this right?? */
2071 ret = True;
2073 done:
2074 unbecome_root(); /* END ROOT BLOCK */
2076 TALLOC_FREE(mem_ctx);
2078 return ret;
2081 /*******************************************************************
2082 Get all users.
2083 ******************************************************************/
2085 static BOOL api_RNetUserEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
2086 int mdrcnt,int mprcnt,
2087 char **rdata,char **rparam,
2088 int *rdata_len,int *rparam_len)
2090 int count_sent=0;
2091 int num_users=0;
2092 int errflags=0;
2093 int i, resume_context, cli_buf_size;
2094 struct pdb_search *search;
2095 struct samr_displayentry *users;
2097 char *str1 = param+2;
2098 char *str2 = skip_string(str1,1);
2099 char *p = skip_string(str2,1);
2101 if (strcmp(str1,"WrLeh") != 0)
2102 return False;
2103 /* parameters
2104 * W-> resume context (number of users to skip)
2105 * r -> return parameter pointer to receive buffer
2106 * L -> length of receive buffer
2107 * e -> return parameter number of entries
2108 * h -> return parameter total number of users
2111 resume_context = SVAL(p,0);
2112 cli_buf_size=SVAL(p+2,0);
2113 DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n",
2114 resume_context, cli_buf_size));
2116 *rparam_len = 8;
2117 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2118 if (!*rparam) {
2119 return False;
2122 /* check it's a supported varient */
2123 if (strcmp("B21",str2) != 0)
2124 return False;
2126 *rdata_len = cli_buf_size;
2127 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
2128 if (!*rdata) {
2129 return False;
2132 p = *rdata;
2134 become_root();
2135 search = pdb_search_users(ACB_NORMAL);
2136 unbecome_root();
2137 if (search == NULL) {
2138 DEBUG(0, ("api_RNetUserEnum:unable to open sam database.\n"));
2139 return False;
2142 become_root();
2143 num_users = pdb_search_entries(search, resume_context, 0xffffffff,
2144 &users);
2145 unbecome_root();
2147 errflags=NERR_Success;
2149 for (i=0; i<num_users; i++) {
2150 const char *name = users[i].account_name;
2152 if(((PTR_DIFF(p,*rdata)+21)<=*rdata_len)&&(strlen(name)<=21)) {
2153 pstrcpy(p,name);
2154 DEBUG(10,("api_RNetUserEnum:adding entry %d username "
2155 "%s\n",count_sent,p));
2156 p += 21;
2157 count_sent++;
2158 } else {
2159 /* set overflow error */
2160 DEBUG(10,("api_RNetUserEnum:overflow on entry %d "
2161 "username %s\n",count_sent,name));
2162 errflags=234;
2163 break;
2167 pdb_search_destroy(search);
2169 *rdata_len = PTR_DIFF(p,*rdata);
2171 SSVAL(*rparam,0,errflags);
2172 SSVAL(*rparam,2,0); /* converter word */
2173 SSVAL(*rparam,4,count_sent); /* is this right?? */
2174 SSVAL(*rparam,6,num_users); /* is this right?? */
2176 return True;
2179 /****************************************************************************
2180 Get the time of day info.
2181 ****************************************************************************/
2183 static BOOL api_NetRemoteTOD(connection_struct *conn,uint16 vuid, char *param,char *data,
2184 int mdrcnt,int mprcnt,
2185 char **rdata,char **rparam,
2186 int *rdata_len,int *rparam_len)
2188 struct tm *t;
2189 time_t unixdate = time(NULL);
2190 char *p;
2192 *rparam_len = 4;
2193 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2194 if (!*rparam) {
2195 return False;
2198 *rdata_len = 21;
2199 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
2200 if (!*rdata) {
2201 return False;
2204 SSVAL(*rparam,0,NERR_Success);
2205 SSVAL(*rparam,2,0); /* converter word */
2207 p = *rdata;
2209 srv_put_dos_date3(p,0,unixdate); /* this is the time that is looked at
2210 by NT in a "net time" operation,
2211 it seems to ignore the one below */
2213 /* the client expects to get localtime, not GMT, in this bit
2214 (I think, this needs testing) */
2215 t = localtime(&unixdate);
2216 if (!t) {
2217 return False;
2220 SIVAL(p,4,0); /* msecs ? */
2221 SCVAL(p,8,t->tm_hour);
2222 SCVAL(p,9,t->tm_min);
2223 SCVAL(p,10,t->tm_sec);
2224 SCVAL(p,11,0); /* hundredths of seconds */
2225 SSVALS(p,12,get_time_zone(unixdate)/60); /* timezone in minutes from GMT */
2226 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
2227 SCVAL(p,16,t->tm_mday);
2228 SCVAL(p,17,t->tm_mon + 1);
2229 SSVAL(p,18,1900+t->tm_year);
2230 SCVAL(p,20,t->tm_wday);
2232 return True;
2235 /****************************************************************************
2236 Set the user password.
2237 *****************************************************************************/
2239 static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param,char *data,
2240 int mdrcnt,int mprcnt,
2241 char **rdata,char **rparam,
2242 int *rdata_len,int *rparam_len)
2244 char *p = skip_string(param+2,2);
2245 fstring user;
2246 fstring pass1,pass2;
2248 pull_ascii_fstring(user,p);
2250 p = skip_string(p,1);
2252 memset(pass1,'\0',sizeof(pass1));
2253 memset(pass2,'\0',sizeof(pass2));
2254 memcpy(pass1,p,16);
2255 memcpy(pass2,p+16,16);
2257 *rparam_len = 4;
2258 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2259 if (!*rparam) {
2260 return False;
2263 *rdata_len = 0;
2265 SSVAL(*rparam,0,NERR_badpass);
2266 SSVAL(*rparam,2,0); /* converter word */
2268 DEBUG(3,("Set password for <%s>\n",user));
2271 * Attempt to verify the old password against smbpasswd entries
2272 * Win98 clients send old and new password in plaintext for this call.
2276 auth_serversupplied_info *server_info = NULL;
2277 DATA_BLOB password = data_blob(pass1, strlen(pass1)+1);
2279 if (NT_STATUS_IS_OK(check_plaintext_password(user,password,&server_info))) {
2281 become_root();
2282 if (NT_STATUS_IS_OK(change_oem_password(server_info->sam_account, pass1, pass2, False, NULL))) {
2283 SSVAL(*rparam,0,NERR_Success);
2285 unbecome_root();
2287 TALLOC_FREE(server_info);
2289 data_blob_clear_free(&password);
2293 * If the plaintext change failed, attempt
2294 * the old encrypted method. NT will generate this
2295 * after trying the samr method. Note that this
2296 * method is done as a last resort as this
2297 * password change method loses the NT password hash
2298 * and cannot change the UNIX password as no plaintext
2299 * is received.
2302 if(SVAL(*rparam,0) != NERR_Success) {
2303 struct samu *hnd = NULL;
2305 if (check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &hnd)) {
2306 become_root();
2307 if (change_lanman_password(hnd,(uchar *)pass2)) {
2308 SSVAL(*rparam,0,NERR_Success);
2310 unbecome_root();
2311 TALLOC_FREE(hnd);
2315 memset((char *)pass1,'\0',sizeof(fstring));
2316 memset((char *)pass2,'\0',sizeof(fstring));
2318 return(True);
2321 /****************************************************************************
2322 Set the user password (SamOEM version - gets plaintext).
2323 ****************************************************************************/
2325 static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, char *param,char *data,
2326 int mdrcnt,int mprcnt,
2327 char **rdata,char **rparam,
2328 int *rdata_len,int *rparam_len)
2330 fstring user;
2331 char *p = param + 2;
2332 *rparam_len = 2;
2333 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2334 if (!*rparam) {
2335 return False;
2338 *rdata_len = 0;
2340 SSVAL(*rparam,0,NERR_badpass);
2343 * Check the parameter definition is correct.
2346 if(!strequal(param + 2, "zsT")) {
2347 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", param + 2));
2348 return False;
2350 p = skip_string(p, 1);
2352 if(!strequal(p, "B516B16")) {
2353 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p));
2354 return False;
2356 p = skip_string(p,1);
2357 p += pull_ascii_fstring(user,p);
2359 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user));
2362 * Pass the user through the NT -> unix user mapping
2363 * function.
2366 (void)map_username(user);
2368 if (NT_STATUS_IS_OK(pass_oem_change(user, (uchar*) data, (uchar *)&data[516], NULL, NULL, NULL))) {
2369 SSVAL(*rparam,0,NERR_Success);
2372 return(True);
2375 /****************************************************************************
2376 delete a print job
2377 Form: <W> <>
2378 ****************************************************************************/
2380 static BOOL api_RDosPrintJobDel(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 *p = skip_string(str2,1);
2389 uint32 jobid;
2390 int snum;
2391 fstring sharename;
2392 int errcode;
2393 WERROR werr = WERR_OK;
2395 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
2396 return False;
2398 /* check it's a supported varient */
2399 if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
2400 return(False);
2402 *rparam_len = 4;
2403 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2404 if (!*rparam) {
2405 return False;
2407 *rdata_len = 0;
2409 if (!print_job_exists(sharename, jobid)) {
2410 errcode = NERR_JobNotFound;
2411 goto out;
2414 snum = lp_servicenumber( sharename);
2415 if (snum == -1) {
2416 errcode = NERR_DestNotFound;
2417 goto out;
2420 errcode = NERR_notsupported;
2422 switch (function) {
2423 case 81: /* delete */
2424 if (print_job_delete(&current_user, snum, jobid, &werr))
2425 errcode = NERR_Success;
2426 break;
2427 case 82: /* pause */
2428 if (print_job_pause(&current_user, snum, jobid, &werr))
2429 errcode = NERR_Success;
2430 break;
2431 case 83: /* resume */
2432 if (print_job_resume(&current_user, snum, jobid, &werr))
2433 errcode = NERR_Success;
2434 break;
2437 if (!W_ERROR_IS_OK(werr))
2438 errcode = W_ERROR_V(werr);
2440 out:
2441 SSVAL(*rparam,0,errcode);
2442 SSVAL(*rparam,2,0); /* converter word */
2444 return(True);
2447 /****************************************************************************
2448 Purge a print queue - or pause or resume it.
2449 ****************************************************************************/
2451 static BOOL api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid, char *param,char *data,
2452 int mdrcnt,int mprcnt,
2453 char **rdata,char **rparam,
2454 int *rdata_len,int *rparam_len)
2456 int function = SVAL(param,0);
2457 char *str1 = param+2;
2458 char *str2 = skip_string(str1,1);
2459 char *QueueName = skip_string(str2,1);
2460 int errcode = NERR_notsupported;
2461 int snum;
2462 WERROR werr = WERR_OK;
2464 /* check it's a supported varient */
2465 if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
2466 return(False);
2468 *rparam_len = 4;
2469 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2470 if (!*rparam) {
2471 return False;
2473 *rdata_len = 0;
2475 snum = print_queue_snum(QueueName);
2477 if (snum == -1) {
2478 errcode = NERR_JobNotFound;
2479 goto out;
2482 switch (function) {
2483 case 74: /* Pause queue */
2484 if (print_queue_pause(&current_user, snum, &werr)) errcode = NERR_Success;
2485 break;
2486 case 75: /* Resume queue */
2487 if (print_queue_resume(&current_user, snum, &werr)) errcode = NERR_Success;
2488 break;
2489 case 103: /* Purge */
2490 if (print_queue_purge(&current_user, snum, &werr)) errcode = NERR_Success;
2491 break;
2494 if (!W_ERROR_IS_OK(werr)) errcode = W_ERROR_V(werr);
2496 out:
2497 SSVAL(*rparam,0,errcode);
2498 SSVAL(*rparam,2,0); /* converter word */
2500 return(True);
2503 /****************************************************************************
2504 set the property of a print job (undocumented?)
2505 ? function = 0xb -> set name of print job
2506 ? function = 0x6 -> move print job up/down
2507 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
2508 or <WWsTP> <WB21BB16B10zWWzDDz>
2509 ****************************************************************************/
2511 static int check_printjob_info(struct pack_desc* desc,
2512 int uLevel, char* id)
2514 desc->subformat = NULL;
2515 switch( uLevel ) {
2516 case 0: desc->format = "W"; break;
2517 case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
2518 case 2: desc->format = "WWzWWDDzz"; break;
2519 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
2520 case 4: desc->format = "WWzWWDDzzzzzDDDDDDD"; break;
2521 default: return False;
2523 if (strcmp(desc->format,id) != 0) return False;
2524 return True;
2527 static BOOL api_PrintJobInfo(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 struct pack_desc desc;
2533 char *str1 = param+2;
2534 char *str2 = skip_string(str1,1);
2535 char *p = skip_string(str2,1);
2536 uint32 jobid;
2537 int snum;
2538 fstring sharename;
2539 int uLevel = SVAL(p,2);
2540 int function = SVAL(p,4);
2541 int place, errcode;
2543 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
2544 return False;
2545 *rparam_len = 4;
2546 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2547 if (!*rparam) {
2548 return False;
2551 if ( (snum = lp_servicenumber(sharename)) == -1 ) {
2552 DEBUG(0,("api_PrintJobInfo: unable to get service number from sharename [%s]\n",
2553 sharename));
2554 return False;
2557 *rdata_len = 0;
2559 /* check it's a supported varient */
2560 if ((strcmp(str1,"WWsTP")) ||
2561 (!check_printjob_info(&desc,uLevel,str2)))
2562 return(False);
2564 if (!print_job_exists(sharename, jobid)) {
2565 errcode=NERR_JobNotFound;
2566 goto out;
2569 errcode = NERR_notsupported;
2571 switch (function) {
2572 case 0x6:
2573 /* change job place in the queue,
2574 data gives the new place */
2575 place = SVAL(data,0);
2576 if (print_job_set_place(snum, jobid, place)) {
2577 errcode=NERR_Success;
2579 break;
2581 case 0xb:
2582 /* change print job name, data gives the name */
2583 if (print_job_set_name(snum, jobid, data)) {
2584 errcode=NERR_Success;
2586 break;
2588 default:
2589 return False;
2592 out:
2593 SSVALS(*rparam,0,errcode);
2594 SSVAL(*rparam,2,0); /* converter word */
2596 return(True);
2600 /****************************************************************************
2601 Get info about the server.
2602 ****************************************************************************/
2604 static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2605 int mdrcnt,int mprcnt,
2606 char **rdata,char **rparam,
2607 int *rdata_len,int *rparam_len)
2609 char *str1 = param+2;
2610 char *str2 = skip_string(str1,1);
2611 char *p = skip_string(str2,1);
2612 int uLevel = SVAL(p,0);
2613 char *p2;
2614 int struct_len;
2616 DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
2618 /* check it's a supported varient */
2619 if (!prefix_ok(str1,"WrLh")) {
2620 return False;
2623 switch( uLevel ) {
2624 case 0:
2625 if (strcmp(str2,"B16") != 0) {
2626 return False;
2628 struct_len = 16;
2629 break;
2630 case 1:
2631 if (strcmp(str2,"B16BBDz") != 0) {
2632 return False;
2634 struct_len = 26;
2635 break;
2636 case 2:
2637 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")!= 0) {
2638 return False;
2640 struct_len = 134;
2641 break;
2642 case 3:
2643 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz") != 0) {
2644 return False;
2646 struct_len = 144;
2647 break;
2648 case 20:
2649 if (strcmp(str2,"DN") != 0) {
2650 return False;
2652 struct_len = 6;
2653 break;
2654 case 50:
2655 if (strcmp(str2,"B16BBDzWWzzz") != 0) {
2656 return False;
2658 struct_len = 42;
2659 break;
2660 default:
2661 return False;
2664 *rdata_len = mdrcnt;
2665 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
2666 if (!*rdata) {
2667 return False;
2670 p = *rdata;
2671 p2 = p + struct_len;
2672 if (uLevel != 20) {
2673 srvstr_push(NULL, p,get_local_machine_name(),16,
2674 STR_ASCII|STR_UPPER|STR_TERMINATE);
2676 p += 16;
2677 if (uLevel > 0) {
2678 struct srv_info_struct *servers=NULL;
2679 int i,count;
2680 pstring comment;
2681 uint32 servertype= lp_default_server_announce();
2683 push_ascii(comment,lp_serverstring(), MAX_SERVER_STRING_LENGTH,STR_TERMINATE);
2685 if ((count=get_server_info(SV_TYPE_ALL,&servers,lp_workgroup()))>0) {
2686 for (i=0;i<count;i++) {
2687 if (strequal(servers[i].name,get_local_machine_name())) {
2688 servertype = servers[i].type;
2689 push_ascii(comment,servers[i].comment,sizeof(pstring),STR_TERMINATE);
2694 SAFE_FREE(servers);
2696 SCVAL(p,0,lp_major_announce_version());
2697 SCVAL(p,1,lp_minor_announce_version());
2698 SIVAL(p,2,servertype);
2700 if (mdrcnt == struct_len) {
2701 SIVAL(p,6,0);
2702 } else {
2703 SIVAL(p,6,PTR_DIFF(p2,*rdata));
2704 standard_sub_conn(conn,comment,sizeof(comment));
2705 StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
2706 p2 = skip_string(p2,1);
2710 if (uLevel > 1) {
2711 return False; /* not yet implemented */
2714 *rdata_len = PTR_DIFF(p2,*rdata);
2716 *rparam_len = 6;
2717 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2718 if (!*rparam) {
2719 return False;
2721 SSVAL(*rparam,0,NERR_Success);
2722 SSVAL(*rparam,2,0); /* converter word */
2723 SSVAL(*rparam,4,*rdata_len);
2725 return True;
2728 /****************************************************************************
2729 Get info about the server.
2730 ****************************************************************************/
2732 static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2733 int mdrcnt,int mprcnt,
2734 char **rdata,char **rparam,
2735 int *rdata_len,int *rparam_len)
2737 char *str1 = param+2;
2738 char *str2 = skip_string(str1,1);
2739 char *p = skip_string(str2,1);
2740 char *p2;
2741 int level = SVAL(p,0);
2743 DEBUG(4,("NetWkstaGetInfo level %d\n",level));
2745 *rparam_len = 6;
2746 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
2747 if (!*rparam) {
2748 return False;
2751 /* check it's a supported varient */
2752 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz"))) {
2753 return False;
2756 *rdata_len = mdrcnt + 1024;
2757 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
2758 if (!*rdata) {
2759 return False;
2762 SSVAL(*rparam,0,NERR_Success);
2763 SSVAL(*rparam,2,0); /* converter word */
2765 p = *rdata;
2766 p2 = p + 22;
2768 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
2769 pstrcpy(p2,get_local_machine_name());
2770 strupper_m(p2);
2771 p2 = skip_string(p2,1);
2772 p += 4;
2774 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2775 pstrcpy(p2,current_user_info.smb_name);
2776 p2 = skip_string(p2,1);
2777 p += 4;
2779 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
2780 pstrcpy(p2,lp_workgroup());
2781 strupper_m(p2);
2782 p2 = skip_string(p2,1);
2783 p += 4;
2785 SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
2786 SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
2787 p += 2;
2789 SIVAL(p,0,PTR_DIFF(p2,*rdata));
2790 pstrcpy(p2,lp_workgroup()); /* don't know. login domain?? */
2791 p2 = skip_string(p2,1);
2792 p += 4;
2794 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
2795 pstrcpy(p2,"");
2796 p2 = skip_string(p2,1);
2797 p += 4;
2799 *rdata_len = PTR_DIFF(p2,*rdata);
2801 SSVAL(*rparam,4,*rdata_len);
2803 return True;
2806 /****************************************************************************
2807 get info about a user
2809 struct user_info_11 {
2810 char usri11_name[21]; 0-20
2811 char usri11_pad; 21
2812 char *usri11_comment; 22-25
2813 char *usri11_usr_comment; 26-29
2814 unsigned short usri11_priv; 30-31
2815 unsigned long usri11_auth_flags; 32-35
2816 long usri11_password_age; 36-39
2817 char *usri11_homedir; 40-43
2818 char *usri11_parms; 44-47
2819 long usri11_last_logon; 48-51
2820 long usri11_last_logoff; 52-55
2821 unsigned short usri11_bad_pw_count; 56-57
2822 unsigned short usri11_num_logons; 58-59
2823 char *usri11_logon_server; 60-63
2824 unsigned short usri11_country_code; 64-65
2825 char *usri11_workstations; 66-69
2826 unsigned long usri11_max_storage; 70-73
2827 unsigned short usri11_units_per_week; 74-75
2828 unsigned char *usri11_logon_hours; 76-79
2829 unsigned short usri11_code_page; 80-81
2832 where:
2834 usri11_name specifies the user name for which information is retireved
2836 usri11_pad aligns the next data structure element to a word boundary
2838 usri11_comment is a null terminated ASCII comment
2840 usri11_user_comment is a null terminated ASCII comment about the user
2842 usri11_priv specifies the level of the privilege assigned to the user.
2843 The possible values are:
2845 Name Value Description
2846 USER_PRIV_GUEST 0 Guest privilege
2847 USER_PRIV_USER 1 User privilege
2848 USER_PRV_ADMIN 2 Administrator privilege
2850 usri11_auth_flags specifies the account operator privileges. The
2851 possible values are:
2853 Name Value Description
2854 AF_OP_PRINT 0 Print operator
2857 Leach, Naik [Page 28]
2861 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2864 AF_OP_COMM 1 Communications operator
2865 AF_OP_SERVER 2 Server operator
2866 AF_OP_ACCOUNTS 3 Accounts operator
2869 usri11_password_age specifies how many seconds have elapsed since the
2870 password was last changed.
2872 usri11_home_dir points to a null terminated ASCII string that contains
2873 the path name of the user's home directory.
2875 usri11_parms points to a null terminated ASCII string that is set
2876 aside for use by applications.
2878 usri11_last_logon specifies the time when the user last logged on.
2879 This value is stored as the number of seconds elapsed since
2880 00:00:00, January 1, 1970.
2882 usri11_last_logoff specifies the time when the user last logged off.
2883 This value is stored as the number of seconds elapsed since
2884 00:00:00, January 1, 1970. A value of 0 means the last logoff
2885 time is unknown.
2887 usri11_bad_pw_count specifies the number of incorrect passwords
2888 entered since the last successful logon.
2890 usri11_log1_num_logons specifies the number of times this user has
2891 logged on. A value of -1 means the number of logons is unknown.
2893 usri11_logon_server points to a null terminated ASCII string that
2894 contains the name of the server to which logon requests are sent.
2895 A null string indicates logon requests should be sent to the
2896 domain controller.
2898 usri11_country_code specifies the country code for the user's language
2899 of choice.
2901 usri11_workstations points to a null terminated ASCII string that
2902 contains the names of workstations the user may log on from.
2903 There may be up to 8 workstations, with the names separated by
2904 commas. A null strings indicates there are no restrictions.
2906 usri11_max_storage specifies the maximum amount of disk space the user
2907 can occupy. A value of 0xffffffff indicates there are no
2908 restrictions.
2910 usri11_units_per_week specifies the equal number of time units into
2911 which a week is divided. This value must be equal to 168.
2913 usri11_logon_hours points to a 21 byte (168 bits) string that
2914 specifies the time during which the user can log on. Each bit
2915 represents one unique hour in a week. The first bit (bit 0, word
2916 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
2920 Leach, Naik [Page 29]
2924 INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
2927 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
2928 are no restrictions.
2930 usri11_code_page specifies the code page for the user's language of
2931 choice
2933 All of the pointers in this data structure need to be treated
2934 specially. The pointer is a 32 bit pointer. The higher 16 bits need
2935 to be ignored. The converter word returned in the parameters section
2936 needs to be subtracted from the lower 16 bits to calculate an offset
2937 into the return buffer where this ASCII string resides.
2939 There is no auxiliary data in the response.
2941 ****************************************************************************/
2943 #define usri11_name 0
2944 #define usri11_pad 21
2945 #define usri11_comment 22
2946 #define usri11_usr_comment 26
2947 #define usri11_full_name 30
2948 #define usri11_priv 34
2949 #define usri11_auth_flags 36
2950 #define usri11_password_age 40
2951 #define usri11_homedir 44
2952 #define usri11_parms 48
2953 #define usri11_last_logon 52
2954 #define usri11_last_logoff 56
2955 #define usri11_bad_pw_count 60
2956 #define usri11_num_logons 62
2957 #define usri11_logon_server 64
2958 #define usri11_country_code 68
2959 #define usri11_workstations 70
2960 #define usri11_max_storage 74
2961 #define usri11_units_per_week 78
2962 #define usri11_logon_hours 80
2963 #define usri11_code_page 84
2964 #define usri11_end 86
2966 #define USER_PRIV_GUEST 0
2967 #define USER_PRIV_USER 1
2968 #define USER_PRIV_ADMIN 2
2970 #define AF_OP_PRINT 0
2971 #define AF_OP_COMM 1
2972 #define AF_OP_SERVER 2
2973 #define AF_OP_ACCOUNTS 3
2976 static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
2977 int mdrcnt,int mprcnt,
2978 char **rdata,char **rparam,
2979 int *rdata_len,int *rparam_len)
2981 char *str1 = param+2;
2982 char *str2 = skip_string(str1,1);
2983 char *UserName = skip_string(str2,1);
2984 char *p = skip_string(UserName,1);
2985 int uLevel = SVAL(p,0);
2986 char *p2;
2987 const char *level_string;
2989 /* get NIS home of a previously validated user - simeon */
2990 /* With share level security vuid will always be zero.
2991 Don't depend on vuser being non-null !!. JRA */
2992 user_struct *vuser = get_valid_user_struct(vuid);
2993 if(vuser != NULL) {
2994 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid,
2995 vuser->user.unix_name));
2998 *rparam_len = 6;
2999 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3000 if (!*rparam) {
3001 return False;
3004 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
3006 /* check it's a supported variant */
3007 if (strcmp(str1,"zWrLh") != 0) {
3008 return False;
3010 switch( uLevel ) {
3011 case 0: level_string = "B21"; break;
3012 case 1: level_string = "B21BB16DWzzWz"; break;
3013 case 2: level_string = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
3014 case 10: level_string = "B21Bzzz"; break;
3015 case 11: level_string = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
3016 default: return False;
3019 if (strcmp(level_string,str2) != 0) {
3020 return False;
3023 *rdata_len = mdrcnt + 1024;
3024 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
3025 if (!*rdata) {
3026 return False;
3029 SSVAL(*rparam,0,NERR_Success);
3030 SSVAL(*rparam,2,0); /* converter word */
3032 p = *rdata;
3033 p2 = p + usri11_end;
3035 memset(p,0,21);
3036 fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
3038 if (uLevel > 0) {
3039 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
3040 *p2 = 0;
3043 if (uLevel >= 10) {
3044 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
3045 pstrcpy(p2,"Comment");
3046 p2 = skip_string(p2,1);
3048 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
3049 pstrcpy(p2,"UserComment");
3050 p2 = skip_string(p2,1);
3052 /* EEK! the cifsrap.txt doesn't have this in!!!! */
3053 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
3054 pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName));
3055 p2 = skip_string(p2,1);
3058 if (uLevel == 11) {
3059 /* modelled after NTAS 3.51 reply */
3060 SSVAL(p,usri11_priv,conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
3061 SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
3062 SIVALS(p,usri11_password_age,-1); /* password age */
3063 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
3064 pstrcpy(p2, vuser && vuser->homedir ? vuser->homedir : "");
3065 p2 = skip_string(p2,1);
3066 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
3067 pstrcpy(p2,"");
3068 p2 = skip_string(p2,1);
3069 SIVAL(p,usri11_last_logon,0); /* last logon */
3070 SIVAL(p,usri11_last_logoff,0); /* last logoff */
3071 SSVALS(p,usri11_bad_pw_count,-1); /* bad pw counts */
3072 SSVALS(p,usri11_num_logons,-1); /* num logons */
3073 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
3074 pstrcpy(p2,"\\\\*");
3075 p2 = skip_string(p2,1);
3076 SSVAL(p,usri11_country_code,0); /* country code */
3078 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
3079 pstrcpy(p2,"");
3080 p2 = skip_string(p2,1);
3082 SIVALS(p,usri11_max_storage,-1); /* max storage */
3083 SSVAL(p,usri11_units_per_week,168); /* units per week */
3084 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
3086 /* a simple way to get logon hours at all times. */
3087 memset(p2,0xff,21);
3088 SCVAL(p2,21,0); /* fix zero termination */
3089 p2 = skip_string(p2,1);
3091 SSVAL(p,usri11_code_page,0); /* code page */
3094 if (uLevel == 1 || uLevel == 2) {
3095 memset(p+22,' ',16); /* password */
3096 SIVALS(p,38,-1); /* password age */
3097 SSVAL(p,42,
3098 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
3099 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
3100 pstrcpy(p2, vuser && vuser->homedir ? vuser->homedir : "");
3101 p2 = skip_string(p2,1);
3102 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
3103 *p2++ = 0;
3104 SSVAL(p,52,0); /* flags */
3105 SIVAL(p,54,PTR_DIFF(p2,*rdata)); /* script_path */
3106 pstrcpy(p2,vuser && vuser->logon_script ? vuser->logon_script : "");
3107 p2 = skip_string(p2,1);
3108 if (uLevel == 2) {
3109 SIVAL(p,60,0); /* auth_flags */
3110 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
3111 pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName));
3112 p2 = skip_string(p2,1);
3113 SIVAL(p,68,0); /* urs_comment */
3114 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
3115 pstrcpy(p2,"");
3116 p2 = skip_string(p2,1);
3117 SIVAL(p,76,0); /* workstations */
3118 SIVAL(p,80,0); /* last_logon */
3119 SIVAL(p,84,0); /* last_logoff */
3120 SIVALS(p,88,-1); /* acct_expires */
3121 SIVALS(p,92,-1); /* max_storage */
3122 SSVAL(p,96,168); /* units_per_week */
3123 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
3124 memset(p2,-1,21);
3125 p2 += 21;
3126 SSVALS(p,102,-1); /* bad_pw_count */
3127 SSVALS(p,104,-1); /* num_logons */
3128 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
3129 pstrcpy(p2,"\\\\%L");
3130 standard_sub_conn(conn, p2,0);
3131 p2 = skip_string(p2,1);
3132 SSVAL(p,110,49); /* country_code */
3133 SSVAL(p,112,860); /* code page */
3137 *rdata_len = PTR_DIFF(p2,*rdata);
3139 SSVAL(*rparam,4,*rdata_len); /* is this right?? */
3141 return(True);
3144 static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param,char *data,
3145 int mdrcnt,int mprcnt,
3146 char **rdata,char **rparam,
3147 int *rdata_len,int *rparam_len)
3149 char *str1 = param+2;
3150 char *str2 = skip_string(str1,1);
3151 char *p = skip_string(str2,1);
3152 int uLevel;
3153 struct pack_desc desc;
3154 char* name;
3155 /* With share level security vuid will always be zero.
3156 Don't depend on vuser being non-null !!. JRA */
3157 user_struct *vuser = get_valid_user_struct(vuid);
3159 if(vuser != NULL) {
3160 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid,
3161 vuser->user.unix_name));
3164 uLevel = SVAL(p,0);
3165 name = p + 2;
3167 memset((char *)&desc,'\0',sizeof(desc));
3169 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
3171 /* check it's a supported varient */
3172 if (strcmp(str1,"OOWb54WrLh") != 0) {
3173 return False;
3175 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) {
3176 return False;
3178 if (mdrcnt > 0) {
3179 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3180 if (!*rdata) {
3181 return False;
3185 desc.base = *rdata;
3186 desc.buflen = mdrcnt;
3187 desc.subformat = NULL;
3188 desc.format = str2;
3190 if (init_package(&desc,1,0)) {
3191 PACKI(&desc,"W",0); /* code */
3192 PACKS(&desc,"B21",name); /* eff. name */
3193 PACKS(&desc,"B",""); /* pad */
3194 PACKI(&desc,"W", conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
3195 PACKI(&desc,"D",0); /* auth flags XXX */
3196 PACKI(&desc,"W",0); /* num logons */
3197 PACKI(&desc,"W",0); /* bad pw count */
3198 PACKI(&desc,"D",0); /* last logon */
3199 PACKI(&desc,"D",-1); /* last logoff */
3200 PACKI(&desc,"D",-1); /* logoff time */
3201 PACKI(&desc,"D",-1); /* kickoff time */
3202 PACKI(&desc,"D",0); /* password age */
3203 PACKI(&desc,"D",0); /* password can change */
3204 PACKI(&desc,"D",-1); /* password must change */
3207 fstring mypath;
3208 fstrcpy(mypath,"\\\\");
3209 fstrcat(mypath,get_local_machine_name());
3210 strupper_m(mypath);
3211 PACKS(&desc,"z",mypath); /* computer */
3214 PACKS(&desc,"z",lp_workgroup());/* domain */
3215 PACKS(&desc,"z", vuser && vuser->logon_script ? vuser->logon_script :""); /* script path */
3216 PACKI(&desc,"D",0x00000000); /* reserved */
3219 *rdata_len = desc.usedlen;
3220 *rparam_len = 6;
3221 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3222 if (!*rparam) {
3223 return False;
3225 SSVALS(*rparam,0,desc.errcode);
3226 SSVAL(*rparam,2,0);
3227 SSVAL(*rparam,4,desc.neededlen);
3229 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
3231 return True;
3234 /****************************************************************************
3235 api_WAccessGetUserPerms
3236 ****************************************************************************/
3238 static BOOL api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid, char *param,char *data,
3239 int mdrcnt,int mprcnt,
3240 char **rdata,char **rparam,
3241 int *rdata_len,int *rparam_len)
3243 char *str1 = param+2;
3244 char *str2 = skip_string(str1,1);
3245 char *user = skip_string(str2,1);
3246 char *resource = skip_string(user,1);
3248 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
3250 /* check it's a supported varient */
3251 if (strcmp(str1,"zzh") != 0) {
3252 return False;
3254 if (strcmp(str2,"") != 0) {
3255 return False;
3258 *rparam_len = 6;
3259 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3260 if (!*rparam) {
3261 return False;
3263 SSVALS(*rparam,0,0); /* errorcode */
3264 SSVAL(*rparam,2,0); /* converter word */
3265 SSVAL(*rparam,4,0x7f); /* permission flags */
3267 return True;
3270 /****************************************************************************
3271 api_WPrintJobEnumerate
3272 ****************************************************************************/
3274 static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
3275 int mdrcnt,int mprcnt,
3276 char **rdata,char **rparam,
3277 int *rdata_len,int *rparam_len)
3279 char *str1 = param+2;
3280 char *str2 = skip_string(str1,1);
3281 char *p = skip_string(str2,1);
3282 int uLevel;
3283 int count;
3284 int i;
3285 int snum;
3286 fstring sharename;
3287 uint32 jobid;
3288 struct pack_desc desc;
3289 print_queue_struct *queue=NULL;
3290 print_status_struct status;
3291 char *tmpdata=NULL;
3293 uLevel = SVAL(p,2);
3295 memset((char *)&desc,'\0',sizeof(desc));
3296 memset((char *)&status,'\0',sizeof(status));
3298 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
3300 /* check it's a supported varient */
3301 if (strcmp(str1,"WWrLh") != 0) {
3302 return False;
3304 if (!check_printjob_info(&desc,uLevel,str2)) {
3305 return False;
3308 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid)) {
3309 return False;
3312 snum = lp_servicenumber( sharename);
3313 if (snum < 0 || !VALID_SNUM(snum)) {
3314 return(False);
3317 count = print_queue_status(snum,&queue,&status);
3318 for (i = 0; i < count; i++) {
3319 if (queue[i].job == jobid) {
3320 break;
3324 if (mdrcnt > 0) {
3325 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3326 if (!*rdata) {
3327 return False;
3329 desc.base = *rdata;
3330 desc.buflen = mdrcnt;
3331 } else {
3333 * Don't return data but need to get correct length
3334 * init_package will return wrong size if buflen=0
3336 desc.buflen = getlen(desc.format);
3337 desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen );
3340 if (init_package(&desc,1,0)) {
3341 if (i < count) {
3342 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
3343 *rdata_len = desc.usedlen;
3344 } else {
3345 desc.errcode = NERR_JobNotFound;
3346 *rdata_len = 0;
3350 *rparam_len = 6;
3351 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3352 if (!*rparam) {
3353 return False;
3355 SSVALS(*rparam,0,desc.errcode);
3356 SSVAL(*rparam,2,0);
3357 SSVAL(*rparam,4,desc.neededlen);
3359 SAFE_FREE(queue);
3360 SAFE_FREE(tmpdata);
3362 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
3364 return True;
3367 static BOOL api_WPrintJobEnumerate(connection_struct *conn,uint16 vuid, char *param,char *data,
3368 int mdrcnt,int mprcnt,
3369 char **rdata,char **rparam,
3370 int *rdata_len,int *rparam_len)
3372 char *str1 = param+2;
3373 char *str2 = skip_string(str1,1);
3374 char *p = skip_string(str2,1);
3375 char* name = p;
3376 int uLevel;
3377 int count;
3378 int i, succnt=0;
3379 int snum;
3380 struct pack_desc desc;
3381 print_queue_struct *queue=NULL;
3382 print_status_struct status;
3384 memset((char *)&desc,'\0',sizeof(desc));
3385 memset((char *)&status,'\0',sizeof(status));
3387 p = skip_string(p,1);
3388 uLevel = SVAL(p,0);
3390 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
3392 /* check it's a supported variant */
3393 if (strcmp(str1,"zWrLeh") != 0) {
3394 return False;
3397 if (uLevel > 2) {
3398 return False; /* defined only for uLevel 0,1,2 */
3401 if (!check_printjob_info(&desc,uLevel,str2)) {
3402 return False;
3405 snum = find_service(name);
3406 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) ) {
3407 return False;
3410 count = print_queue_status(snum,&queue,&status);
3411 if (mdrcnt > 0) {
3412 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3413 if (!*rdata) {
3414 return False;
3417 desc.base = *rdata;
3418 desc.buflen = mdrcnt;
3420 if (init_package(&desc,count,0)) {
3421 succnt = 0;
3422 for (i = 0; i < count; i++) {
3423 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
3424 if (desc.errcode == NERR_Success) {
3425 succnt = i+1;
3430 *rdata_len = desc.usedlen;
3432 *rparam_len = 8;
3433 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3434 if (!*rparam) {
3435 return False;
3437 SSVALS(*rparam,0,desc.errcode);
3438 SSVAL(*rparam,2,0);
3439 SSVAL(*rparam,4,succnt);
3440 SSVAL(*rparam,6,count);
3442 SAFE_FREE(queue);
3444 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
3446 return True;
3449 static int check_printdest_info(struct pack_desc* desc,
3450 int uLevel, char* id)
3452 desc->subformat = NULL;
3453 switch( uLevel ) {
3454 case 0:
3455 desc->format = "B9";
3456 break;
3457 case 1:
3458 desc->format = "B9B21WWzW";
3459 break;
3460 case 2:
3461 desc->format = "z";
3462 break;
3463 case 3:
3464 desc->format = "zzzWWzzzWW";
3465 break;
3466 default:
3467 return False;
3469 if (strcmp(desc->format,id) != 0) {
3470 return False;
3472 return True;
3475 static void fill_printdest_info(connection_struct *conn, int snum, int uLevel,
3476 struct pack_desc* desc)
3478 char buf[100];
3480 strncpy(buf,SERVICE(snum),sizeof(buf)-1);
3481 buf[sizeof(buf)-1] = 0;
3482 strupper_m(buf);
3484 if (uLevel <= 1) {
3485 PACKS(desc,"B9",buf); /* szName */
3486 if (uLevel == 1) {
3487 PACKS(desc,"B21",""); /* szUserName */
3488 PACKI(desc,"W",0); /* uJobId */
3489 PACKI(desc,"W",0); /* fsStatus */
3490 PACKS(desc,"z",""); /* pszStatus */
3491 PACKI(desc,"W",0); /* time */
3495 if (uLevel == 2 || uLevel == 3) {
3496 PACKS(desc,"z",buf); /* pszPrinterName */
3497 if (uLevel == 3) {
3498 PACKS(desc,"z",""); /* pszUserName */
3499 PACKS(desc,"z",""); /* pszLogAddr */
3500 PACKI(desc,"W",0); /* uJobId */
3501 PACKI(desc,"W",0); /* fsStatus */
3502 PACKS(desc,"z",""); /* pszStatus */
3503 PACKS(desc,"z",""); /* pszComment */
3504 PACKS(desc,"z","NULL"); /* pszDrivers */
3505 PACKI(desc,"W",0); /* time */
3506 PACKI(desc,"W",0); /* pad1 */
3511 static BOOL api_WPrintDestGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
3512 int mdrcnt,int mprcnt,
3513 char **rdata,char **rparam,
3514 int *rdata_len,int *rparam_len)
3516 char *str1 = param+2;
3517 char *str2 = skip_string(str1,1);
3518 char *p = skip_string(str2,1);
3519 char* PrinterName = p;
3520 int uLevel;
3521 struct pack_desc desc;
3522 int snum;
3523 char *tmpdata=NULL;
3525 memset((char *)&desc,'\0',sizeof(desc));
3527 p = skip_string(p,1);
3528 uLevel = SVAL(p,0);
3530 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
3532 /* check it's a supported varient */
3533 if (strcmp(str1,"zWrLh") != 0) {
3534 return False;
3536 if (!check_printdest_info(&desc,uLevel,str2)) {
3537 return False;
3540 snum = find_service(PrinterName);
3541 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) ) {
3542 *rdata_len = 0;
3543 desc.errcode = NERR_DestNotFound;
3544 desc.neededlen = 0;
3545 } else {
3546 if (mdrcnt > 0) {
3547 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3548 if (!*rdata) {
3549 return False;
3551 desc.base = *rdata;
3552 desc.buflen = mdrcnt;
3553 } else {
3555 * Don't return data but need to get correct length
3556 * init_package will return wrong size if buflen=0
3558 desc.buflen = getlen(desc.format);
3559 desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen );
3561 if (init_package(&desc,1,0)) {
3562 fill_printdest_info(conn,snum,uLevel,&desc);
3564 *rdata_len = desc.usedlen;
3567 *rparam_len = 6;
3568 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3569 if (!*rparam) {
3570 return False;
3572 SSVALS(*rparam,0,desc.errcode);
3573 SSVAL(*rparam,2,0);
3574 SSVAL(*rparam,4,desc.neededlen);
3576 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
3577 SAFE_FREE(tmpdata);
3579 return True;
3582 static BOOL api_WPrintDestEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3583 int mdrcnt,int mprcnt,
3584 char **rdata,char **rparam,
3585 int *rdata_len,int *rparam_len)
3587 char *str1 = param+2;
3588 char *str2 = skip_string(str1,1);
3589 char *p = skip_string(str2,1);
3590 int uLevel;
3591 int queuecnt;
3592 int i, n, succnt=0;
3593 struct pack_desc desc;
3594 int services = lp_numservices();
3596 memset((char *)&desc,'\0',sizeof(desc));
3598 uLevel = SVAL(p,0);
3600 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
3602 /* check it's a supported varient */
3603 if (strcmp(str1,"WrLeh") != 0) {
3604 return False;
3606 if (!check_printdest_info(&desc,uLevel,str2)) {
3607 return False;
3610 queuecnt = 0;
3611 for (i = 0; i < services; i++) {
3612 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
3613 queuecnt++;
3617 if (mdrcnt > 0) {
3618 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3619 if (!*rdata) {
3620 return False;
3624 desc.base = *rdata;
3625 desc.buflen = mdrcnt;
3626 if (init_package(&desc,queuecnt,0)) {
3627 succnt = 0;
3628 n = 0;
3629 for (i = 0; i < services; i++) {
3630 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
3631 fill_printdest_info(conn,i,uLevel,&desc);
3632 n++;
3633 if (desc.errcode == NERR_Success) {
3634 succnt = n;
3640 *rdata_len = desc.usedlen;
3642 *rparam_len = 8;
3643 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3644 if (!*rparam) {
3645 return False;
3647 SSVALS(*rparam,0,desc.errcode);
3648 SSVAL(*rparam,2,0);
3649 SSVAL(*rparam,4,succnt);
3650 SSVAL(*rparam,6,queuecnt);
3652 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
3654 return True;
3657 static BOOL api_WPrintDriverEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3658 int mdrcnt,int mprcnt,
3659 char **rdata,char **rparam,
3660 int *rdata_len,int *rparam_len)
3662 char *str1 = param+2;
3663 char *str2 = skip_string(str1,1);
3664 char *p = skip_string(str2,1);
3665 int uLevel;
3666 int succnt;
3667 struct pack_desc desc;
3669 memset((char *)&desc,'\0',sizeof(desc));
3671 uLevel = SVAL(p,0);
3673 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
3675 /* check it's a supported varient */
3676 if (strcmp(str1,"WrLeh") != 0) {
3677 return False;
3679 if (uLevel != 0 || strcmp(str2,"B41") != 0) {
3680 return False;
3683 if (mdrcnt > 0) {
3684 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3685 if (!*rdata) {
3686 return False;
3689 desc.base = *rdata;
3690 desc.buflen = mdrcnt;
3691 if (init_package(&desc,1,0)) {
3692 PACKS(&desc,"B41","NULL");
3695 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3697 *rdata_len = desc.usedlen;
3699 *rparam_len = 8;
3700 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3701 if (!*rparam) {
3702 return False;
3704 SSVALS(*rparam,0,desc.errcode);
3705 SSVAL(*rparam,2,0);
3706 SSVAL(*rparam,4,succnt);
3707 SSVAL(*rparam,6,1);
3709 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
3711 return True;
3714 static BOOL api_WPrintQProcEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3715 int mdrcnt,int mprcnt,
3716 char **rdata,char **rparam,
3717 int *rdata_len,int *rparam_len)
3719 char *str1 = param+2;
3720 char *str2 = skip_string(str1,1);
3721 char *p = skip_string(str2,1);
3722 int uLevel;
3723 int succnt;
3724 struct pack_desc desc;
3726 memset((char *)&desc,'\0',sizeof(desc));
3728 uLevel = SVAL(p,0);
3730 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
3732 /* check it's a supported varient */
3733 if (strcmp(str1,"WrLeh") != 0) {
3734 return False;
3736 if (uLevel != 0 || strcmp(str2,"B13") != 0) {
3737 return False;
3740 if (mdrcnt > 0) {
3741 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3742 if (!*rdata) {
3743 return False;
3746 desc.base = *rdata;
3747 desc.buflen = mdrcnt;
3748 desc.format = str2;
3749 if (init_package(&desc,1,0)) {
3750 PACKS(&desc,"B13","lpd");
3753 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3755 *rdata_len = desc.usedlen;
3757 *rparam_len = 8;
3758 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3759 if (!*rparam) {
3760 return False;
3762 SSVALS(*rparam,0,desc.errcode);
3763 SSVAL(*rparam,2,0);
3764 SSVAL(*rparam,4,succnt);
3765 SSVAL(*rparam,6,1);
3767 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
3769 return True;
3772 static BOOL api_WPrintPortEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
3773 int mdrcnt,int mprcnt,
3774 char **rdata,char **rparam,
3775 int *rdata_len,int *rparam_len)
3777 char *str1 = param+2;
3778 char *str2 = skip_string(str1,1);
3779 char *p = skip_string(str2,1);
3780 int uLevel;
3781 int succnt;
3782 struct pack_desc desc;
3784 memset((char *)&desc,'\0',sizeof(desc));
3786 uLevel = SVAL(p,0);
3788 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
3790 /* check it's a supported varient */
3791 if (strcmp(str1,"WrLeh") != 0) {
3792 return False;
3794 if (uLevel != 0 || strcmp(str2,"B9") != 0) {
3795 return False;
3798 if (mdrcnt > 0) {
3799 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3800 if (!*rdata) {
3801 return False;
3804 memset((char *)&desc,'\0',sizeof(desc));
3805 desc.base = *rdata;
3806 desc.buflen = mdrcnt;
3807 desc.format = str2;
3808 if (init_package(&desc,1,0)) {
3809 PACKS(&desc,"B13","lp0");
3812 succnt = (desc.errcode == NERR_Success ? 1 : 0);
3814 *rdata_len = desc.usedlen;
3816 *rparam_len = 8;
3817 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3818 if (!*rparam) {
3819 return False;
3821 SSVALS(*rparam,0,desc.errcode);
3822 SSVAL(*rparam,2,0);
3823 SSVAL(*rparam,4,succnt);
3824 SSVAL(*rparam,6,1);
3826 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
3828 return True;
3832 /****************************************************************************
3833 List open sessions
3834 ****************************************************************************/
3835 static BOOL api_RNetSessionEnum(connection_struct *conn,uint16 vuid, char *param, char *data,
3836 int mdrcnt,int mprcnt,
3837 char **rdata,char **rparam,
3838 int *rdata_len,int *rparam_len)
3841 char *str1 = param+2;
3842 char *str2 = skip_string(str1,1);
3843 char *p = skip_string(str2,1);
3844 int uLevel;
3845 struct pack_desc desc;
3846 struct sessionid *session_list;
3847 int i, num_sessions;
3849 memset((char *)&desc,'\0',sizeof(desc));
3851 uLevel = SVAL(p,0);
3853 DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel));
3854 DEBUG(7,("RNetSessionEnum req string=%s\n",str1));
3855 DEBUG(7,("RNetSessionEnum ret string=%s\n",str2));
3857 /* check it's a supported varient */
3858 if (strcmp(str1,RAP_NetSessionEnum_REQ) != 0) {
3859 return False;
3861 if (uLevel != 2 || strcmp(str2,RAP_SESSION_INFO_L2) != 0) {
3862 return False;
3865 num_sessions = list_sessions(&session_list);
3867 if (mdrcnt > 0) {
3868 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
3869 if (!*rdata) {
3870 return False;
3873 memset((char *)&desc,'\0',sizeof(desc));
3874 desc.base = *rdata;
3875 desc.buflen = mdrcnt;
3876 desc.format = str2;
3877 if (!init_package(&desc,num_sessions,0)) {
3878 return False;
3881 for(i=0; i<num_sessions; i++) {
3882 PACKS(&desc, "z", session_list[i].remote_machine);
3883 PACKS(&desc, "z", session_list[i].username);
3884 PACKI(&desc, "W", 1); /* num conns */
3885 PACKI(&desc, "W", 0); /* num opens */
3886 PACKI(&desc, "W", 1); /* num users */
3887 PACKI(&desc, "D", 0); /* session time */
3888 PACKI(&desc, "D", 0); /* idle time */
3889 PACKI(&desc, "D", 0); /* flags */
3890 PACKS(&desc, "z", "Unknown Client"); /* client type string */
3893 *rdata_len = desc.usedlen;
3895 *rparam_len = 8;
3896 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3897 if (!*rparam) {
3898 return False;
3900 SSVALS(*rparam,0,desc.errcode);
3901 SSVAL(*rparam,2,0); /* converter */
3902 SSVAL(*rparam,4,num_sessions); /* count */
3904 DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc.errcode));
3906 return True;
3910 /****************************************************************************
3911 The buffer was too small.
3912 ****************************************************************************/
3914 static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param, char *data,
3915 int mdrcnt, int mprcnt,
3916 char **rdata, char **rparam,
3917 int *rdata_len, int *rparam_len)
3919 *rparam_len = MIN(*rparam_len,mprcnt);
3920 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3921 if (!*rparam) {
3922 return False;
3925 *rdata_len = 0;
3927 SSVAL(*rparam,0,NERR_BufTooSmall);
3929 DEBUG(3,("Supplied buffer too small in API command\n"));
3931 return True;
3934 /****************************************************************************
3935 The request is not supported.
3936 ****************************************************************************/
3938 static BOOL api_Unsupported(connection_struct *conn, uint16 vuid, char *param, char *data,
3939 int mdrcnt, int mprcnt,
3940 char **rdata, char **rparam,
3941 int *rdata_len, int *rparam_len)
3943 *rparam_len = 4;
3944 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
3945 if (!*rparam) {
3946 return False;
3949 *rdata_len = 0;
3951 SSVAL(*rparam,0,NERR_notsupported);
3952 SSVAL(*rparam,2,0); /* converter word */
3954 DEBUG(3,("Unsupported API command\n"));
3956 return True;
3959 static const struct {
3960 const char *name;
3961 int id;
3962 BOOL (*fn)(connection_struct *,uint16,char *,char *,
3963 int,int,char **,char **,int *,int *);
3964 BOOL auth_user; /* Deny anonymous access? */
3965 } api_commands[] = {
3966 {"RNetShareEnum", RAP_WshareEnum, api_RNetShareEnum, True},
3967 {"RNetShareGetInfo", RAP_WshareGetInfo, api_RNetShareGetInfo},
3968 {"RNetShareAdd", RAP_WshareAdd, api_RNetShareAdd},
3969 {"RNetSessionEnum", RAP_WsessionEnum, api_RNetSessionEnum, True},
3970 {"RNetServerGetInfo", RAP_WserverGetInfo, api_RNetServerGetInfo},
3971 {"RNetGroupEnum", RAP_WGroupEnum, api_RNetGroupEnum, True},
3972 {"RNetGroupGetUsers", RAP_WGroupGetUsers, api_RNetGroupGetUsers, True},
3973 {"RNetUserEnum", RAP_WUserEnum, api_RNetUserEnum, True},
3974 {"RNetUserGetInfo", RAP_WUserGetInfo, api_RNetUserGetInfo},
3975 {"NetUserGetGroups", RAP_WUserGetGroups, api_NetUserGetGroups},
3976 {"NetWkstaGetInfo", RAP_WWkstaGetInfo, api_NetWkstaGetInfo},
3977 {"DosPrintQEnum", RAP_WPrintQEnum, api_DosPrintQEnum, True},
3978 {"DosPrintQGetInfo", RAP_WPrintQGetInfo, api_DosPrintQGetInfo},
3979 {"WPrintQueuePause", RAP_WPrintQPause, api_WPrintQueueCtrl},
3980 {"WPrintQueueResume", RAP_WPrintQContinue, api_WPrintQueueCtrl},
3981 {"WPrintJobEnumerate",RAP_WPrintJobEnum, api_WPrintJobEnumerate},
3982 {"WPrintJobGetInfo", RAP_WPrintJobGetInfo, api_WPrintJobGetInfo},
3983 {"RDosPrintJobDel", RAP_WPrintJobDel, api_RDosPrintJobDel},
3984 {"RDosPrintJobPause", RAP_WPrintJobPause, api_RDosPrintJobDel},
3985 {"RDosPrintJobResume",RAP_WPrintJobContinue, api_RDosPrintJobDel},
3986 {"WPrintDestEnum", RAP_WPrintDestEnum, api_WPrintDestEnum},
3987 {"WPrintDestGetInfo", RAP_WPrintDestGetInfo, api_WPrintDestGetInfo},
3988 {"NetRemoteTOD", RAP_NetRemoteTOD, api_NetRemoteTOD},
3989 {"WPrintQueuePurge", RAP_WPrintQPurge, api_WPrintQueueCtrl},
3990 {"NetServerEnum", RAP_NetServerEnum2, api_RNetServerEnum}, /* anon OK */
3991 {"WAccessGetUserPerms",RAP_WAccessGetUserPerms,api_WAccessGetUserPerms},
3992 {"SetUserPassword", RAP_WUserPasswordSet2, api_SetUserPassword},
3993 {"WWkstaUserLogon", RAP_WWkstaUserLogon, api_WWkstaUserLogon},
3994 {"PrintJobInfo", RAP_WPrintJobSetInfo, api_PrintJobInfo},
3995 {"WPrintDriverEnum", RAP_WPrintDriverEnum, api_WPrintDriverEnum},
3996 {"WPrintQProcEnum", RAP_WPrintQProcessorEnum,api_WPrintQProcEnum},
3997 {"WPrintPortEnum", RAP_WPrintPortEnum, api_WPrintPortEnum},
3998 {"SamOEMChangePassword",RAP_SamOEMChgPasswordUser2_P,api_SamOEMChangePassword}, /* anon OK */
3999 {NULL, -1, api_Unsupported}
4000 /* The following RAP calls are not implemented by Samba:
4002 RAP_WFileEnum2 - anon not OK
4007 /****************************************************************************
4008 Handle remote api calls
4009 ****************************************************************************/
4011 int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data,char *params,
4012 int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
4014 int api_command;
4015 char *rdata = NULL;
4016 char *rparam = NULL;
4017 int rdata_len = 0;
4018 int rparam_len = 0;
4019 BOOL reply=False;
4020 int i;
4022 if (!params) {
4023 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
4024 return 0;
4027 api_command = SVAL(params,0);
4029 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
4030 api_command,
4031 params+2,
4032 skip_string(params+2,1),
4033 tdscnt,tpscnt,mdrcnt,mprcnt));
4035 for (i=0;api_commands[i].name;i++) {
4036 if (api_commands[i].id == api_command && api_commands[i].fn) {
4037 DEBUG(3,("Doing %s\n",api_commands[i].name));
4038 break;
4042 /* Check whether this api call can be done anonymously */
4044 if (api_commands[i].auth_user && lp_restrict_anonymous()) {
4045 user_struct *user = get_valid_user_struct(vuid);
4047 if (!user || user->guest) {
4048 return ERROR_NT(NT_STATUS_ACCESS_DENIED);
4052 rdata = (char *)SMB_MALLOC(1024);
4053 if (rdata) {
4054 memset(rdata,'\0',1024);
4057 rparam = (char *)SMB_MALLOC(1024);
4058 if (rparam) {
4059 memset(rparam,'\0',1024);
4062 if(!rdata || !rparam) {
4063 DEBUG(0,("api_reply: malloc fail !\n"));
4064 SAFE_FREE(rdata);
4065 SAFE_FREE(rparam);
4066 return -1;
4069 reply = api_commands[i].fn(conn,vuid,params,data,mdrcnt,mprcnt,
4070 &rdata,&rparam,&rdata_len,&rparam_len);
4073 if (rdata_len > mdrcnt || rparam_len > mprcnt) {
4074 reply = api_TooSmall(conn,vuid,params,data,mdrcnt,mprcnt,
4075 &rdata,&rparam,&rdata_len,&rparam_len);
4078 /* if we get False back then it's actually unsupported */
4079 if (!reply) {
4080 reply = api_Unsupported(conn,vuid,params,data,mdrcnt,mprcnt,
4081 &rdata,&rparam,&rdata_len,&rparam_len);
4084 /* If api_Unsupported returns false we can't return anything. */
4085 if (reply) {
4086 send_trans_reply(outbuf, rparam, rparam_len, rdata, rdata_len, False);
4089 SAFE_FREE(rdata);
4090 SAFE_FREE(rparam);
4091 return -1;