root/source3/smbd/lanman.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. smb_realloc_limit
  2. CopyExpanded
  3. CopyAndAdvance
  4. StrlenExpanded
  5. Expand
  6. prefix_ok
  7. get_counter
  8. getlen
  9. init_package
  10. package
  11. PACKI
  12. PACKS
  13. PackDriverData
  14. check_printq_info
  15. printj_status
  16. printq_status
  17. fill_printjob_info
  18. get_driver_name
  19. fill_printq_info_52
  20. fill_printq_info
  21. get_printerdrivernumber
  22. api_DosPrintQGetInfo
  23. api_DosPrintQEnum
  24. check_server_info
  25. get_server_info
  26. fill_srv_info
  27. srv_comp
  28. api_RNetServerEnum
  29. api_RNetGroupGetUsers
  30. check_share_info
  31. fill_share_info
  32. api_RNetShareGetInfo
  33. api_RNetShareEnum
  34. api_RNetShareAdd
  35. api_RNetGroupEnum
  36. api_NetUserGetGroups
  37. api_RNetUserEnum
  38. api_NetRemoteTOD
  39. api_SetUserPassword
  40. api_SamOEMChangePassword
  41. api_RDosPrintJobDel
  42. api_WPrintQueueCtrl
  43. check_printjob_info
  44. api_PrintJobInfo
  45. api_RNetServerGetInfo
  46. api_NetWkstaGetInfo
  47. api_RNetUserGetInfo
  48. api_WWkstaUserLogon
  49. api_WAccessGetUserPerms
  50. api_WPrintJobGetInfo
  51. api_WPrintJobEnumerate
  52. check_printdest_info
  53. fill_printdest_info
  54. api_WPrintDestGetInfo
  55. api_WPrintDestEnum
  56. api_WPrintDriverEnum
  57. api_WPrintQProcEnum
  58. api_WPrintPortEnum
  59. api_RNetSessionEnum
  60. api_TooSmall
  61. api_Unsupported
  62. api_reply

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

/* [<][>][^][v][top][bottom][index][help] */