2
Unix SMB/CIFS implementation.
3
Inter-process communication and named pipe handling
4
Copyright (C) Andrew Tridgell 1992-1998
5
Copyright (C) Jeremy Allison 2007.
8
Copyright (C) John H Terpstra 1995-1998
10
This program is free software; you can redistribute it and/or modify
11
it under the terms of the GNU General Public License as published by
12
the Free Software Foundation; either version 3 of the License, or
13
(at your option) any later version.
15
This program is distributed in the hope that it will be useful,
16
but WITHOUT ANY WARRANTY; without even the implied warranty of
17
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18
GNU General Public License for more details.
20
You should have received a copy of the GNU General Public License
21
along with this program. If not, see <http://www.gnu.org/licenses/>.
24
This file handles the named pipe and mailslot calls
25
in the SMBtrans protocol
29
#include "../lib/util/binsearch.h"
36
#define NERR_Success 0
37
#define NERR_badpass 86
38
#define NERR_notsupported 50
40
#define NERR_BASE (2100)
41
#define NERR_BufTooSmall (NERR_BASE+23)
42
#define NERR_JobNotFound (NERR_BASE+51)
43
#define NERR_DestNotFound (NERR_BASE+52)
45
#define ACCESS_READ 0x01
46
#define ACCESS_WRITE 0x02
47
#define ACCESS_CREATE 0x04
49
#define SHPWLEN 8 /* share password length */
51
/* Limit size of ipc replies */
53
static char *smb_realloc_limit(void *ptr, size_t size)
57
size = MAX((size),4*1024);
58
val = (char *)SMB_REALLOC(ptr,size);
60
memset(val,'\0',size);
65
static bool api_Unsupported(connection_struct *conn, uint16 vuid,
66
char *param, int tpscnt,
67
char *data, int tdscnt,
68
int mdrcnt, int mprcnt,
69
char **rdata, char **rparam,
70
int *rdata_len, int *rparam_len);
72
static bool api_TooSmall(connection_struct *conn, uint16 vuid, char *param, char *data,
73
int mdrcnt, int mprcnt,
74
char **rdata, char **rparam,
75
int *rdata_len, int *rparam_len);
78
static int CopyExpanded(connection_struct *conn,
79
int snum, char **dst, char *src, int *p_space_remaining)
81
TALLOC_CTX *ctx = talloc_tos();
85
if (!src || !dst || !p_space_remaining || !(*dst) ||
86
*p_space_remaining <= 0) {
90
buf = talloc_strdup(ctx, src);
92
*p_space_remaining = 0;
95
buf = talloc_string_sub(ctx, buf,"%S",lp_servicename(snum));
97
*p_space_remaining = 0;
100
buf = talloc_sub_advanced(ctx,
101
lp_servicename(SNUM(conn)),
102
conn->server_info->unix_name,
104
conn->server_info->utok.gid,
105
conn->server_info->sanitized_username,
106
pdb_get_domain(conn->server_info->sam_account),
109
*p_space_remaining = 0;
112
l = push_ascii(*dst,buf,*p_space_remaining, STR_TERMINATE);
117
(*p_space_remaining) -= l;
121
static int CopyAndAdvance(char **dst, char *src, int *n)
124
if (!src || !dst || !n || !(*dst)) {
127
l = push_ascii(*dst,src,*n, STR_TERMINATE);
136
static int StrlenExpanded(connection_struct *conn, int snum, char *s)
138
TALLOC_CTX *ctx = talloc_tos();
143
buf = talloc_strdup(ctx,s);
147
buf = talloc_string_sub(ctx,buf,"%S",lp_servicename(snum));
151
buf = talloc_sub_advanced(ctx,
152
lp_servicename(SNUM(conn)),
153
conn->server_info->unix_name,
155
conn->server_info->utok.gid,
156
conn->server_info->sanitized_username,
157
pdb_get_domain(conn->server_info->sam_account),
162
return strlen(buf) + 1;
165
static char *Expand(connection_struct *conn, int snum, char *s)
167
TALLOC_CTX *ctx = talloc_tos();
173
buf = talloc_strdup(ctx,s);
177
buf = talloc_string_sub(ctx,buf,"%S",lp_servicename(snum));
181
return talloc_sub_advanced(ctx,
182
lp_servicename(SNUM(conn)),
183
conn->server_info->unix_name,
185
conn->server_info->utok.gid,
186
conn->server_info->sanitized_username,
187
pdb_get_domain(conn->server_info->sam_account),
191
/*******************************************************************
192
Check a API string for validity when we only need to check the prefix.
193
******************************************************************/
195
static bool prefix_ok(const char *str, const char *prefix)
197
return(strncmp(str,prefix,strlen(prefix)) == 0);
201
const char *format; /* formatstring for structure */
202
const char *subformat; /* subformat for structure */
203
char *base; /* baseaddress of buffer */
204
int buflen; /* remaining size for fixed part; on init: length of base */
205
int subcount; /* count of substructures */
206
char *structbuf; /* pointer into buffer for remaining fixed part */
207
int stringlen; /* remaining size for variable part */
208
char *stringbuf; /* pointer into buffer for remaining variable part */
209
int neededlen; /* total needed size */
210
int usedlen; /* total used size (usedlen <= neededlen and usedlen <= buflen) */
211
const char *curpos; /* current position; pointer into format or subformat */
215
static int get_counter(const char **p)
221
if (!isdigit((int)**p)) {
227
n = 10 * n + (i - '0');
235
static int getlen(const char *p)
244
case 'W': /* word (2 byte) */
247
case 'K': /* status word? (2 byte) */
250
case 'N': /* count of substructures (word) at end */
253
case 'D': /* double word (4 byte) */
254
case 'z': /* offset to zero terminated string (4 byte) */
255
case 'l': /* offset to user data (4 byte) */
258
case 'b': /* offset to data (with counter) (4 byte) */
262
case 'B': /* byte (with optional counter) */
263
n += get_counter(&p);
270
static bool init_package(struct pack_desc *p, int count, int subcount)
275
if (!p->format || !p->base) {
279
i = count * getlen(p->format);
281
i += subcount * getlen(p->subformat);
283
p->structbuf = p->base;
287
p->curpos = p->format;
293
* This is the old error code we used. Aparently
294
* WinNT/2k systems return ERRbuftoosmall (2123) and
295
* OS/2 needs this. I'm leaving this here so we can revert
298
p->errcode = ERRmoredata;
300
p->errcode = ERRbuftoosmall;
303
p->errcode = NERR_Success;
307
p->stringbuf = p->base + i;
309
return (p->errcode == NERR_Success);
312
static int package(struct pack_desc *p, ...)
315
int needed=0, stringneeded;
316
const char *str=NULL;
317
int is_string=0, stringused;
324
p->curpos = p->format;
326
p->curpos = p->subformat;
331
str = va_arg(args,char*);
332
SMB_ASSERT(strncmp(str,p->curpos,strlen(str)) == 0);
341
switch( *p->curpos++ ) {
342
case 'W': /* word (2 byte) */
344
temp = va_arg(args,int);
345
if (p->buflen >= needed) {
346
SSVAL(p->structbuf,0,temp);
349
case 'K': /* status word? (2 byte) */
351
temp = va_arg(args,int);
352
if (p->buflen >= needed) {
353
SSVAL(p->structbuf,0,temp);
356
case 'N': /* count of substructures (word) at end */
358
p->subcount = va_arg(args,int);
359
if (p->buflen >= needed) {
360
SSVAL(p->structbuf,0,p->subcount);
363
case 'D': /* double word (4 byte) */
365
temp = va_arg(args,int);
366
if (p->buflen >= needed) {
367
SIVAL(p->structbuf,0,temp);
370
case 'B': /* byte (with optional counter) */
371
needed = get_counter(&p->curpos);
373
char *s = va_arg(args,char*);
374
if (p->buflen >= needed) {
375
StrnCpy(p->structbuf,s?s:"",needed-1);
379
case 'z': /* offset to zero terminated string (4 byte) */
380
str = va_arg(args,char*);
381
stringneeded = (str ? strlen(str)+1 : 0);
384
case 'l': /* offset to user data (4 byte) */
385
str = va_arg(args,char*);
386
stringneeded = va_arg(args,int);
389
case 'b': /* offset to data (with counter) (4 byte) */
390
str = va_arg(args,char*);
391
stringneeded = get_counter(&p->curpos);
397
if (stringneeded >= 0) {
399
if (p->buflen >= needed) {
400
stringused = stringneeded;
401
if (stringused > p->stringlen) {
402
stringused = (is_string ? p->stringlen : 0);
403
if (p->errcode == NERR_Success) {
404
p->errcode = ERRmoredata;
408
SIVAL(p->structbuf,0,0);
410
SIVAL(p->structbuf,0,PTR_DIFF(p->stringbuf,p->base));
411
memcpy(p->stringbuf,str?str:"",stringused);
413
p->stringbuf[stringused-1] = '\0';
415
p->stringbuf += stringused;
416
p->stringlen -= stringused;
417
p->usedlen += stringused;
420
p->neededlen += stringneeded;
423
p->neededlen += needed;
424
if (p->buflen >= needed) {
425
p->structbuf += needed;
427
p->usedlen += needed;
429
if (p->errcode == NERR_Success) {
430
p->errcode = ERRmoredata;
437
#define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
438
#define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
440
#define PACK(desc,t,v) package(desc,v)
441
#define PACKl(desc,t,v,l) package(desc,v,l)
444
static void PACKI(struct pack_desc* desc, const char *t,int v)
449
static void PACKS(struct pack_desc* desc,const char *t,const char *v)
454
/****************************************************************************
456
****************************************************************************/
458
static void PackDriverData(struct pack_desc* desc)
460
char drivdata[4+4+32];
461
SIVAL(drivdata,0,sizeof drivdata); /* cb */
462
SIVAL(drivdata,4,1000); /* lVersion */
463
memset(drivdata+8,0,32); /* szDeviceName */
464
push_ascii(drivdata+8,"NULL",32, STR_TERMINATE);
465
PACKl(desc,"l",drivdata,sizeof drivdata); /* pDriverData */
468
static int check_printq_info(struct pack_desc* desc,
469
unsigned int uLevel, char *id1, char *id2)
471
desc->subformat = NULL;
474
desc->format = "B13";
477
desc->format = "B13BWWWzzzzzWW";
480
desc->format = "B13BWWWzzzzzWN";
481
desc->subformat = "WB21BB16B10zWWzDDz";
484
desc->format = "zWWWWzzzzWWzzl";
487
desc->format = "zWWWWzzzzWNzzl";
488
desc->subformat = "WWzWWDDzz";
497
desc->format = "WzzzzzzzzN";
498
desc->subformat = "z";
501
DEBUG(0,("check_printq_info: invalid level %d\n",
505
if (id1 == NULL || strcmp(desc->format,id1) != 0) {
506
DEBUG(0,("check_printq_info: invalid format %s\n",
507
id1 ? id1 : "<NULL>" ));
510
if (desc->subformat && (id2 == NULL || strcmp(desc->subformat,id2) != 0)) {
511
DEBUG(0,("check_printq_info: invalid subformat %s\n",
512
id2 ? id2 : "<NULL>" ));
519
#define RAP_JOB_STATUS_QUEUED 0
520
#define RAP_JOB_STATUS_PAUSED 1
521
#define RAP_JOB_STATUS_SPOOLING 2
522
#define RAP_JOB_STATUS_PRINTING 3
523
#define RAP_JOB_STATUS_PRINTED 4
525
#define RAP_QUEUE_STATUS_PAUSED 1
526
#define RAP_QUEUE_STATUS_ERROR 2
528
/* turn a print job status into a on the wire status
530
static int printj_status(int v)
534
return RAP_JOB_STATUS_QUEUED;
536
return RAP_JOB_STATUS_PAUSED;
538
return RAP_JOB_STATUS_SPOOLING;
540
return RAP_JOB_STATUS_PRINTING;
545
/* turn a print queue status into a on the wire status
547
static int printq_status(int v)
553
return RAP_QUEUE_STATUS_PAUSED;
555
return RAP_QUEUE_STATUS_ERROR;
558
static void fill_printjob_info(connection_struct *conn, int snum, int uLevel,
559
struct pack_desc *desc,
560
print_queue_struct *queue, int n)
562
time_t t = queue->time;
564
/* the client expects localtime */
565
t -= get_time_zone(t);
567
PACKI(desc,"W",pjobid_to_rap(lp_const_servicename(snum),queue->job)); /* uJobId */
569
PACKS(desc,"B21",queue->fs_user); /* szUserName */
570
PACKS(desc,"B",""); /* pad */
571
PACKS(desc,"B16",""); /* szNotifyName */
572
PACKS(desc,"B10","PM_Q_RAW"); /* szDataType */
573
PACKS(desc,"z",""); /* pszParms */
574
PACKI(desc,"W",n+1); /* uPosition */
575
PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */
576
PACKS(desc,"z",""); /* pszStatus */
577
PACKI(desc,"D",t); /* ulSubmitted */
578
PACKI(desc,"D",queue->size); /* ulSize */
579
PACKS(desc,"z",queue->fs_file); /* pszComment */
581
if (uLevel == 2 || uLevel == 3 || uLevel == 4) {
582
PACKI(desc,"W",queue->priority); /* uPriority */
583
PACKS(desc,"z",queue->fs_user); /* pszUserName */
584
PACKI(desc,"W",n+1); /* uPosition */
585
PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */
586
PACKI(desc,"D",t); /* ulSubmitted */
587
PACKI(desc,"D",queue->size); /* ulSize */
588
PACKS(desc,"z","Samba"); /* pszComment */
589
PACKS(desc,"z",queue->fs_file); /* pszDocument */
591
PACKS(desc,"z",""); /* pszNotifyName */
592
PACKS(desc,"z","PM_Q_RAW"); /* pszDataType */
593
PACKS(desc,"z",""); /* pszParms */
594
PACKS(desc,"z",""); /* pszStatus */
595
PACKS(desc,"z",SERVICE(snum)); /* pszQueue */
596
PACKS(desc,"z","lpd"); /* pszQProcName */
597
PACKS(desc,"z",""); /* pszQProcParms */
598
PACKS(desc,"z","NULL"); /* pszDriverName */
599
PackDriverData(desc); /* pDriverData */
600
PACKS(desc,"z",""); /* pszPrinterName */
601
} else if (uLevel == 4) { /* OS2 */
602
PACKS(desc,"z",""); /* pszSpoolFileName */
603
PACKS(desc,"z",""); /* pszPortName */
604
PACKS(desc,"z",""); /* pszStatus */
605
PACKI(desc,"D",0); /* ulPagesSpooled */
606
PACKI(desc,"D",0); /* ulPagesSent */
607
PACKI(desc,"D",0); /* ulPagesPrinted */
608
PACKI(desc,"D",0); /* ulTimePrinted */
609
PACKI(desc,"D",0); /* ulExtendJobStatus */
610
PACKI(desc,"D",0); /* ulStartPage */
611
PACKI(desc,"D",0); /* ulEndPage */
616
/********************************************************************
617
Return a driver name given an snum.
618
Returns True if from tdb, False otherwise.
619
********************************************************************/
621
static bool get_driver_name(int snum, char **pp_drivername)
623
NT_PRINTER_INFO_LEVEL *info = NULL;
626
get_a_printer (NULL, &info, 2, lp_servicename(snum));
628
*pp_drivername = talloc_strdup(talloc_tos(),
629
info->info_2->drivername);
631
free_a_printer(&info, 2);
632
if (!*pp_drivername) {
640
/********************************************************************
641
Respond to the DosPrintQInfo command with a level of 52
642
This is used to get printer driver information for Win9x clients
643
********************************************************************/
644
static void fill_printq_info_52(connection_struct *conn, int snum,
645
struct pack_desc* desc, int count )
649
NT_PRINTER_DRIVER_INFO_LEVEL driver;
650
NT_PRINTER_INFO_LEVEL *printer = NULL;
654
if ( !W_ERROR_IS_OK(get_a_printer( NULL, &printer, 2, lp_servicename(snum))) ) {
655
DEBUG(3,("fill_printq_info_52: Failed to lookup printer [%s]\n",
656
lp_servicename(snum)));
660
if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername,
663
DEBUG(3,("fill_printq_info_52: Failed to lookup driver [%s]\n",
664
printer->info_2->drivername));
668
trim_string(driver.info_3->driverpath, "\\print$\\WIN40\\0\\", 0);
669
trim_string(driver.info_3->datafile, "\\print$\\WIN40\\0\\", 0);
670
trim_string(driver.info_3->helpfile, "\\print$\\WIN40\\0\\", 0);
672
PACKI(desc, "W", 0x0400); /* don't know */
673
PACKS(desc, "z", driver.info_3->name); /* long printer name */
674
PACKS(desc, "z", driver.info_3->driverpath); /* Driverfile Name */
675
PACKS(desc, "z", driver.info_3->datafile); /* Datafile name */
676
PACKS(desc, "z", driver.info_3->monitorname); /* language monitor */
678
fstrcpy(location, "\\\\%L\\print$\\WIN40\\0");
679
standard_sub_basic( "", "", location, sizeof(location)-1 );
680
PACKS(desc,"z", location); /* share to retrieve files */
682
PACKS(desc,"z", driver.info_3->defaultdatatype); /* default data type */
683
PACKS(desc,"z", driver.info_3->helpfile); /* helpfile name */
684
PACKS(desc,"z", driver.info_3->driverpath); /* driver name */
686
DEBUG(3,("Printer Driver Name: %s:\n",driver.info_3->name));
687
DEBUG(3,("Driver: %s:\n",driver.info_3->driverpath));
688
DEBUG(3,("Data File: %s:\n",driver.info_3->datafile));
689
DEBUG(3,("Language Monitor: %s:\n",driver.info_3->monitorname));
690
DEBUG(3,("Driver Location: %s:\n",location));
691
DEBUG(3,("Data Type: %s:\n",driver.info_3->defaultdatatype));
692
DEBUG(3,("Help File: %s:\n",driver.info_3->helpfile));
693
PACKI(desc,"N",count); /* number of files to copy */
695
for ( i=0; i<count && driver.info_3->dependentfiles && *driver.info_3->dependentfiles[i]; i++)
697
trim_string(driver.info_3->dependentfiles[i], "\\print$\\WIN40\\0\\", 0);
698
PACKS(desc,"z",driver.info_3->dependentfiles[i]); /* driver files to copy */
699
DEBUG(3,("Dependent File: %s:\n",driver.info_3->dependentfiles[i]));
704
DEBUG(3,("fill_printq_info_52: file count specified by client [%d] != number of dependent files [%i]\n",
707
DEBUG(3,("fill_printq_info on <%s> gave %d entries\n", SERVICE(snum),i));
709
desc->errcode=NERR_Success;
713
DEBUG(3,("fill_printq_info: Can't supply driver files\n"));
714
desc->errcode=NERR_notsupported;
718
free_a_printer( &printer, 2 );
721
free_a_printer_driver( driver, 3 );
725
static void fill_printq_info(connection_struct *conn, int snum, int uLevel,
726
struct pack_desc* desc,
727
int count, print_queue_struct* queue,
728
print_status_struct* status)
733
PACKS(desc,"B13",SERVICE(snum));
738
PACKS(desc,"z",Expand(conn,snum,SERVICE(snum)));
741
PACKI(desc,"K",printq_status(status->status));
745
if (uLevel == 1 || uLevel == 2) {
746
PACKS(desc,"B",""); /* alignment */
747
PACKI(desc,"W",5); /* priority */
748
PACKI(desc,"W",0); /* start time */
749
PACKI(desc,"W",0); /* until time */
750
PACKS(desc,"z",""); /* pSepFile */
751
PACKS(desc,"z","lpd"); /* pPrProc */
752
PACKS(desc,"z",SERVICE(snum)); /* pDestinations */
753
PACKS(desc,"z",""); /* pParms */
755
PACKS(desc,"z","UNKNOWN PRINTER");
756
PACKI(desc,"W",LPSTAT_ERROR);
758
else if (!status || !status->message[0]) {
759
PACKS(desc,"z",Expand(conn,snum,lp_comment(snum)));
760
PACKI(desc,"W",LPSTAT_OK); /* status */
762
PACKS(desc,"z",status->message);
763
PACKI(desc,"W",printq_status(status->status)); /* status */
765
PACKI(desc,(uLevel == 1 ? "W" : "N"),count);
768
if (uLevel == 3 || uLevel == 4) {
769
char *drivername = NULL;
771
PACKI(desc,"W",5); /* uPriority */
772
PACKI(desc,"W",0); /* uStarttime */
773
PACKI(desc,"W",0); /* uUntiltime */
774
PACKI(desc,"W",5); /* pad1 */
775
PACKS(desc,"z",""); /* pszSepFile */
776
PACKS(desc,"z","WinPrint"); /* pszPrProc */
777
PACKS(desc,"z",NULL); /* pszParms */
778
PACKS(desc,"z",NULL); /* pszComment - don't ask.... JRA */
779
/* "don't ask" that it's done this way to fix corrupted
780
Win9X/ME printer comments. */
782
PACKI(desc,"W",LPSTAT_OK); /* fsStatus */
784
PACKI(desc,"W",printq_status(status->status)); /* fsStatus */
786
PACKI(desc,(uLevel == 3 ? "W" : "N"),count); /* cJobs */
787
PACKS(desc,"z",SERVICE(snum)); /* pszPrinters */
788
get_driver_name(snum,&drivername);
792
PACKS(desc,"z",drivername); /* pszDriverName */
793
PackDriverData(desc); /* pDriverData */
796
if (uLevel == 2 || uLevel == 4) {
798
for (i=0;i<count;i++)
799
fill_printjob_info(conn,snum,uLevel == 2 ? 1 : 2,desc,&queue[i],i);
803
fill_printq_info_52( conn, snum, desc, count );
806
/* This function returns the number of files for a given driver */
807
static int get_printerdrivernumber(int snum)
810
NT_PRINTER_DRIVER_INFO_LEVEL driver;
811
NT_PRINTER_INFO_LEVEL *printer = NULL;
815
if ( !W_ERROR_IS_OK(get_a_printer( NULL, &printer, 2, lp_servicename(snum))) ) {
816
DEBUG(3,("get_printerdrivernumber: Failed to lookup printer [%s]\n",
817
lp_servicename(snum)));
821
if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername,
824
DEBUG(3,("get_printerdrivernumber: Failed to lookup driver [%s]\n",
825
printer->info_2->drivername));
829
/* count the number of files */
830
while ( driver.info_3->dependentfiles && *driver.info_3->dependentfiles[result] )
835
free_a_printer( &printer, 2 );
838
free_a_printer_driver( driver, 3 );
843
static bool api_DosPrintQGetInfo(connection_struct *conn, uint16 vuid,
844
char *param, int tpscnt,
845
char *data, int tdscnt,
846
int mdrcnt,int mprcnt,
847
char **rdata,char **rparam,
848
int *rdata_len,int *rparam_len)
850
char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
851
char *str2 = skip_string(param,tpscnt,str1);
852
char *p = skip_string(param,tpscnt,str2);
858
struct pack_desc desc;
859
print_queue_struct *queue=NULL;
860
print_status_struct status;
863
if (!str1 || !str2 || !p) {
866
memset((char *)&status,'\0',sizeof(status));
867
memset((char *)&desc,'\0',sizeof(desc));
869
p = skip_string(param,tpscnt,p);
873
uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
874
str3 = get_safe_str_ptr(param,tpscnt,p,4);
875
/* str3 may be null here and is checked in check_printq_info(). */
877
/* remove any trailing username */
878
if ((p = strchr_m(QueueName,'%')))
881
DEBUG(3,("api_DosPrintQGetInfo uLevel=%d name=%s\n",uLevel,QueueName));
883
/* check it's a supported varient */
884
if (!prefix_ok(str1,"zWrLh"))
886
if (!check_printq_info(&desc,uLevel,str2,str3)) {
888
* Patch from Scott Moomaw <scott@bridgewater.edu>
889
* to return the 'invalid info level' error if an
890
* unknown level was requested.
894
*rparam = smb_realloc_limit(*rparam,*rparam_len);
898
SSVALS(*rparam,0,ERRunknownlevel);
904
snum = find_service(QueueName);
905
if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
909
count = get_printerdrivernumber(snum);
910
DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count));
912
count = print_queue_status(snum, &queue,&status);
916
*rdata = smb_realloc_limit(*rdata,mdrcnt);
922
desc.buflen = mdrcnt;
925
* Don't return data but need to get correct length
926
* init_package will return wrong size if buflen=0
928
desc.buflen = getlen(desc.format);
929
desc.base = tmpdata = (char *) SMB_MALLOC (desc.buflen);
932
if (init_package(&desc,1,count)) {
933
desc.subcount = count;
934
fill_printq_info(conn,snum,uLevel,&desc,count,queue,&status);
937
*rdata_len = desc.usedlen;
940
* We must set the return code to ERRbuftoosmall
941
* in order to support lanman style printing with Win NT/2k
944
if (!mdrcnt && lp_disable_spoolss())
945
desc.errcode = ERRbuftoosmall;
947
*rdata_len = desc.usedlen;
949
*rparam = smb_realloc_limit(*rparam,*rparam_len);
955
SSVALS(*rparam,0,desc.errcode);
957
SSVAL(*rparam,4,desc.neededlen);
959
DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode));
967
/****************************************************************************
968
View list of all print jobs on all queues.
969
****************************************************************************/
971
static bool api_DosPrintQEnum(connection_struct *conn, uint16 vuid,
972
char *param, int tpscnt,
973
char *data, int tdscnt,
974
int mdrcnt, int mprcnt,
975
char **rdata, char** rparam,
976
int *rdata_len, int *rparam_len)
978
char *param_format = get_safe_str_ptr(param,tpscnt,param,2);
979
char *output_format1 = skip_string(param,tpscnt,param_format);
980
char *p = skip_string(param,tpscnt,output_format1);
981
unsigned int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
982
char *output_format2 = get_safe_str_ptr(param,tpscnt,p,4);
983
int services = lp_numservices();
985
struct pack_desc desc;
986
print_queue_struct **queue = NULL;
987
print_status_struct *status = NULL;
988
int *subcntarr = NULL;
989
int queuecnt = 0, subcnt = 0, succnt = 0;
991
if (!param_format || !output_format1 || !p) {
995
memset((char *)&desc,'\0',sizeof(desc));
997
DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
999
if (!prefix_ok(param_format,"WrLeh")) {
1002
if (!check_printq_info(&desc,uLevel,output_format1,output_format2)) {
1004
* Patch from Scott Moomaw <scott@bridgewater.edu>
1005
* to return the 'invalid info level' error if an
1006
* unknown level was requested.
1010
*rparam = smb_realloc_limit(*rparam,*rparam_len);
1014
SSVALS(*rparam,0,ERRunknownlevel);
1020
for (i = 0; i < services; i++) {
1021
if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
1026
if((queue = SMB_MALLOC_ARRAY(print_queue_struct*, queuecnt)) == NULL) {
1027
DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
1030
memset(queue,0,queuecnt*sizeof(print_queue_struct*));
1031
if((status = SMB_MALLOC_ARRAY(print_status_struct,queuecnt)) == NULL) {
1032
DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
1035
memset(status,0,queuecnt*sizeof(print_status_struct));
1036
if((subcntarr = SMB_MALLOC_ARRAY(int,queuecnt)) == NULL) {
1037
DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
1043
for (i = 0; i < services; i++) {
1044
if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
1045
subcntarr[n] = print_queue_status(i, &queue[n],&status[n]);
1046
subcnt += subcntarr[n];
1052
*rdata = smb_realloc_limit(*rdata,mdrcnt);
1058
desc.buflen = mdrcnt;
1060
if (init_package(&desc,queuecnt,subcnt)) {
1063
for (i = 0; i < services; i++) {
1064
if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
1065
fill_printq_info(conn,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]);
1067
if (desc.errcode == NERR_Success) {
1074
SAFE_FREE(subcntarr);
1076
*rdata_len = desc.usedlen;
1078
*rparam = smb_realloc_limit(*rparam,*rparam_len);
1082
SSVALS(*rparam,0,desc.errcode);
1084
SSVAL(*rparam,4,succnt);
1085
SSVAL(*rparam,6,queuecnt);
1087
for (i = 0; i < queuecnt; i++) {
1089
SAFE_FREE(queue[i]);
1100
SAFE_FREE(subcntarr);
1101
for (i = 0; i < queuecnt; i++) {
1103
SAFE_FREE(queue[i]);
1112
/****************************************************************************
1113
Get info level for a server list query.
1114
****************************************************************************/
1116
static bool check_server_info(int uLevel, char* id)
1120
if (strcmp(id,"B16") != 0) {
1125
if (strcmp(id,"B16BBDz") != 0) {
1135
struct srv_info_struct {
1143
/*******************************************************************
1144
Get server info lists from the files saved by nmbd. Return the
1146
******************************************************************/
1148
static int get_server_info(uint32 servertype,
1149
struct srv_info_struct **servers,
1155
bool local_list_only;
1158
lines = file_lines_load(cache_path(SERVER_LIST), NULL, 0, NULL);
1160
DEBUG(4,("Can't open %s - %s\n",cache_path(SERVER_LIST),strerror(errno)));
1164
/* request for everything is code for request all servers */
1165
if (servertype == SV_TYPE_ALL) {
1166
servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1169
local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY);
1171
DEBUG(4,("Servertype search: %8x\n",servertype));
1173
for (i=0;lines[i];i++) {
1175
struct srv_info_struct *s;
1176
const char *ptr = lines[i];
1178
TALLOC_CTX *frame = NULL;
1185
if (count == alloced) {
1187
*servers = SMB_REALLOC_ARRAY(*servers,struct srv_info_struct, alloced);
1189
DEBUG(0,("get_server_info: failed to enlarge servers info struct!\n"));
1193
memset((char *)((*servers)+count),'\0',sizeof(**servers)*(alloced-count));
1195
s = &(*servers)[count];
1197
frame = talloc_stackframe();
1199
if (!next_token_talloc(frame,&ptr,&p, NULL)) {
1203
fstrcpy(s->name, p);
1206
if (!next_token_talloc(frame,&ptr, &p, NULL)) {
1212
s->comment[0] = '\0';
1213
if (!next_token_talloc(frame,&ptr, &p, NULL)) {
1217
fstrcpy(s->comment, p);
1218
string_truncate(s->comment, MAX_SERVER_STRING_LENGTH);
1220
s->domain[0] = '\0';
1221
if (!next_token_talloc(frame,&ptr,&p, NULL)) {
1222
/* this allows us to cope with an old nmbd */
1223
fstrcpy(s->domain,lp_workgroup());
1225
fstrcpy(s->domain, p);
1229
if (sscanf(stype,"%X",&s->type) != 1) {
1230
DEBUG(4,("r:host file "));
1234
/* Filter the servers/domains we return based on what was asked for. */
1236
/* Check to see if we are being asked for a local list only. */
1237
if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) {
1238
DEBUG(4,("r: local list only"));
1242
/* doesn't match up: don't want it */
1243
if (!(servertype & s->type)) {
1244
DEBUG(4,("r:serv type "));
1248
if ((servertype & SV_TYPE_DOMAIN_ENUM) !=
1249
(s->type & SV_TYPE_DOMAIN_ENUM)) {
1250
DEBUG(4,("s: dom mismatch "));
1254
if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM)) {
1258
/* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
1259
s->type &= ~SV_TYPE_LOCAL_LIST_ONLY;
1262
DEBUG(4,("**SV** %20s %8x %25s %15s\n",
1263
s->name, s->type, s->comment, s->domain));
1264
s->server_added = True;
1267
DEBUG(4,("%20s %8x %25s %15s\n",
1268
s->name, s->type, s->comment, s->domain));
1276
/*******************************************************************
1277
Fill in a server info structure.
1278
******************************************************************/
1280
static int fill_srv_info(struct srv_info_struct *service,
1281
int uLevel, char **buf, int *buflen,
1282
char **stringbuf, int *stringspace, char *baseaddr)
1305
len = strlen(service->comment)+1;
1309
*buflen = struct_len;
1311
return struct_len + len;
1316
if (*buflen < struct_len) {
1323
p2 = p + struct_len;
1324
l2 = *buflen - struct_len;
1332
push_ascii(p,service->name, MAX_NETBIOSNAME_LEN, STR_TERMINATE);
1336
push_ascii(p,service->name,MAX_NETBIOSNAME_LEN, STR_TERMINATE);
1337
SIVAL(p,18,service->type);
1338
SIVAL(p,22,PTR_DIFF(p2,baseaddr));
1339
len += CopyAndAdvance(&p2,service->comment,&l2);
1344
*buf = p + struct_len;
1345
*buflen -= struct_len;
1356
static int srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
1358
return StrCaseCmp(s1->name,s2->name);
1361
/****************************************************************************
1362
View list of servers available (or possibly domains). The info is
1363
extracted from lists saved by nmbd on the local host.
1364
****************************************************************************/
1366
static bool api_RNetServerEnum2(connection_struct *conn, uint16 vuid,
1367
char *param, int tpscnt,
1368
char *data, int tdscnt,
1369
int mdrcnt, int mprcnt, char **rdata,
1370
char **rparam, int *rdata_len, int *rparam_len)
1372
char *str1 = get_safe_str_ptr(param, tpscnt, param, 2);
1373
char *str2 = skip_string(param,tpscnt,str1);
1374
char *p = skip_string(param,tpscnt,str2);
1375
int uLevel = get_safe_SVAL(param, tpscnt, p, 0, -1);
1376
int buf_len = get_safe_SVAL(param,tpscnt, p, 2, 0);
1377
uint32 servertype = get_safe_IVAL(param,tpscnt,p,4, 0);
1379
int data_len, fixed_len, string_len;
1380
int f_len = 0, s_len = 0;
1381
struct srv_info_struct *servers=NULL;
1382
int counted=0,total=0;
1385
bool domain_request;
1388
if (!str1 || !str2 || !p) {
1392
/* If someone sets all the bits they don't really mean to set
1393
DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1396
if (servertype == SV_TYPE_ALL) {
1397
servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1400
/* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1401
any other bit (they may just set this bit on its own) they
1402
want all the locally seen servers. However this bit can be
1403
set on its own so set the requested servers to be
1404
ALL - DOMAIN_ENUM. */
1406
if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM)) {
1407
servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
1410
domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
1411
local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
1415
if (!prefix_ok(str1,"WrLehD")) {
1418
if (!check_server_info(uLevel,str2)) {
1422
DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1423
DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1424
DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1426
if (strcmp(str1, "WrLehDz") == 0) {
1427
if (skip_string(param,tpscnt,p) == NULL) {
1430
pull_ascii_fstring(domain, p);
1432
fstrcpy(domain, lp_workgroup());
1435
DEBUG(4, ("domain [%s]\n", domain));
1437
if (lp_browse_list()) {
1438
total = get_server_info(servertype,&servers,domain);
1441
data_len = fixed_len = string_len = 0;
1445
qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
1449
char *lastname=NULL;
1451
for (i=0;i<total;i++) {
1452
struct srv_info_struct *s = &servers[i];
1454
if (lastname && strequal(lastname,s->name)) {
1458
data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1459
DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1460
i, s->name, s->type, s->comment, s->domain));
1462
if (data_len < buf_len) {
1465
string_len += s_len;
1472
*rdata_len = fixed_len + string_len;
1473
*rdata = smb_realloc_limit(*rdata,*rdata_len);
1478
p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1484
char *lastname=NULL;
1485
int count2 = counted;
1487
for (i = 0; i < total && count2;i++) {
1488
struct srv_info_struct *s = &servers[i];
1490
if (lastname && strequal(lastname,s->name)) {
1494
fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1495
DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1496
i, s->name, s->type, s->comment, s->domain));
1502
*rparam = smb_realloc_limit(*rparam,*rparam_len);
1506
SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata));
1508
SSVAL(*rparam,4,counted);
1509
SSVAL(*rparam,6,counted+missed);
1513
DEBUG(3,("NetServerEnum2 domain = %s uLevel=%d counted=%d total=%d\n",
1514
domain,uLevel,counted,counted+missed));
1519
static int srv_name_match(const char *n1, const char *n2)
1522
* [MS-RAP] footnote <88> for Section 3.2.5.15 says:
1524
* In Windows, FirstNameToReturn need not be an exact match:
1525
* the server will return a list of servers that exist on
1526
* the network greater than or equal to the FirstNameToReturn.
1528
int ret = StrCaseCmp(n1, n2);
1537
static bool api_RNetServerEnum3(connection_struct *conn, uint16 vuid,
1538
char *param, int tpscnt,
1539
char *data, int tdscnt,
1540
int mdrcnt, int mprcnt, char **rdata,
1541
char **rparam, int *rdata_len, int *rparam_len)
1543
char *str1 = get_safe_str_ptr(param, tpscnt, param, 2);
1544
char *str2 = skip_string(param,tpscnt,str1);
1545
char *p = skip_string(param,tpscnt,str2);
1546
int uLevel = get_safe_SVAL(param, tpscnt, p, 0, -1);
1547
int buf_len = get_safe_SVAL(param,tpscnt, p, 2, 0);
1548
uint32 servertype = get_safe_IVAL(param,tpscnt,p,4, 0);
1550
int data_len, fixed_len, string_len;
1551
int f_len = 0, s_len = 0;
1552
struct srv_info_struct *servers=NULL;
1553
int counted=0,first=0,total=0;
1557
bool domain_request;
1560
if (!str1 || !str2 || !p) {
1564
/* If someone sets all the bits they don't really mean to set
1565
DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
1568
if (servertype == SV_TYPE_ALL) {
1569
servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
1572
/* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
1573
any other bit (they may just set this bit on its own) they
1574
want all the locally seen servers. However this bit can be
1575
set on its own so set the requested servers to be
1576
ALL - DOMAIN_ENUM. */
1578
if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM)) {
1579
servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
1582
domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
1583
local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
1587
if (strcmp(str1, "WrLehDzz") != 0) {
1590
if (!check_server_info(uLevel,str2)) {
1594
DEBUG(4, ("server request level: %s %8x ", str2, servertype));
1595
DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
1596
DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
1598
if (skip_string(param,tpscnt,p) == NULL) {
1601
pull_ascii_fstring(domain, p);
1602
if (domain[0] == '\0') {
1603
fstrcpy(domain, lp_workgroup());
1605
p = skip_string(param,tpscnt,p);
1606
if (skip_string(param,tpscnt,p) == NULL) {
1609
pull_ascii_fstring(first_name, p);
1611
DEBUG(4, ("domain: '%s' first_name: '%s'\n",
1612
domain, first_name));
1614
if (lp_browse_list()) {
1615
total = get_server_info(servertype,&servers,domain);
1618
data_len = fixed_len = string_len = 0;
1622
qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
1625
if (first_name[0] != '\0') {
1626
struct srv_info_struct *first_server = NULL;
1628
BINARY_ARRAY_SEARCH(servers, total, name, first_name,
1629
srv_name_match, first_server);
1631
first = PTR_DIFF(first_server, servers) / sizeof(*servers);
1633
* The binary search may not find the exact match
1634
* so we need to search backward to find the first match
1636
* This implements the strange matching windows
1637
* implements. (see the comment in srv_name_match().
1641
ret = StrCaseCmp(first_name,
1642
servers[first-1].name);
1649
/* we should return no entries */
1655
char *lastname=NULL;
1657
for (i=first;i<total;i++) {
1658
struct srv_info_struct *s = &servers[i];
1660
if (lastname && strequal(lastname,s->name)) {
1664
data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
1665
DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1666
i, s->name, s->type, s->comment, s->domain));
1668
if (data_len < buf_len) {
1671
string_len += s_len;
1678
*rdata_len = fixed_len + string_len;
1679
*rdata = smb_realloc_limit(*rdata,*rdata_len);
1684
p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */
1690
char *lastname=NULL;
1691
int count2 = counted;
1693
for (i = first; i < total && count2;i++) {
1694
struct srv_info_struct *s = &servers[i];
1696
if (lastname && strequal(lastname,s->name)) {
1700
fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
1701
DEBUG(4,("fill_srv_info[%d] %20s %8x %25s %15s\n",
1702
i, s->name, s->type, s->comment, s->domain));
1708
*rparam = smb_realloc_limit(*rparam,*rparam_len);
1712
SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata));
1714
SSVAL(*rparam,4,counted);
1715
SSVAL(*rparam,6,counted+missed);
1717
DEBUG(3,("NetServerEnum3 domain = %s uLevel=%d first=%d[%s => %s] counted=%d total=%d\n",
1718
domain,uLevel,first,first_name,
1719
first < total ? servers[first].name : "",
1720
counted,counted+missed));
1727
/****************************************************************************
1728
command 0x34 - suspected of being a "Lookup Names" stub api
1729
****************************************************************************/
1731
static bool api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid,
1732
char *param, int tpscnt,
1733
char *data, int tdscnt,
1734
int mdrcnt, int mprcnt, char **rdata,
1735
char **rparam, int *rdata_len, int *rparam_len)
1737
char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
1738
char *str2 = skip_string(param,tpscnt,str1);
1739
char *p = skip_string(param,tpscnt,str2);
1740
int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
1741
int buf_len = get_safe_SVAL(param,tpscnt,p,2,0);
1745
if (!str1 || !str2 || !p) {
1749
DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
1750
str1, str2, p, uLevel, buf_len));
1752
if (!prefix_ok(str1,"zWrLeh")) {
1759
*rparam = smb_realloc_limit(*rparam,*rparam_len);
1764
SSVAL(*rparam,0,0x08AC); /* informational warning message */
1766
SSVAL(*rparam,4,counted);
1767
SSVAL(*rparam,6,counted+missed);
1772
/****************************************************************************
1773
get info about a share
1774
****************************************************************************/
1776
static bool check_share_info(int uLevel, char* id)
1780
if (strcmp(id,"B13") != 0) {
1785
if (strcmp(id,"B13BWz") != 0) {
1790
if (strcmp(id,"B13BWzWWWzB9B") != 0) {
1795
if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) {
1805
static int fill_share_info(connection_struct *conn, int snum, int uLevel,
1806
char** buf, int* buflen,
1807
char** stringbuf, int* stringspace, char* baseaddr)
1836
len += StrlenExpanded(conn,snum,lp_comment(snum));
1839
len += strlen(lp_pathname(snum)) + 1;
1842
*buflen = struct_len;
1847
return struct_len + len;
1852
if ((*buflen) < struct_len) {
1860
p2 = p + struct_len;
1861
l2 = (*buflen) - struct_len;
1868
push_ascii(p,lp_servicename(snum),13, STR_TERMINATE);
1874
type = STYPE_DISKTREE;
1875
if (lp_print_ok(snum)) {
1876
type = STYPE_PRINTQ;
1878
if (strequal("IPC",lp_fstype(snum))) {
1881
SSVAL(p,14,type); /* device type */
1882
SIVAL(p,16,PTR_DIFF(p2,baseaddr));
1883
len += CopyExpanded(conn,snum,&p2,lp_comment(snum),&l2);
1887
SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
1888
SSVALS(p,22,-1); /* max uses */
1889
SSVAL(p,24,1); /* current uses */
1890
SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
1891
len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
1892
memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
1896
memset(p+40,0,SHPWLEN+2);
1907
(*buf) = p + struct_len;
1908
(*buflen) -= struct_len;
1910
(*stringspace) = l2;
1919
static bool api_RNetShareGetInfo(connection_struct *conn,uint16 vuid,
1920
char *param, int tpscnt,
1921
char *data, int tdscnt,
1922
int mdrcnt,int mprcnt,
1923
char **rdata,char **rparam,
1924
int *rdata_len,int *rparam_len)
1926
char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
1927
char *str2 = skip_string(param,tpscnt,str1);
1928
char *netname = skip_string(param,tpscnt,str2);
1929
char *p = skip_string(param,tpscnt,netname);
1930
int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
1933
if (!str1 || !str2 || !netname || !p) {
1937
snum = find_service(netname);
1942
/* check it's a supported varient */
1943
if (!prefix_ok(str1,"zWrLh")) {
1946
if (!check_share_info(uLevel,str2)) {
1950
*rdata = smb_realloc_limit(*rdata,mdrcnt);
1955
*rdata_len = fill_share_info(conn,snum,uLevel,&p,&mdrcnt,0,0,0);
1956
if (*rdata_len < 0) {
1961
*rparam = smb_realloc_limit(*rparam,*rparam_len);
1965
SSVAL(*rparam,0,NERR_Success);
1966
SSVAL(*rparam,2,0); /* converter word */
1967
SSVAL(*rparam,4,*rdata_len);
1972
/****************************************************************************
1973
View the list of available shares.
1975
This function is the server side of the NetShareEnum() RAP call.
1976
It fills the return buffer with share names and share comments.
1977
Note that the return buffer normally (in all known cases) allows only
1978
twelve byte strings for share names (plus one for a nul terminator).
1979
Share names longer than 12 bytes must be skipped.
1980
****************************************************************************/
1982
static bool api_RNetShareEnum( connection_struct *conn, uint16 vuid,
1983
char *param, int tpscnt,
1984
char *data, int tdscnt,
1992
char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
1993
char *str2 = skip_string(param,tpscnt,str1);
1994
char *p = skip_string(param,tpscnt,str2);
1995
int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
1996
int buf_len = get_safe_SVAL(param,tpscnt,p,2,0);
1999
int total=0,counted=0;
2000
bool missed = False;
2002
int data_len, fixed_len, string_len;
2003
int f_len = 0, s_len = 0;
2005
if (!str1 || !str2 || !p) {
2009
if (!prefix_ok(str1,"WrLeh")) {
2012
if (!check_share_info(uLevel,str2)) {
2016
/* Ensure all the usershares are loaded. */
2018
load_registry_shares();
2019
count = load_usershare_shares();
2022
data_len = fixed_len = string_len = 0;
2023
for (i=0;i<count;i++) {
2024
fstring servicename_dos;
2025
if (!(lp_browseable(i) && lp_snum_ok(i))) {
2028
push_ascii_fstring(servicename_dos, lp_servicename(i));
2029
/* Maximum name length = 13. */
2030
if( lp_browseable( i ) && lp_snum_ok( i ) && (strlen(servicename_dos) < 13)) {
2032
data_len += fill_share_info(conn,i,uLevel,0,&f_len,0,&s_len,0);
2033
if (data_len < buf_len) {
2036
string_len += s_len;
2043
*rdata_len = fixed_len + string_len;
2044
*rdata = smb_realloc_limit(*rdata,*rdata_len);
2049
p2 = (*rdata) + fixed_len; /* auxiliary data (strings) will go here */
2054
for( i = 0; i < count; i++ ) {
2055
fstring servicename_dos;
2056
if (!(lp_browseable(i) && lp_snum_ok(i))) {
2060
push_ascii_fstring(servicename_dos, lp_servicename(i));
2061
if (lp_browseable(i) && lp_snum_ok(i) && (strlen(servicename_dos) < 13)) {
2062
if (fill_share_info( conn,i,uLevel,&p,&f_len,&p2,&s_len,*rdata ) < 0) {
2069
*rparam = smb_realloc_limit(*rparam,*rparam_len);
2073
SSVAL(*rparam,0,missed ? ERRmoredata : NERR_Success);
2075
SSVAL(*rparam,4,counted);
2076
SSVAL(*rparam,6,total);
2078
DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
2079
counted,total,uLevel,
2080
buf_len,*rdata_len,mdrcnt));
2085
/****************************************************************************
2087
****************************************************************************/
2089
static bool api_RNetShareAdd(connection_struct *conn,uint16 vuid,
2090
char *param, int tpscnt,
2091
char *data, int tdscnt,
2092
int mdrcnt,int mprcnt,
2093
char **rdata,char **rparam,
2094
int *rdata_len,int *rparam_len)
2096
char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2097
char *str2 = skip_string(param,tpscnt,str1);
2098
char *p = skip_string(param,tpscnt,str2);
2099
int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
2102
char *pathname = NULL;
2103
char *command, *cmdname;
2104
unsigned int offset;
2107
size_t converted_size;
2109
if (!str1 || !str2 || !p) {
2113
/* check it's a supported varient */
2114
if (!prefix_ok(str1,RAP_WShareAdd_REQ)) {
2117
if (!check_share_info(uLevel,str2)) {
2124
/* Do we have a string ? */
2125
if (skip_string(data,mdrcnt,data) == NULL) {
2128
pull_ascii_fstring(sharename,data);
2129
snum = find_service(sharename);
2130
if (snum >= 0) { /* already exists */
2139
/* only support disk share adds */
2140
if (SVAL(data,14)!=STYPE_DISKTREE) {
2144
offset = IVAL(data, 16);
2145
if (offset >= mdrcnt) {
2146
res = ERRinvalidparam;
2150
/* Do we have a string ? */
2151
if (skip_string(data,mdrcnt,data+offset) == NULL) {
2154
pull_ascii_fstring(comment, offset? (data+offset) : "");
2156
offset = IVAL(data, 26);
2158
if (offset >= mdrcnt) {
2159
res = ERRinvalidparam;
2163
/* Do we have a string ? */
2164
if (skip_string(data,mdrcnt,data+offset) == NULL) {
2168
if (!pull_ascii_talloc(talloc_tos(), &pathname,
2169
offset ? (data+offset) : "", &converted_size))
2171
DEBUG(0,("api_RNetShareAdd: pull_ascii_talloc failed: %s",
2179
string_replace(sharename, '"', ' ');
2180
string_replace(pathname, '"', ' ');
2181
string_replace(comment, '"', ' ');
2183
cmdname = lp_add_share_cmd();
2185
if (!cmdname || *cmdname == '\0') {
2189
if (asprintf(&command, "%s \"%s\" \"%s\" \"%s\" \"%s\"",
2190
lp_add_share_cmd(), get_dyn_CONFIGFILE(), sharename,
2191
pathname, comment) == -1) {
2195
DEBUG(10,("api_RNetShareAdd: Running [%s]\n", command ));
2197
if ((res = smbrun(command, NULL)) != 0) {
2198
DEBUG(1,("api_RNetShareAdd: Running [%s] returned (%d)\n",
2205
message_send_all(smbd_messaging_context(),
2206
MSG_SMB_CONF_UPDATED, NULL, 0, NULL);
2210
*rparam = smb_realloc_limit(*rparam,*rparam_len);
2214
SSVAL(*rparam,0,NERR_Success);
2215
SSVAL(*rparam,2,0); /* converter word */
2216
SSVAL(*rparam,4,*rdata_len);
2224
*rparam = smb_realloc_limit(*rparam,*rparam_len);
2229
SSVAL(*rparam,0,res);
2234
/****************************************************************************
2235
view list of groups available
2236
****************************************************************************/
2238
static bool api_RNetGroupEnum(connection_struct *conn,uint16 vuid,
2239
char *param, int tpscnt,
2240
char *data, int tdscnt,
2241
int mdrcnt,int mprcnt,
2242
char **rdata,char **rparam,
2243
int *rdata_len,int *rparam_len)
2247
int resume_context, cli_buf_size;
2248
char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2249
char *str2 = skip_string(param,tpscnt,str1);
2250
char *p = skip_string(param,tpscnt,str2);
2252
uint32_t num_groups;
2253
uint32_t resume_handle;
2254
struct rpc_pipe_client *samr_pipe;
2255
struct policy_handle samr_handle, domain_handle;
2258
if (!str1 || !str2 || !p) {
2262
if (strcmp(str1,"WrLeh") != 0) {
2267
* W-> resume context (number of users to skip)
2268
* r -> return parameter pointer to receive buffer
2269
* L -> length of receive buffer
2270
* e -> return parameter number of entries
2271
* h -> return parameter total number of users
2274
if (strcmp("B21",str2) != 0) {
2278
status = rpc_pipe_open_internal(
2279
talloc_tos(), &ndr_table_samr.syntax_id, rpc_samr_dispatch,
2280
conn->server_info, &samr_pipe);
2281
if (!NT_STATUS_IS_OK(status)) {
2282
DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2283
nt_errstr(status)));
2287
status = rpccli_samr_Connect2(samr_pipe, talloc_tos(), global_myname(),
2288
SAMR_ACCESS_LOOKUP_DOMAIN, &samr_handle);
2289
if (!NT_STATUS_IS_OK(status)) {
2290
DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2291
nt_errstr(status)));
2295
status = rpccli_samr_OpenDomain(samr_pipe, talloc_tos(), &samr_handle,
2296
SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS,
2297
get_global_sam_sid(), &domain_handle);
2298
if (!NT_STATUS_IS_OK(status)) {
2299
DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2300
nt_errstr(status)));
2301
rpccli_samr_Close(samr_pipe, talloc_tos(), &samr_handle);
2305
resume_context = get_safe_SVAL(param,tpscnt,p,0,-1);
2306
cli_buf_size= get_safe_SVAL(param,tpscnt,p,2,0);
2307
DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: "
2308
"%d\n", resume_context, cli_buf_size));
2310
*rdata_len = cli_buf_size;
2311
*rdata = smb_realloc_limit(*rdata,*rdata_len);
2318
errflags = NERR_Success;
2323
struct samr_SamArray *sam_entries;
2324
uint32_t num_entries;
2326
status = rpccli_samr_EnumDomainGroups(samr_pipe, talloc_tos(),
2331
if (!NT_STATUS_IS_OK(status)) {
2332
DEBUG(10, ("rpccli_samr_EnumDomainGroups returned "
2333
"%s\n", nt_errstr(status)));
2337
if (num_entries == 0) {
2338
DEBUG(10, ("rpccli_samr_EnumDomainGroups returned "
2339
"no entries -- done\n"));
2343
for(i=0; i<num_entries; i++) {
2346
name = sam_entries->entries[i].name.string;
2348
if( ((PTR_DIFF(p,*rdata)+21) > *rdata_len) ) {
2349
/* set overflow error */
2350
DEBUG(3,("overflow on entry %d group %s\n", i,
2356
/* truncate the name at 21 chars. */
2358
strlcpy(p, name, 21);
2359
DEBUG(10,("adding entry %d group %s\n", i, p));
2361
p += 5; /* Both NT4 and W2k3SP1 do padding here. No
2366
if (errflags != NERR_Success) {
2370
TALLOC_FREE(sam_entries);
2373
rpccli_samr_Close(samr_pipe, talloc_tos(), &domain_handle);
2374
rpccli_samr_Close(samr_pipe, talloc_tos(), &samr_handle);
2376
*rdata_len = PTR_DIFF(p,*rdata);
2379
*rparam = smb_realloc_limit(*rparam,*rparam_len);
2383
SSVAL(*rparam, 0, errflags);
2384
SSVAL(*rparam, 2, 0); /* converter word */
2385
SSVAL(*rparam, 4, num_groups); /* is this right?? */
2386
SSVAL(*rparam, 6, resume_context+num_groups); /* is this right?? */
2391
/*******************************************************************
2392
Get groups that a user is a member of.
2393
******************************************************************/
2395
static bool api_NetUserGetGroups(connection_struct *conn,uint16 vuid,
2396
char *param, int tpscnt,
2397
char *data, int tdscnt,
2398
int mdrcnt,int mprcnt,
2399
char **rdata,char **rparam,
2400
int *rdata_len,int *rparam_len)
2402
char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2403
char *str2 = skip_string(param,tpscnt,str1);
2404
char *UserName = skip_string(param,tpscnt,str2);
2405
char *p = skip_string(param,tpscnt,UserName);
2406
int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
2407
const char *level_string;
2413
struct rpc_pipe_client *samr_pipe;
2414
struct policy_handle samr_handle, domain_handle, user_handle;
2415
struct lsa_String name;
2416
struct lsa_Strings names;
2417
struct samr_Ids type, rid;
2418
struct samr_RidWithAttributeArray *rids;
2421
if (!str1 || !str2 || !UserName || !p) {
2426
*rparam = smb_realloc_limit(*rparam,*rparam_len);
2431
/* check it's a supported varient */
2433
if ( strcmp(str1,"zWrLeh") != 0 )
2438
level_string = "B21";
2444
if (strcmp(level_string,str2) != 0)
2447
*rdata_len = mdrcnt + 1024;
2448
*rdata = smb_realloc_limit(*rdata,*rdata_len);
2453
SSVAL(*rparam,0,NERR_Success);
2454
SSVAL(*rparam,2,0); /* converter word */
2457
endp = *rdata + *rdata_len;
2459
status = rpc_pipe_open_internal(
2460
talloc_tos(), &ndr_table_samr.syntax_id, rpc_samr_dispatch,
2461
conn->server_info, &samr_pipe);
2462
if (!NT_STATUS_IS_OK(status)) {
2463
DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2464
nt_errstr(status)));
2468
status = rpccli_samr_Connect2(samr_pipe, talloc_tos(), global_myname(),
2469
SAMR_ACCESS_LOOKUP_DOMAIN, &samr_handle);
2470
if (!NT_STATUS_IS_OK(status)) {
2471
DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2472
nt_errstr(status)));
2476
status = rpccli_samr_OpenDomain(samr_pipe, talloc_tos(), &samr_handle,
2477
SAMR_DOMAIN_ACCESS_OPEN_ACCOUNT,
2478
get_global_sam_sid(), &domain_handle);
2479
if (!NT_STATUS_IS_OK(status)) {
2480
DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2481
nt_errstr(status)));
2485
name.string = UserName;
2487
status = rpccli_samr_LookupNames(samr_pipe, talloc_tos(),
2488
&domain_handle, 1, &name,
2490
if (!NT_STATUS_IS_OK(status)) {
2491
DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2492
nt_errstr(status)));
2496
if (type.ids[0] != SID_NAME_USER) {
2497
DEBUG(10, ("%s is a %s, not a user\n", UserName,
2498
sid_type_lookup(type.ids[0])));
2502
status = rpccli_samr_OpenUser(samr_pipe, talloc_tos(),
2504
SAMR_USER_ACCESS_GET_GROUPS,
2505
rid.ids[0], &user_handle);
2506
if (!NT_STATUS_IS_OK(status)) {
2507
DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2508
nt_errstr(status)));
2512
status = rpccli_samr_GetGroupsForUser(samr_pipe, talloc_tos(),
2513
&user_handle, &rids);
2514
if (!NT_STATUS_IS_OK(status)) {
2515
DEBUG(0, ("api_RNetUserEnum: samr_LookupNames failed: %s\n",
2516
nt_errstr(status)));
2520
for (i=0; i<rids->count; i++) {
2522
status = rpccli_samr_LookupRids(samr_pipe, talloc_tos(),
2524
1, &rids->rids[i].rid,
2526
if (NT_STATUS_IS_OK(status) && (names.count == 1)) {
2527
strlcpy(p, names.names[0].string, PTR_DIFF(endp,p));
2533
*rdata_len = PTR_DIFF(p,*rdata);
2535
SSVAL(*rparam,4,count); /* is this right?? */
2536
SSVAL(*rparam,6,count); /* is this right?? */
2541
rpccli_samr_Close(samr_pipe, talloc_tos(), &user_handle);
2543
rpccli_samr_Close(samr_pipe, talloc_tos(), &domain_handle);
2545
rpccli_samr_Close(samr_pipe, talloc_tos(), &samr_handle);
2550
/*******************************************************************
2552
******************************************************************/
2554
static bool api_RNetUserEnum(connection_struct *conn, uint16 vuid,
2555
char *param, int tpscnt,
2556
char *data, int tdscnt,
2557
int mdrcnt,int mprcnt,
2558
char **rdata,char **rparam,
2559
int *rdata_len,int *rparam_len)
2564
int i, resume_context, cli_buf_size;
2565
uint32_t resume_handle;
2567
struct rpc_pipe_client *samr_pipe;
2568
struct policy_handle samr_handle, domain_handle;
2571
char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2572
char *str2 = skip_string(param,tpscnt,str1);
2573
char *p = skip_string(param,tpscnt,str2);
2576
if (!str1 || !str2 || !p) {
2580
if (strcmp(str1,"WrLeh") != 0)
2583
* W-> resume context (number of users to skip)
2584
* r -> return parameter pointer to receive buffer
2585
* L -> length of receive buffer
2586
* e -> return parameter number of entries
2587
* h -> return parameter total number of users
2590
resume_context = get_safe_SVAL(param,tpscnt,p,0,-1);
2591
cli_buf_size= get_safe_SVAL(param,tpscnt,p,2,0);
2592
DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n",
2593
resume_context, cli_buf_size));
2596
*rparam = smb_realloc_limit(*rparam,*rparam_len);
2601
/* check it's a supported varient */
2602
if (strcmp("B21",str2) != 0)
2605
*rdata_len = cli_buf_size;
2606
*rdata = smb_realloc_limit(*rdata,*rdata_len);
2612
endp = *rdata + *rdata_len;
2614
status = rpc_pipe_open_internal(
2615
talloc_tos(), &ndr_table_samr.syntax_id, rpc_samr_dispatch,
2616
conn->server_info, &samr_pipe);
2617
if (!NT_STATUS_IS_OK(status)) {
2618
DEBUG(0, ("api_RNetUserEnum: Could not connect to samr: %s\n",
2619
nt_errstr(status)));
2623
status = rpccli_samr_Connect2(samr_pipe, talloc_tos(), global_myname(),
2624
SAMR_ACCESS_LOOKUP_DOMAIN, &samr_handle);
2625
if (!NT_STATUS_IS_OK(status)) {
2626
DEBUG(0, ("api_RNetUserEnum: samr_Connect2 failed: %s\n",
2627
nt_errstr(status)));
2631
status = rpccli_samr_OpenDomain(samr_pipe, talloc_tos(), &samr_handle,
2632
SAMR_DOMAIN_ACCESS_ENUM_ACCOUNTS,
2633
get_global_sam_sid(), &domain_handle);
2634
if (!NT_STATUS_IS_OK(status)) {
2635
DEBUG(0, ("api_RNetUserEnum: samr_OpenDomain failed: %s\n",
2636
nt_errstr(status)));
2637
rpccli_samr_Close(samr_pipe, talloc_tos(), &samr_handle);
2641
errflags=NERR_Success;
2646
struct samr_SamArray *sam_entries;
2647
uint32_t num_entries;
2649
status = rpccli_samr_EnumDomainUsers(samr_pipe, talloc_tos(),
2655
if (!NT_STATUS_IS_OK(status)) {
2656
DEBUG(10, ("rpccli_samr_EnumDomainUsers returned "
2657
"%s\n", nt_errstr(status)));
2661
if (num_entries == 0) {
2662
DEBUG(10, ("rpccli_samr_EnumDomainUsers returned "
2663
"no entries -- done\n"));
2667
for (i=0; i<num_entries; i++) {
2670
name = sam_entries->entries[i].name.string;
2672
if(((PTR_DIFF(p,*rdata)+21)<=*rdata_len)
2673
&&(strlen(name)<=21)) {
2674
strlcpy(p,name,PTR_DIFF(endp,p));
2675
DEBUG(10,("api_RNetUserEnum:adding entry %d "
2676
"username %s\n",count_sent,p));
2680
/* set overflow error */
2681
DEBUG(10,("api_RNetUserEnum:overflow on entry %d "
2682
"username %s\n",count_sent,name));
2688
if (errflags != NERR_Success) {
2692
TALLOC_FREE(sam_entries);
2695
rpccli_samr_Close(samr_pipe, talloc_tos(), &domain_handle);
2696
rpccli_samr_Close(samr_pipe, talloc_tos(), &samr_handle);
2698
*rdata_len = PTR_DIFF(p,*rdata);
2700
SSVAL(*rparam,0,errflags);
2701
SSVAL(*rparam,2,0); /* converter word */
2702
SSVAL(*rparam,4,count_sent); /* is this right?? */
2703
SSVAL(*rparam,6,num_users); /* is this right?? */
2708
/****************************************************************************
2709
Get the time of day info.
2710
****************************************************************************/
2712
static bool api_NetRemoteTOD(connection_struct *conn,uint16 vuid,
2713
char *param, int tpscnt,
2714
char *data, int tdscnt,
2715
int mdrcnt,int mprcnt,
2716
char **rdata,char **rparam,
2717
int *rdata_len,int *rparam_len)
2720
time_t unixdate = time(NULL);
2724
*rparam = smb_realloc_limit(*rparam,*rparam_len);
2730
*rdata = smb_realloc_limit(*rdata,*rdata_len);
2735
SSVAL(*rparam,0,NERR_Success);
2736
SSVAL(*rparam,2,0); /* converter word */
2740
srv_put_dos_date3(p,0,unixdate); /* this is the time that is looked at
2741
by NT in a "net time" operation,
2742
it seems to ignore the one below */
2744
/* the client expects to get localtime, not GMT, in this bit
2745
(I think, this needs testing) */
2746
t = localtime(&unixdate);
2751
SIVAL(p,4,0); /* msecs ? */
2752
SCVAL(p,8,t->tm_hour);
2753
SCVAL(p,9,t->tm_min);
2754
SCVAL(p,10,t->tm_sec);
2755
SCVAL(p,11,0); /* hundredths of seconds */
2756
SSVALS(p,12,get_time_zone(unixdate)/60); /* timezone in minutes from GMT */
2757
SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */
2758
SCVAL(p,16,t->tm_mday);
2759
SCVAL(p,17,t->tm_mon + 1);
2760
SSVAL(p,18,1900+t->tm_year);
2761
SCVAL(p,20,t->tm_wday);
2766
/****************************************************************************
2767
Set the user password.
2768
*****************************************************************************/
2770
static bool api_SetUserPassword(connection_struct *conn,uint16 vuid,
2771
char *param, int tpscnt,
2772
char *data, int tdscnt,
2773
int mdrcnt,int mprcnt,
2774
char **rdata,char **rparam,
2775
int *rdata_len,int *rparam_len)
2777
char *np = get_safe_str_ptr(param,tpscnt,param,2);
2780
fstring pass1,pass2;
2782
/* Skip 2 strings. */
2783
p = skip_string(param,tpscnt,np);
2784
p = skip_string(param,tpscnt,p);
2790
/* Do we have a string ? */
2791
if (skip_string(param,tpscnt,p) == NULL) {
2794
pull_ascii_fstring(user,p);
2796
p = skip_string(param,tpscnt,p);
2801
memset(pass1,'\0',sizeof(pass1));
2802
memset(pass2,'\0',sizeof(pass2));
2804
* We use 31 here not 32 as we're checking
2805
* the last byte we want to access is safe.
2807
if (!is_offset_safe(param,tpscnt,p,31)) {
2811
memcpy(pass2,p+16,16);
2814
*rparam = smb_realloc_limit(*rparam,*rparam_len);
2821
SSVAL(*rparam,0,NERR_badpass);
2822
SSVAL(*rparam,2,0); /* converter word */
2824
DEBUG(3,("Set password for <%s>\n",user));
2827
* Attempt to verify the old password against smbpasswd entries
2828
* Win98 clients send old and new password in plaintext for this call.
2832
auth_serversupplied_info *server_info = NULL;
2833
DATA_BLOB password = data_blob(pass1, strlen(pass1)+1);
2835
if (NT_STATUS_IS_OK(check_plaintext_password(user,password,&server_info))) {
2838
if (NT_STATUS_IS_OK(change_oem_password(server_info->sam_account, pass1, pass2, False, NULL))) {
2839
SSVAL(*rparam,0,NERR_Success);
2843
TALLOC_FREE(server_info);
2845
data_blob_clear_free(&password);
2849
* If the plaintext change failed, attempt
2850
* the old encrypted method. NT will generate this
2851
* after trying the samr method. Note that this
2852
* method is done as a last resort as this
2853
* password change method loses the NT password hash
2854
* and cannot change the UNIX password as no plaintext
2858
if(SVAL(*rparam,0) != NERR_Success) {
2859
struct samu *hnd = NULL;
2861
if (check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &hnd)) {
2863
if (change_lanman_password(hnd,(uchar *)pass2)) {
2864
SSVAL(*rparam,0,NERR_Success);
2871
memset((char *)pass1,'\0',sizeof(fstring));
2872
memset((char *)pass2,'\0',sizeof(fstring));
2877
/****************************************************************************
2878
Set the user password (SamOEM version - gets plaintext).
2879
****************************************************************************/
2881
static bool api_SamOEMChangePassword(connection_struct *conn,uint16 vuid,
2882
char *param, int tpscnt,
2883
char *data, int tdscnt,
2884
int mdrcnt,int mprcnt,
2885
char **rdata,char **rparam,
2886
int *rdata_len,int *rparam_len)
2889
char *p = get_safe_str_ptr(param,tpscnt,param,2);
2891
*rparam = smb_realloc_limit(*rparam,*rparam_len);
2901
SSVAL(*rparam,0,NERR_badpass);
2904
* Check the parameter definition is correct.
2907
/* Do we have a string ? */
2908
if (skip_string(param,tpscnt,p) == 0) {
2911
if(!strequal(p, "zsT")) {
2912
DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", p));
2915
p = skip_string(param, tpscnt, p);
2920
/* Do we have a string ? */
2921
if (skip_string(param,tpscnt,p) == 0) {
2924
if(!strequal(p, "B516B16")) {
2925
DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p));
2928
p = skip_string(param,tpscnt,p);
2932
/* Do we have a string ? */
2933
if (skip_string(param,tpscnt,p) == 0) {
2936
p += pull_ascii_fstring(user,p);
2938
DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user));
2941
* Pass the user through the NT -> unix user mapping
2945
(void)map_username(user);
2947
if (NT_STATUS_IS_OK(pass_oem_change(user, (uchar*) data, (uchar *)&data[516], NULL, NULL, NULL))) {
2948
SSVAL(*rparam,0,NERR_Success);
2954
/****************************************************************************
2957
****************************************************************************/
2959
static bool api_RDosPrintJobDel(connection_struct *conn,uint16 vuid,
2960
char *param, int tpscnt,
2961
char *data, int tdscnt,
2962
int mdrcnt,int mprcnt,
2963
char **rdata,char **rparam,
2964
int *rdata_len,int *rparam_len)
2966
int function = get_safe_SVAL(param,tpscnt,param,0,0);
2967
char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
2968
char *str2 = skip_string(param,tpscnt,str1);
2969
char *p = skip_string(param,tpscnt,str2);
2974
WERROR werr = WERR_OK;
2976
if (!str1 || !str2 || !p) {
2980
* We use 1 here not 2 as we're checking
2981
* the last byte we want to access is safe.
2983
if (!is_offset_safe(param,tpscnt,p,1)) {
2986
if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
2989
/* check it's a supported varient */
2990
if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
2994
*rparam = smb_realloc_limit(*rparam,*rparam_len);
3000
if (!print_job_exists(sharename, jobid)) {
3001
errcode = NERR_JobNotFound;
3005
snum = lp_servicenumber( sharename);
3007
errcode = NERR_DestNotFound;
3011
errcode = NERR_notsupported;
3014
case 81: /* delete */
3015
if (print_job_delete(conn->server_info, snum, jobid, &werr))
3016
errcode = NERR_Success;
3018
case 82: /* pause */
3019
if (print_job_pause(conn->server_info, snum, jobid, &werr))
3020
errcode = NERR_Success;
3022
case 83: /* resume */
3023
if (print_job_resume(conn->server_info, snum, jobid, &werr))
3024
errcode = NERR_Success;
3028
if (!W_ERROR_IS_OK(werr))
3029
errcode = W_ERROR_V(werr);
3032
SSVAL(*rparam,0,errcode);
3033
SSVAL(*rparam,2,0); /* converter word */
3038
/****************************************************************************
3039
Purge a print queue - or pause or resume it.
3040
****************************************************************************/
3042
static bool api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid,
3043
char *param, int tpscnt,
3044
char *data, int tdscnt,
3045
int mdrcnt,int mprcnt,
3046
char **rdata,char **rparam,
3047
int *rdata_len,int *rparam_len)
3049
int function = get_safe_SVAL(param,tpscnt,param,0,0);
3050
char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3051
char *str2 = skip_string(param,tpscnt,str1);
3052
char *QueueName = skip_string(param,tpscnt,str2);
3053
int errcode = NERR_notsupported;
3055
WERROR werr = WERR_OK;
3057
if (!str1 || !str2 || !QueueName) {
3061
/* check it's a supported varient */
3062
if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
3066
*rparam = smb_realloc_limit(*rparam,*rparam_len);
3072
if (skip_string(param,tpscnt,QueueName) == NULL) {
3075
snum = print_queue_snum(QueueName);
3078
errcode = NERR_JobNotFound;
3083
case 74: /* Pause queue */
3084
werr = print_queue_pause(conn->server_info, snum);
3086
case 75: /* Resume queue */
3087
werr = print_queue_resume(conn->server_info, snum);
3089
case 103: /* Purge */
3090
werr = print_queue_purge(conn->server_info, snum);
3093
werr = WERR_NOT_SUPPORTED;
3097
errcode = W_ERROR_V(werr);
3100
SSVAL(*rparam,0,errcode);
3101
SSVAL(*rparam,2,0); /* converter word */
3106
/****************************************************************************
3107
set the property of a print job (undocumented?)
3108
? function = 0xb -> set name of print job
3109
? function = 0x6 -> move print job up/down
3110
Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz>
3111
or <WWsTP> <WB21BB16B10zWWzDDz>
3112
****************************************************************************/
3114
static int check_printjob_info(struct pack_desc* desc,
3115
int uLevel, char* id)
3117
desc->subformat = NULL;
3119
case 0: desc->format = "W"; break;
3120
case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
3121
case 2: desc->format = "WWzWWDDzz"; break;
3122
case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
3123
case 4: desc->format = "WWzWWDDzzzzzDDDDDDD"; break;
3125
DEBUG(0,("check_printjob_info: invalid level %d\n",
3129
if (id == NULL || strcmp(desc->format,id) != 0) {
3130
DEBUG(0,("check_printjob_info: invalid format %s\n",
3131
id ? id : "<NULL>" ));
3137
static bool api_PrintJobInfo(connection_struct *conn, uint16 vuid,
3138
char *param, int tpscnt,
3139
char *data, int tdscnt,
3140
int mdrcnt,int mprcnt,
3141
char **rdata,char **rparam,
3142
int *rdata_len,int *rparam_len)
3144
struct pack_desc desc;
3145
char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3146
char *str2 = skip_string(param,tpscnt,str1);
3147
char *p = skip_string(param,tpscnt,str2);
3150
int uLevel = get_safe_SVAL(param,tpscnt,p,2,-1);
3151
int function = get_safe_SVAL(param,tpscnt,p,4,-1);
3154
if (!str1 || !str2 || !p) {
3158
* We use 1 here not 2 as we're checking
3159
* the last byte we want to access is safe.
3161
if (!is_offset_safe(param,tpscnt,p,1)) {
3164
if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
3167
*rparam = smb_realloc_limit(*rparam,*rparam_len);
3172
if (!share_defined(sharename)) {
3173
DEBUG(0,("api_PrintJobInfo: sharen [%s] not defined\n",
3180
/* check it's a supported varient */
3181
if ((strcmp(str1,"WWsTP")) ||
3182
(!check_printjob_info(&desc,uLevel,str2)))
3185
if (!print_job_exists(sharename, jobid)) {
3186
errcode=NERR_JobNotFound;
3190
errcode = NERR_notsupported;
3194
/* change job place in the queue,
3195
data gives the new place */
3196
place = SVAL(data,0);
3197
if (print_job_set_place(sharename, jobid, place)) {
3198
errcode=NERR_Success;
3203
/* change print job name, data gives the name */
3204
if (print_job_set_name(sharename, jobid, data)) {
3205
errcode=NERR_Success;
3214
SSVALS(*rparam,0,errcode);
3215
SSVAL(*rparam,2,0); /* converter word */
3221
/****************************************************************************
3222
Get info about the server.
3223
****************************************************************************/
3225
static bool api_RNetServerGetInfo(connection_struct *conn,uint16 vuid,
3226
char *param, int tpscnt,
3227
char *data, int tdscnt,
3228
int mdrcnt,int mprcnt,
3229
char **rdata,char **rparam,
3230
int *rdata_len,int *rparam_len)
3232
char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3233
char *str2 = skip_string(param,tpscnt,str1);
3234
char *p = skip_string(param,tpscnt,str2);
3235
int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
3239
if (!str1 || !str2 || !p) {
3243
DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
3245
/* check it's a supported varient */
3246
if (!prefix_ok(str1,"WrLh")) {
3252
if (strcmp(str2,"B16") != 0) {
3258
if (strcmp(str2,"B16BBDz") != 0) {
3264
if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")!= 0) {
3270
if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz") != 0) {
3276
if (strcmp(str2,"DN") != 0) {
3282
if (strcmp(str2,"B16BBDzWWzzz") != 0) {
3291
*rdata_len = mdrcnt;
3292
*rdata = smb_realloc_limit(*rdata,*rdata_len);
3298
p2 = p + struct_len;
3300
srvstr_push(NULL, 0, p,global_myname(),16,
3301
STR_ASCII|STR_UPPER|STR_TERMINATE);
3305
struct srv_info_struct *servers=NULL;
3307
char *comment = NULL;
3308
TALLOC_CTX *ctx = talloc_tos();
3309
uint32 servertype= lp_default_server_announce();
3311
comment = talloc_strdup(ctx,lp_serverstring());
3316
if ((count=get_server_info(SV_TYPE_ALL,&servers,lp_workgroup()))>0) {
3317
for (i=0;i<count;i++) {
3318
if (strequal(servers[i].name,global_myname())) {
3319
servertype = servers[i].type;
3320
TALLOC_FREE(comment);
3321
comment = talloc_strdup(ctx,
3322
servers[i].comment);
3332
SCVAL(p,0,lp_major_announce_version());
3333
SCVAL(p,1,lp_minor_announce_version());
3334
SIVAL(p,2,servertype);
3336
if (mdrcnt == struct_len) {
3339
SIVAL(p,6,PTR_DIFF(p2,*rdata));
3340
comment = talloc_sub_advanced(
3342
lp_servicename(SNUM(conn)),
3343
conn->server_info->unix_name,
3345
conn->server_info->utok.gid,
3346
conn->server_info->sanitized_username,
3347
pdb_get_domain(conn->server_info->sam_account),
3352
if (mdrcnt - struct_len <= 0) {
3357
MIN(mdrcnt - struct_len,
3358
MAX_SERVER_STRING_LENGTH),
3360
p2 = skip_string(*rdata,*rdata_len,p2);
3368
return False; /* not yet implemented */
3371
*rdata_len = PTR_DIFF(p2,*rdata);
3374
*rparam = smb_realloc_limit(*rparam,*rparam_len);
3378
SSVAL(*rparam,0,NERR_Success);
3379
SSVAL(*rparam,2,0); /* converter word */
3380
SSVAL(*rparam,4,*rdata_len);
3385
/****************************************************************************
3386
Get info about the server.
3387
****************************************************************************/
3389
static bool api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid,
3390
char *param, int tpscnt,
3391
char *data, int tdscnt,
3392
int mdrcnt,int mprcnt,
3393
char **rdata,char **rparam,
3394
int *rdata_len,int *rparam_len)
3396
char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3397
char *str2 = skip_string(param,tpscnt,str1);
3398
char *p = skip_string(param,tpscnt,str2);
3401
int level = get_safe_SVAL(param,tpscnt,p,0,-1);
3403
if (!str1 || !str2 || !p) {
3407
DEBUG(4,("NetWkstaGetInfo level %d\n",level));
3410
*rparam = smb_realloc_limit(*rparam,*rparam_len);
3415
/* check it's a supported varient */
3416
if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz"))) {
3420
*rdata_len = mdrcnt + 1024;
3421
*rdata = smb_realloc_limit(*rdata,*rdata_len);
3426
SSVAL(*rparam,0,NERR_Success);
3427
SSVAL(*rparam,2,0); /* converter word */
3430
endp = *rdata + *rdata_len;
3432
p2 = get_safe_ptr(*rdata,*rdata_len,p,22);
3437
SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
3438
strlcpy(p2,get_local_machine_name(),PTR_DIFF(endp,p2));
3440
p2 = skip_string(*rdata,*rdata_len,p2);
3446
SIVAL(p,0,PTR_DIFF(p2,*rdata));
3447
strlcpy(p2,conn->server_info->sanitized_username,PTR_DIFF(endp,p2));
3448
p2 = skip_string(*rdata,*rdata_len,p2);
3454
SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
3455
strlcpy(p2,lp_workgroup(),PTR_DIFF(endp,p2));
3457
p2 = skip_string(*rdata,*rdata_len,p2);
3463
SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
3464
SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
3467
SIVAL(p,0,PTR_DIFF(p2,*rdata));
3468
strlcpy(p2,lp_workgroup(),PTR_DIFF(endp,p2)); /* don't know. login domain?? */
3469
p2 = skip_string(*rdata,*rdata_len,p2);
3475
SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
3476
strlcpy(p2,"",PTR_DIFF(endp,p2));
3477
p2 = skip_string(*rdata,*rdata_len,p2);
3483
*rdata_len = PTR_DIFF(p2,*rdata);
3485
SSVAL(*rparam,4,*rdata_len);
3490
/****************************************************************************
3491
get info about a user
3493
struct user_info_11 {
3494
char usri11_name[21]; 0-20
3496
char *usri11_comment; 22-25
3497
char *usri11_usr_comment; 26-29
3498
unsigned short usri11_priv; 30-31
3499
unsigned long usri11_auth_flags; 32-35
3500
long usri11_password_age; 36-39
3501
char *usri11_homedir; 40-43
3502
char *usri11_parms; 44-47
3503
long usri11_last_logon; 48-51
3504
long usri11_last_logoff; 52-55
3505
unsigned short usri11_bad_pw_count; 56-57
3506
unsigned short usri11_num_logons; 58-59
3507
char *usri11_logon_server; 60-63
3508
unsigned short usri11_country_code; 64-65
3509
char *usri11_workstations; 66-69
3510
unsigned long usri11_max_storage; 70-73
3511
unsigned short usri11_units_per_week; 74-75
3512
unsigned char *usri11_logon_hours; 76-79
3513
unsigned short usri11_code_page; 80-81
3518
usri11_name specifies the user name for which information is retrieved
3520
usri11_pad aligns the next data structure element to a word boundary
3522
usri11_comment is a null terminated ASCII comment
3524
usri11_user_comment is a null terminated ASCII comment about the user
3526
usri11_priv specifies the level of the privilege assigned to the user.
3527
The possible values are:
3529
Name Value Description
3530
USER_PRIV_GUEST 0 Guest privilege
3531
USER_PRIV_USER 1 User privilege
3532
USER_PRV_ADMIN 2 Administrator privilege
3534
usri11_auth_flags specifies the account operator privileges. The
3535
possible values are:
3537
Name Value Description
3538
AF_OP_PRINT 0 Print operator
3541
Leach, Naik [Page 28]
3545
INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
3548
AF_OP_COMM 1 Communications operator
3549
AF_OP_SERVER 2 Server operator
3550
AF_OP_ACCOUNTS 3 Accounts operator
3553
usri11_password_age specifies how many seconds have elapsed since the
3554
password was last changed.
3556
usri11_home_dir points to a null terminated ASCII string that contains
3557
the path name of the user's home directory.
3559
usri11_parms points to a null terminated ASCII string that is set
3560
aside for use by applications.
3562
usri11_last_logon specifies the time when the user last logged on.
3563
This value is stored as the number of seconds elapsed since
3564
00:00:00, January 1, 1970.
3566
usri11_last_logoff specifies the time when the user last logged off.
3567
This value is stored as the number of seconds elapsed since
3568
00:00:00, January 1, 1970. A value of 0 means the last logoff
3571
usri11_bad_pw_count specifies the number of incorrect passwords
3572
entered since the last successful logon.
3574
usri11_log1_num_logons specifies the number of times this user has
3575
logged on. A value of -1 means the number of logons is unknown.
3577
usri11_logon_server points to a null terminated ASCII string that
3578
contains the name of the server to which logon requests are sent.
3579
A null string indicates logon requests should be sent to the
3582
usri11_country_code specifies the country code for the user's language
3585
usri11_workstations points to a null terminated ASCII string that
3586
contains the names of workstations the user may log on from.
3587
There may be up to 8 workstations, with the names separated by
3588
commas. A null strings indicates there are no restrictions.
3590
usri11_max_storage specifies the maximum amount of disk space the user
3591
can occupy. A value of 0xffffffff indicates there are no
3594
usri11_units_per_week specifies the equal number of time units into
3595
which a week is divided. This value must be equal to 168.
3597
usri11_logon_hours points to a 21 byte (168 bits) string that
3598
specifies the time during which the user can log on. Each bit
3599
represents one unique hour in a week. The first bit (bit 0, word
3600
0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
3604
Leach, Naik [Page 29]
3608
INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997
3611
Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
3612
are no restrictions.
3614
usri11_code_page specifies the code page for the user's language of
3617
All of the pointers in this data structure need to be treated
3618
specially. The pointer is a 32 bit pointer. The higher 16 bits need
3619
to be ignored. The converter word returned in the parameters section
3620
needs to be subtracted from the lower 16 bits to calculate an offset
3621
into the return buffer where this ASCII string resides.
3623
There is no auxiliary data in the response.
3625
****************************************************************************/
3627
#define usri11_name 0
3628
#define usri11_pad 21
3629
#define usri11_comment 22
3630
#define usri11_usr_comment 26
3631
#define usri11_full_name 30
3632
#define usri11_priv 34
3633
#define usri11_auth_flags 36
3634
#define usri11_password_age 40
3635
#define usri11_homedir 44
3636
#define usri11_parms 48
3637
#define usri11_last_logon 52
3638
#define usri11_last_logoff 56
3639
#define usri11_bad_pw_count 60
3640
#define usri11_num_logons 62
3641
#define usri11_logon_server 64
3642
#define usri11_country_code 68
3643
#define usri11_workstations 70
3644
#define usri11_max_storage 74
3645
#define usri11_units_per_week 78
3646
#define usri11_logon_hours 80
3647
#define usri11_code_page 84
3648
#define usri11_end 86
3650
#define USER_PRIV_GUEST 0
3651
#define USER_PRIV_USER 1
3652
#define USER_PRIV_ADMIN 2
3654
#define AF_OP_PRINT 0
3655
#define AF_OP_COMM 1
3656
#define AF_OP_SERVER 2
3657
#define AF_OP_ACCOUNTS 3
3660
static bool api_RNetUserGetInfo(connection_struct *conn, uint16 vuid,
3661
char *param, int tpscnt,
3662
char *data, int tdscnt,
3663
int mdrcnt,int mprcnt,
3664
char **rdata,char **rparam,
3665
int *rdata_len,int *rparam_len)
3667
char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3668
char *str2 = skip_string(param,tpscnt,str1);
3669
char *UserName = skip_string(param,tpscnt,str2);
3670
char *p = skip_string(param,tpscnt,UserName);
3671
int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
3674
const char *level_string;
3676
/* get NIS home of a previously validated user - simeon */
3677
/* With share level security vuid will always be zero.
3678
Don't depend on vuser being non-null !!. JRA */
3679
user_struct *vuser = get_valid_user_struct(vuid);
3681
DEBUG(3,(" Username of UID %d is %s\n",
3682
(int)vuser->server_info->utok.uid,
3683
vuser->server_info->unix_name));
3686
if (!str1 || !str2 || !UserName || !p) {
3691
*rparam = smb_realloc_limit(*rparam,*rparam_len);
3696
DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
3698
/* check it's a supported variant */
3699
if (strcmp(str1,"zWrLh") != 0) {
3703
case 0: level_string = "B21"; break;
3704
case 1: level_string = "B21BB16DWzzWz"; break;
3705
case 2: level_string = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
3706
case 10: level_string = "B21Bzzz"; break;
3707
case 11: level_string = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
3708
default: return False;
3711
if (strcmp(level_string,str2) != 0) {
3715
*rdata_len = mdrcnt + 1024;
3716
*rdata = smb_realloc_limit(*rdata,*rdata_len);
3721
SSVAL(*rparam,0,NERR_Success);
3722
SSVAL(*rparam,2,0); /* converter word */
3725
endp = *rdata + *rdata_len;
3726
p2 = get_safe_ptr(*rdata,*rdata_len,p,usri11_end);
3732
fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
3735
SCVAL(p,usri11_pad,0); /* padding - 1 byte */
3740
SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
3741
strlcpy(p2,"Comment",PTR_DIFF(endp,p2));
3742
p2 = skip_string(*rdata,*rdata_len,p2);
3747
SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
3748
strlcpy(p2,"UserComment",PTR_DIFF(endp,p2));
3749
p2 = skip_string(*rdata,*rdata_len,p2);
3754
/* EEK! the cifsrap.txt doesn't have this in!!!! */
3755
SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
3756
strlcpy(p2,((vuser != NULL)
3757
? pdb_get_fullname(vuser->server_info->sam_account)
3758
: UserName),PTR_DIFF(endp,p2));
3759
p2 = skip_string(*rdata,*rdata_len,p2);
3766
const char *homedir = "";
3767
if (vuser != NULL) {
3768
homedir = pdb_get_homedir(
3769
vuser->server_info->sam_account);
3771
/* modelled after NTAS 3.51 reply */
3772
SSVAL(p,usri11_priv,conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
3773
SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
3774
SIVALS(p,usri11_password_age,-1); /* password age */
3775
SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
3776
strlcpy(p2, homedir, PTR_DIFF(endp,p2));
3777
p2 = skip_string(*rdata,*rdata_len,p2);
3781
SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
3782
strlcpy(p2,"",PTR_DIFF(endp,p2));
3783
p2 = skip_string(*rdata,*rdata_len,p2);
3787
SIVAL(p,usri11_last_logon,0); /* last logon */
3788
SIVAL(p,usri11_last_logoff,0); /* last logoff */
3789
SSVALS(p,usri11_bad_pw_count,-1); /* bad pw counts */
3790
SSVALS(p,usri11_num_logons,-1); /* num logons */
3791
SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
3792
strlcpy(p2,"\\\\*",PTR_DIFF(endp,p2));
3793
p2 = skip_string(*rdata,*rdata_len,p2);
3797
SSVAL(p,usri11_country_code,0); /* country code */
3799
SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
3800
strlcpy(p2,"",PTR_DIFF(endp,p2));
3801
p2 = skip_string(*rdata,*rdata_len,p2);
3806
SIVALS(p,usri11_max_storage,-1); /* max storage */
3807
SSVAL(p,usri11_units_per_week,168); /* units per week */
3808
SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
3810
/* a simple way to get logon hours at all times. */
3812
SCVAL(p2,21,0); /* fix zero termination */
3813
p2 = skip_string(*rdata,*rdata_len,p2);
3818
SSVAL(p,usri11_code_page,0); /* code page */
3821
if (uLevel == 1 || uLevel == 2) {
3822
memset(p+22,' ',16); /* password */
3823
SIVALS(p,38,-1); /* password age */
3825
conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
3826
SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
3827
strlcpy(p2, vuser ? pdb_get_homedir(
3828
vuser->server_info->sam_account) : "",
3830
p2 = skip_string(*rdata,*rdata_len,p2);
3834
SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
3836
SSVAL(p,52,0); /* flags */
3837
SIVAL(p,54,PTR_DIFF(p2,*rdata)); /* script_path */
3838
strlcpy(p2, vuser ? pdb_get_logon_script(
3839
vuser->server_info->sam_account) : "",
3841
p2 = skip_string(*rdata,*rdata_len,p2);
3846
SIVAL(p,60,0); /* auth_flags */
3847
SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
3848
strlcpy(p2,((vuser != NULL)
3849
? pdb_get_fullname(vuser->server_info->sam_account)
3850
: UserName),PTR_DIFF(endp,p2));
3851
p2 = skip_string(*rdata,*rdata_len,p2);
3855
SIVAL(p,68,0); /* urs_comment */
3856
SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
3857
strlcpy(p2,"",PTR_DIFF(endp,p2));
3858
p2 = skip_string(*rdata,*rdata_len,p2);
3862
SIVAL(p,76,0); /* workstations */
3863
SIVAL(p,80,0); /* last_logon */
3864
SIVAL(p,84,0); /* last_logoff */
3865
SIVALS(p,88,-1); /* acct_expires */
3866
SIVALS(p,92,-1); /* max_storage */
3867
SSVAL(p,96,168); /* units_per_week */
3868
SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
3871
SSVALS(p,102,-1); /* bad_pw_count */
3872
SSVALS(p,104,-1); /* num_logons */
3873
SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
3875
TALLOC_CTX *ctx = talloc_tos();
3876
int space_rem = *rdata_len - (p2 - *rdata);
3879
if (space_rem <= 0) {
3882
tmp = talloc_strdup(ctx, "\\\\%L");
3886
tmp = talloc_sub_basic(ctx,
3899
p2 = skip_string(*rdata,*rdata_len,p2);
3903
SSVAL(p,110,49); /* country_code */
3904
SSVAL(p,112,860); /* code page */
3908
*rdata_len = PTR_DIFF(p2,*rdata);
3910
SSVAL(*rparam,4,*rdata_len); /* is this right?? */
3915
static bool api_WWkstaUserLogon(connection_struct *conn,uint16 vuid,
3916
char *param, int tpscnt,
3917
char *data, int tdscnt,
3918
int mdrcnt,int mprcnt,
3919
char **rdata,char **rparam,
3920
int *rdata_len,int *rparam_len)
3922
char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
3923
char *str2 = skip_string(param,tpscnt,str1);
3924
char *p = skip_string(param,tpscnt,str2);
3926
struct pack_desc desc;
3928
/* With share level security vuid will always be zero.
3929
Don't depend on vuser being non-null !!. JRA */
3930
user_struct *vuser = get_valid_user_struct(vuid);
3932
if (!str1 || !str2 || !p) {
3937
DEBUG(3,(" Username of UID %d is %s\n",
3938
(int)vuser->server_info->utok.uid,
3939
vuser->server_info->unix_name));
3942
uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
3943
name = get_safe_str_ptr(param,tpscnt,p,2);
3948
memset((char *)&desc,'\0',sizeof(desc));
3950
DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
3952
/* check it's a supported varient */
3953
if (strcmp(str1,"OOWb54WrLh") != 0) {
3956
if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) {
3960
*rdata = smb_realloc_limit(*rdata,mdrcnt);
3967
desc.buflen = mdrcnt;
3968
desc.subformat = NULL;
3971
if (init_package(&desc,1,0)) {
3972
PACKI(&desc,"W",0); /* code */
3973
PACKS(&desc,"B21",name); /* eff. name */
3974
PACKS(&desc,"B",""); /* pad */
3975
PACKI(&desc,"W", conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
3976
PACKI(&desc,"D",0); /* auth flags XXX */
3977
PACKI(&desc,"W",0); /* num logons */
3978
PACKI(&desc,"W",0); /* bad pw count */
3979
PACKI(&desc,"D",0); /* last logon */
3980
PACKI(&desc,"D",-1); /* last logoff */
3981
PACKI(&desc,"D",-1); /* logoff time */
3982
PACKI(&desc,"D",-1); /* kickoff time */
3983
PACKI(&desc,"D",0); /* password age */
3984
PACKI(&desc,"D",0); /* password can change */
3985
PACKI(&desc,"D",-1); /* password must change */
3989
fstrcpy(mypath,"\\\\");
3990
fstrcat(mypath,get_local_machine_name());
3992
PACKS(&desc,"z",mypath); /* computer */
3995
PACKS(&desc,"z",lp_workgroup());/* domain */
3996
PACKS(&desc,"z", vuser ? pdb_get_logon_script(
3997
vuser->server_info->sam_account) : ""); /* script path */
3998
PACKI(&desc,"D",0x00000000); /* reserved */
4001
*rdata_len = desc.usedlen;
4003
*rparam = smb_realloc_limit(*rparam,*rparam_len);
4007
SSVALS(*rparam,0,desc.errcode);
4009
SSVAL(*rparam,4,desc.neededlen);
4011
DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
4016
/****************************************************************************
4017
api_WAccessGetUserPerms
4018
****************************************************************************/
4020
static bool api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid,
4021
char *param, int tpscnt,
4022
char *data, int tdscnt,
4023
int mdrcnt,int mprcnt,
4024
char **rdata,char **rparam,
4025
int *rdata_len,int *rparam_len)
4027
char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4028
char *str2 = skip_string(param,tpscnt,str1);
4029
char *user = skip_string(param,tpscnt,str2);
4030
char *resource = skip_string(param,tpscnt,user);
4032
if (!str1 || !str2 || !user || !resource) {
4036
if (skip_string(param,tpscnt,resource) == NULL) {
4039
DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
4041
/* check it's a supported varient */
4042
if (strcmp(str1,"zzh") != 0) {
4045
if (strcmp(str2,"") != 0) {
4050
*rparam = smb_realloc_limit(*rparam,*rparam_len);
4054
SSVALS(*rparam,0,0); /* errorcode */
4055
SSVAL(*rparam,2,0); /* converter word */
4056
SSVAL(*rparam,4,0x7f); /* permission flags */
4061
/****************************************************************************
4062
api_WPrintJobEnumerate
4063
****************************************************************************/
4065
static bool api_WPrintJobGetInfo(connection_struct *conn, uint16 vuid,
4066
char *param, int tpscnt,
4067
char *data, int tdscnt,
4068
int mdrcnt,int mprcnt,
4069
char **rdata,char **rparam,
4070
int *rdata_len,int *rparam_len)
4072
char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4073
char *str2 = skip_string(param,tpscnt,str1);
4074
char *p = skip_string(param,tpscnt,str2);
4081
struct pack_desc desc;
4082
print_queue_struct *queue=NULL;
4083
print_status_struct status;
4086
if (!str1 || !str2 || !p) {
4090
uLevel = get_safe_SVAL(param,tpscnt,p,2,-1);
4092
memset((char *)&desc,'\0',sizeof(desc));
4093
memset((char *)&status,'\0',sizeof(status));
4095
DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
4097
/* check it's a supported varient */
4098
if (strcmp(str1,"WWrLh") != 0) {
4101
if (!check_printjob_info(&desc,uLevel,str2)) {
4105
if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid)) {
4109
snum = lp_servicenumber( sharename);
4110
if (snum < 0 || !VALID_SNUM(snum)) {
4114
count = print_queue_status(snum,&queue,&status);
4115
for (i = 0; i < count; i++) {
4116
if (queue[i].job == jobid) {
4122
*rdata = smb_realloc_limit(*rdata,mdrcnt);
4127
desc.buflen = mdrcnt;
4130
* Don't return data but need to get correct length
4131
* init_package will return wrong size if buflen=0
4133
desc.buflen = getlen(desc.format);
4134
desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen );
4137
if (init_package(&desc,1,0)) {
4139
fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
4140
*rdata_len = desc.usedlen;
4142
desc.errcode = NERR_JobNotFound;
4148
*rparam = smb_realloc_limit(*rparam,*rparam_len);
4152
SSVALS(*rparam,0,desc.errcode);
4154
SSVAL(*rparam,4,desc.neededlen);
4159
DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
4164
static bool api_WPrintJobEnumerate(connection_struct *conn, uint16 vuid,
4165
char *param, int tpscnt,
4166
char *data, int tdscnt,
4167
int mdrcnt,int mprcnt,
4168
char **rdata,char **rparam,
4169
int *rdata_len,int *rparam_len)
4171
char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4172
char *str2 = skip_string(param,tpscnt,str1);
4173
char *p = skip_string(param,tpscnt,str2);
4179
struct pack_desc desc;
4180
print_queue_struct *queue=NULL;
4181
print_status_struct status;
4183
if (!str1 || !str2 || !p) {
4187
memset((char *)&desc,'\0',sizeof(desc));
4188
memset((char *)&status,'\0',sizeof(status));
4190
p = skip_string(param,tpscnt,p);
4194
uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4196
DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
4198
/* check it's a supported variant */
4199
if (strcmp(str1,"zWrLeh") != 0) {
4204
return False; /* defined only for uLevel 0,1,2 */
4207
if (!check_printjob_info(&desc,uLevel,str2)) {
4211
snum = find_service(name);
4212
if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) ) {
4216
count = print_queue_status(snum,&queue,&status);
4218
*rdata = smb_realloc_limit(*rdata,mdrcnt);
4224
desc.buflen = mdrcnt;
4226
if (init_package(&desc,count,0)) {
4228
for (i = 0; i < count; i++) {
4229
fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
4230
if (desc.errcode == NERR_Success) {
4236
*rdata_len = desc.usedlen;
4239
*rparam = smb_realloc_limit(*rparam,*rparam_len);
4243
SSVALS(*rparam,0,desc.errcode);
4245
SSVAL(*rparam,4,succnt);
4246
SSVAL(*rparam,6,count);
4250
DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
4255
static int check_printdest_info(struct pack_desc* desc,
4256
int uLevel, char* id)
4258
desc->subformat = NULL;
4261
desc->format = "B9";
4264
desc->format = "B9B21WWzW";
4270
desc->format = "zzzWWzzzWW";
4273
DEBUG(0,("check_printdest_info: invalid level %d\n",
4277
if (id == NULL || strcmp(desc->format,id) != 0) {
4278
DEBUG(0,("check_printdest_info: invalid string %s\n",
4279
id ? id : "<NULL>" ));
4285
static void fill_printdest_info(connection_struct *conn, int snum, int uLevel,
4286
struct pack_desc* desc)
4290
strncpy(buf,SERVICE(snum),sizeof(buf)-1);
4291
buf[sizeof(buf)-1] = 0;
4295
PACKS(desc,"B9",buf); /* szName */
4297
PACKS(desc,"B21",""); /* szUserName */
4298
PACKI(desc,"W",0); /* uJobId */
4299
PACKI(desc,"W",0); /* fsStatus */
4300
PACKS(desc,"z",""); /* pszStatus */
4301
PACKI(desc,"W",0); /* time */
4305
if (uLevel == 2 || uLevel == 3) {
4306
PACKS(desc,"z",buf); /* pszPrinterName */
4308
PACKS(desc,"z",""); /* pszUserName */
4309
PACKS(desc,"z",""); /* pszLogAddr */
4310
PACKI(desc,"W",0); /* uJobId */
4311
PACKI(desc,"W",0); /* fsStatus */
4312
PACKS(desc,"z",""); /* pszStatus */
4313
PACKS(desc,"z",""); /* pszComment */
4314
PACKS(desc,"z","NULL"); /* pszDrivers */
4315
PACKI(desc,"W",0); /* time */
4316
PACKI(desc,"W",0); /* pad1 */
4321
static bool api_WPrintDestGetInfo(connection_struct *conn, uint16 vuid,
4322
char *param, int tpscnt,
4323
char *data, int tdscnt,
4324
int mdrcnt,int mprcnt,
4325
char **rdata,char **rparam,
4326
int *rdata_len,int *rparam_len)
4328
char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4329
char *str2 = skip_string(param,tpscnt,str1);
4330
char *p = skip_string(param,tpscnt,str2);
4331
char* PrinterName = p;
4333
struct pack_desc desc;
4337
if (!str1 || !str2 || !p) {
4341
memset((char *)&desc,'\0',sizeof(desc));
4343
p = skip_string(param,tpscnt,p);
4347
uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4349
DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
4351
/* check it's a supported varient */
4352
if (strcmp(str1,"zWrLh") != 0) {
4355
if (!check_printdest_info(&desc,uLevel,str2)) {
4359
snum = find_service(PrinterName);
4360
if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) ) {
4362
desc.errcode = NERR_DestNotFound;
4366
*rdata = smb_realloc_limit(*rdata,mdrcnt);
4371
desc.buflen = mdrcnt;
4374
* Don't return data but need to get correct length
4375
* init_package will return wrong size if buflen=0
4377
desc.buflen = getlen(desc.format);
4378
desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen );
4380
if (init_package(&desc,1,0)) {
4381
fill_printdest_info(conn,snum,uLevel,&desc);
4383
*rdata_len = desc.usedlen;
4387
*rparam = smb_realloc_limit(*rparam,*rparam_len);
4391
SSVALS(*rparam,0,desc.errcode);
4393
SSVAL(*rparam,4,desc.neededlen);
4395
DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
4401
static bool api_WPrintDestEnum(connection_struct *conn, uint16 vuid,
4402
char *param, int tpscnt,
4403
char *data, int tdscnt,
4404
int mdrcnt,int mprcnt,
4405
char **rdata,char **rparam,
4406
int *rdata_len,int *rparam_len)
4408
char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4409
char *str2 = skip_string(param,tpscnt,str1);
4410
char *p = skip_string(param,tpscnt,str2);
4414
struct pack_desc desc;
4415
int services = lp_numservices();
4417
if (!str1 || !str2 || !p) {
4421
memset((char *)&desc,'\0',sizeof(desc));
4423
uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4425
DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
4427
/* check it's a supported varient */
4428
if (strcmp(str1,"WrLeh") != 0) {
4431
if (!check_printdest_info(&desc,uLevel,str2)) {
4436
for (i = 0; i < services; i++) {
4437
if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
4443
*rdata = smb_realloc_limit(*rdata,mdrcnt);
4450
desc.buflen = mdrcnt;
4451
if (init_package(&desc,queuecnt,0)) {
4454
for (i = 0; i < services; i++) {
4455
if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
4456
fill_printdest_info(conn,i,uLevel,&desc);
4458
if (desc.errcode == NERR_Success) {
4465
*rdata_len = desc.usedlen;
4468
*rparam = smb_realloc_limit(*rparam,*rparam_len);
4472
SSVALS(*rparam,0,desc.errcode);
4474
SSVAL(*rparam,4,succnt);
4475
SSVAL(*rparam,6,queuecnt);
4477
DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
4482
static bool api_WPrintDriverEnum(connection_struct *conn, uint16 vuid,
4483
char *param, int tpscnt,
4484
char *data, int tdscnt,
4485
int mdrcnt,int mprcnt,
4486
char **rdata,char **rparam,
4487
int *rdata_len,int *rparam_len)
4489
char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4490
char *str2 = skip_string(param,tpscnt,str1);
4491
char *p = skip_string(param,tpscnt,str2);
4494
struct pack_desc desc;
4496
if (!str1 || !str2 || !p) {
4500
memset((char *)&desc,'\0',sizeof(desc));
4502
uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4504
DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
4506
/* check it's a supported varient */
4507
if (strcmp(str1,"WrLeh") != 0) {
4510
if (uLevel != 0 || strcmp(str2,"B41") != 0) {
4515
*rdata = smb_realloc_limit(*rdata,mdrcnt);
4521
desc.buflen = mdrcnt;
4522
if (init_package(&desc,1,0)) {
4523
PACKS(&desc,"B41","NULL");
4526
succnt = (desc.errcode == NERR_Success ? 1 : 0);
4528
*rdata_len = desc.usedlen;
4531
*rparam = smb_realloc_limit(*rparam,*rparam_len);
4535
SSVALS(*rparam,0,desc.errcode);
4537
SSVAL(*rparam,4,succnt);
4540
DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
4545
static bool api_WPrintQProcEnum(connection_struct *conn, uint16 vuid,
4546
char *param, int tpscnt,
4547
char *data, int tdscnt,
4548
int mdrcnt,int mprcnt,
4549
char **rdata,char **rparam,
4550
int *rdata_len,int *rparam_len)
4552
char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4553
char *str2 = skip_string(param,tpscnt,str1);
4554
char *p = skip_string(param,tpscnt,str2);
4557
struct pack_desc desc;
4559
if (!str1 || !str2 || !p) {
4562
memset((char *)&desc,'\0',sizeof(desc));
4564
uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4566
DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
4568
/* check it's a supported varient */
4569
if (strcmp(str1,"WrLeh") != 0) {
4572
if (uLevel != 0 || strcmp(str2,"B13") != 0) {
4577
*rdata = smb_realloc_limit(*rdata,mdrcnt);
4583
desc.buflen = mdrcnt;
4585
if (init_package(&desc,1,0)) {
4586
PACKS(&desc,"B13","lpd");
4589
succnt = (desc.errcode == NERR_Success ? 1 : 0);
4591
*rdata_len = desc.usedlen;
4594
*rparam = smb_realloc_limit(*rparam,*rparam_len);
4598
SSVALS(*rparam,0,desc.errcode);
4600
SSVAL(*rparam,4,succnt);
4603
DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
4608
static bool api_WPrintPortEnum(connection_struct *conn, uint16 vuid,
4609
char *param, int tpscnt,
4610
char *data, int tdscnt,
4611
int mdrcnt,int mprcnt,
4612
char **rdata,char **rparam,
4613
int *rdata_len,int *rparam_len)
4615
char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4616
char *str2 = skip_string(param,tpscnt,str1);
4617
char *p = skip_string(param,tpscnt,str2);
4620
struct pack_desc desc;
4622
if (!str1 || !str2 || !p) {
4626
memset((char *)&desc,'\0',sizeof(desc));
4628
uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4630
DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
4632
/* check it's a supported varient */
4633
if (strcmp(str1,"WrLeh") != 0) {
4636
if (uLevel != 0 || strcmp(str2,"B9") != 0) {
4641
*rdata = smb_realloc_limit(*rdata,mdrcnt);
4646
memset((char *)&desc,'\0',sizeof(desc));
4648
desc.buflen = mdrcnt;
4650
if (init_package(&desc,1,0)) {
4651
PACKS(&desc,"B13","lp0");
4654
succnt = (desc.errcode == NERR_Success ? 1 : 0);
4656
*rdata_len = desc.usedlen;
4659
*rparam = smb_realloc_limit(*rparam,*rparam_len);
4663
SSVALS(*rparam,0,desc.errcode);
4665
SSVAL(*rparam,4,succnt);
4668
DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
4673
/****************************************************************************
4675
****************************************************************************/
4677
static bool api_RNetSessionEnum(connection_struct *conn, uint16 vuid,
4678
char *param, int tpscnt,
4679
char *data, int tdscnt,
4680
int mdrcnt,int mprcnt,
4681
char **rdata,char **rparam,
4682
int *rdata_len,int *rparam_len)
4685
char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
4686
char *str2 = skip_string(param,tpscnt,str1);
4687
char *p = skip_string(param,tpscnt,str2);
4689
struct pack_desc desc;
4690
struct sessionid *session_list;
4691
int i, num_sessions;
4693
if (!str1 || !str2 || !p) {
4697
memset((char *)&desc,'\0',sizeof(desc));
4699
uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
4701
DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel));
4702
DEBUG(7,("RNetSessionEnum req string=%s\n",str1));
4703
DEBUG(7,("RNetSessionEnum ret string=%s\n",str2));
4705
/* check it's a supported varient */
4706
if (strcmp(str1,RAP_NetSessionEnum_REQ) != 0) {
4709
if (uLevel != 2 || strcmp(str2,RAP_SESSION_INFO_L2) != 0) {
4713
num_sessions = list_sessions(talloc_tos(), &session_list);
4716
*rdata = smb_realloc_limit(*rdata,mdrcnt);
4721
memset((char *)&desc,'\0',sizeof(desc));
4723
desc.buflen = mdrcnt;
4725
if (!init_package(&desc,num_sessions,0)) {
4729
for(i=0; i<num_sessions; i++) {
4730
PACKS(&desc, "z", session_list[i].remote_machine);
4731
PACKS(&desc, "z", session_list[i].username);
4732
PACKI(&desc, "W", 1); /* num conns */
4733
PACKI(&desc, "W", 0); /* num opens */
4734
PACKI(&desc, "W", 1); /* num users */
4735
PACKI(&desc, "D", 0); /* session time */
4736
PACKI(&desc, "D", 0); /* idle time */
4737
PACKI(&desc, "D", 0); /* flags */
4738
PACKS(&desc, "z", "Unknown Client"); /* client type string */
4741
*rdata_len = desc.usedlen;
4744
*rparam = smb_realloc_limit(*rparam,*rparam_len);
4748
SSVALS(*rparam,0,desc.errcode);
4749
SSVAL(*rparam,2,0); /* converter */
4750
SSVAL(*rparam,4,num_sessions); /* count */
4752
DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc.errcode));
4758
/****************************************************************************
4759
The buffer was too small.
4760
****************************************************************************/
4762
static bool api_TooSmall(connection_struct *conn,uint16 vuid, char *param, char *data,
4763
int mdrcnt, int mprcnt,
4764
char **rdata, char **rparam,
4765
int *rdata_len, int *rparam_len)
4767
*rparam_len = MIN(*rparam_len,mprcnt);
4768
*rparam = smb_realloc_limit(*rparam,*rparam_len);
4775
SSVAL(*rparam,0,NERR_BufTooSmall);
4777
DEBUG(3,("Supplied buffer too small in API command\n"));
4782
/****************************************************************************
4783
The request is not supported.
4784
****************************************************************************/
4786
static bool api_Unsupported(connection_struct *conn, uint16 vuid,
4787
char *param, int tpscnt,
4788
char *data, int tdscnt,
4789
int mdrcnt, int mprcnt,
4790
char **rdata, char **rparam,
4791
int *rdata_len, int *rparam_len)
4794
*rparam = smb_realloc_limit(*rparam,*rparam_len);
4801
SSVAL(*rparam,0,NERR_notsupported);
4802
SSVAL(*rparam,2,0); /* converter word */
4804
DEBUG(3,("Unsupported API command\n"));
4809
static const struct {
4812
bool (*fn)(connection_struct *, uint16,
4815
int,int,char **,char **,int *,int *);
4816
bool auth_user; /* Deny anonymous access? */
4817
} api_commands[] = {
4818
{"RNetShareEnum", RAP_WshareEnum, api_RNetShareEnum, True},
4819
{"RNetShareGetInfo", RAP_WshareGetInfo, api_RNetShareGetInfo},
4820
{"RNetShareAdd", RAP_WshareAdd, api_RNetShareAdd},
4821
{"RNetSessionEnum", RAP_WsessionEnum, api_RNetSessionEnum, True},
4822
{"RNetServerGetInfo", RAP_WserverGetInfo, api_RNetServerGetInfo},
4823
{"RNetGroupEnum", RAP_WGroupEnum, api_RNetGroupEnum, True},
4824
{"RNetGroupGetUsers", RAP_WGroupGetUsers, api_RNetGroupGetUsers, True},
4825
{"RNetUserEnum", RAP_WUserEnum, api_RNetUserEnum, True},
4826
{"RNetUserGetInfo", RAP_WUserGetInfo, api_RNetUserGetInfo},
4827
{"NetUserGetGroups", RAP_WUserGetGroups, api_NetUserGetGroups},
4828
{"NetWkstaGetInfo", RAP_WWkstaGetInfo, api_NetWkstaGetInfo},
4829
{"DosPrintQEnum", RAP_WPrintQEnum, api_DosPrintQEnum, True},
4830
{"DosPrintQGetInfo", RAP_WPrintQGetInfo, api_DosPrintQGetInfo},
4831
{"WPrintQueuePause", RAP_WPrintQPause, api_WPrintQueueCtrl},
4832
{"WPrintQueueResume", RAP_WPrintQContinue, api_WPrintQueueCtrl},
4833
{"WPrintJobEnumerate",RAP_WPrintJobEnum, api_WPrintJobEnumerate},
4834
{"WPrintJobGetInfo", RAP_WPrintJobGetInfo, api_WPrintJobGetInfo},
4835
{"RDosPrintJobDel", RAP_WPrintJobDel, api_RDosPrintJobDel},
4836
{"RDosPrintJobPause", RAP_WPrintJobPause, api_RDosPrintJobDel},
4837
{"RDosPrintJobResume",RAP_WPrintJobContinue, api_RDosPrintJobDel},
4838
{"WPrintDestEnum", RAP_WPrintDestEnum, api_WPrintDestEnum},
4839
{"WPrintDestGetInfo", RAP_WPrintDestGetInfo, api_WPrintDestGetInfo},
4840
{"NetRemoteTOD", RAP_NetRemoteTOD, api_NetRemoteTOD},
4841
{"WPrintQueuePurge", RAP_WPrintQPurge, api_WPrintQueueCtrl},
4842
{"NetServerEnum2", RAP_NetServerEnum2, api_RNetServerEnum2}, /* anon OK */
4843
{"NetServerEnum3", RAP_NetServerEnum3, api_RNetServerEnum3}, /* anon OK */
4844
{"WAccessGetUserPerms",RAP_WAccessGetUserPerms,api_WAccessGetUserPerms},
4845
{"SetUserPassword", RAP_WUserPasswordSet2, api_SetUserPassword},
4846
{"WWkstaUserLogon", RAP_WWkstaUserLogon, api_WWkstaUserLogon},
4847
{"PrintJobInfo", RAP_WPrintJobSetInfo, api_PrintJobInfo},
4848
{"WPrintDriverEnum", RAP_WPrintDriverEnum, api_WPrintDriverEnum},
4849
{"WPrintQProcEnum", RAP_WPrintQProcessorEnum,api_WPrintQProcEnum},
4850
{"WPrintPortEnum", RAP_WPrintPortEnum, api_WPrintPortEnum},
4851
{"SamOEMChangePassword",RAP_SamOEMChgPasswordUser2_P,api_SamOEMChangePassword}, /* anon OK */
4852
{NULL, -1, api_Unsupported}
4853
/* The following RAP calls are not implemented by Samba:
4855
RAP_WFileEnum2 - anon not OK
4860
/****************************************************************************
4861
Handle remote api calls.
4862
****************************************************************************/
4864
void api_reply(connection_struct *conn, uint16 vuid,
4865
struct smb_request *req,
4866
char *data, char *params,
4867
int tdscnt, int tpscnt,
4868
int mdrcnt, int mprcnt)
4872
char *rparam = NULL;
4873
const char *name1 = NULL;
4874
const char *name2 = NULL;
4881
DEBUG(0,("ERROR: NULL params in api_reply()\n"));
4882
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4887
reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
4890
api_command = SVAL(params,0);
4891
/* Is there a string at position params+2 ? */
4892
if (skip_string(params,tpscnt,params+2)) {
4897
name2 = skip_string(params,tpscnt,params+2);
4902
DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
4906
tdscnt,tpscnt,mdrcnt,mprcnt));
4908
for (i=0;api_commands[i].name;i++) {
4909
if (api_commands[i].id == api_command && api_commands[i].fn) {
4910
DEBUG(3,("Doing %s\n",api_commands[i].name));
4915
/* Check whether this api call can be done anonymously */
4917
if (api_commands[i].auth_user && lp_restrict_anonymous()) {
4918
user_struct *user = get_valid_user_struct(vuid);
4920
if (!user || user->server_info->guest) {
4921
reply_nterror(req, NT_STATUS_ACCESS_DENIED);
4926
rdata = (char *)SMB_MALLOC(1024);
4928
memset(rdata,'\0',1024);
4931
rparam = (char *)SMB_MALLOC(1024);
4933
memset(rparam,'\0',1024);
4936
if(!rdata || !rparam) {
4937
DEBUG(0,("api_reply: malloc fail !\n"));
4940
reply_nterror(req, NT_STATUS_NO_MEMORY);
4944
reply = api_commands[i].fn(conn,
4946
params,tpscnt, /* params + length */
4947
data,tdscnt, /* data + length */
4949
&rdata,&rparam,&rdata_len,&rparam_len);
4952
if (rdata_len > mdrcnt || rparam_len > mprcnt) {
4953
reply = api_TooSmall(conn,vuid,params,data,mdrcnt,mprcnt,
4954
&rdata,&rparam,&rdata_len,&rparam_len);
4957
/* if we get False back then it's actually unsupported */
4959
reply = api_Unsupported(conn,vuid,params,tpscnt,data,tdscnt,mdrcnt,mprcnt,
4960
&rdata,&rparam,&rdata_len,&rparam_len);
4963
/* If api_Unsupported returns false we can't return anything. */
4965
send_trans_reply(conn, req, rparam, rparam_len,
4966
rdata, rdata_len, False);