1/* 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. 6 7 SMB Version handling 8 Copyright (C) John H Terpstra 1995-1998 9 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 2 of the License, or 13 (at your option) any later version. 14 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. 19 20 You should have received a copy of the GNU General Public License 21 along with this program; if not, write to the Free Software 22 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 23 */ 24/* 25 This file handles the named pipe and mailslot calls 26 in the SMBtrans protocol 27 */ 28 29#include "includes.h" 30 31extern struct current_user current_user; 32extern userdom_struct current_user_info; 33 34#ifdef CHECK_TYPES 35#undef CHECK_TYPES 36#endif 37#define CHECK_TYPES 0 38 39#define NERR_Success 0 40#define NERR_badpass 86 41#define NERR_notsupported 50 42 43#define NERR_BASE (2100) 44#define NERR_BufTooSmall (NERR_BASE+23) 45#define NERR_JobNotFound (NERR_BASE+51) 46#define NERR_DestNotFound (NERR_BASE+52) 47 48#define ACCESS_READ 0x01 49#define ACCESS_WRITE 0x02 50#define ACCESS_CREATE 0x04 51 52#define SHPWLEN 8 /* share password length */ 53 54static BOOL api_Unsupported(connection_struct *conn, uint16 vuid, 55 char *param, int tpscnt, 56 char *data, int tdscnt, 57 int mdrcnt, int mprcnt, 58 char **rdata, char **rparam, 59 int *rdata_len, int *rparam_len); 60 61static BOOL api_TooSmall(connection_struct *conn, uint16 vuid, char *param, char *data, 62 int mdrcnt, int mprcnt, 63 char **rdata, char **rparam, 64 int *rdata_len, int *rparam_len); 65 66 67static int CopyExpanded(connection_struct *conn, 68 int snum, char **dst, char *src, int *n) 69{ 70 pstring buf; 71 int l; 72 73 if (!src || !dst || !n || !(*dst)) { 74 return 0; 75 } 76 77 StrnCpy(buf,src,sizeof(buf)/2); 78 pstring_sub(buf,"%S",lp_servicename(snum)); 79 standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user, 80 conn->connectpath, conn->gid, 81 get_current_username(), 82 current_user_info.domain, 83 buf, sizeof(buf)); 84 l = push_ascii(*dst,buf,*n, STR_TERMINATE); 85 (*dst) += l; 86 (*n) -= l; 87 return l; 88} 89 90static int CopyAndAdvance(char **dst, char *src, int *n) 91{ 92 int l; 93 if (!src || !dst || !n || !(*dst)) { 94 return 0; 95 } 96 l = push_ascii(*dst,src,*n, STR_TERMINATE); 97 (*dst) += l; 98 (*n) -= l; 99 return l; 100} 101 102static int StrlenExpanded(connection_struct *conn, int snum, char *s) 103{ 104 pstring buf; 105 if (!s) { 106 return 0; 107 } 108 StrnCpy(buf,s,sizeof(buf)/2); 109 pstring_sub(buf,"%S",lp_servicename(snum)); 110 standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user, 111 conn->connectpath, conn->gid, 112 get_current_username(), 113 current_user_info.domain, 114 buf, sizeof(buf)); 115 return strlen(buf) + 1; 116} 117 118static char *Expand(connection_struct *conn, int snum, char *s) 119{ 120 static pstring buf; 121 if (!s) { 122 return NULL; 123 } 124 StrnCpy(buf,s,sizeof(buf)/2); 125 pstring_sub(buf,"%S",lp_servicename(snum)); 126 standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user, 127 conn->connectpath, conn->gid, 128 get_current_username(), 129 current_user_info.domain, 130 buf, sizeof(buf)); 131 return &buf[0]; 132} 133 134/******************************************************************* 135 Check a API string for validity when we only need to check the prefix. 136******************************************************************/ 137 138static BOOL prefix_ok(const char *str, const char *prefix) 139{ 140 return(strncmp(str,prefix,strlen(prefix)) == 0); 141} 142 143struct pack_desc { 144 const char *format; /* formatstring for structure */ 145 const char *subformat; /* subformat for structure */ 146 char *base; /* baseaddress of buffer */ 147 int buflen; /* remaining size for fixed part; on init: length of base */ 148 int subcount; /* count of substructures */ 149 char *structbuf; /* pointer into buffer for remaining fixed part */ 150 int stringlen; /* remaining size for variable part */ 151 char *stringbuf; /* pointer into buffer for remaining variable part */ 152 int neededlen; /* total needed size */ 153 int usedlen; /* total used size (usedlen <= neededlen and usedlen <= buflen) */ 154 const char *curpos; /* current position; pointer into format or subformat */ 155 int errcode; 156}; 157 158static int get_counter(const char **p) 159{ 160 int i, n; 161 if (!p || !(*p)) { 162 return 1; 163 } 164 if (!isdigit((int)**p)) { 165 return 1; 166 } 167 for (n = 0;;) { 168 i = **p; 169 if (isdigit(i)) { 170 n = 10 * n + (i - '0'); 171 } else { 172 return n; 173 } 174 (*p)++; 175 } 176} 177 178static int getlen(const char *p) 179{ 180 int n = 0; 181 if (!p) { 182 return 0; 183 } 184 185 while (*p) { 186 switch( *p++ ) { 187 case 'W': /* word (2 byte) */ 188 n += 2; 189 break; 190 case 'K': /* status word? (2 byte) */ 191 n += 2; 192 break; 193 case 'N': /* count of substructures (word) at end */ 194 n += 2; 195 break; 196 case 'D': /* double word (4 byte) */ 197 case 'z': /* offset to zero terminated string (4 byte) */ 198 case 'l': /* offset to user data (4 byte) */ 199 n += 4; 200 break; 201 case 'b': /* offset to data (with counter) (4 byte) */ 202 n += 4; 203 get_counter(&p); 204 break; 205 case 'B': /* byte (with optional counter) */ 206 n += get_counter(&p); 207 break; 208 } 209 } 210 return n; 211} 212 213static BOOL init_package(struct pack_desc *p, int count, int subcount) 214{ 215 int n = p->buflen; 216 int i; 217 218 if (!p->format || !p->base) { 219 return False; 220 } 221 222 i = count * getlen(p->format); 223 if (p->subformat) { 224 i += subcount * getlen(p->subformat); 225 } 226 p->structbuf = p->base; 227 p->neededlen = 0; 228 p->usedlen = 0; 229 p->subcount = 0; 230 p->curpos = p->format; 231 if (i > n) { 232 p->neededlen = i; 233 i = n = 0; 234#if 0 235 /* 236 * This is the old error code we used. Aparently 237 * WinNT/2k systems return ERRbuftoosmall (2123) and 238 * OS/2 needs this. I'm leaving this here so we can revert 239 * if needed. JRA. 240 */ 241 p->errcode = ERRmoredata; 242#else 243 p->errcode = ERRbuftoosmall; 244#endif 245 } else { 246 p->errcode = NERR_Success; 247 } 248 p->buflen = i; 249 n -= i; 250 p->stringbuf = p->base + i; 251 p->stringlen = n; 252 return (p->errcode == NERR_Success); 253} 254 255static int package(struct pack_desc *p, ...) 256{ 257 va_list args; 258 int needed=0, stringneeded; 259 const char *str=NULL; 260 int is_string=0, stringused; 261 int32 temp; 262 263 va_start(args,p); 264 265 if (!*p->curpos) { 266 if (!p->subcount) { 267 p->curpos = p->format; 268 } else { 269 p->curpos = p->subformat; 270 p->subcount--; 271 } 272 } 273#if CHECK_TYPES 274 str = va_arg(args,char*); 275 SMB_ASSERT(strncmp(str,p->curpos,strlen(str)) == 0); 276#endif 277 stringneeded = -1; 278 279 if (!p->curpos) { 280 va_end(args); 281 return 0; 282 } 283 284 switch( *p->curpos++ ) { 285 case 'W': /* word (2 byte) */ 286 needed = 2; 287 temp = va_arg(args,int); 288 if (p->buflen >= needed) { 289 SSVAL(p->structbuf,0,temp); 290 } 291 break; 292 case 'K': /* status word? (2 byte) */ 293 needed = 2; 294 temp = va_arg(args,int); 295 if (p->buflen >= needed) { 296 SSVAL(p->structbuf,0,temp); 297 } 298 break; 299 case 'N': /* count of substructures (word) at end */ 300 needed = 2; 301 p->subcount = va_arg(args,int); 302 if (p->buflen >= needed) { 303 SSVAL(p->structbuf,0,p->subcount); 304 } 305 break; 306 case 'D': /* double word (4 byte) */ 307 needed = 4; 308 temp = va_arg(args,int); 309 if (p->buflen >= needed) { 310 SIVAL(p->structbuf,0,temp); 311 } 312 break; 313 case 'B': /* byte (with optional counter) */ 314 needed = get_counter(&p->curpos); 315 { 316 char *s = va_arg(args,char*); 317 if (p->buflen >= needed) { 318 StrnCpy(p->structbuf,s?s:"",needed-1); 319 } 320 } 321 break; 322 case 'z': /* offset to zero terminated string (4 byte) */ 323 str = va_arg(args,char*); 324 stringneeded = (str ? strlen(str)+1 : 0); 325 is_string = 1; 326 break; 327 case 'l': /* offset to user data (4 byte) */ 328 str = va_arg(args,char*); 329 stringneeded = va_arg(args,int); 330 is_string = 0; 331 break; 332 case 'b': /* offset to data (with counter) (4 byte) */ 333 str = va_arg(args,char*); 334 stringneeded = get_counter(&p->curpos); 335 is_string = 0; 336 break; 337 } 338 339 va_end(args); 340 if (stringneeded >= 0) { 341 needed = 4; 342 if (p->buflen >= needed) { 343 stringused = stringneeded; 344 if (stringused > p->stringlen) { 345 stringused = (is_string ? p->stringlen : 0); 346 if (p->errcode == NERR_Success) { 347 p->errcode = ERRmoredata; 348 } 349 } 350 if (!stringused) { 351 SIVAL(p->structbuf,0,0); 352 } else { 353 SIVAL(p->structbuf,0,PTR_DIFF(p->stringbuf,p->base)); 354 memcpy(p->stringbuf,str?str:"",stringused); 355 if (is_string) { 356 p->stringbuf[stringused-1] = '\0'; 357 } 358 p->stringbuf += stringused; 359 p->stringlen -= stringused; 360 p->usedlen += stringused; 361 } 362 } 363 p->neededlen += stringneeded; 364 } 365 366 p->neededlen += needed; 367 if (p->buflen >= needed) { 368 p->structbuf += needed; 369 p->buflen -= needed; 370 p->usedlen += needed; 371 } else { 372 if (p->errcode == NERR_Success) { 373 p->errcode = ERRmoredata; 374 } 375 } 376 return 1; 377} 378 379#if CHECK_TYPES 380#define PACK(desc,t,v) package(desc,t,v,0,0,0,0) 381#define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0) 382#else 383#define PACK(desc,t,v) package(desc,v) 384#define PACKl(desc,t,v,l) package(desc,v,l) 385#endif 386 387static void PACKI(struct pack_desc* desc, const char *t,int v) 388{ 389 PACK(desc,t,v); 390} 391 392static void PACKS(struct pack_desc* desc,const char *t,const char *v) 393{ 394 PACK(desc,t,v); 395} 396 397/**************************************************************************** 398 Get a print queue. 399****************************************************************************/ 400 401static void PackDriverData(struct pack_desc* desc) 402{ 403 char drivdata[4+4+32]; 404 SIVAL(drivdata,0,sizeof drivdata); /* cb */ 405 SIVAL(drivdata,4,1000); /* lVersion */ 406 memset(drivdata+8,0,32); /* szDeviceName */ 407 push_ascii(drivdata+8,"NULL",-1, STR_TERMINATE); 408 PACKl(desc,"l",drivdata,sizeof drivdata); /* pDriverData */ 409} 410 411static int check_printq_info(struct pack_desc* desc, 412 unsigned int uLevel, char *id1, char *id2) 413{ 414 desc->subformat = NULL; 415 switch( uLevel ) { 416 case 0: 417 desc->format = "B13"; 418 break; 419 case 1: 420 desc->format = "B13BWWWzzzzzWW"; 421 break; 422 case 2: 423 desc->format = "B13BWWWzzzzzWN"; 424 desc->subformat = "WB21BB16B10zWWzDDz"; 425 break; 426 case 3: 427 desc->format = "zWWWWzzzzWWzzl"; 428 break; 429 case 4: 430 desc->format = "zWWWWzzzzWNzzl"; 431 desc->subformat = "WWzWWDDzz"; 432 break; 433 case 5: 434 desc->format = "z"; 435 break; 436 case 51: 437 desc->format = "K"; 438 break; 439 case 52: 440 desc->format = "WzzzzzzzzN"; 441 desc->subformat = "z"; 442 break; 443 default: 444 DEBUG(0,("check_printq_info: invalid level %d\n", 445 uLevel )); 446 return False; 447 } 448 if (id1 == NULL || strcmp(desc->format,id1) != 0) { 449 DEBUG(0,("check_printq_info: invalid format %s\n", 450 id1 ? id1 : "<NULL>" )); 451 return False; 452 } 453 if (desc->subformat && (id2 == NULL || strcmp(desc->subformat,id2) != 0)) { 454 DEBUG(0,("check_printq_info: invalid subformat %s\n", 455 id2 ? id2 : "<NULL>" )); 456 return False; 457 } 458 return True; 459} 460 461 462#define RAP_JOB_STATUS_QUEUED 0 463#define RAP_JOB_STATUS_PAUSED 1 464#define RAP_JOB_STATUS_SPOOLING 2 465#define RAP_JOB_STATUS_PRINTING 3 466#define RAP_JOB_STATUS_PRINTED 4 467 468#define RAP_QUEUE_STATUS_PAUSED 1 469#define RAP_QUEUE_STATUS_ERROR 2 470 471/* turn a print job status into a on the wire status 472*/ 473static int printj_status(int v) 474{ 475 switch (v) { 476 case LPQ_QUEUED: 477 return RAP_JOB_STATUS_QUEUED; 478 case LPQ_PAUSED: 479 return RAP_JOB_STATUS_PAUSED; 480 case LPQ_SPOOLING: 481 return RAP_JOB_STATUS_SPOOLING; 482 case LPQ_PRINTING: 483 return RAP_JOB_STATUS_PRINTING; 484 } 485 return 0; 486} 487 488/* turn a print queue status into a on the wire status 489*/ 490static int printq_status(int v) 491{ 492 switch (v) { 493 case LPQ_QUEUED: 494 return 0; 495 case LPQ_PAUSED: 496 return RAP_QUEUE_STATUS_PAUSED; 497 } 498 return RAP_QUEUE_STATUS_ERROR; 499} 500 501static void fill_printjob_info(connection_struct *conn, int snum, int uLevel, 502 struct pack_desc *desc, 503 print_queue_struct *queue, int n) 504{ 505 time_t t = queue->time; 506 507 /* the client expects localtime */ 508 t -= get_time_zone(t); 509 510 PACKI(desc,"W",pjobid_to_rap(lp_const_servicename(snum),queue->job)); /* uJobId */ 511 if (uLevel == 1) { 512 PACKS(desc,"B21",queue->fs_user); /* szUserName */ 513 PACKS(desc,"B",""); /* pad */ 514 PACKS(desc,"B16",""); /* szNotifyName */ 515 PACKS(desc,"B10","PM_Q_RAW"); /* szDataType */ 516 PACKS(desc,"z",""); /* pszParms */ 517 PACKI(desc,"W",n+1); /* uPosition */ 518 PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */ 519 PACKS(desc,"z",""); /* pszStatus */ 520 PACKI(desc,"D",t); /* ulSubmitted */ 521 PACKI(desc,"D",queue->size); /* ulSize */ 522 PACKS(desc,"z",queue->fs_file); /* pszComment */ 523 } 524 if (uLevel == 2 || uLevel == 3 || uLevel == 4) { 525 PACKI(desc,"W",queue->priority); /* uPriority */ 526 PACKS(desc,"z",queue->fs_user); /* pszUserName */ 527 PACKI(desc,"W",n+1); /* uPosition */ 528 PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */ 529 PACKI(desc,"D",t); /* ulSubmitted */ 530 PACKI(desc,"D",queue->size); /* ulSize */ 531 PACKS(desc,"z","Samba"); /* pszComment */ 532 PACKS(desc,"z",queue->fs_file); /* pszDocument */ 533 if (uLevel == 3) { 534 PACKS(desc,"z",""); /* pszNotifyName */ 535 PACKS(desc,"z","PM_Q_RAW"); /* pszDataType */ 536 PACKS(desc,"z",""); /* pszParms */ 537 PACKS(desc,"z",""); /* pszStatus */ 538 PACKS(desc,"z",SERVICE(snum)); /* pszQueue */ 539 PACKS(desc,"z","lpd"); /* pszQProcName */ 540 PACKS(desc,"z",""); /* pszQProcParms */ 541 PACKS(desc,"z","NULL"); /* pszDriverName */ 542 PackDriverData(desc); /* pDriverData */ 543 PACKS(desc,"z",""); /* pszPrinterName */ 544 } else if (uLevel == 4) { /* OS2 */ 545 PACKS(desc,"z",""); /* pszSpoolFileName */ 546 PACKS(desc,"z",""); /* pszPortName */ 547 PACKS(desc,"z",""); /* pszStatus */ 548 PACKI(desc,"D",0); /* ulPagesSpooled */ 549 PACKI(desc,"D",0); /* ulPagesSent */ 550 PACKI(desc,"D",0); /* ulPagesPrinted */ 551 PACKI(desc,"D",0); /* ulTimePrinted */ 552 PACKI(desc,"D",0); /* ulExtendJobStatus */ 553 PACKI(desc,"D",0); /* ulStartPage */ 554 PACKI(desc,"D",0); /* ulEndPage */ 555 } 556 } 557} 558 559/******************************************************************** 560 Return a driver name given an snum. 561 Returns True if from tdb, False otherwise. 562 ********************************************************************/ 563 564static BOOL get_driver_name(int snum, pstring drivername) 565{ 566 NT_PRINTER_INFO_LEVEL *info = NULL; 567 BOOL in_tdb = False; 568 569 get_a_printer (NULL, &info, 2, lp_servicename(snum)); 570 if (info != NULL) { 571 pstrcpy( drivername, info->info_2->drivername); 572 in_tdb = True; 573 free_a_printer(&info, 2); 574 } 575 576 return in_tdb; 577} 578 579/******************************************************************** 580 Respond to the DosPrintQInfo command with a level of 52 581 This is used to get printer driver information for Win9x clients 582 ********************************************************************/ 583static void fill_printq_info_52(connection_struct *conn, int snum, 584 struct pack_desc* desc, int count ) 585{ 586 int i; 587 fstring location; 588 NT_PRINTER_DRIVER_INFO_LEVEL driver; 589 NT_PRINTER_INFO_LEVEL *printer = NULL; 590 591 ZERO_STRUCT(driver); 592 593 if ( !W_ERROR_IS_OK(get_a_printer( NULL, &printer, 2, lp_servicename(snum))) ) { 594 DEBUG(3,("fill_printq_info_52: Failed to lookup printer [%s]\n", 595 lp_servicename(snum))); 596 goto err; 597 } 598 599 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, 600 "Windows 4.0", 0)) ) 601 { 602 DEBUG(3,("fill_printq_info_52: Failed to lookup driver [%s]\n", 603 printer->info_2->drivername)); 604 goto err; 605 } 606 607 trim_string(driver.info_3->driverpath, "\\print$\\WIN40\\0\\", 0); 608 trim_string(driver.info_3->datafile, "\\print$\\WIN40\\0\\", 0); 609 trim_string(driver.info_3->helpfile, "\\print$\\WIN40\\0\\", 0); 610 611 PACKI(desc, "W", 0x0400); /* don't know */ 612 PACKS(desc, "z", driver.info_3->name); /* long printer name */ 613 PACKS(desc, "z", driver.info_3->driverpath); /* Driverfile Name */ 614 PACKS(desc, "z", driver.info_3->datafile); /* Datafile name */ 615 PACKS(desc, "z", driver.info_3->monitorname); /* language monitor */ 616 617 fstrcpy(location, "\\\\%L\\print$\\WIN40\\0"); 618 standard_sub_basic( "", "", location, sizeof(location)-1 ); 619 PACKS(desc,"z", location); /* share to retrieve files */ 620 621 PACKS(desc,"z", driver.info_3->defaultdatatype); /* default data type */ 622 PACKS(desc,"z", driver.info_3->helpfile); /* helpfile name */ 623 PACKS(desc,"z", driver.info_3->driverpath); /* driver name */ 624 625 DEBUG(3,("Printer Driver Name: %s:\n",driver.info_3->name)); 626 DEBUG(3,("Driver: %s:\n",driver.info_3->driverpath)); 627 DEBUG(3,("Data File: %s:\n",driver.info_3->datafile)); 628 DEBUG(3,("Language Monitor: %s:\n",driver.info_3->monitorname)); 629 DEBUG(3,("Driver Location: %s:\n",location)); 630 DEBUG(3,("Data Type: %s:\n",driver.info_3->defaultdatatype)); 631 DEBUG(3,("Help File: %s:\n",driver.info_3->helpfile)); 632 PACKI(desc,"N",count); /* number of files to copy */ 633 634 for ( i=0; i<count && driver.info_3->dependentfiles && *driver.info_3->dependentfiles[i]; i++) 635 { 636 trim_string(driver.info_3->dependentfiles[i], "\\print$\\WIN40\\0\\", 0); 637 PACKS(desc,"z",driver.info_3->dependentfiles[i]); /* driver files to copy */ 638 DEBUG(3,("Dependent File: %s:\n",driver.info_3->dependentfiles[i])); 639 } 640 641 /* sanity check */ 642 if ( i != count ) 643 DEBUG(3,("fill_printq_info_52: file count specified by client [%d] != number of dependent files [%i]\n", 644 count, i)); 645 646 DEBUG(3,("fill_printq_info on <%s> gave %d entries\n", SERVICE(snum),i)); 647 648 desc->errcode=NERR_Success; 649 goto done; 650 651err: 652 DEBUG(3,("fill_printq_info: Can't supply driver files\n")); 653 desc->errcode=NERR_notsupported; 654 655done: 656 if ( printer ) 657 free_a_printer( &printer, 2 ); 658 659 if ( driver.info_3 ) 660 free_a_printer_driver( driver, 3 ); 661} 662 663 664static void fill_printq_info(connection_struct *conn, int snum, int uLevel, 665 struct pack_desc* desc, 666 int count, print_queue_struct* queue, 667 print_status_struct* status) 668{ 669 switch (uLevel) { 670 case 1: 671 case 2: 672 PACKS(desc,"B13",SERVICE(snum)); 673 break; 674 case 3: 675 case 4: 676 case 5: 677 PACKS(desc,"z",Expand(conn,snum,SERVICE(snum))); 678 break; 679 case 51: 680 PACKI(desc,"K",printq_status(status->status)); 681 break; 682 } 683 684 if (uLevel == 1 || uLevel == 2) { 685 PACKS(desc,"B",""); /* alignment */ 686 PACKI(desc,"W",5); /* priority */ 687 PACKI(desc,"W",0); /* start time */ 688 PACKI(desc,"W",0); /* until time */ 689 PACKS(desc,"z",""); /* pSepFile */ 690 PACKS(desc,"z","lpd"); /* pPrProc */ 691 PACKS(desc,"z",SERVICE(snum)); /* pDestinations */ 692 PACKS(desc,"z",""); /* pParms */ 693 if (snum < 0) { 694 PACKS(desc,"z","UNKNOWN PRINTER"); 695 PACKI(desc,"W",LPSTAT_ERROR); 696 } 697 else if (!status || !status->message[0]) { 698 PACKS(desc,"z",Expand(conn,snum,lp_comment(snum))); 699 PACKI(desc,"W",LPSTAT_OK); /* status */ 700 } else { 701 PACKS(desc,"z",status->message); 702 PACKI(desc,"W",printq_status(status->status)); /* status */ 703 } 704 PACKI(desc,(uLevel == 1 ? "W" : "N"),count); 705 } 706 707 if (uLevel == 3 || uLevel == 4) { 708 pstring drivername; 709 710 PACKI(desc,"W",5); /* uPriority */ 711 PACKI(desc,"W",0); /* uStarttime */ 712 PACKI(desc,"W",0); /* uUntiltime */ 713 PACKI(desc,"W",5); /* pad1 */ 714 PACKS(desc,"z",""); /* pszSepFile */ 715 PACKS(desc,"z","WinPrint"); /* pszPrProc */ 716 PACKS(desc,"z",NULL); /* pszParms */ 717 PACKS(desc,"z",NULL); /* pszComment - don't ask.... JRA */ 718 /* "don't ask" that it's done this way to fix corrupted 719 Win9X/ME printer comments. */ 720 if (!status) { 721 PACKI(desc,"W",LPSTAT_OK); /* fsStatus */ 722 } else { 723 PACKI(desc,"W",printq_status(status->status)); /* fsStatus */ 724 } 725 PACKI(desc,(uLevel == 3 ? "W" : "N"),count); /* cJobs */ 726 PACKS(desc,"z",SERVICE(snum)); /* pszPrinters */ 727 get_driver_name(snum,drivername); 728 PACKS(desc,"z",drivername); /* pszDriverName */ 729 PackDriverData(desc); /* pDriverData */ 730 } 731 732 if (uLevel == 2 || uLevel == 4) { 733 int i; 734 for (i=0;i<count;i++) 735 fill_printjob_info(conn,snum,uLevel == 2 ? 1 : 2,desc,&queue[i],i); 736 } 737 738 if (uLevel==52) 739 fill_printq_info_52( conn, snum, desc, count ); 740} 741 742/* This function returns the number of files for a given driver */ 743static int get_printerdrivernumber(int snum) 744{ 745 int result = 0; 746 NT_PRINTER_DRIVER_INFO_LEVEL driver; 747 NT_PRINTER_INFO_LEVEL *printer = NULL; 748 749 ZERO_STRUCT(driver); 750 751 if ( !W_ERROR_IS_OK(get_a_printer( NULL, &printer, 2, lp_servicename(snum))) ) { 752 DEBUG(3,("get_printerdrivernumber: Failed to lookup printer [%s]\n", 753 lp_servicename(snum))); 754 goto done; 755 } 756 757 if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, 758 "Windows 4.0", 0)) ) 759 { 760 DEBUG(3,("get_printerdrivernumber: Failed to lookup driver [%s]\n", 761 printer->info_2->drivername)); 762 goto done; 763 } 764 765 /* count the number of files */ 766 while ( driver.info_3->dependentfiles && *driver.info_3->dependentfiles[result] ) 767 result++; 768 \ 769 done: 770 if ( printer ) 771 free_a_printer( &printer, 2 ); 772 773 if ( driver.info_3 ) 774 free_a_printer_driver( driver, 3 ); 775 776 return result; 777} 778 779static BOOL api_DosPrintQGetInfo(connection_struct *conn, uint16 vuid, 780 char *param, int tpscnt, 781 char *data, int tdscnt, 782 int mdrcnt,int mprcnt, 783 char **rdata,char **rparam, 784 int *rdata_len,int *rparam_len) 785{ 786 char *str1 = get_safe_str_ptr(param,tpscnt,param,2); 787 char *str2 = skip_string(param,tpscnt,str1); 788 char *p = skip_string(param,tpscnt,str2); 789 char *QueueName = p; 790 unsigned int uLevel; 791 int count=0; 792 int snum; 793 char *str3; 794 struct pack_desc desc; 795 print_queue_struct *queue=NULL; 796 print_status_struct status; 797 char* tmpdata=NULL; 798 799 if (!str1 || !str2 || !p) { 800 return False; 801 } 802 memset((char *)&status,'\0',sizeof(status)); 803 memset((char *)&desc,'\0',sizeof(desc)); 804 805 p = skip_string(param,tpscnt,p); 806 if (!p) { 807 return False; 808 } 809 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1); 810 str3 = get_safe_str_ptr(param,tpscnt,p,4); 811 /* str3 may be null here and is checked in check_printq_info(). */ 812 813 /* remove any trailing username */ 814 if ((p = strchr_m(QueueName,'%'))) 815 *p = 0; 816 817 DEBUG(3,("api_DosPrintQGetInfo uLevel=%d name=%s\n",uLevel,QueueName)); 818 819 /* check it's a supported varient */ 820 if (!prefix_ok(str1,"zWrLh")) 821 return False; 822 if (!check_printq_info(&desc,uLevel,str2,str3)) { 823 /* 824 * Patch from Scott Moomaw <scott@bridgewater.edu> 825 * to return the 'invalid info level' error if an 826 * unknown level was requested. 827 */ 828 *rdata_len = 0; 829 *rparam_len = 6; 830 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); 831 if (!*rparam) { 832 return False; 833 } 834 SSVALS(*rparam,0,ERRunknownlevel); 835 SSVAL(*rparam,2,0); 836 SSVAL(*rparam,4,0); 837 return(True); 838 } 839 840 snum = find_service(QueueName); 841 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) ) 842 return False; 843 844 if (uLevel==52) { 845 count = get_printerdrivernumber(snum); 846 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count)); 847 } else { 848 count = print_queue_status(snum, &queue,&status); 849 } 850 851 if (mdrcnt > 0) { 852 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt); 853 if (!*rdata) { 854 return False; 855 } 856 desc.base = *rdata; 857 desc.buflen = mdrcnt; 858 } else { 859 /* 860 * Don't return data but need to get correct length 861 * init_package will return wrong size if buflen=0 862 */ 863 desc.buflen = getlen(desc.format); 864 desc.base = tmpdata = (char *) SMB_MALLOC (desc.buflen); 865 } 866 867 if (init_package(&desc,1,count)) { 868 desc.subcount = count; 869 fill_printq_info(conn,snum,uLevel,&desc,count,queue,&status); 870 } 871 872 *rdata_len = desc.usedlen; 873 874 /* 875 * We must set the return code to ERRbuftoosmall 876 * in order to support lanman style printing with Win NT/2k 877 * clients --jerry 878 */ 879 if (!mdrcnt && lp_disable_spoolss()) 880 desc.errcode = ERRbuftoosmall; 881 882 *rdata_len = desc.usedlen; 883 *rparam_len = 6; 884 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); 885 if (!*rparam) { 886 return False; 887 } 888 SSVALS(*rparam,0,desc.errcode); 889 SSVAL(*rparam,2,0); 890 SSVAL(*rparam,4,desc.neededlen); 891 892 DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode)); 893 894 SAFE_FREE(queue); 895 SAFE_FREE(tmpdata); 896 897 return(True); 898} 899 900/**************************************************************************** 901 View list of all print jobs on all queues. 902****************************************************************************/ 903 904static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid, 905 char *param, int tpscnt, 906 char *data, int tdscnt, 907 int mdrcnt, int mprcnt, 908 char **rdata, char** rparam, 909 int *rdata_len, int *rparam_len) 910{ 911 char *param_format = get_safe_str_ptr(param,tpscnt,param,2); 912 char *output_format1 = skip_string(param,tpscnt,param_format); 913 char *p = skip_string(param,tpscnt,output_format1); 914 unsigned int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1); 915 char *output_format2 = get_safe_str_ptr(param,tpscnt,p,4); 916 int services = lp_numservices(); 917 int i, n; 918 struct pack_desc desc; 919 print_queue_struct **queue = NULL; 920 print_status_struct *status = NULL; 921 int *subcntarr = NULL; 922 int queuecnt = 0, subcnt = 0, succnt = 0; 923 924 if (!param_format || !output_format1 || !p) { 925 return False; 926 } 927 928 memset((char *)&desc,'\0',sizeof(desc)); 929 930 DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel)); 931 932 if (!prefix_ok(param_format,"WrLeh")) { 933 return False; 934 } 935 if (!check_printq_info(&desc,uLevel,output_format1,output_format2)) { 936 /* 937 * Patch from Scott Moomaw <scott@bridgewater.edu> 938 * to return the 'invalid info level' error if an 939 * unknown level was requested. 940 */ 941 *rdata_len = 0; 942 *rparam_len = 6; 943 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); 944 if (!*rparam) { 945 return False; 946 } 947 SSVALS(*rparam,0,ERRunknownlevel); 948 SSVAL(*rparam,2,0); 949 SSVAL(*rparam,4,0); 950 return(True); 951 } 952 953 for (i = 0; i < services; i++) { 954 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) { 955 queuecnt++; 956 } 957 } 958 959 if((queue = SMB_MALLOC_ARRAY(print_queue_struct*, queuecnt)) == NULL) { 960 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n")); 961 goto err; 962 } 963 memset(queue,0,queuecnt*sizeof(print_queue_struct*)); 964 if((status = SMB_MALLOC_ARRAY(print_status_struct,queuecnt)) == NULL) { 965 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n")); 966 goto err; 967 } 968 memset(status,0,queuecnt*sizeof(print_status_struct)); 969 if((subcntarr = SMB_MALLOC_ARRAY(int,queuecnt)) == NULL) { 970 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n")); 971 goto err; 972 } 973 974 subcnt = 0; 975 n = 0; 976 for (i = 0; i < services; i++) { 977 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) { 978 subcntarr[n] = print_queue_status(i, &queue[n],&status[n]); 979 subcnt += subcntarr[n]; 980 n++; 981 } 982 } 983 984 if (mdrcnt > 0) { 985 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt); 986 if (!*rdata) { 987 goto err; 988 } 989 } 990 desc.base = *rdata; 991 desc.buflen = mdrcnt; 992 993 if (init_package(&desc,queuecnt,subcnt)) { 994 n = 0; 995 succnt = 0; 996 for (i = 0; i < services; i++) { 997 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) { 998 fill_printq_info(conn,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]); 999 n++; 1000 if (desc.errcode == NERR_Success) { 1001 succnt = n; 1002 } 1003 } 1004 } 1005 } 1006 1007 SAFE_FREE(subcntarr); 1008 1009 *rdata_len = desc.usedlen; 1010 *rparam_len = 8; 1011 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); 1012 if (!*rparam) { 1013 goto err; 1014 } 1015 SSVALS(*rparam,0,desc.errcode); 1016 SSVAL(*rparam,2,0); 1017 SSVAL(*rparam,4,succnt); 1018 SSVAL(*rparam,6,queuecnt); 1019 1020 for (i = 0; i < queuecnt; i++) { 1021 if (queue) { 1022 SAFE_FREE(queue[i]); 1023 } 1024 } 1025 1026 SAFE_FREE(queue); 1027 SAFE_FREE(status); 1028 1029 return True; 1030 1031 err: 1032 1033 SAFE_FREE(subcntarr); 1034 for (i = 0; i < queuecnt; i++) { 1035 if (queue) { 1036 SAFE_FREE(queue[i]); 1037 } 1038 } 1039 SAFE_FREE(queue); 1040 SAFE_FREE(status); 1041 1042 return False; 1043} 1044 1045/**************************************************************************** 1046 Get info level for a server list query. 1047****************************************************************************/ 1048 1049static BOOL check_server_info(int uLevel, char* id) 1050{ 1051 switch( uLevel ) { 1052 case 0: 1053 if (strcmp(id,"B16") != 0) { 1054 return False; 1055 } 1056 break; 1057 case 1: 1058 if (strcmp(id,"B16BBDz") != 0) { 1059 return False; 1060 } 1061 break; 1062 default: 1063 return False; 1064 } 1065 return True; 1066} 1067 1068struct srv_info_struct { 1069 fstring name; 1070 uint32 type; 1071 fstring comment; 1072 fstring domain; 1073 BOOL server_added; 1074}; 1075 1076/******************************************************************* 1077 Get server info lists from the files saved by nmbd. Return the 1078 number of entries. 1079******************************************************************/ 1080 1081static int get_server_info(uint32 servertype, 1082 struct srv_info_struct **servers, 1083 const char *domain) 1084{ 1085 int count=0; 1086 int alloced=0; 1087 char **lines; 1088 BOOL local_list_only; 1089 int i; 1090 1091 lines = file_lines_load(lock_path(SERVER_LIST), NULL, 0); 1092 if (!lines) { 1093 DEBUG(4,("Can't open %s - %s\n",lock_path(SERVER_LIST),strerror(errno))); 1094 return 0; 1095 } 1096 1097 /* request for everything is code for request all servers */ 1098 if (servertype == SV_TYPE_ALL) { 1099 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY); 1100 } 1101 1102 local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY); 1103 1104 DEBUG(4,("Servertype search: %8x\n",servertype)); 1105 1106 for (i=0;lines[i];i++) { 1107 fstring stype; 1108 struct srv_info_struct *s; 1109 const char *ptr = lines[i]; 1110 BOOL ok = True; 1111 1112 if (!*ptr) { 1113 continue; 1114 } 1115 1116 if (count == alloced) { 1117 alloced += 10; 1118 *servers = SMB_REALLOC_ARRAY(*servers,struct srv_info_struct, alloced); 1119 if (!*servers) { 1120 DEBUG(0,("get_server_info: failed to enlarge servers info struct!\n")); 1121 file_lines_free(lines); 1122 return 0; 1123 } 1124 memset((char *)((*servers)+count),'\0',sizeof(**servers)*(alloced-count)); 1125 } 1126 s = &(*servers)[count]; 1127 1128 if (!next_token(&ptr,s->name, NULL, sizeof(s->name))) { 1129 continue; 1130 } 1131 if (!next_token(&ptr,stype, NULL, sizeof(stype))) { 1132 continue; 1133 } 1134 if (!next_token(&ptr,s->comment, NULL, sizeof(s->comment))) { 1135 continue; 1136 } 1137 if (!next_token(&ptr,s->domain, NULL, sizeof(s->domain))) { 1138 /* this allows us to cope with an old nmbd */ 1139 fstrcpy(s->domain,lp_workgroup()); 1140 } 1141 1142 if (sscanf(stype,"%X",&s->type) != 1) { 1143 DEBUG(4,("r:host file ")); 1144 ok = False; 1145 } 1146 1147 /* Filter the servers/domains we return based on what was asked for. */ 1148 1149 /* Check to see if we are being asked for a local list only. */ 1150 if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) { 1151 DEBUG(4,("r: local list only")); 1152 ok = False; 1153 } 1154 1155 /* doesn't match up: don't want it */ 1156 if (!(servertype & s->type)) { 1157 DEBUG(4,("r:serv type ")); 1158 ok = False; 1159 } 1160 1161 if ((servertype & SV_TYPE_DOMAIN_ENUM) != 1162 (s->type & SV_TYPE_DOMAIN_ENUM)) { 1163 DEBUG(4,("s: dom mismatch ")); 1164 ok = False; 1165 } 1166 1167 if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM)) { 1168 ok = False; 1169 } 1170 1171 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */ 1172 s->type &= ~SV_TYPE_LOCAL_LIST_ONLY; 1173 1174 if (ok) { 1175 DEBUG(4,("**SV** %20s %8x %25s %15s\n", 1176 s->name, s->type, s->comment, s->domain)); 1177 s->server_added = True; 1178 count++; 1179 } else { 1180 DEBUG(4,("%20s %8x %25s %15s\n", 1181 s->name, s->type, s->comment, s->domain)); 1182 } 1183 } 1184 1185 file_lines_free(lines); 1186 return count; 1187} 1188 1189/******************************************************************* 1190 Fill in a server info structure. 1191******************************************************************/ 1192 1193static int fill_srv_info(struct srv_info_struct *service, 1194 int uLevel, char **buf, int *buflen, 1195 char **stringbuf, int *stringspace, char *baseaddr) 1196{ 1197 int struct_len; 1198 char* p; 1199 char* p2; 1200 int l2; 1201 int len; 1202 1203 switch (uLevel) { 1204 case 0: 1205 struct_len = 16; 1206 break; 1207 case 1: 1208 struct_len = 26; 1209 break; 1210 default: 1211 return -1; 1212 } 1213 1214 if (!buf) { 1215 len = 0; 1216 switch (uLevel) { 1217 case 1: 1218 len = strlen(service->comment)+1; 1219 break; 1220 } 1221 1222 *buflen = struct_len; 1223 *stringspace = len; 1224 return struct_len + len; 1225 } 1226 1227 len = struct_len; 1228 p = *buf; 1229 if (*buflen < struct_len) { 1230 return -1; 1231 } 1232 if (stringbuf) { 1233 p2 = *stringbuf; 1234 l2 = *stringspace; 1235 } else { 1236 p2 = p + struct_len; 1237 l2 = *buflen - struct_len; 1238 } 1239 if (!baseaddr) { 1240 baseaddr = p; 1241 } 1242 1243 switch (uLevel) { 1244 case 0: 1245 push_ascii(p,service->name, MAX_NETBIOSNAME_LEN, STR_TERMINATE); 1246 break; 1247 1248 case 1: 1249 push_ascii(p,service->name,MAX_NETBIOSNAME_LEN, STR_TERMINATE); 1250 SIVAL(p,18,service->type); 1251 SIVAL(p,22,PTR_DIFF(p2,baseaddr)); 1252 len += CopyAndAdvance(&p2,service->comment,&l2); 1253 break; 1254 } 1255 1256 if (stringbuf) { 1257 *buf = p + struct_len; 1258 *buflen -= struct_len; 1259 *stringbuf = p2; 1260 *stringspace = l2; 1261 } else { 1262 *buf = p2; 1263 *buflen -= len; 1264 } 1265 return len; 1266} 1267 1268 1269static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2) 1270{ 1271 return(strcmp(s1->name,s2->name)); 1272} 1273 1274/**************************************************************************** 1275 View list of servers available (or possibly domains). The info is 1276 extracted from lists saved by nmbd on the local host. 1277****************************************************************************/ 1278 1279static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid, 1280 char *param, int tpscnt, 1281 char *data, int tdscnt, 1282 int mdrcnt, int mprcnt, char **rdata, 1283 char **rparam, int *rdata_len, int *rparam_len) 1284{ 1285 char *str1 = get_safe_str_ptr(param, tpscnt, param, 2); 1286 char *str2 = skip_string(param,tpscnt,str1); 1287 char *p = skip_string(param,tpscnt,str2); 1288 int uLevel = get_safe_SVAL(param, tpscnt, p, 0, -1); 1289 int buf_len = get_safe_SVAL(param,tpscnt, p, 2, 0); 1290 uint32 servertype = get_safe_IVAL(param,tpscnt,p,4, 0); 1291 char *p2; 1292 int data_len, fixed_len, string_len; 1293 int f_len = 0, s_len = 0; 1294 struct srv_info_struct *servers=NULL; 1295 int counted=0,total=0; 1296 int i,missed; 1297 fstring domain; 1298 BOOL domain_request; 1299 BOOL local_request; 1300 1301 if (!str1 || !str2 || !p) { 1302 return False; 1303 } 1304 1305 /* If someone sets all the bits they don't really mean to set 1306 DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the 1307 known servers. */ 1308 1309 if (servertype == SV_TYPE_ALL) { 1310 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY); 1311 } 1312 1313 /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set 1314 any other bit (they may just set this bit on it's own) they 1315 want all the locally seen servers. However this bit can be 1316 set on its own so set the requested servers to be 1317 ALL - DOMAIN_ENUM. */ 1318 1319 if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM)) { 1320 servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM); 1321 } 1322 1323 domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0); 1324 local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0); 1325 1326 p += 8; 1327 1328 if (!prefix_ok(str1,"WrLehD")) { 1329 return False; 1330 } 1331 if (!check_server_info(uLevel,str2)) { 1332 return False; 1333 } 1334 1335 DEBUG(4, ("server request level: %s %8x ", str2, servertype)); 1336 DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request))); 1337 DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request))); 1338 1339 if (strcmp(str1, "WrLehDz") == 0) { 1340 if (skip_string(param,tpscnt,p) == NULL) { 1341 return False; 1342 } 1343 pull_ascii_fstring(domain, p); 1344 } else { 1345 fstrcpy(domain, lp_workgroup()); 1346 } 1347 1348 if (lp_browse_list()) { 1349 total = get_server_info(servertype,&servers,domain); 1350 } 1351 1352 data_len = fixed_len = string_len = 0; 1353 missed = 0; 1354 1355 if (total > 0) { 1356 qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp); 1357 } 1358 1359 { 1360 char *lastname=NULL; 1361 1362 for (i=0;i<total;i++) { 1363 struct srv_info_struct *s = &servers[i]; 1364 1365 if (lastname && strequal(lastname,s->name)) { 1366 continue; 1367 } 1368 lastname = s->name; 1369 data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0); 1370 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n", 1371 s->name, s->type, s->comment, s->domain)); 1372 1373 if (data_len <= buf_len) { 1374 counted++; 1375 fixed_len += f_len; 1376 string_len += s_len; 1377 } else { 1378 missed++; 1379 } 1380 } 1381 } 1382 1383 *rdata_len = fixed_len + string_len; 1384 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len); 1385 if (!*rdata) { 1386 return False; 1387 } 1388 memset(*rdata,'\0',*rdata_len); 1389 1390 p2 = (*rdata) + fixed_len; /* auxilliary data (strings) will go here */ 1391 p = *rdata; 1392 f_len = fixed_len; 1393 s_len = string_len; 1394 1395 { 1396 char *lastname=NULL; 1397 int count2 = counted; 1398 1399 for (i = 0; i < total && count2;i++) { 1400 struct srv_info_struct *s = &servers[i]; 1401 1402 if (lastname && strequal(lastname,s->name)) { 1403 continue; 1404 } 1405 lastname = s->name; 1406 fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata); 1407 DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n", 1408 s->name, s->type, s->comment, s->domain)); 1409 count2--; 1410 } 1411 } 1412 1413 *rparam_len = 8; 1414 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); 1415 if (!*rparam) { 1416 return False; 1417 } 1418 SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata)); 1419 SSVAL(*rparam,2,0); 1420 SSVAL(*rparam,4,counted); 1421 SSVAL(*rparam,6,counted+missed); 1422 1423 SAFE_FREE(servers); 1424 1425 DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n", 1426 domain,uLevel,counted,counted+missed)); 1427 1428 return True; 1429} 1430 1431/**************************************************************************** 1432 command 0x34 - suspected of being a "Lookup Names" stub api 1433 ****************************************************************************/ 1434 1435static BOOL api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid, 1436 char *param, int tpscnt, 1437 char *data, int tdscnt, 1438 int mdrcnt, int mprcnt, char **rdata, 1439 char **rparam, int *rdata_len, int *rparam_len) 1440{ 1441 char *str1 = get_safe_str_ptr(param,tpscnt,param,2); 1442 char *str2 = skip_string(param,tpscnt,str1); 1443 char *p = skip_string(param,tpscnt,str2); 1444 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1); 1445 int buf_len = get_safe_SVAL(param,tpscnt,p,2,0); 1446 int counted=0; 1447 int missed=0; 1448 1449 if (!str1 || !str2 || !p) { 1450 return False; 1451 } 1452 1453 DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n", 1454 str1, str2, p, uLevel, buf_len)); 1455 1456 if (!prefix_ok(str1,"zWrLeh")) { 1457 return False; 1458 } 1459 1460 *rdata_len = 0; 1461 1462 *rparam_len = 8; 1463 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); 1464 if (!*rparam) { 1465 return False; 1466 } 1467 1468 SSVAL(*rparam,0,0x08AC); /* informational warning message */ 1469 SSVAL(*rparam,2,0); 1470 SSVAL(*rparam,4,counted); 1471 SSVAL(*rparam,6,counted+missed); 1472 1473 return True; 1474} 1475 1476/**************************************************************************** 1477 get info about a share 1478 ****************************************************************************/ 1479 1480static BOOL check_share_info(int uLevel, char* id) 1481{ 1482 switch( uLevel ) { 1483 case 0: 1484 if (strcmp(id,"B13") != 0) { 1485 return False; 1486 } 1487 break; 1488 case 1: 1489 if (strcmp(id,"B13BWz") != 0) { 1490 return False; 1491 } 1492 break; 1493 case 2: 1494 if (strcmp(id,"B13BWzWWWzB9B") != 0) { 1495 return False; 1496 } 1497 break; 1498 case 91: 1499 if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) { 1500 return False; 1501 } 1502 break; 1503 default: 1504 return False; 1505 } 1506 return True; 1507} 1508 1509static int fill_share_info(connection_struct *conn, int snum, int uLevel, 1510 char** buf, int* buflen, 1511 char** stringbuf, int* stringspace, char* baseaddr) 1512{ 1513 int struct_len; 1514 char* p; 1515 char* p2; 1516 int l2; 1517 int len; 1518 1519 switch( uLevel ) { 1520 case 0: 1521 struct_len = 13; 1522 break; 1523 case 1: 1524 struct_len = 20; 1525 break; 1526 case 2: 1527 struct_len = 40; 1528 break; 1529 case 91: 1530 struct_len = 68; 1531 break; 1532 default: 1533 return -1; 1534 } 1535 1536 1537 if (!buf) { 1538 len = 0; 1539 1540 if (uLevel > 0) { 1541 len += StrlenExpanded(conn,snum,lp_comment(snum)); 1542 } 1543 if (uLevel > 1) { 1544 len += strlen(lp_pathname(snum)) + 1; 1545 } 1546 if (buflen) { 1547 *buflen = struct_len; 1548 } 1549 if (stringspace) { 1550 *stringspace = len; 1551 } 1552 return struct_len + len; 1553 } 1554 1555 len = struct_len; 1556 p = *buf; 1557 if ((*buflen) < struct_len) { 1558 return -1; 1559 } 1560 1561 if (stringbuf) { 1562 p2 = *stringbuf; 1563 l2 = *stringspace; 1564 } else { 1565 p2 = p + struct_len; 1566 l2 = (*buflen) - struct_len; 1567 } 1568 1569 if (!baseaddr) { 1570 baseaddr = p; 1571 } 1572 1573 push_ascii(p,lp_servicename(snum),13, STR_TERMINATE); 1574 1575 if (uLevel > 0) { 1576 int type; 1577 1578 SCVAL(p,13,0); 1579 type = STYPE_DISKTREE; 1580 if (lp_print_ok(snum)) { 1581 type = STYPE_PRINTQ; 1582 } 1583 if (strequal("IPC",lp_fstype(snum))) { 1584 type = STYPE_IPC; 1585 } 1586 SSVAL(p,14,type); /* device type */ 1587 SIVAL(p,16,PTR_DIFF(p2,baseaddr)); 1588 len += CopyExpanded(conn,snum,&p2,lp_comment(snum),&l2); 1589 } 1590 1591 if (uLevel > 1) { 1592 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */ 1593 SSVALS(p,22,-1); /* max uses */ 1594 SSVAL(p,24,1); /* current uses */ 1595 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */ 1596 len += CopyAndAdvance(&p2,lp_pathname(snum),&l2); 1597 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */ 1598 } 1599 1600 if (uLevel > 2) { 1601 memset(p+40,0,SHPWLEN+2); 1602 SSVAL(p,50,0); 1603 SIVAL(p,52,0); 1604 SSVAL(p,56,0); 1605 SSVAL(p,58,0); 1606 SIVAL(p,60,0); 1607 SSVAL(p,64,0); 1608 SSVAL(p,66,0); 1609 } 1610 1611 if (stringbuf) { 1612 (*buf) = p + struct_len; 1613 (*buflen) -= struct_len; 1614 (*stringbuf) = p2; 1615 (*stringspace) = l2; 1616 } else { 1617 (*buf) = p2; 1618 (*buflen) -= len; 1619 } 1620 1621 return len; 1622} 1623 1624static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid, 1625 char *param, int tpscnt, 1626 char *data, int tdscnt, 1627 int mdrcnt,int mprcnt, 1628 char **rdata,char **rparam, 1629 int *rdata_len,int *rparam_len) 1630{ 1631 char *str1 = get_safe_str_ptr(param,tpscnt,param,2); 1632 char *str2 = skip_string(param,tpscnt,str1); 1633 char *netname = skip_string(param,tpscnt,str2); 1634 char *p = skip_string(param,tpscnt,netname); 1635 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1); 1636 int snum; 1637 1638 if (!str1 || !str2 || !netname || !p) { 1639 return False; 1640 } 1641 1642 snum = find_service(netname); 1643 if (snum < 0) { 1644 return False; 1645 } 1646 1647 /* check it's a supported varient */ 1648 if (!prefix_ok(str1,"zWrLh")) { 1649 return False; 1650 } 1651 if (!check_share_info(uLevel,str2)) { 1652 return False; 1653 } 1654 1655 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt); 1656 if (!*rdata) { 1657 return False; 1658 } 1659 p = *rdata; 1660 *rdata_len = fill_share_info(conn,snum,uLevel,&p,&mdrcnt,0,0,0); 1661 if (*rdata_len < 0) { 1662 return False; 1663 } 1664 1665 *rparam_len = 6; 1666 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); 1667 if (!*rparam) { 1668 return False; 1669 } 1670 SSVAL(*rparam,0,NERR_Success); 1671 SSVAL(*rparam,2,0); /* converter word */ 1672 SSVAL(*rparam,4,*rdata_len); 1673 1674 return True; 1675} 1676 1677/**************************************************************************** 1678 View the list of available shares. 1679 1680 This function is the server side of the NetShareEnum() RAP call. 1681 It fills the return buffer with share names and share comments. 1682 Note that the return buffer normally (in all known cases) allows only 1683 twelve byte strings for share names (plus one for a nul terminator). 1684 Share names longer than 12 bytes must be skipped. 1685 ****************************************************************************/ 1686 1687static BOOL api_RNetShareEnum( connection_struct *conn, uint16 vuid, 1688 char *param, int tpscnt, 1689 char *data, int tdscnt, 1690 int mdrcnt, 1691 int mprcnt, 1692 char **rdata, 1693 char **rparam, 1694 int *rdata_len, 1695 int *rparam_len ) 1696{ 1697 char *str1 = get_safe_str_ptr(param,tpscnt,param,2); 1698 char *str2 = skip_string(param,tpscnt,str1); 1699 char *p = skip_string(param,tpscnt,str2); 1700 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1); 1701 int buf_len = get_safe_SVAL(param,tpscnt,p,2,0); 1702 char *p2; 1703 int count = 0; 1704 int total=0,counted=0; 1705 BOOL missed = False; 1706 int i; 1707 int data_len, fixed_len, string_len; 1708 int f_len = 0, s_len = 0; 1709 1710 if (!str1 || !str2 || !p) { 1711 return False; 1712 } 1713 1714 if (!prefix_ok(str1,"WrLeh")) { 1715 return False; 1716 } 1717 if (!check_share_info(uLevel,str2)) { 1718 return False; 1719 } 1720 1721 /* Ensure all the usershares are loaded. */ 1722 become_root(); 1723 count = load_usershare_shares(); 1724 unbecome_root(); 1725 1726 data_len = fixed_len = string_len = 0; 1727 for (i=0;i<count;i++) { 1728 fstring servicename_dos; 1729 if (!(lp_browseable(i) && lp_snum_ok(i))) { 1730 continue; 1731 } 1732 push_ascii_fstring(servicename_dos, lp_servicename(i)); 1733 /* Maximum name length = 13. */ 1734 if( lp_browseable( i ) && lp_snum_ok( i ) && (strlen(servicename_dos) < 13)) { 1735 total++; 1736 data_len += fill_share_info(conn,i,uLevel,0,&f_len,0,&s_len,0); 1737 if (data_len <= buf_len) { 1738 counted++; 1739 fixed_len += f_len; 1740 string_len += s_len; 1741 } else { 1742 missed = True; 1743 } 1744 } 1745 } 1746 1747 *rdata_len = fixed_len + string_len; 1748 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len); 1749 if (!*rdata) { 1750 return False; 1751 } 1752 memset(*rdata,0,*rdata_len); 1753 1754 p2 = (*rdata) + fixed_len; /* auxiliary data (strings) will go here */ 1755 p = *rdata; 1756 f_len = fixed_len; 1757 s_len = string_len; 1758 1759 for( i = 0; i < count; i++ ) { 1760 fstring servicename_dos; 1761 if (!(lp_browseable(i) && lp_snum_ok(i))) { 1762 continue; 1763 } 1764 1765 push_ascii_fstring(servicename_dos, lp_servicename(i)); 1766 if (lp_browseable(i) && lp_snum_ok(i) && (strlen(servicename_dos) < 13)) { 1767 if (fill_share_info( conn,i,uLevel,&p,&f_len,&p2,&s_len,*rdata ) < 0) { 1768 break; 1769 } 1770 } 1771 } 1772 1773 *rparam_len = 8; 1774 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); 1775 if (!*rparam) { 1776 return False; 1777 } 1778 SSVAL(*rparam,0,missed ? ERRmoredata : NERR_Success); 1779 SSVAL(*rparam,2,0); 1780 SSVAL(*rparam,4,counted); 1781 SSVAL(*rparam,6,total); 1782 1783 DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n", 1784 counted,total,uLevel, 1785 buf_len,*rdata_len,mdrcnt)); 1786 1787 return True; 1788} 1789 1790/**************************************************************************** 1791 Add a share 1792 ****************************************************************************/ 1793 1794static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid, 1795 char *param, int tpscnt, 1796 char *data, int tdscnt, 1797 int mdrcnt,int mprcnt, 1798 char **rdata,char **rparam, 1799 int *rdata_len,int *rparam_len) 1800{ 1801 char *str1 = get_safe_str_ptr(param,tpscnt,param,2); 1802 char *str2 = skip_string(param,tpscnt,str1); 1803 char *p = skip_string(param,tpscnt,str2); 1804 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1); 1805 fstring sharename; 1806 fstring comment; 1807 pstring pathname; 1808 char *command, *cmdname; 1809 unsigned int offset; 1810 int snum; 1811 int res = ERRunsup; 1812 1813 if (!str1 || !str2 || !p) { 1814 return False; 1815 } 1816 1817 /* check it's a supported varient */ 1818 if (!prefix_ok(str1,RAP_WShareAdd_REQ)) { 1819 return False; 1820 } 1821 if (!check_share_info(uLevel,str2)) { 1822 return False; 1823 } 1824 if (uLevel != 2) { 1825 return False; 1826 } 1827 1828 /* Do we have a string ? */ 1829 if (skip_string(data,mdrcnt,data) == NULL) { 1830 return False; 1831 } 1832 pull_ascii_fstring(sharename,data); 1833 snum = find_service(sharename); 1834 if (snum >= 0) { /* already exists */ 1835 res = ERRfilexists; 1836 goto error_exit; 1837 } 1838 1839 if (mdrcnt < 28) { 1840 return False; 1841 } 1842 1843 /* only support disk share adds */ 1844 if (SVAL(data,14)!=STYPE_DISKTREE) { 1845 return False; 1846 } 1847 1848 offset = IVAL(data, 16); 1849 if (offset >= mdrcnt) { 1850 res = ERRinvalidparam; 1851 goto error_exit; 1852 } 1853 1854 /* Do we have a string ? */ 1855 if (skip_string(data,mdrcnt,data+offset) == NULL) { 1856 return False; 1857 } 1858 pull_ascii_fstring(comment, offset? (data+offset) : ""); 1859 1860 offset = IVAL(data, 26); 1861 1862 if (offset >= mdrcnt) { 1863 res = ERRinvalidparam; 1864 goto error_exit; 1865 } 1866 1867 /* Do we have a string ? */ 1868 if (skip_string(data,mdrcnt,data+offset) == NULL) { 1869 return False; 1870 } 1871 pull_ascii_pstring(pathname, offset? (data+offset) : ""); 1872 1873 string_replace(sharename, '"', ' '); 1874 string_replace(pathname, '"', ' '); 1875 string_replace(comment, '"', ' '); 1876 1877 cmdname = lp_add_share_cmd(); 1878 1879 if (!cmdname || *cmdname == '\0') { 1880 return False; 1881 } 1882 1883 asprintf(&command, "%s \"%s\" \"%s\" \"%s\" \"%s\"", 1884 lp_add_share_cmd(), dyn_CONFIGFILE, sharename, pathname, comment); 1885 1886 if (command) { 1887 DEBUG(10,("api_RNetShareAdd: Running [%s]\n", command )); 1888 1889 if ((res = smbrun(command, NULL)) != 0) { 1890 DEBUG(1,("api_RNetShareAdd: Running [%s] returned (%d)\n", command, res )); 1891 SAFE_FREE(command); 1892 res = ERRnoaccess; 1893 goto error_exit; 1894 } else { 1895 SAFE_FREE(command); 1896 message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL); 1897 } 1898 } else { 1899 return False; 1900 } 1901 1902 *rparam_len = 6; 1903 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); 1904 if (!*rparam) { 1905 return False; 1906 } 1907 SSVAL(*rparam,0,NERR_Success); 1908 SSVAL(*rparam,2,0); /* converter word */ 1909 SSVAL(*rparam,4,*rdata_len); 1910 *rdata_len = 0; 1911 1912 return True; 1913 1914 error_exit: 1915 1916 *rparam_len = 4; 1917 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); 1918 if (!*rparam) { 1919 return False; 1920 } 1921 *rdata_len = 0; 1922 SSVAL(*rparam,0,res); 1923 SSVAL(*rparam,2,0); 1924 return True; 1925} 1926 1927/**************************************************************************** 1928 view list of groups available 1929 ****************************************************************************/ 1930 1931static BOOL api_RNetGroupEnum(connection_struct *conn,uint16 vuid, 1932 char *param, int tpscnt, 1933 char *data, int tdscnt, 1934 int mdrcnt,int mprcnt, 1935 char **rdata,char **rparam, 1936 int *rdata_len,int *rparam_len) 1937{ 1938 int i; 1939 int errflags=0; 1940 int resume_context, cli_buf_size; 1941 char *str1 = get_safe_str_ptr(param,tpscnt,param,2); 1942 char *str2 = skip_string(param,tpscnt,str1); 1943 char *p = skip_string(param,tpscnt,str2); 1944 1945 struct pdb_search *search; 1946 struct samr_displayentry *entries; 1947 1948 int num_entries; 1949 1950 if (!str1 || !str2 || !p) { 1951 return False; 1952 } 1953 1954 if (strcmp(str1,"WrLeh") != 0) { 1955 return False; 1956 } 1957 1958 /* parameters 1959 * W-> resume context (number of users to skip) 1960 * r -> return parameter pointer to receive buffer 1961 * L -> length of receive buffer 1962 * e -> return parameter number of entries 1963 * h -> return parameter total number of users 1964 */ 1965 1966 if (strcmp("B21",str2) != 0) { 1967 return False; 1968 } 1969 1970 /* get list of domain groups SID_DOMAIN_GRP=2 */ 1971 become_root(); 1972 search = pdb_search_groups(); 1973 unbecome_root(); 1974 1975 if (search == NULL) { 1976 DEBUG(3,("api_RNetGroupEnum:failed to get group list")); 1977 return False; 1978 } 1979 1980 resume_context = get_safe_SVAL(param,tpscnt,p,0,-1); 1981 cli_buf_size= get_safe_SVAL(param,tpscnt,p,2,0); 1982 DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: " 1983 "%d\n", resume_context, cli_buf_size)); 1984 1985 become_root(); 1986 num_entries = pdb_search_entries(search, resume_context, 0xffffffff, 1987 &entries); 1988 unbecome_root(); 1989 1990 *rdata_len = cli_buf_size; 1991 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len); 1992 if (!*rdata) { 1993 return False; 1994 } 1995 1996 p = *rdata; 1997 1998 for(i=0; i<num_entries; i++) { 1999 fstring name; 2000 fstrcpy(name, entries[i].account_name); 2001 if( ((PTR_DIFF(p,*rdata)+21) <= *rdata_len) ) { 2002 /* truncate the name at 21 chars. */ 2003 memcpy(p, name, 21); 2004 DEBUG(10,("adding entry %d group %s\n", i, p)); 2005 p += 21; 2006 p += 5; /* Both NT4 and W2k3SP1 do padding here. 2007 No idea why... */ 2008 } else { 2009 /* set overflow error */ 2010 DEBUG(3,("overflow on entry %d group %s\n", i, name)); 2011 errflags=234; 2012 break; 2013 } 2014 } 2015 2016 pdb_search_destroy(search); 2017 2018 *rdata_len = PTR_DIFF(p,*rdata); 2019 2020 *rparam_len = 8; 2021 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); 2022 if (!*rparam) { 2023 return False; 2024 } 2025 SSVAL(*rparam, 0, errflags); 2026 SSVAL(*rparam, 2, 0); /* converter word */ 2027 SSVAL(*rparam, 4, i); /* is this right?? */ 2028 SSVAL(*rparam, 6, resume_context+num_entries); /* is this right?? */ 2029 2030 return(True); 2031} 2032 2033/******************************************************************* 2034 Get groups that a user is a member of. 2035******************************************************************/ 2036 2037static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, 2038 char *param, int tpscnt, 2039 char *data, int tdscnt, 2040 int mdrcnt,int mprcnt, 2041 char **rdata,char **rparam, 2042 int *rdata_len,int *rparam_len) 2043{ 2044 char *str1 = get_safe_str_ptr(param,tpscnt,param,2); 2045 char *str2 = skip_string(param,tpscnt,str1); 2046 char *UserName = skip_string(param,tpscnt,str2); 2047 char *p = skip_string(param,tpscnt,UserName); 2048 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1); 2049 const char *level_string; 2050 int count=0; 2051 struct samu *sampw = NULL; 2052 BOOL ret = False; 2053 DOM_SID *sids; 2054 gid_t *gids; 2055 size_t num_groups; 2056 size_t i; 2057 NTSTATUS result; 2058 DOM_SID user_sid; 2059 enum lsa_SidType type; 2060 TALLOC_CTX *mem_ctx; 2061 2062 if (!str1 || !str2 || !UserName || !p) { 2063 return False; 2064 } 2065 2066 *rparam_len = 8; 2067 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); 2068 if (!*rparam) { 2069 return False; 2070 } 2071 2072 /* check it's a supported varient */ 2073 2074 if ( strcmp(str1,"zWrLeh") != 0 ) 2075 return False; 2076 2077 switch( uLevel ) { 2078 case 0: 2079 level_string = "B21"; 2080 break; 2081 default: 2082 return False; 2083 } 2084 2085 if (strcmp(level_string,str2) != 0) 2086 return False; 2087 2088 *rdata_len = mdrcnt + 1024; 2089 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len); 2090 if (!*rdata) { 2091 return False; 2092 } 2093 SSVAL(*rparam,0,NERR_Success); 2094 SSVAL(*rparam,2,0); /* converter word */ 2095 2096 p = *rdata; 2097 2098 mem_ctx = talloc_new(NULL); 2099 if (mem_ctx == NULL) { 2100 DEBUG(0, ("talloc_new failed\n")); 2101 return False; 2102 } 2103 2104 if ( !(sampw = samu_new(mem_ctx)) ) { 2105 DEBUG(0, ("samu_new() failed!\n")); 2106 TALLOC_FREE(mem_ctx); 2107 return False; 2108 } 2109 2110 /* Lookup the user information; This should only be one of 2111 our accounts (not remote domains) */ 2112 2113 become_root(); /* ROOT BLOCK */ 2114 2115 if (!lookup_name(mem_ctx, UserName, LOOKUP_NAME_ALL, 2116 NULL, NULL, &user_sid, &type)) { 2117 DEBUG(10, ("lookup_name(%s) failed\n", UserName)); 2118 goto done; 2119 } 2120 2121 if (type != SID_NAME_USER) { 2122 DEBUG(10, ("%s is a %s, not a user\n", UserName, 2123 sid_type_lookup(type))); 2124 goto done; 2125 } 2126 2127 if ( !pdb_getsampwsid(sampw, &user_sid) ) { 2128 DEBUG(10, ("pdb_getsampwsid(%s) failed for user %s\n", 2129 sid_string_static(&user_sid), UserName)); 2130 goto done; 2131 } 2132 2133 gids = NULL; 2134 sids = NULL; 2135 num_groups = 0; 2136 2137 result = pdb_enum_group_memberships(mem_ctx, sampw, 2138 &sids, &gids, &num_groups); 2139 2140 if (!NT_STATUS_IS_OK(result)) { 2141 DEBUG(10, ("pdb_enum_group_memberships failed for %s\n", 2142 UserName)); 2143 goto done; 2144 } 2145 2146 for (i=0; i<num_groups; i++) { 2147 2148 const char *grp_name; 2149 2150 if ( lookup_sid(mem_ctx, &sids[i], NULL, &grp_name, NULL) ) { 2151 pstrcpy(p, grp_name); 2152 p += 21; 2153 count++; 2154 } 2155 } 2156 2157 *rdata_len = PTR_DIFF(p,*rdata); 2158 2159 SSVAL(*rparam,4,count); /* is this right?? */ 2160 SSVAL(*rparam,6,count); /* is this right?? */ 2161 2162 ret = True; 2163 2164done: 2165 unbecome_root(); /* END ROOT BLOCK */ 2166 2167 TALLOC_FREE(mem_ctx); 2168 2169 return ret; 2170} 2171 2172/******************************************************************* 2173 Get all users. 2174******************************************************************/ 2175 2176static BOOL api_RNetUserEnum(connection_struct *conn, uint16 vuid, 2177 char *param, int tpscnt, 2178 char *data, int tdscnt, 2179 int mdrcnt,int mprcnt, 2180 char **rdata,char **rparam, 2181 int *rdata_len,int *rparam_len) 2182{ 2183 int count_sent=0; 2184 int num_users=0; 2185 int errflags=0; 2186 int i, resume_context, cli_buf_size; 2187 struct pdb_search *search; 2188 struct samr_displayentry *users; 2189 2190 char *str1 = get_safe_str_ptr(param,tpscnt,param,2); 2191 char *str2 = skip_string(param,tpscnt,str1); 2192 char *p = skip_string(param,tpscnt,str2); 2193 2194 if (!str1 || !str2 || !p) { 2195 return False; 2196 } 2197 2198 if (strcmp(str1,"WrLeh") != 0) 2199 return False; 2200 /* parameters 2201 * W-> resume context (number of users to skip) 2202 * r -> return parameter pointer to receive buffer 2203 * L -> length of receive buffer 2204 * e -> return parameter number of entries 2205 * h -> return parameter total number of users 2206 */ 2207 2208 resume_context = get_safe_SVAL(param,tpscnt,p,0,-1); 2209 cli_buf_size= get_safe_SVAL(param,tpscnt,p,2,0); 2210 DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n", 2211 resume_context, cli_buf_size)); 2212 2213 *rparam_len = 8; 2214 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); 2215 if (!*rparam) { 2216 return False; 2217 } 2218 2219 /* check it's a supported varient */ 2220 if (strcmp("B21",str2) != 0) 2221 return False; 2222 2223 *rdata_len = cli_buf_size; 2224 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len); 2225 if (!*rdata) { 2226 return False; 2227 } 2228 2229 p = *rdata; 2230 2231 become_root(); 2232 search = pdb_search_users(ACB_NORMAL); 2233 unbecome_root(); 2234 if (search == NULL) { 2235 DEBUG(0, ("api_RNetUserEnum:unable to open sam database.\n")); 2236 return False; 2237 } 2238 2239 become_root(); 2240 num_users = pdb_search_entries(search, resume_context, 0xffffffff, 2241 &users); 2242 unbecome_root(); 2243 2244 errflags=NERR_Success; 2245 2246 for (i=0; i<num_users; i++) { 2247 const char *name = users[i].account_name; 2248 2249 if(((PTR_DIFF(p,*rdata)+21)<=*rdata_len)&&(strlen(name)<=21)) { 2250 pstrcpy(p,name); 2251 DEBUG(10,("api_RNetUserEnum:adding entry %d username " 2252 "%s\n",count_sent,p)); 2253 p += 21; 2254 count_sent++; 2255 } else { 2256 /* set overflow error */ 2257 DEBUG(10,("api_RNetUserEnum:overflow on entry %d " 2258 "username %s\n",count_sent,name)); 2259 errflags=234; 2260 break; 2261 } 2262 } 2263 2264 pdb_search_destroy(search); 2265 2266 *rdata_len = PTR_DIFF(p,*rdata); 2267 2268 SSVAL(*rparam,0,errflags); 2269 SSVAL(*rparam,2,0); /* converter word */ 2270 SSVAL(*rparam,4,count_sent); /* is this right?? */ 2271 SSVAL(*rparam,6,num_users); /* is this right?? */ 2272 2273 return True; 2274} 2275 2276/**************************************************************************** 2277 Get the time of day info. 2278****************************************************************************/ 2279 2280static BOOL api_NetRemoteTOD(connection_struct *conn,uint16 vuid, 2281 char *param, int tpscnt, 2282 char *data, int tdscnt, 2283 int mdrcnt,int mprcnt, 2284 char **rdata,char **rparam, 2285 int *rdata_len,int *rparam_len) 2286{ 2287 struct tm *t; 2288 time_t unixdate = time(NULL); 2289 char *p; 2290 2291 *rparam_len = 4; 2292 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); 2293 if (!*rparam) { 2294 return False; 2295 } 2296 2297 *rdata_len = 21; 2298 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len); 2299 if (!*rdata) { 2300 return False; 2301 } 2302 2303 SSVAL(*rparam,0,NERR_Success); 2304 SSVAL(*rparam,2,0); /* converter word */ 2305 2306 p = *rdata; 2307 2308 srv_put_dos_date3(p,0,unixdate); /* this is the time that is looked at 2309 by NT in a "net time" operation, 2310 it seems to ignore the one below */ 2311 2312 /* the client expects to get localtime, not GMT, in this bit 2313 (I think, this needs testing) */ 2314 t = localtime(&unixdate); 2315 if (!t) { 2316 return False; 2317 } 2318 2319 SIVAL(p,4,0); /* msecs ? */ 2320 SCVAL(p,8,t->tm_hour); 2321 SCVAL(p,9,t->tm_min); 2322 SCVAL(p,10,t->tm_sec); 2323 SCVAL(p,11,0); /* hundredths of seconds */ 2324 SSVALS(p,12,get_time_zone(unixdate)/60); /* timezone in minutes from GMT */ 2325 SSVAL(p,14,10000); /* timer interval in 0.0001 of sec */ 2326 SCVAL(p,16,t->tm_mday); 2327 SCVAL(p,17,t->tm_mon + 1); 2328 SSVAL(p,18,1900+t->tm_year); 2329 SCVAL(p,20,t->tm_wday); 2330 2331 return True; 2332} 2333 2334/**************************************************************************** 2335 Set the user password. 2336*****************************************************************************/ 2337 2338static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, 2339 char *param, int tpscnt, 2340 char *data, int tdscnt, 2341 int mdrcnt,int mprcnt, 2342 char **rdata,char **rparam, 2343 int *rdata_len,int *rparam_len) 2344{ 2345 char *np = get_safe_str_ptr(param,tpscnt,param,2); 2346 char *p = NULL; 2347 fstring user; 2348 fstring pass1,pass2; 2349 2350 /* Skip 2 strings. */ 2351 p = skip_string(param,tpscnt,np); 2352 p = skip_string(param,tpscnt,p); 2353 2354 if (!np || !p) { 2355 return False; 2356 } 2357 2358 /* Do we have a string ? */ 2359 if (skip_string(param,tpscnt,p) == NULL) { 2360 return False; 2361 } 2362 pull_ascii_fstring(user,p); 2363 2364 p = skip_string(param,tpscnt,p); 2365 if (!p) { 2366 return False; 2367 } 2368 2369 memset(pass1,'\0',sizeof(pass1)); 2370 memset(pass2,'\0',sizeof(pass2)); 2371 /* 2372 * We use 31 here not 32 as we're checking 2373 * the last byte we want to access is safe. 2374 */ 2375 if (!is_offset_safe(param,tpscnt,p,31)) { 2376 return False; 2377 } 2378 memcpy(pass1,p,16); 2379 memcpy(pass2,p+16,16); 2380 2381 *rparam_len = 4; 2382 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); 2383 if (!*rparam) { 2384 return False; 2385 } 2386 2387 *rdata_len = 0; 2388 2389 SSVAL(*rparam,0,NERR_badpass); 2390 SSVAL(*rparam,2,0); /* converter word */ 2391 2392 DEBUG(3,("Set password for <%s>\n",user)); 2393 2394 /* 2395 * Attempt to verify the old password against smbpasswd entries 2396 * Win98 clients send old and new password in plaintext for this call. 2397 */ 2398 2399 { 2400 auth_serversupplied_info *server_info = NULL; 2401 DATA_BLOB password = data_blob(pass1, strlen(pass1)+1); 2402 2403 if (NT_STATUS_IS_OK(check_plaintext_password(user,password,&server_info))) { 2404 2405 become_root(); 2406 if (NT_STATUS_IS_OK(change_oem_password(server_info->sam_account, pass1, pass2, False, NULL))) { 2407 SSVAL(*rparam,0,NERR_Success); 2408 } 2409 unbecome_root(); 2410 2411 TALLOC_FREE(server_info); 2412 } 2413 data_blob_clear_free(&password); 2414 } 2415 2416 /* 2417 * If the plaintext change failed, attempt 2418 * the old encrypted method. NT will generate this 2419 * after trying the samr method. Note that this 2420 * method is done as a last resort as this 2421 * password change method loses the NT password hash 2422 * and cannot change the UNIX password as no plaintext 2423 * is received. 2424 */ 2425 2426 if(SVAL(*rparam,0) != NERR_Success) { 2427 struct samu *hnd = NULL; 2428 2429 if (check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &hnd)) { 2430 become_root(); 2431 if (change_lanman_password(hnd,(uchar *)pass2)) { 2432 SSVAL(*rparam,0,NERR_Success); 2433 } 2434 unbecome_root(); 2435 TALLOC_FREE(hnd); 2436 } 2437 } 2438 2439 memset((char *)pass1,'\0',sizeof(fstring)); 2440 memset((char *)pass2,'\0',sizeof(fstring)); 2441 2442 return(True); 2443} 2444 2445/**************************************************************************** 2446 Set the user password (SamOEM version - gets plaintext). 2447****************************************************************************/ 2448 2449static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid, 2450 char *param, int tpscnt, 2451 char *data, int tdscnt, 2452 int mdrcnt,int mprcnt, 2453 char **rdata,char **rparam, 2454 int *rdata_len,int *rparam_len) 2455{ 2456 fstring user; 2457 char *p = get_safe_str_ptr(param,tpscnt,param,2); 2458 *rparam_len = 2; 2459 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); 2460 if (!*rparam) { 2461 return False; 2462 } 2463 2464 if (!p) { 2465 return False; 2466 } 2467 *rdata_len = 0; 2468 2469 SSVAL(*rparam,0,NERR_badpass); 2470 2471 /* 2472 * Check the parameter definition is correct. 2473 */ 2474 2475 /* Do we have a string ? */ 2476 if (skip_string(param,tpscnt,p) == 0) { 2477 return False; 2478 } 2479 if(!strequal(p, "zsT")) { 2480 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", p)); 2481 return False; 2482 } 2483 p = skip_string(param, tpscnt, p); 2484 if (!p) { 2485 return False; 2486 } 2487 2488 /* Do we have a string ? */ 2489 if (skip_string(param,tpscnt,p) == 0) { 2490 return False; 2491 } 2492 if(!strequal(p, "B516B16")) { 2493 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p)); 2494 return False; 2495 } 2496 p = skip_string(param,tpscnt,p); 2497 if (!p) { 2498 return False; 2499 } 2500 /* Do we have a string ? */ 2501 if (skip_string(param,tpscnt,p) == 0) { 2502 return False; 2503 } 2504 p += pull_ascii_fstring(user,p); 2505 2506 DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user)); 2507 2508 /* 2509 * Pass the user through the NT -> unix user mapping 2510 * function. 2511 */ 2512 2513 (void)map_username(user); 2514 2515 if (NT_STATUS_IS_OK(pass_oem_change(user, (uchar*) data, (uchar *)&data[516], NULL, NULL, NULL))) { 2516 SSVAL(*rparam,0,NERR_Success); 2517 } 2518 2519 return(True); 2520} 2521 2522/**************************************************************************** 2523 delete a print job 2524 Form: <W> <> 2525 ****************************************************************************/ 2526 2527static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, 2528 char *param, int tpscnt, 2529 char *data, int tdscnt, 2530 int mdrcnt,int mprcnt, 2531 char **rdata,char **rparam, 2532 int *rdata_len,int *rparam_len) 2533{ 2534 int function = get_safe_SVAL(param,tpscnt,param,0,0); 2535 char *str1 = get_safe_str_ptr(param,tpscnt,param,2); 2536 char *str2 = skip_string(param,tpscnt,str1); 2537 char *p = skip_string(param,tpscnt,str2); 2538 uint32 jobid; 2539 int snum; 2540 fstring sharename; 2541 int errcode; 2542 WERROR werr = WERR_OK; 2543 2544 if (!str1 || !str2 || !p) { 2545 return False; 2546 } 2547 /* 2548 * We use 1 here not 2 as we're checking 2549 * the last byte we want to access is safe. 2550 */ 2551 if (!is_offset_safe(param,tpscnt,p,1)) { 2552 return False; 2553 } 2554 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid)) 2555 return False; 2556 2557 /* check it's a supported varient */ 2558 if (!(strcsequal(str1,"W") && strcsequal(str2,""))) 2559 return(False); 2560 2561 *rparam_len = 4; 2562 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); 2563 if (!*rparam) { 2564 return False; 2565 } 2566 *rdata_len = 0; 2567 2568 if (!print_job_exists(sharename, jobid)) { 2569 errcode = NERR_JobNotFound; 2570 goto out; 2571 } 2572 2573 snum = lp_servicenumber( sharename); 2574 if (snum == -1) { 2575 errcode = NERR_DestNotFound; 2576 goto out; 2577 } 2578 2579 errcode = NERR_notsupported; 2580 2581 switch (function) { 2582 case 81: /* delete */ 2583 if (print_job_delete(¤t_user, snum, jobid, &werr)) 2584 errcode = NERR_Success; 2585 break; 2586 case 82: /* pause */ 2587 if (print_job_pause(¤t_user, snum, jobid, &werr)) 2588 errcode = NERR_Success; 2589 break; 2590 case 83: /* resume */ 2591 if (print_job_resume(¤t_user, snum, jobid, &werr)) 2592 errcode = NERR_Success; 2593 break; 2594 } 2595 2596 if (!W_ERROR_IS_OK(werr)) 2597 errcode = W_ERROR_V(werr); 2598 2599 out: 2600 SSVAL(*rparam,0,errcode); 2601 SSVAL(*rparam,2,0); /* converter word */ 2602 2603 return(True); 2604} 2605 2606/**************************************************************************** 2607 Purge a print queue - or pause or resume it. 2608 ****************************************************************************/ 2609 2610static BOOL api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid, 2611 char *param, int tpscnt, 2612 char *data, int tdscnt, 2613 int mdrcnt,int mprcnt, 2614 char **rdata,char **rparam, 2615 int *rdata_len,int *rparam_len) 2616{ 2617 int function = get_safe_SVAL(param,tpscnt,param,0,0); 2618 char *str1 = get_safe_str_ptr(param,tpscnt,param,2); 2619 char *str2 = skip_string(param,tpscnt,str1); 2620 char *QueueName = skip_string(param,tpscnt,str2); 2621 int errcode = NERR_notsupported; 2622 int snum; 2623 WERROR werr = WERR_OK; 2624 2625 if (!str1 || !str2 || !QueueName) { 2626 return False; 2627 } 2628 2629 /* check it's a supported varient */ 2630 if (!(strcsequal(str1,"z") && strcsequal(str2,""))) 2631 return(False); 2632 2633 *rparam_len = 4; 2634 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); 2635 if (!*rparam) { 2636 return False; 2637 } 2638 *rdata_len = 0; 2639 2640 if (skip_string(param,tpscnt,QueueName) == NULL) { 2641 return False; 2642 } 2643 snum = print_queue_snum(QueueName); 2644 2645 if (snum == -1) { 2646 errcode = NERR_JobNotFound; 2647 goto out; 2648 } 2649 2650 switch (function) { 2651 case 74: /* Pause queue */ 2652 if (print_queue_pause(¤t_user, snum, &werr)) errcode = NERR_Success; 2653 break; 2654 case 75: /* Resume queue */ 2655 if (print_queue_resume(¤t_user, snum, &werr)) errcode = NERR_Success; 2656 break; 2657 case 103: /* Purge */ 2658 if (print_queue_purge(¤t_user, snum, &werr)) errcode = NERR_Success; 2659 break; 2660 } 2661 2662 if (!W_ERROR_IS_OK(werr)) errcode = W_ERROR_V(werr); 2663 2664 out: 2665 SSVAL(*rparam,0,errcode); 2666 SSVAL(*rparam,2,0); /* converter word */ 2667 2668 return(True); 2669} 2670 2671/**************************************************************************** 2672 set the property of a print job (undocumented?) 2673 ? function = 0xb -> set name of print job 2674 ? function = 0x6 -> move print job up/down 2675 Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz> 2676 or <WWsTP> <WB21BB16B10zWWzDDz> 2677****************************************************************************/ 2678 2679static int check_printjob_info(struct pack_desc* desc, 2680 int uLevel, char* id) 2681{ 2682 desc->subformat = NULL; 2683 switch( uLevel ) { 2684 case 0: desc->format = "W"; break; 2685 case 1: desc->format = "WB21BB16B10zWWzDDz"; break; 2686 case 2: desc->format = "WWzWWDDzz"; break; 2687 case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break; 2688 case 4: desc->format = "WWzWWDDzzzzzDDDDDDD"; break; 2689 default: 2690 DEBUG(0,("check_printjob_info: invalid level %d\n", 2691 uLevel )); 2692 return False; 2693 } 2694 if (id == NULL || strcmp(desc->format,id) != 0) { 2695 DEBUG(0,("check_printjob_info: invalid format %s\n", 2696 id ? id : "<NULL>" )); 2697 return False; 2698 } 2699 return True; 2700} 2701 2702static BOOL api_PrintJobInfo(connection_struct *conn, uint16 vuid, 2703 char *param, int tpscnt, 2704 char *data, int tdscnt, 2705 int mdrcnt,int mprcnt, 2706 char **rdata,char **rparam, 2707 int *rdata_len,int *rparam_len) 2708{ 2709 struct pack_desc desc; 2710 char *str1 = get_safe_str_ptr(param,tpscnt,param,2); 2711 char *str2 = skip_string(param,tpscnt,str1); 2712 char *p = skip_string(param,tpscnt,str2); 2713 uint32 jobid; 2714 fstring sharename; 2715 int uLevel = get_safe_SVAL(param,tpscnt,p,2,-1); 2716 int function = get_safe_SVAL(param,tpscnt,p,4,-1); 2717 int place, errcode; 2718 2719 if (!str1 || !str2 || !p) { 2720 return False; 2721 } 2722 /* 2723 * We use 1 here not 2 as we're checking 2724 * the last byte we want to access is safe. 2725 */ 2726 if (!is_offset_safe(param,tpscnt,p,1)) { 2727 return False; 2728 } 2729 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid)) 2730 return False; 2731 *rparam_len = 4; 2732 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); 2733 if (!*rparam) { 2734 return False; 2735 } 2736 2737 if (!share_defined(sharename)) { 2738 DEBUG(0,("api_PrintJobInfo: sharen [%s] not defined\n", 2739 sharename)); 2740 return False; 2741 } 2742 2743 *rdata_len = 0; 2744 2745 /* check it's a supported varient */ 2746 if ((strcmp(str1,"WWsTP")) || 2747 (!check_printjob_info(&desc,uLevel,str2))) 2748 return(False); 2749 2750 if (!print_job_exists(sharename, jobid)) { 2751 errcode=NERR_JobNotFound; 2752 goto out; 2753 } 2754 2755 errcode = NERR_notsupported; 2756 2757 switch (function) { 2758 case 0x6: 2759 /* change job place in the queue, 2760 data gives the new place */ 2761 place = SVAL(data,0); 2762 if (print_job_set_place(sharename, jobid, place)) { 2763 errcode=NERR_Success; 2764 } 2765 break; 2766 2767 case 0xb: 2768 /* change print job name, data gives the name */ 2769 if (print_job_set_name(sharename, jobid, data)) { 2770 errcode=NERR_Success; 2771 } 2772 break; 2773 2774 default: 2775 return False; 2776 } 2777 2778 out: 2779 SSVALS(*rparam,0,errcode); 2780 SSVAL(*rparam,2,0); /* converter word */ 2781 2782 return(True); 2783} 2784 2785 2786/**************************************************************************** 2787 Get info about the server. 2788****************************************************************************/ 2789 2790static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, 2791 char *param, int tpscnt, 2792 char *data, int tdscnt, 2793 int mdrcnt,int mprcnt, 2794 char **rdata,char **rparam, 2795 int *rdata_len,int *rparam_len) 2796{ 2797 char *str1 = get_safe_str_ptr(param,tpscnt,param,2); 2798 char *str2 = skip_string(param,tpscnt,str1); 2799 char *p = skip_string(param,tpscnt,str2); 2800 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1); 2801 char *p2; 2802 int struct_len; 2803 2804 if (!str1 || !str2 || !p) { 2805 return False; 2806 } 2807 2808 DEBUG(4,("NetServerGetInfo level %d\n",uLevel)); 2809 2810 /* check it's a supported varient */ 2811 if (!prefix_ok(str1,"WrLh")) { 2812 return False; 2813 } 2814 2815 switch( uLevel ) { 2816 case 0: 2817 if (strcmp(str2,"B16") != 0) { 2818 return False; 2819 } 2820 struct_len = 16; 2821 break; 2822 case 1: 2823 if (strcmp(str2,"B16BBDz") != 0) { 2824 return False; 2825 } 2826 struct_len = 26; 2827 break; 2828 case 2: 2829 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")!= 0) { 2830 return False; 2831 } 2832 struct_len = 134; 2833 break; 2834 case 3: 2835 if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz") != 0) { 2836 return False; 2837 } 2838 struct_len = 144; 2839 break; 2840 case 20: 2841 if (strcmp(str2,"DN") != 0) { 2842 return False; 2843 } 2844 struct_len = 6; 2845 break; 2846 case 50: 2847 if (strcmp(str2,"B16BBDzWWzzz") != 0) { 2848 return False; 2849 } 2850 struct_len = 42; 2851 break; 2852 default: 2853 return False; 2854 } 2855 2856 *rdata_len = mdrcnt; 2857 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len); 2858 if (!*rdata) { 2859 return False; 2860 } 2861 2862 p = *rdata; 2863 p2 = p + struct_len; 2864 if (uLevel != 20) { 2865 srvstr_push(NULL, p,global_myname(),16, 2866 STR_ASCII|STR_UPPER|STR_TERMINATE); 2867 } 2868 p += 16; 2869 if (uLevel > 0) { 2870 struct srv_info_struct *servers=NULL; 2871 int i,count; 2872 pstring comment; 2873 uint32 servertype= lp_default_server_announce(); 2874 2875 push_ascii(comment,lp_serverstring(), MAX_SERVER_STRING_LENGTH,STR_TERMINATE); 2876 2877 if ((count=get_server_info(SV_TYPE_ALL,&servers,lp_workgroup()))>0) { 2878 for (i=0;i<count;i++) { 2879 if (strequal(servers[i].name,global_myname())) { 2880 servertype = servers[i].type; 2881 push_ascii(comment,servers[i].comment,sizeof(pstring),STR_TERMINATE); 2882 } 2883 } 2884 } 2885 2886 SAFE_FREE(servers); 2887 2888 SCVAL(p,0,lp_major_announce_version()); 2889 SCVAL(p,1,lp_minor_announce_version()); 2890 SIVAL(p,2,servertype); 2891 2892 if (mdrcnt == struct_len) { 2893 SIVAL(p,6,0); 2894 } else { 2895 SIVAL(p,6,PTR_DIFF(p2,*rdata)); 2896 standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user, 2897 conn->connectpath, conn->gid, 2898 get_current_username(), 2899 current_user_info.domain, 2900 comment, sizeof(comment)); 2901 StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0)); 2902 p2 = skip_string(*rdata,*rdata_len,p2); 2903 if (!p2) { 2904 return False; 2905 } 2906 } 2907 } 2908 2909 if (uLevel > 1) { 2910 return False; /* not yet implemented */ 2911 } 2912 2913 *rdata_len = PTR_DIFF(p2,*rdata); 2914 2915 *rparam_len = 6; 2916 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); 2917 if (!*rparam) { 2918 return False; 2919 } 2920 SSVAL(*rparam,0,NERR_Success); 2921 SSVAL(*rparam,2,0); /* converter word */ 2922 SSVAL(*rparam,4,*rdata_len); 2923 2924 return True; 2925} 2926 2927/**************************************************************************** 2928 Get info about the server. 2929****************************************************************************/ 2930 2931static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, 2932 char *param, int tpscnt, 2933 char *data, int tdscnt, 2934 int mdrcnt,int mprcnt, 2935 char **rdata,char **rparam, 2936 int *rdata_len,int *rparam_len) 2937{ 2938 char *str1 = get_safe_str_ptr(param,tpscnt,param,2); 2939 char *str2 = skip_string(param,tpscnt,str1); 2940 char *p = skip_string(param,tpscnt,str2); 2941 char *p2; 2942 int level = get_safe_SVAL(param,tpscnt,p,0,-1); 2943 2944 if (!str1 || !str2 || !p) { 2945 return False; 2946 } 2947 2948 DEBUG(4,("NetWkstaGetInfo level %d\n",level)); 2949 2950 *rparam_len = 6; 2951 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); 2952 if (!*rparam) { 2953 return False; 2954 } 2955 2956 /* check it's a supported varient */ 2957 if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz"))) { 2958 return False; 2959 } 2960 2961 *rdata_len = mdrcnt + 1024; 2962 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len); 2963 if (!*rdata) { 2964 return False; 2965 } 2966 2967 SSVAL(*rparam,0,NERR_Success); 2968 SSVAL(*rparam,2,0); /* converter word */ 2969 2970 p = *rdata; 2971 p2 = get_safe_ptr(*rdata,*rdata_len,p,22); 2972 if (!p2) { 2973 return False; 2974 } 2975 2976 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */ 2977 pstrcpy(p2,get_local_machine_name()); 2978 strupper_m(p2); 2979 p2 = skip_string(*rdata,*rdata_len,p2); 2980 if (!p2) { 2981 return False; 2982 } 2983 p += 4; 2984 2985 SIVAL(p,0,PTR_DIFF(p2,*rdata)); 2986 pstrcpy(p2,current_user_info.smb_name); 2987 p2 = skip_string(*rdata,*rdata_len,p2); 2988 if (!p2) { 2989 return False; 2990 } 2991 p += 4; 2992 2993 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */ 2994 pstrcpy(p2,lp_workgroup()); 2995 strupper_m(p2); 2996 p2 = skip_string(*rdata,*rdata_len,p2); 2997 if (!p2) { 2998 return False; 2999 } 3000 p += 4; 3001 3002 SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */ 3003 SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */ 3004 p += 2; 3005 3006 SIVAL(p,0,PTR_DIFF(p2,*rdata)); 3007 pstrcpy(p2,lp_workgroup()); /* don't know. login domain?? */ 3008 p2 = skip_string(*rdata,*rdata_len,p2); 3009 if (!p2) { 3010 return False; 3011 } 3012 p += 4; 3013 3014 SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */ 3015 pstrcpy(p2,""); 3016 p2 = skip_string(*rdata,*rdata_len,p2); 3017 if (!p2) { 3018 return False; 3019 } 3020 p += 4; 3021 3022 *rdata_len = PTR_DIFF(p2,*rdata); 3023 3024 SSVAL(*rparam,4,*rdata_len); 3025 3026 return True; 3027} 3028 3029/**************************************************************************** 3030 get info about a user 3031 3032 struct user_info_11 { 3033 char usri11_name[21]; 0-20 3034 char usri11_pad; 21 3035 char *usri11_comment; 22-25 3036 char *usri11_usr_comment; 26-29 3037 unsigned short usri11_priv; 30-31 3038 unsigned long usri11_auth_flags; 32-35 3039 long usri11_password_age; 36-39 3040 char *usri11_homedir; 40-43 3041 char *usri11_parms; 44-47 3042 long usri11_last_logon; 48-51 3043 long usri11_last_logoff; 52-55 3044 unsigned short usri11_bad_pw_count; 56-57 3045 unsigned short usri11_num_logons; 58-59 3046 char *usri11_logon_server; 60-63 3047 unsigned short usri11_country_code; 64-65 3048 char *usri11_workstations; 66-69 3049 unsigned long usri11_max_storage; 70-73 3050 unsigned short usri11_units_per_week; 74-75 3051 unsigned char *usri11_logon_hours; 76-79 3052 unsigned short usri11_code_page; 80-81 3053 }; 3054 3055where: 3056 3057 usri11_name specifies the user name for which information is retireved 3058 3059 usri11_pad aligns the next data structure element to a word boundary 3060 3061 usri11_comment is a null terminated ASCII comment 3062 3063 usri11_user_comment is a null terminated ASCII comment about the user 3064 3065 usri11_priv specifies the level of the privilege assigned to the user. 3066 The possible values are: 3067 3068Name Value Description 3069USER_PRIV_GUEST 0 Guest privilege 3070USER_PRIV_USER 1 User privilege 3071USER_PRV_ADMIN 2 Administrator privilege 3072 3073 usri11_auth_flags specifies the account operator privileges. The 3074 possible values are: 3075 3076Name Value Description 3077AF_OP_PRINT 0 Print operator 3078 3079 3080Leach, Naik [Page 28] 3081 3082 3083 3084INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997 3085 3086 3087AF_OP_COMM 1 Communications operator 3088AF_OP_SERVER 2 Server operator 3089AF_OP_ACCOUNTS 3 Accounts operator 3090 3091 3092 usri11_password_age specifies how many seconds have elapsed since the 3093 password was last changed. 3094 3095 usri11_home_dir points to a null terminated ASCII string that contains 3096 the path name of the user's home directory. 3097 3098 usri11_parms points to a null terminated ASCII string that is set 3099 aside for use by applications. 3100 3101 usri11_last_logon specifies the time when the user last logged on. 3102 This value is stored as the number of seconds elapsed since 3103 00:00:00, January 1, 1970. 3104 3105 usri11_last_logoff specifies the time when the user last logged off. 3106 This value is stored as the number of seconds elapsed since 3107 00:00:00, January 1, 1970. A value of 0 means the last logoff 3108 time is unknown. 3109 3110 usri11_bad_pw_count specifies the number of incorrect passwords 3111 entered since the last successful logon. 3112 3113 usri11_log1_num_logons specifies the number of times this user has 3114 logged on. A value of -1 means the number of logons is unknown. 3115 3116 usri11_logon_server points to a null terminated ASCII string that 3117 contains the name of the server to which logon requests are sent. 3118 A null string indicates logon requests should be sent to the 3119 domain controller. 3120 3121 usri11_country_code specifies the country code for the user's language 3122 of choice. 3123 3124 usri11_workstations points to a null terminated ASCII string that 3125 contains the names of workstations the user may log on from. 3126 There may be up to 8 workstations, with the names separated by 3127 commas. A null strings indicates there are no restrictions. 3128 3129 usri11_max_storage specifies the maximum amount of disk space the user 3130 can occupy. A value of 0xffffffff indicates there are no 3131 restrictions. 3132 3133 usri11_units_per_week specifies the equal number of time units into 3134 which a week is divided. This value must be equal to 168. 3135 3136 usri11_logon_hours points to a 21 byte (168 bits) string that 3137 specifies the time during which the user can log on. Each bit 3138 represents one unique hour in a week. The first bit (bit 0, word 3139 0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is 3140 3141 3142 3143Leach, Naik [Page 29] 3144 3145 3146 3147INTERNET-DRAFT CIFS Remote Admin Protocol January 10, 1997 3148 3149 3150 Sunday, 1:00 to 1:59 and so on. A null pointer indicates there 3151 are no restrictions. 3152 3153 usri11_code_page specifies the code page for the user's language of 3154 choice 3155 3156All of the pointers in this data structure need to be treated 3157specially. The pointer is a 32 bit pointer. The higher 16 bits need 3158to be ignored. The converter word returned in the parameters section 3159needs to be subtracted from the lower 16 bits to calculate an offset 3160into the return buffer where this ASCII string resides. 3161 3162There is no auxiliary data in the response. 3163 3164 ****************************************************************************/ 3165 3166#define usri11_name 0 3167#define usri11_pad 21 3168#define usri11_comment 22 3169#define usri11_usr_comment 26 3170#define usri11_full_name 30 3171#define usri11_priv 34 3172#define usri11_auth_flags 36 3173#define usri11_password_age 40 3174#define usri11_homedir 44 3175#define usri11_parms 48 3176#define usri11_last_logon 52 3177#define usri11_last_logoff 56 3178#define usri11_bad_pw_count 60 3179#define usri11_num_logons 62 3180#define usri11_logon_server 64 3181#define usri11_country_code 68 3182#define usri11_workstations 70 3183#define usri11_max_storage 74 3184#define usri11_units_per_week 78 3185#define usri11_logon_hours 80 3186#define usri11_code_page 84 3187#define usri11_end 86 3188 3189#define USER_PRIV_GUEST 0 3190#define USER_PRIV_USER 1 3191#define USER_PRIV_ADMIN 2 3192 3193#define AF_OP_PRINT 0 3194#define AF_OP_COMM 1 3195#define AF_OP_SERVER 2 3196#define AF_OP_ACCOUNTS 3 3197 3198 3199static BOOL api_RNetUserGetInfo(connection_struct *conn, uint16 vuid, 3200 char *param, int tpscnt, 3201 char *data, int tdscnt, 3202 int mdrcnt,int mprcnt, 3203 char **rdata,char **rparam, 3204 int *rdata_len,int *rparam_len) 3205{ 3206 char *str1 = get_safe_str_ptr(param,tpscnt,param,2); 3207 char *str2 = skip_string(param,tpscnt,str1); 3208 char *UserName = skip_string(param,tpscnt,str2); 3209 char *p = skip_string(param,tpscnt,UserName); 3210 int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1); 3211 char *p2; 3212 const char *level_string; 3213 3214 /* get NIS home of a previously validated user - simeon */ 3215 /* With share level security vuid will always be zero. 3216 Don't depend on vuser being non-null !!. JRA */ 3217 user_struct *vuser = get_valid_user_struct(vuid); 3218 if(vuser != NULL) { 3219 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid, 3220 vuser->user.unix_name)); 3221 } 3222 3223 if (!str1 || !str2 || !UserName || !p) { 3224 return False; 3225 } 3226 3227 *rparam_len = 6; 3228 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); 3229 if (!*rparam) { 3230 return False; 3231 } 3232 3233 DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel)); 3234 3235 /* check it's a supported variant */ 3236 if (strcmp(str1,"zWrLh") != 0) { 3237 return False; 3238 } 3239 switch( uLevel ) { 3240 case 0: level_string = "B21"; break; 3241 case 1: level_string = "B21BB16DWzzWz"; break; 3242 case 2: level_string = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break; 3243 case 10: level_string = "B21Bzzz"; break; 3244 case 11: level_string = "B21BzzzWDDzzDDWWzWzDWb21W"; break; 3245 default: return False; 3246 } 3247 3248 if (strcmp(level_string,str2) != 0) { 3249 return False; 3250 } 3251 3252 *rdata_len = mdrcnt + 1024; 3253 *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len); 3254 if (!*rdata) { 3255 return False; 3256 } 3257 3258 SSVAL(*rparam,0,NERR_Success); 3259 SSVAL(*rparam,2,0); /* converter word */ 3260 3261 p = *rdata; 3262 p2 = get_safe_ptr(*rdata,*rdata_len,p,usri11_end); 3263 if (!p2) { 3264 return False; 3265 } 3266 3267 memset(p,0,21); 3268 fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */ 3269 3270 if (uLevel > 0) { 3271 SCVAL(p,usri11_pad,0); /* padding - 1 byte */ 3272 *p2 = 0; 3273 } 3274 3275 if (uLevel >= 10) { 3276 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */ 3277 pstrcpy(p2,"Comment"); 3278 p2 = skip_string(*rdata,*rdata_len,p2); 3279 if (!p2) { 3280 return False; 3281 } 3282 3283 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */ 3284 pstrcpy(p2,"UserComment"); 3285 p2 = skip_string(*rdata,*rdata_len,p2); 3286 if (!p2) { 3287 return False; 3288 } 3289 3290 /* EEK! the cifsrap.txt doesn't have this in!!!! */ 3291 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */ 3292 pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName)); 3293 p2 = skip_string(*rdata,*rdata_len,p2); 3294 if (!p2) { 3295 return False; 3296 } 3297 } 3298 3299 if (uLevel == 11) { 3300 /* modelled after NTAS 3.51 reply */ 3301 SSVAL(p,usri11_priv,conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER); 3302 SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */ 3303 SIVALS(p,usri11_password_age,-1); /* password age */ 3304 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */ 3305 pstrcpy(p2, vuser && vuser->homedir ? vuser->homedir : ""); 3306 p2 = skip_string(*rdata,*rdata_len,p2); 3307 if (!p2) { 3308 return False; 3309 } 3310 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */ 3311 pstrcpy(p2,""); 3312 p2 = skip_string(*rdata,*rdata_len,p2); 3313 if (!p2) { 3314 return False; 3315 } 3316 SIVAL(p,usri11_last_logon,0); /* last logon */ 3317 SIVAL(p,usri11_last_logoff,0); /* last logoff */ 3318 SSVALS(p,usri11_bad_pw_count,-1); /* bad pw counts */ 3319 SSVALS(p,usri11_num_logons,-1); /* num logons */ 3320 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */ 3321 pstrcpy(p2,"\\\\*"); 3322 p2 = skip_string(*rdata,*rdata_len,p2); 3323 if (!p2) { 3324 return False; 3325 } 3326 SSVAL(p,usri11_country_code,0); /* country code */ 3327 3328 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */ 3329 pstrcpy(p2,""); 3330 p2 = skip_string(*rdata,*rdata_len,p2); 3331 if (!p2) { 3332 return False; 3333 } 3334 3335 SIVALS(p,usri11_max_storage,-1); /* max storage */ 3336 SSVAL(p,usri11_units_per_week,168); /* units per week */ 3337 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */ 3338 3339 /* a simple way to get logon hours at all times. */ 3340 memset(p2,0xff,21); 3341 SCVAL(p2,21,0); /* fix zero termination */ 3342 p2 = skip_string(*rdata,*rdata_len,p2); 3343 if (!p2) { 3344 return False; 3345 } 3346 3347 SSVAL(p,usri11_code_page,0); /* code page */ 3348 } 3349 3350 if (uLevel == 1 || uLevel == 2) { 3351 memset(p+22,' ',16); /* password */ 3352 SIVALS(p,38,-1); /* password age */ 3353 SSVAL(p,42, 3354 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER); 3355 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */ 3356 pstrcpy(p2, vuser && vuser->homedir ? vuser->homedir : ""); 3357 p2 = skip_string(*rdata,*rdata_len,p2); 3358 if (!p2) { 3359 return False; 3360 } 3361 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */ 3362 *p2++ = 0; 3363 SSVAL(p,52,0); /* flags */ 3364 SIVAL(p,54,PTR_DIFF(p2,*rdata)); /* script_path */ 3365 pstrcpy(p2,vuser && vuser->logon_script ? vuser->logon_script : ""); 3366 p2 = skip_string(*rdata,*rdata_len,p2); 3367 if (!p2) { 3368 return False; 3369 } 3370 if (uLevel == 2) { 3371 SIVAL(p,60,0); /* auth_flags */ 3372 SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */ 3373 pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName)); 3374 p2 = skip_string(*rdata,*rdata_len,p2); 3375 if (!p2) { 3376 return False; 3377 } 3378 SIVAL(p,68,0); /* urs_comment */ 3379 SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */ 3380 pstrcpy(p2,""); 3381 p2 = skip_string(*rdata,*rdata_len,p2); 3382 if (!p2) { 3383 return False; 3384 } 3385 SIVAL(p,76,0); /* workstations */ 3386 SIVAL(p,80,0); /* last_logon */ 3387 SIVAL(p,84,0); /* last_logoff */ 3388 SIVALS(p,88,-1); /* acct_expires */ 3389 SIVALS(p,92,-1); /* max_storage */ 3390 SSVAL(p,96,168); /* units_per_week */ 3391 SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */ 3392 memset(p2,-1,21); 3393 p2 += 21; 3394 SSVALS(p,102,-1); /* bad_pw_count */ 3395 SSVALS(p,104,-1); /* num_logons */ 3396 SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */ 3397 { 3398 pstring tmp; 3399 pstrcpy(tmp, "\\\\%L"); 3400 standard_sub_basic("", "", tmp, sizeof(tmp)); 3401 pstrcpy(p2, tmp); 3402 } 3403 p2 = skip_string(*rdata,*rdata_len,p2); 3404 if (!p2) { 3405 return False; 3406 } 3407 SSVAL(p,110,49); /* country_code */ 3408 SSVAL(p,112,860); /* code page */ 3409 } 3410 } 3411 3412 *rdata_len = PTR_DIFF(p2,*rdata); 3413 3414 SSVAL(*rparam,4,*rdata_len); /* is this right?? */ 3415 3416 return(True); 3417} 3418 3419static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, 3420 char *param, int tpscnt, 3421 char *data, int tdscnt, 3422 int mdrcnt,int mprcnt, 3423 char **rdata,char **rparam, 3424 int *rdata_len,int *rparam_len) 3425{ 3426 char *str1 = get_safe_str_ptr(param,tpscnt,param,2); 3427 char *str2 = skip_string(param,tpscnt,str1); 3428 char *p = skip_string(param,tpscnt,str2); 3429 int uLevel; 3430 struct pack_desc desc; 3431 char* name; 3432 /* With share level security vuid will always be zero. 3433 Don't depend on vuser being non-null !!. JRA */ 3434 user_struct *vuser = get_valid_user_struct(vuid); 3435 3436 if (!str1 || !str2 || !p) { 3437 return False; 3438 } 3439 3440 if(vuser != NULL) { 3441 DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid, 3442 vuser->user.unix_name)); 3443 } 3444 3445 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1); 3446 name = get_safe_str_ptr(param,tpscnt,p,2); 3447 if (!name) { 3448 return False; 3449 } 3450 3451 memset((char *)&desc,'\0',sizeof(desc)); 3452 3453 DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name)); 3454 3455 /* check it's a supported varient */ 3456 if (strcmp(str1,"OOWb54WrLh") != 0) { 3457 return False; 3458 } 3459 if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) { 3460 return False; 3461 } 3462 if (mdrcnt > 0) { 3463 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt); 3464 if (!*rdata) { 3465 return False; 3466 } 3467 } 3468 3469 desc.base = *rdata; 3470 desc.buflen = mdrcnt; 3471 desc.subformat = NULL; 3472 desc.format = str2; 3473 3474 if (init_package(&desc,1,0)) { 3475 PACKI(&desc,"W",0); /* code */ 3476 PACKS(&desc,"B21",name); /* eff. name */ 3477 PACKS(&desc,"B",""); /* pad */ 3478 PACKI(&desc,"W", conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER); 3479 PACKI(&desc,"D",0); /* auth flags XXX */ 3480 PACKI(&desc,"W",0); /* num logons */ 3481 PACKI(&desc,"W",0); /* bad pw count */ 3482 PACKI(&desc,"D",0); /* last logon */ 3483 PACKI(&desc,"D",-1); /* last logoff */ 3484 PACKI(&desc,"D",-1); /* logoff time */ 3485 PACKI(&desc,"D",-1); /* kickoff time */ 3486 PACKI(&desc,"D",0); /* password age */ 3487 PACKI(&desc,"D",0); /* password can change */ 3488 PACKI(&desc,"D",-1); /* password must change */ 3489 3490 { 3491 fstring mypath; 3492 fstrcpy(mypath,"\\\\"); 3493 fstrcat(mypath,get_local_machine_name()); 3494 strupper_m(mypath); 3495 PACKS(&desc,"z",mypath); /* computer */ 3496 } 3497 3498 PACKS(&desc,"z",lp_workgroup());/* domain */ 3499 PACKS(&desc,"z", vuser && vuser->logon_script ? vuser->logon_script :""); /* script path */ 3500 PACKI(&desc,"D",0x00000000); /* reserved */ 3501 } 3502 3503 *rdata_len = desc.usedlen; 3504 *rparam_len = 6; 3505 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); 3506 if (!*rparam) { 3507 return False; 3508 } 3509 SSVALS(*rparam,0,desc.errcode); 3510 SSVAL(*rparam,2,0); 3511 SSVAL(*rparam,4,desc.neededlen); 3512 3513 DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode)); 3514 3515 return True; 3516} 3517 3518/**************************************************************************** 3519 api_WAccessGetUserPerms 3520****************************************************************************/ 3521 3522static BOOL api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid, 3523 char *param, int tpscnt, 3524 char *data, int tdscnt, 3525 int mdrcnt,int mprcnt, 3526 char **rdata,char **rparam, 3527 int *rdata_len,int *rparam_len) 3528{ 3529 char *str1 = get_safe_str_ptr(param,tpscnt,param,2); 3530 char *str2 = skip_string(param,tpscnt,str1); 3531 char *user = skip_string(param,tpscnt,str2); 3532 char *resource = skip_string(param,tpscnt,user); 3533 3534 if (!str1 || !str2 || !user || !resource) { 3535 return False; 3536 } 3537 3538 if (skip_string(param,tpscnt,resource) == NULL) { 3539 return False; 3540 } 3541 DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource)); 3542 3543 /* check it's a supported varient */ 3544 if (strcmp(str1,"zzh") != 0) { 3545 return False; 3546 } 3547 if (strcmp(str2,"") != 0) { 3548 return False; 3549 } 3550 3551 *rparam_len = 6; 3552 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); 3553 if (!*rparam) { 3554 return False; 3555 } 3556 SSVALS(*rparam,0,0); /* errorcode */ 3557 SSVAL(*rparam,2,0); /* converter word */ 3558 SSVAL(*rparam,4,0x7f); /* permission flags */ 3559 3560 return True; 3561} 3562 3563/**************************************************************************** 3564 api_WPrintJobEnumerate 3565 ****************************************************************************/ 3566 3567static BOOL api_WPrintJobGetInfo(connection_struct *conn, uint16 vuid, 3568 char *param, int tpscnt, 3569 char *data, int tdscnt, 3570 int mdrcnt,int mprcnt, 3571 char **rdata,char **rparam, 3572 int *rdata_len,int *rparam_len) 3573{ 3574 char *str1 = get_safe_str_ptr(param,tpscnt,param,2); 3575 char *str2 = skip_string(param,tpscnt,str1); 3576 char *p = skip_string(param,tpscnt,str2); 3577 int uLevel; 3578 int count; 3579 int i; 3580 int snum; 3581 fstring sharename; 3582 uint32 jobid; 3583 struct pack_desc desc; 3584 print_queue_struct *queue=NULL; 3585 print_status_struct status; 3586 char *tmpdata=NULL; 3587 3588 if (!str1 || !str2 || !p) { 3589 return False; 3590 } 3591 3592 uLevel = get_safe_SVAL(param,tpscnt,p,2,-1); 3593 3594 memset((char *)&desc,'\0',sizeof(desc)); 3595 memset((char *)&status,'\0',sizeof(status)); 3596 3597 DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0))); 3598 3599 /* check it's a supported varient */ 3600 if (strcmp(str1,"WWrLh") != 0) { 3601 return False; 3602 } 3603 if (!check_printjob_info(&desc,uLevel,str2)) { 3604 return False; 3605 } 3606 3607 if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid)) { 3608 return False; 3609 } 3610 3611 snum = lp_servicenumber( sharename); 3612 if (snum < 0 || !VALID_SNUM(snum)) { 3613 return(False); 3614 } 3615 3616 count = print_queue_status(snum,&queue,&status); 3617 for (i = 0; i < count; i++) { 3618 if (queue[i].job == jobid) { 3619 break; 3620 } 3621 } 3622 3623 if (mdrcnt > 0) { 3624 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt); 3625 if (!*rdata) { 3626 return False; 3627 } 3628 desc.base = *rdata; 3629 desc.buflen = mdrcnt; 3630 } else { 3631 /* 3632 * Don't return data but need to get correct length 3633 * init_package will return wrong size if buflen=0 3634 */ 3635 desc.buflen = getlen(desc.format); 3636 desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen ); 3637 } 3638 3639 if (init_package(&desc,1,0)) { 3640 if (i < count) { 3641 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i); 3642 *rdata_len = desc.usedlen; 3643 } else { 3644 desc.errcode = NERR_JobNotFound; 3645 *rdata_len = 0; 3646 } 3647 } 3648 3649 *rparam_len = 6; 3650 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); 3651 if (!*rparam) { 3652 return False; 3653 } 3654 SSVALS(*rparam,0,desc.errcode); 3655 SSVAL(*rparam,2,0); 3656 SSVAL(*rparam,4,desc.neededlen); 3657 3658 SAFE_FREE(queue); 3659 SAFE_FREE(tmpdata); 3660 3661 DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode)); 3662 3663 return True; 3664} 3665 3666static BOOL api_WPrintJobEnumerate(connection_struct *conn, uint16 vuid, 3667 char *param, int tpscnt, 3668 char *data, int tdscnt, 3669 int mdrcnt,int mprcnt, 3670 char **rdata,char **rparam, 3671 int *rdata_len,int *rparam_len) 3672{ 3673 char *str1 = get_safe_str_ptr(param,tpscnt,param,2); 3674 char *str2 = skip_string(param,tpscnt,str1); 3675 char *p = skip_string(param,tpscnt,str2); 3676 char *name = p; 3677 int uLevel; 3678 int count; 3679 int i, succnt=0; 3680 int snum; 3681 struct pack_desc desc; 3682 print_queue_struct *queue=NULL; 3683 print_status_struct status; 3684 3685 if (!str1 || !str2 || !p) { 3686 return False; 3687 } 3688 3689 memset((char *)&desc,'\0',sizeof(desc)); 3690 memset((char *)&status,'\0',sizeof(status)); 3691 3692 p = skip_string(param,tpscnt,p); 3693 if (!p) { 3694 return False; 3695 } 3696 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1); 3697 3698 DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name)); 3699 3700 /* check it's a supported variant */ 3701 if (strcmp(str1,"zWrLeh") != 0) { 3702 return False; 3703 } 3704 3705 if (uLevel > 2) { 3706 return False; /* defined only for uLevel 0,1,2 */ 3707 } 3708 3709 if (!check_printjob_info(&desc,uLevel,str2)) { 3710 return False; 3711 } 3712 3713 snum = find_service(name); 3714 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) ) { 3715 return False; 3716 } 3717 3718 count = print_queue_status(snum,&queue,&status); 3719 if (mdrcnt > 0) { 3720 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt); 3721 if (!*rdata) { 3722 return False; 3723 } 3724 } 3725 desc.base = *rdata; 3726 desc.buflen = mdrcnt; 3727 3728 if (init_package(&desc,count,0)) { 3729 succnt = 0; 3730 for (i = 0; i < count; i++) { 3731 fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i); 3732 if (desc.errcode == NERR_Success) { 3733 succnt = i+1; 3734 } 3735 } 3736 } 3737 3738 *rdata_len = desc.usedlen; 3739 3740 *rparam_len = 8; 3741 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); 3742 if (!*rparam) { 3743 return False; 3744 } 3745 SSVALS(*rparam,0,desc.errcode); 3746 SSVAL(*rparam,2,0); 3747 SSVAL(*rparam,4,succnt); 3748 SSVAL(*rparam,6,count); 3749 3750 SAFE_FREE(queue); 3751 3752 DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode)); 3753 3754 return True; 3755} 3756 3757static int check_printdest_info(struct pack_desc* desc, 3758 int uLevel, char* id) 3759{ 3760 desc->subformat = NULL; 3761 switch( uLevel ) { 3762 case 0: 3763 desc->format = "B9"; 3764 break; 3765 case 1: 3766 desc->format = "B9B21WWzW"; 3767 break; 3768 case 2: 3769 desc->format = "z"; 3770 break; 3771 case 3: 3772 desc->format = "zzzWWzzzWW"; 3773 break; 3774 default: 3775 DEBUG(0,("check_printdest_info: invalid level %d\n", 3776 uLevel)); 3777 return False; 3778 } 3779 if (id == NULL || strcmp(desc->format,id) != 0) { 3780 DEBUG(0,("check_printdest_info: invalid string %s\n", 3781 id ? id : "<NULL>" )); 3782 return False; 3783 } 3784 return True; 3785} 3786 3787static void fill_printdest_info(connection_struct *conn, int snum, int uLevel, 3788 struct pack_desc* desc) 3789{ 3790 char buf[100]; 3791 3792 strncpy(buf,SERVICE(snum),sizeof(buf)-1); 3793 buf[sizeof(buf)-1] = 0; 3794 strupper_m(buf); 3795 3796 if (uLevel <= 1) { 3797 PACKS(desc,"B9",buf); /* szName */ 3798 if (uLevel == 1) { 3799 PACKS(desc,"B21",""); /* szUserName */ 3800 PACKI(desc,"W",0); /* uJobId */ 3801 PACKI(desc,"W",0); /* fsStatus */ 3802 PACKS(desc,"z",""); /* pszStatus */ 3803 PACKI(desc,"W",0); /* time */ 3804 } 3805 } 3806 3807 if (uLevel == 2 || uLevel == 3) { 3808 PACKS(desc,"z",buf); /* pszPrinterName */ 3809 if (uLevel == 3) { 3810 PACKS(desc,"z",""); /* pszUserName */ 3811 PACKS(desc,"z",""); /* pszLogAddr */ 3812 PACKI(desc,"W",0); /* uJobId */ 3813 PACKI(desc,"W",0); /* fsStatus */ 3814 PACKS(desc,"z",""); /* pszStatus */ 3815 PACKS(desc,"z",""); /* pszComment */ 3816 PACKS(desc,"z","NULL"); /* pszDrivers */ 3817 PACKI(desc,"W",0); /* time */ 3818 PACKI(desc,"W",0); /* pad1 */ 3819 } 3820 } 3821} 3822 3823static BOOL api_WPrintDestGetInfo(connection_struct *conn, uint16 vuid, 3824 char *param, int tpscnt, 3825 char *data, int tdscnt, 3826 int mdrcnt,int mprcnt, 3827 char **rdata,char **rparam, 3828 int *rdata_len,int *rparam_len) 3829{ 3830 char *str1 = get_safe_str_ptr(param,tpscnt,param,2); 3831 char *str2 = skip_string(param,tpscnt,str1); 3832 char *p = skip_string(param,tpscnt,str2); 3833 char* PrinterName = p; 3834 int uLevel; 3835 struct pack_desc desc; 3836 int snum; 3837 char *tmpdata=NULL; 3838 3839 if (!str1 || !str2 || !p) { 3840 return False; 3841 } 3842 3843 memset((char *)&desc,'\0',sizeof(desc)); 3844 3845 p = skip_string(param,tpscnt,p); 3846 if (!p) { 3847 return False; 3848 } 3849 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1); 3850 3851 DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName)); 3852 3853 /* check it's a supported varient */ 3854 if (strcmp(str1,"zWrLh") != 0) { 3855 return False; 3856 } 3857 if (!check_printdest_info(&desc,uLevel,str2)) { 3858 return False; 3859 } 3860 3861 snum = find_service(PrinterName); 3862 if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) ) { 3863 *rdata_len = 0; 3864 desc.errcode = NERR_DestNotFound; 3865 desc.neededlen = 0; 3866 } else { 3867 if (mdrcnt > 0) { 3868 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt); 3869 if (!*rdata) { 3870 return False; 3871 } 3872 desc.base = *rdata; 3873 desc.buflen = mdrcnt; 3874 } else { 3875 /* 3876 * Don't return data but need to get correct length 3877 * init_package will return wrong size if buflen=0 3878 */ 3879 desc.buflen = getlen(desc.format); 3880 desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen ); 3881 } 3882 if (init_package(&desc,1,0)) { 3883 fill_printdest_info(conn,snum,uLevel,&desc); 3884 } 3885 *rdata_len = desc.usedlen; 3886 } 3887 3888 *rparam_len = 6; 3889 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); 3890 if (!*rparam) { 3891 return False; 3892 } 3893 SSVALS(*rparam,0,desc.errcode); 3894 SSVAL(*rparam,2,0); 3895 SSVAL(*rparam,4,desc.neededlen); 3896 3897 DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode)); 3898 SAFE_FREE(tmpdata); 3899 3900 return True; 3901} 3902 3903static BOOL api_WPrintDestEnum(connection_struct *conn, uint16 vuid, 3904 char *param, int tpscnt, 3905 char *data, int tdscnt, 3906 int mdrcnt,int mprcnt, 3907 char **rdata,char **rparam, 3908 int *rdata_len,int *rparam_len) 3909{ 3910 char *str1 = get_safe_str_ptr(param,tpscnt,param,2); 3911 char *str2 = skip_string(param,tpscnt,str1); 3912 char *p = skip_string(param,tpscnt,str2); 3913 int uLevel; 3914 int queuecnt; 3915 int i, n, succnt=0; 3916 struct pack_desc desc; 3917 int services = lp_numservices(); 3918 3919 if (!str1 || !str2 || !p) { 3920 return False; 3921 } 3922 3923 memset((char *)&desc,'\0',sizeof(desc)); 3924 3925 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1); 3926 3927 DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel)); 3928 3929 /* check it's a supported varient */ 3930 if (strcmp(str1,"WrLeh") != 0) { 3931 return False; 3932 } 3933 if (!check_printdest_info(&desc,uLevel,str2)) { 3934 return False; 3935 } 3936 3937 queuecnt = 0; 3938 for (i = 0; i < services; i++) { 3939 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) { 3940 queuecnt++; 3941 } 3942 } 3943 3944 if (mdrcnt > 0) { 3945 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt); 3946 if (!*rdata) { 3947 return False; 3948 } 3949 } 3950 3951 desc.base = *rdata; 3952 desc.buflen = mdrcnt; 3953 if (init_package(&desc,queuecnt,0)) { 3954 succnt = 0; 3955 n = 0; 3956 for (i = 0; i < services; i++) { 3957 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) { 3958 fill_printdest_info(conn,i,uLevel,&desc); 3959 n++; 3960 if (desc.errcode == NERR_Success) { 3961 succnt = n; 3962 } 3963 } 3964 } 3965 } 3966 3967 *rdata_len = desc.usedlen; 3968 3969 *rparam_len = 8; 3970 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); 3971 if (!*rparam) { 3972 return False; 3973 } 3974 SSVALS(*rparam,0,desc.errcode); 3975 SSVAL(*rparam,2,0); 3976 SSVAL(*rparam,4,succnt); 3977 SSVAL(*rparam,6,queuecnt); 3978 3979 DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode)); 3980 3981 return True; 3982} 3983 3984static BOOL api_WPrintDriverEnum(connection_struct *conn, uint16 vuid, 3985 char *param, int tpscnt, 3986 char *data, int tdscnt, 3987 int mdrcnt,int mprcnt, 3988 char **rdata,char **rparam, 3989 int *rdata_len,int *rparam_len) 3990{ 3991 char *str1 = get_safe_str_ptr(param,tpscnt,param,2); 3992 char *str2 = skip_string(param,tpscnt,str1); 3993 char *p = skip_string(param,tpscnt,str2); 3994 int uLevel; 3995 int succnt; 3996 struct pack_desc desc; 3997 3998 if (!str1 || !str2 || !p) { 3999 return False; 4000 } 4001 4002 memset((char *)&desc,'\0',sizeof(desc)); 4003 4004 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1); 4005 4006 DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel)); 4007 4008 /* check it's a supported varient */ 4009 if (strcmp(str1,"WrLeh") != 0) { 4010 return False; 4011 } 4012 if (uLevel != 0 || strcmp(str2,"B41") != 0) { 4013 return False; 4014 } 4015 4016 if (mdrcnt > 0) { 4017 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt); 4018 if (!*rdata) { 4019 return False; 4020 } 4021 } 4022 desc.base = *rdata; 4023 desc.buflen = mdrcnt; 4024 if (init_package(&desc,1,0)) { 4025 PACKS(&desc,"B41","NULL"); 4026 } 4027 4028 succnt = (desc.errcode == NERR_Success ? 1 : 0); 4029 4030 *rdata_len = desc.usedlen; 4031 4032 *rparam_len = 8; 4033 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); 4034 if (!*rparam) { 4035 return False; 4036 } 4037 SSVALS(*rparam,0,desc.errcode); 4038 SSVAL(*rparam,2,0); 4039 SSVAL(*rparam,4,succnt); 4040 SSVAL(*rparam,6,1); 4041 4042 DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode)); 4043 4044 return True; 4045} 4046 4047static BOOL api_WPrintQProcEnum(connection_struct *conn, uint16 vuid, 4048 char *param, int tpscnt, 4049 char *data, int tdscnt, 4050 int mdrcnt,int mprcnt, 4051 char **rdata,char **rparam, 4052 int *rdata_len,int *rparam_len) 4053{ 4054 char *str1 = get_safe_str_ptr(param,tpscnt,param,2); 4055 char *str2 = skip_string(param,tpscnt,str1); 4056 char *p = skip_string(param,tpscnt,str2); 4057 int uLevel; 4058 int succnt; 4059 struct pack_desc desc; 4060 4061 if (!str1 || !str2 || !p) { 4062 return False; 4063 } 4064 memset((char *)&desc,'\0',sizeof(desc)); 4065 4066 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1); 4067 4068 DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel)); 4069 4070 /* check it's a supported varient */ 4071 if (strcmp(str1,"WrLeh") != 0) { 4072 return False; 4073 } 4074 if (uLevel != 0 || strcmp(str2,"B13") != 0) { 4075 return False; 4076 } 4077 4078 if (mdrcnt > 0) { 4079 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt); 4080 if (!*rdata) { 4081 return False; 4082 } 4083 } 4084 desc.base = *rdata; 4085 desc.buflen = mdrcnt; 4086 desc.format = str2; 4087 if (init_package(&desc,1,0)) { 4088 PACKS(&desc,"B13","lpd"); 4089 } 4090 4091 succnt = (desc.errcode == NERR_Success ? 1 : 0); 4092 4093 *rdata_len = desc.usedlen; 4094 4095 *rparam_len = 8; 4096 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); 4097 if (!*rparam) { 4098 return False; 4099 } 4100 SSVALS(*rparam,0,desc.errcode); 4101 SSVAL(*rparam,2,0); 4102 SSVAL(*rparam,4,succnt); 4103 SSVAL(*rparam,6,1); 4104 4105 DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode)); 4106 4107 return True; 4108} 4109 4110static BOOL api_WPrintPortEnum(connection_struct *conn, uint16 vuid, 4111 char *param, int tpscnt, 4112 char *data, int tdscnt, 4113 int mdrcnt,int mprcnt, 4114 char **rdata,char **rparam, 4115 int *rdata_len,int *rparam_len) 4116{ 4117 char *str1 = get_safe_str_ptr(param,tpscnt,param,2); 4118 char *str2 = skip_string(param,tpscnt,str1); 4119 char *p = skip_string(param,tpscnt,str2); 4120 int uLevel; 4121 int succnt; 4122 struct pack_desc desc; 4123 4124 if (!str1 || !str2 || !p) { 4125 return False; 4126 } 4127 4128 memset((char *)&desc,'\0',sizeof(desc)); 4129 4130 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1); 4131 4132 DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel)); 4133 4134 /* check it's a supported varient */ 4135 if (strcmp(str1,"WrLeh") != 0) { 4136 return False; 4137 } 4138 if (uLevel != 0 || strcmp(str2,"B9") != 0) { 4139 return False; 4140 } 4141 4142 if (mdrcnt > 0) { 4143 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt); 4144 if (!*rdata) { 4145 return False; 4146 } 4147 } 4148 memset((char *)&desc,'\0',sizeof(desc)); 4149 desc.base = *rdata; 4150 desc.buflen = mdrcnt; 4151 desc.format = str2; 4152 if (init_package(&desc,1,0)) { 4153 PACKS(&desc,"B13","lp0"); 4154 } 4155 4156 succnt = (desc.errcode == NERR_Success ? 1 : 0); 4157 4158 *rdata_len = desc.usedlen; 4159 4160 *rparam_len = 8; 4161 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); 4162 if (!*rparam) { 4163 return False; 4164 } 4165 SSVALS(*rparam,0,desc.errcode); 4166 SSVAL(*rparam,2,0); 4167 SSVAL(*rparam,4,succnt); 4168 SSVAL(*rparam,6,1); 4169 4170 DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode)); 4171 4172 return True; 4173} 4174 4175/**************************************************************************** 4176 List open sessions 4177 ****************************************************************************/ 4178 4179static BOOL api_RNetSessionEnum(connection_struct *conn, uint16 vuid, 4180 char *param, int tpscnt, 4181 char *data, int tdscnt, 4182 int mdrcnt,int mprcnt, 4183 char **rdata,char **rparam, 4184 int *rdata_len,int *rparam_len) 4185 4186{ 4187 char *str1 = get_safe_str_ptr(param,tpscnt,param,2); 4188 char *str2 = skip_string(param,tpscnt,str1); 4189 char *p = skip_string(param,tpscnt,str2); 4190 int uLevel; 4191 struct pack_desc desc; 4192 struct sessionid *session_list = NULL; 4193 int i, num_sessions; 4194 4195 if (!str1 || !str2 || !p) { 4196 return False; 4197 } 4198 4199 memset((char *)&desc,'\0',sizeof(desc)); 4200 4201 uLevel = get_safe_SVAL(param,tpscnt,p,0,-1); 4202 4203 DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel)); 4204 DEBUG(7,("RNetSessionEnum req string=%s\n",str1)); 4205 DEBUG(7,("RNetSessionEnum ret string=%s\n",str2)); 4206 4207 /* check it's a supported varient */ 4208 if (strcmp(str1,RAP_NetSessionEnum_REQ) != 0) { 4209 return False; 4210 } 4211 if (uLevel != 2 || strcmp(str2,RAP_SESSION_INFO_L2) != 0) { 4212 return False; 4213 } 4214 4215 num_sessions = list_sessions(&session_list); 4216 4217 if (mdrcnt > 0) { 4218 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt); 4219 if (!*rdata) { 4220 SAFE_FREE(session_list); 4221 return False; 4222 } 4223 } 4224 memset((char *)&desc,'\0',sizeof(desc)); 4225 desc.base = *rdata; 4226 desc.buflen = mdrcnt; 4227 desc.format = str2; 4228 if (!init_package(&desc,num_sessions,0)) { 4229 SAFE_FREE(session_list); 4230 return False; 4231 } 4232 4233 for(i=0; i<num_sessions; i++) { 4234 PACKS(&desc, "z", session_list[i].remote_machine); 4235 PACKS(&desc, "z", session_list[i].username); 4236 PACKI(&desc, "W", 1); /* num conns */ 4237 PACKI(&desc, "W", 0); /* num opens */ 4238 PACKI(&desc, "W", 1); /* num users */ 4239 PACKI(&desc, "D", 0); /* session time */ 4240 PACKI(&desc, "D", 0); /* idle time */ 4241 PACKI(&desc, "D", 0); /* flags */ 4242 PACKS(&desc, "z", "Unknown Client"); /* client type string */ 4243 } 4244 4245 *rdata_len = desc.usedlen; 4246 4247 *rparam_len = 8; 4248 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); 4249 if (!*rparam) { 4250 SAFE_FREE(session_list); 4251 return False; 4252 } 4253 SSVALS(*rparam,0,desc.errcode); 4254 SSVAL(*rparam,2,0); /* converter */ 4255 SSVAL(*rparam,4,num_sessions); /* count */ 4256 4257 DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc.errcode)); 4258 4259 SAFE_FREE(session_list); 4260 return True; 4261} 4262 4263 4264/**************************************************************************** 4265 The buffer was too small. 4266 ****************************************************************************/ 4267 4268static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param, char *data, 4269 int mdrcnt, int mprcnt, 4270 char **rdata, char **rparam, 4271 int *rdata_len, int *rparam_len) 4272{ 4273 *rparam_len = MIN(*rparam_len,mprcnt); 4274 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); 4275 if (!*rparam) { 4276 return False; 4277 } 4278 4279 *rdata_len = 0; 4280 4281 SSVAL(*rparam,0,NERR_BufTooSmall); 4282 4283 DEBUG(3,("Supplied buffer too small in API command\n")); 4284 4285 return True; 4286} 4287 4288/**************************************************************************** 4289 The request is not supported. 4290 ****************************************************************************/ 4291 4292static BOOL api_Unsupported(connection_struct *conn, uint16 vuid, 4293 char *param, int tpscnt, 4294 char *data, int tdscnt, 4295 int mdrcnt, int mprcnt, 4296 char **rdata, char **rparam, 4297 int *rdata_len, int *rparam_len) 4298{ 4299 *rparam_len = 4; 4300 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len); 4301 if (!*rparam) { 4302 return False; 4303 } 4304 4305 *rdata_len = 0; 4306 4307 SSVAL(*rparam,0,NERR_notsupported); 4308 SSVAL(*rparam,2,0); /* converter word */ 4309 4310 DEBUG(3,("Unsupported API command\n")); 4311 4312 return True; 4313} 4314 4315static const struct { 4316 const char *name; 4317 int id; 4318 BOOL (*fn)(connection_struct *, uint16, 4319 char *, int, 4320 char *, int, 4321 int,int,char **,char **,int *,int *); 4322 BOOL auth_user; /* Deny anonymous access? */ 4323} api_commands[] = { 4324 {"RNetShareEnum", RAP_WshareEnum, api_RNetShareEnum, True}, 4325 {"RNetShareGetInfo", RAP_WshareGetInfo, api_RNetShareGetInfo}, 4326 {"RNetShareAdd", RAP_WshareAdd, api_RNetShareAdd}, 4327 {"RNetSessionEnum", RAP_WsessionEnum, api_RNetSessionEnum, True}, 4328 {"RNetServerGetInfo", RAP_WserverGetInfo, api_RNetServerGetInfo}, 4329 {"RNetGroupEnum", RAP_WGroupEnum, api_RNetGroupEnum, True}, 4330 {"RNetGroupGetUsers", RAP_WGroupGetUsers, api_RNetGroupGetUsers, True}, 4331 {"RNetUserEnum", RAP_WUserEnum, api_RNetUserEnum, True}, 4332 {"RNetUserGetInfo", RAP_WUserGetInfo, api_RNetUserGetInfo}, 4333 {"NetUserGetGroups", RAP_WUserGetGroups, api_NetUserGetGroups}, 4334 {"NetWkstaGetInfo", RAP_WWkstaGetInfo, api_NetWkstaGetInfo}, 4335 {"DosPrintQEnum", RAP_WPrintQEnum, api_DosPrintQEnum, True}, 4336 {"DosPrintQGetInfo", RAP_WPrintQGetInfo, api_DosPrintQGetInfo}, 4337 {"WPrintQueuePause", RAP_WPrintQPause, api_WPrintQueueCtrl}, 4338 {"WPrintQueueResume", RAP_WPrintQContinue, api_WPrintQueueCtrl}, 4339 {"WPrintJobEnumerate",RAP_WPrintJobEnum, api_WPrintJobEnumerate}, 4340 {"WPrintJobGetInfo", RAP_WPrintJobGetInfo, api_WPrintJobGetInfo}, 4341 {"RDosPrintJobDel", RAP_WPrintJobDel, api_RDosPrintJobDel}, 4342 {"RDosPrintJobPause", RAP_WPrintJobPause, api_RDosPrintJobDel}, 4343 {"RDosPrintJobResume",RAP_WPrintJobContinue, api_RDosPrintJobDel}, 4344 {"WPrintDestEnum", RAP_WPrintDestEnum, api_WPrintDestEnum}, 4345 {"WPrintDestGetInfo", RAP_WPrintDestGetInfo, api_WPrintDestGetInfo}, 4346 {"NetRemoteTOD", RAP_NetRemoteTOD, api_NetRemoteTOD}, 4347 {"WPrintQueuePurge", RAP_WPrintQPurge, api_WPrintQueueCtrl}, 4348 {"NetServerEnum", RAP_NetServerEnum2, api_RNetServerEnum}, /* anon OK */ 4349 {"WAccessGetUserPerms",RAP_WAccessGetUserPerms,api_WAccessGetUserPerms}, 4350 {"SetUserPassword", RAP_WUserPasswordSet2, api_SetUserPassword}, 4351 {"WWkstaUserLogon", RAP_WWkstaUserLogon, api_WWkstaUserLogon}, 4352 {"PrintJobInfo", RAP_WPrintJobSetInfo, api_PrintJobInfo}, 4353 {"WPrintDriverEnum", RAP_WPrintDriverEnum, api_WPrintDriverEnum}, 4354 {"WPrintQProcEnum", RAP_WPrintQProcessorEnum,api_WPrintQProcEnum}, 4355 {"WPrintPortEnum", RAP_WPrintPortEnum, api_WPrintPortEnum}, 4356 {"SamOEMChangePassword",RAP_SamOEMChgPasswordUser2_P,api_SamOEMChangePassword}, /* anon OK */ 4357 {NULL, -1, api_Unsupported} 4358 /* The following RAP calls are not implemented by Samba: 4359 4360 RAP_WFileEnum2 - anon not OK 4361 */ 4362}; 4363 4364 4365/**************************************************************************** 4366 Handle remote api calls 4367 ****************************************************************************/ 4368 4369int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data,char *params, 4370 int tdscnt,int tpscnt,int mdrcnt,int mprcnt) 4371{ 4372 int api_command; 4373 char *rdata = NULL; 4374 char *rparam = NULL; 4375 const char *name1 = NULL; 4376 const char *name2 = NULL; 4377 int rdata_len = 0; 4378 int rparam_len = 0; 4379 BOOL reply=False; 4380 int i; 4381 4382 if (!params) { 4383 DEBUG(0,("ERROR: NULL params in api_reply()\n")); 4384 return 0; 4385 } 4386 4387 if (tpscnt < 2) { 4388 return 0; 4389 } 4390 api_command = SVAL(params,0); 4391 /* Is there a string at position params+2 ? */ 4392 if (skip_string(params,tpscnt,params+2)) { 4393 name1 = params + 2; 4394 } else { 4395 name1 = ""; 4396 } 4397 name2 = skip_string(params,tpscnt,params+2); 4398 if (!name2) { 4399 name2 = ""; 4400 } 4401 4402 DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n", 4403 api_command, 4404 name1, 4405 name2, 4406 tdscnt,tpscnt,mdrcnt,mprcnt)); 4407 4408 for (i=0;api_commands[i].name;i++) { 4409 if (api_commands[i].id == api_command && api_commands[i].fn) { 4410 DEBUG(3,("Doing %s\n",api_commands[i].name)); 4411 break; 4412 } 4413 } 4414 4415 /* Check whether this api call can be done anonymously */ 4416 4417 if (api_commands[i].auth_user && lp_restrict_anonymous()) { 4418 user_struct *user = get_valid_user_struct(vuid); 4419 4420 if (!user || user->guest) { 4421 return ERROR_NT(NT_STATUS_ACCESS_DENIED); 4422 } 4423 } 4424 4425 rdata = (char *)SMB_MALLOC(1024); 4426 if (rdata) { 4427 memset(rdata,'\0',1024); 4428 } 4429 4430 rparam = (char *)SMB_MALLOC(1024); 4431 if (rparam) { 4432 memset(rparam,'\0',1024); 4433 } 4434 4435 if(!rdata || !rparam) { 4436 DEBUG(0,("api_reply: malloc fail !\n")); 4437 SAFE_FREE(rdata); 4438 SAFE_FREE(rparam); 4439 return -1; 4440 } 4441 4442 reply = api_commands[i].fn(conn, 4443 vuid, 4444 params,tpscnt, /* params + length */ 4445 data,tdscnt, /* data + length */ 4446 mdrcnt,mprcnt, 4447 &rdata,&rparam,&rdata_len,&rparam_len); 4448 4449 4450 if (rdata_len > mdrcnt || rparam_len > mprcnt) { 4451 reply = api_TooSmall(conn,vuid,params,data,mdrcnt,mprcnt, 4452 &rdata,&rparam,&rdata_len,&rparam_len); 4453 } 4454 4455 /* if we get False back then it's actually unsupported */ 4456 if (!reply) { 4457 reply = api_Unsupported(conn,vuid,params,tpscnt,data,tdscnt,mdrcnt,mprcnt, 4458 &rdata,&rparam,&rdata_len,&rparam_len); 4459 } 4460 4461 /* If api_Unsupported returns false we can't return anything. */ 4462 if (reply) { 4463 send_trans_reply(outbuf, rparam, rparam_len, rdata, rdata_len, False); 4464 } 4465 4466 SAFE_FREE(rdata); 4467 SAFE_FREE(rparam); 4468 return -1; 4469} 4470