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