smbd/lanman.c

説明を見る。
00001 /* 
00002    Unix SMB/CIFS implementation.
00003    Inter-process communication and named pipe handling
00004    Copyright (C) Andrew Tridgell 1992-1998
00005    Copyright (C) Jeremy Allison 2007.
00006 
00007    SMB Version handling
00008    Copyright (C) John H Terpstra 1995-1998
00009    
00010    This program is free software; you can redistribute it and/or modify
00011    it under the terms of the GNU General Public License as published by
00012    the Free Software Foundation; either version 2 of the License, or
00013    (at your option) any later version.
00014    
00015    This program is distributed in the hope that it will be useful,
00016    but WITHOUT ANY WARRANTY; without even the implied warranty of
00017    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018    GNU General Public License for more details.
00019    
00020    You should have received a copy of the GNU General Public License
00021    along with this program; if not, write to the Free Software
00022    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00023    */
00024 /*
00025    This file handles the named pipe and mailslot calls
00026    in the SMBtrans protocol
00027    */
00028 
00029 #include "includes.h"
00030 
00031 extern struct current_user current_user;
00032 extern userdom_struct current_user_info;
00033 
00034 #ifdef CHECK_TYPES
00035 #undef CHECK_TYPES
00036 #endif
00037 #define CHECK_TYPES 0
00038 
00039 #define NERR_Success 0
00040 #define NERR_badpass 86
00041 #define NERR_notsupported 50
00042 
00043 #define NERR_BASE (2100)
00044 #define NERR_BufTooSmall (NERR_BASE+23)
00045 #define NERR_JobNotFound (NERR_BASE+51)
00046 #define NERR_DestNotFound (NERR_BASE+52)
00047 
00048 #define ACCESS_READ 0x01
00049 #define ACCESS_WRITE 0x02
00050 #define ACCESS_CREATE 0x04
00051 
00052 #define SHPWLEN 8               /* share password length */
00053 
00054 static BOOL api_Unsupported(connection_struct *conn, uint16 vuid,
00055                                 char *param, int tpscnt,
00056                                 char *data, int tdscnt,
00057                                 int mdrcnt, int mprcnt,
00058                                 char **rdata, char **rparam,
00059                                 int *rdata_len, int *rparam_len);
00060 
00061 static BOOL api_TooSmall(connection_struct *conn, uint16 vuid, char *param, char *data,
00062                          int mdrcnt, int mprcnt,
00063                          char **rdata, char **rparam,
00064                          int *rdata_len, int *rparam_len);
00065 
00066 
00067 static int CopyExpanded(connection_struct *conn, 
00068                         int snum, char **dst, char *src, int *n)
00069 {
00070         pstring buf;
00071         int l;
00072 
00073         if (!src || !dst || !n || !(*dst)) {
00074                 return 0;
00075         }
00076 
00077         StrnCpy(buf,src,sizeof(buf)/2);
00078         pstring_sub(buf,"%S",lp_servicename(snum));
00079         standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
00080                               conn->connectpath, conn->gid,
00081                               get_current_username(),
00082                               current_user_info.domain,
00083                               buf, sizeof(buf));
00084         l = push_ascii(*dst,buf,*n, STR_TERMINATE);
00085         if (l == -1) {
00086                 return 0;
00087         }
00088         (*dst) += l;
00089         (*n) -= l;
00090         return l;
00091 }
00092 
00093 static int CopyAndAdvance(char **dst, char *src, int *n)
00094 {
00095         int l;
00096         if (!src || !dst || !n || !(*dst)) {
00097                 return 0;
00098         }
00099         l = push_ascii(*dst,src,*n, STR_TERMINATE);
00100         if (l == -1) {
00101                 return 0;
00102         }
00103         (*dst) += l;
00104         (*n) -= l;
00105         return l;
00106 }
00107 
00108 static int StrlenExpanded(connection_struct *conn, int snum, char *s)
00109 {
00110         pstring buf;
00111         if (!s) {
00112                 return 0;
00113         }
00114         StrnCpy(buf,s,sizeof(buf)/2);
00115         pstring_sub(buf,"%S",lp_servicename(snum));
00116         standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
00117                               conn->connectpath, conn->gid,
00118                               get_current_username(),
00119                               current_user_info.domain,
00120                               buf, sizeof(buf));
00121         return strlen(buf) + 1;
00122 }
00123 
00124 static char *Expand(connection_struct *conn, int snum, char *s)
00125 {
00126         static pstring buf;
00127         if (!s) {
00128                 return NULL;
00129         }
00130         StrnCpy(buf,s,sizeof(buf)/2);
00131         pstring_sub(buf,"%S",lp_servicename(snum));
00132         standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
00133                               conn->connectpath, conn->gid,
00134                               get_current_username(),
00135                               current_user_info.domain,
00136                               buf, sizeof(buf));
00137         return &buf[0];
00138 }
00139 
00140 /*******************************************************************
00141  Check a API string for validity when we only need to check the prefix.
00142 ******************************************************************/
00143 
00144 static BOOL prefix_ok(const char *str, const char *prefix)
00145 {
00146         return(strncmp(str,prefix,strlen(prefix)) == 0);
00147 }
00148 
00149 struct pack_desc {
00150         const char *format;         /* formatstring for structure */
00151         const char *subformat;  /* subformat for structure */
00152         char *base;         /* baseaddress of buffer */
00153         int buflen;        /* remaining size for fixed part; on init: length of base */
00154         int subcount;       /* count of substructures */
00155         char *structbuf;  /* pointer into buffer for remaining fixed part */
00156         int stringlen;    /* remaining size for variable part */                
00157         char *stringbuf;  /* pointer into buffer for remaining variable part */
00158         int neededlen;    /* total needed size */
00159         int usedlen;        /* total used size (usedlen <= neededlen and usedlen <= buflen) */
00160         const char *curpos;         /* current position; pointer into format or subformat */
00161         int errcode;
00162 };
00163 
00164 static int get_counter(const char **p)
00165 {
00166         int i, n;
00167         if (!p || !(*p)) {
00168                 return 1;
00169         }
00170         if (!isdigit((int)**p)) {
00171                 return 1;
00172         }
00173         for (n = 0;;) {
00174                 i = **p;
00175                 if (isdigit(i)) {
00176                         n = 10 * n + (i - '0');
00177                 } else {
00178                         return n;
00179                 }
00180                 (*p)++;
00181         }
00182 }
00183 
00184 static int getlen(const char *p)
00185 {
00186         int n = 0;
00187         if (!p) {
00188                 return 0;
00189         }
00190 
00191         while (*p) {
00192                 switch( *p++ ) {
00193                 case 'W':                       /* word (2 byte) */
00194                         n += 2;
00195                         break;
00196                 case 'K':                       /* status word? (2 byte) */
00197                         n += 2;
00198                         break;
00199                 case 'N':                       /* count of substructures (word) at end */
00200                         n += 2;
00201                         break;
00202                 case 'D':                       /* double word (4 byte) */
00203                 case 'z':                       /* offset to zero terminated string (4 byte) */
00204                 case 'l':                       /* offset to user data (4 byte) */
00205                         n += 4;
00206                         break;
00207                 case 'b':                       /* offset to data (with counter) (4 byte) */
00208                         n += 4;
00209                         get_counter(&p);
00210                         break;
00211                 case 'B':                       /* byte (with optional counter) */
00212                         n += get_counter(&p);
00213                         break;
00214                 }
00215         }
00216         return n;
00217 }
00218 
00219 static BOOL init_package(struct pack_desc *p, int count, int subcount)
00220 {
00221         int n = p->buflen;
00222         int i;
00223 
00224         if (!p->format || !p->base) {
00225                 return False;
00226         }
00227 
00228         i = count * getlen(p->format);
00229         if (p->subformat) {
00230                 i += subcount * getlen(p->subformat);
00231         }
00232         p->structbuf = p->base;
00233         p->neededlen = 0;
00234         p->usedlen = 0;
00235         p->subcount = 0;
00236         p->curpos = p->format;
00237         if (i > n) {
00238                 p->neededlen = i;
00239                 i = n = 0;
00240 #if 0
00241                 /*
00242                  * This is the old error code we used. Aparently
00243                  * WinNT/2k systems return ERRbuftoosmall (2123) and
00244                  * OS/2 needs this. I'm leaving this here so we can revert
00245                  * if needed. JRA.
00246                  */
00247                 p->errcode = ERRmoredata;
00248 #else
00249                 p->errcode = ERRbuftoosmall;
00250 #endif
00251         } else {
00252                 p->errcode = NERR_Success;
00253         }
00254         p->buflen = i;
00255         n -= i;
00256         p->stringbuf = p->base + i;
00257         p->stringlen = n;
00258         return (p->errcode == NERR_Success);
00259 }
00260 
00261 static int package(struct pack_desc *p, ...)
00262 {
00263         va_list args;
00264         int needed=0, stringneeded;
00265         const char *str=NULL;
00266         int is_string=0, stringused;
00267         int32 temp;
00268 
00269         va_start(args,p);
00270 
00271         if (!*p->curpos) {
00272                 if (!p->subcount) {
00273                         p->curpos = p->format;
00274                 } else {
00275                         p->curpos = p->subformat;
00276                         p->subcount--;
00277                 }
00278         }
00279 #if CHECK_TYPES
00280         str = va_arg(args,char*);
00281         SMB_ASSERT(strncmp(str,p->curpos,strlen(str)) == 0);
00282 #endif
00283         stringneeded = -1;
00284 
00285         if (!p->curpos) {
00286                 va_end(args);
00287                 return 0;
00288         }
00289 
00290         switch( *p->curpos++ ) {
00291                 case 'W':                       /* word (2 byte) */
00292                         needed = 2;
00293                         temp = va_arg(args,int);
00294                         if (p->buflen >= needed) {
00295                                 SSVAL(p->structbuf,0,temp);
00296                         }
00297                         break;
00298                 case 'K':                       /* status word? (2 byte) */
00299                         needed = 2;
00300                         temp = va_arg(args,int);
00301                         if (p->buflen >= needed) {
00302                                 SSVAL(p->structbuf,0,temp);
00303                         }
00304                         break;
00305                 case 'N':                       /* count of substructures (word) at end */
00306                         needed = 2;
00307                         p->subcount = va_arg(args,int);
00308                         if (p->buflen >= needed) {
00309                                 SSVAL(p->structbuf,0,p->subcount);
00310                         }
00311                         break;
00312                 case 'D':                       /* double word (4 byte) */
00313                         needed = 4;
00314                         temp = va_arg(args,int);
00315                         if (p->buflen >= needed) {
00316                                 SIVAL(p->structbuf,0,temp);
00317                         }
00318                         break;
00319                 case 'B':                       /* byte (with optional counter) */
00320                         needed = get_counter(&p->curpos);
00321                         {
00322                                 char *s = va_arg(args,char*);
00323                                 if (p->buflen >= needed) {
00324                                         StrnCpy(p->structbuf,s?s:"",needed-1);
00325                                 }
00326                         }
00327                         break;
00328                 case 'z':                       /* offset to zero terminated string (4 byte) */
00329                         str = va_arg(args,char*);
00330                         stringneeded = (str ? strlen(str)+1 : 0);
00331                         is_string = 1;
00332                         break;
00333                 case 'l':                       /* offset to user data (4 byte) */
00334                         str = va_arg(args,char*);
00335                         stringneeded = va_arg(args,int);
00336                         is_string = 0;
00337                         break;
00338                 case 'b':                       /* offset to data (with counter) (4 byte) */
00339                         str = va_arg(args,char*);
00340                         stringneeded = get_counter(&p->curpos);
00341                         is_string = 0;
00342                         break;
00343         }
00344 
00345         va_end(args);
00346         if (stringneeded >= 0) {
00347                 needed = 4;
00348                 if (p->buflen >= needed) {
00349                         stringused = stringneeded;
00350                         if (stringused > p->stringlen) {
00351                                 stringused = (is_string ? p->stringlen : 0);
00352                                 if (p->errcode == NERR_Success) {
00353                                         p->errcode = ERRmoredata;
00354                                 }
00355                         }
00356                         if (!stringused) {
00357                                 SIVAL(p->structbuf,0,0);
00358                         } else {
00359                                 SIVAL(p->structbuf,0,PTR_DIFF(p->stringbuf,p->base));
00360                                 memcpy(p->stringbuf,str?str:"",stringused);
00361                                 if (is_string) {
00362                                         p->stringbuf[stringused-1] = '\0';
00363                                 }
00364                                 p->stringbuf += stringused;
00365                                 p->stringlen -= stringused;
00366                                 p->usedlen += stringused;
00367                         }
00368                 }
00369                 p->neededlen += stringneeded;
00370         }
00371 
00372         p->neededlen += needed;
00373         if (p->buflen >= needed) {
00374                 p->structbuf += needed;
00375                 p->buflen -= needed;
00376                 p->usedlen += needed;
00377         } else {
00378                 if (p->errcode == NERR_Success) {
00379                         p->errcode = ERRmoredata;
00380                 }
00381         }
00382         return 1;
00383 }
00384 
00385 #if CHECK_TYPES
00386 #define PACK(desc,t,v) package(desc,t,v,0,0,0,0)
00387 #define PACKl(desc,t,v,l) package(desc,t,v,l,0,0,0,0)
00388 #else
00389 #define PACK(desc,t,v) package(desc,v)
00390 #define PACKl(desc,t,v,l) package(desc,v,l)
00391 #endif
00392 
00393 static void PACKI(struct pack_desc* desc, const char *t,int v)
00394 {
00395         PACK(desc,t,v);
00396 }
00397 
00398 static void PACKS(struct pack_desc* desc,const char *t,const char *v)
00399 {
00400         PACK(desc,t,v);
00401 }
00402 
00403 /****************************************************************************
00404  Get a print queue.
00405 ****************************************************************************/
00406 
00407 static void PackDriverData(struct pack_desc* desc)
00408 {
00409         char drivdata[4+4+32];
00410         SIVAL(drivdata,0,sizeof drivdata); /* cb */
00411         SIVAL(drivdata,4,1000); /* lVersion */
00412         memset(drivdata+8,0,32);        /* szDeviceName */
00413         push_ascii(drivdata+8,"NULL",32, STR_TERMINATE);
00414         PACKl(desc,"l",drivdata,sizeof drivdata); /* pDriverData */
00415 }
00416 
00417 static int check_printq_info(struct pack_desc* desc,
00418                                 unsigned int uLevel, char *id1, char *id2)
00419 {
00420         desc->subformat = NULL;
00421         switch( uLevel ) {
00422                 case 0:
00423                         desc->format = "B13";
00424                         break;
00425                 case 1:
00426                         desc->format = "B13BWWWzzzzzWW";
00427                         break;
00428                 case 2:
00429                         desc->format = "B13BWWWzzzzzWN";
00430                         desc->subformat = "WB21BB16B10zWWzDDz";
00431                         break;
00432                 case 3:
00433                         desc->format = "zWWWWzzzzWWzzl";
00434                         break;
00435                 case 4:
00436                         desc->format = "zWWWWzzzzWNzzl";
00437                         desc->subformat = "WWzWWDDzz";
00438                         break;
00439                 case 5:
00440                         desc->format = "z";
00441                         break;
00442                 case 51:
00443                         desc->format = "K";
00444                         break;
00445                 case 52:
00446                         desc->format = "WzzzzzzzzN";
00447                         desc->subformat = "z";
00448                         break;
00449                 default:
00450                         DEBUG(0,("check_printq_info: invalid level %d\n",
00451                                 uLevel ));
00452                         return False;
00453         }
00454         if (id1 == NULL || strcmp(desc->format,id1) != 0) {
00455                 DEBUG(0,("check_printq_info: invalid format %s\n",
00456                         id1 ? id1 : "<NULL>" ));
00457                 return False;
00458         }
00459         if (desc->subformat && (id2 == NULL || strcmp(desc->subformat,id2) != 0)) {
00460                 DEBUG(0,("check_printq_info: invalid subformat %s\n",
00461                         id2 ? id2 : "<NULL>" ));
00462                 return False;
00463         }
00464         return True;
00465 }
00466 
00467 
00468 #define RAP_JOB_STATUS_QUEUED 0
00469 #define RAP_JOB_STATUS_PAUSED 1
00470 #define RAP_JOB_STATUS_SPOOLING 2
00471 #define RAP_JOB_STATUS_PRINTING 3
00472 #define RAP_JOB_STATUS_PRINTED 4
00473 
00474 #define RAP_QUEUE_STATUS_PAUSED 1
00475 #define RAP_QUEUE_STATUS_ERROR 2
00476 
00477 /* turn a print job status into a on the wire status 
00478 */
00479 static int printj_status(int v)
00480 {
00481         switch (v) {
00482         case LPQ_QUEUED:
00483                 return RAP_JOB_STATUS_QUEUED;
00484         case LPQ_PAUSED:
00485                 return RAP_JOB_STATUS_PAUSED;
00486         case LPQ_SPOOLING:
00487                 return RAP_JOB_STATUS_SPOOLING;
00488         case LPQ_PRINTING:
00489                 return RAP_JOB_STATUS_PRINTING;
00490         }
00491         return 0;
00492 }
00493 
00494 /* turn a print queue status into a on the wire status 
00495 */
00496 static int printq_status(int v)
00497 {
00498         switch (v) {
00499         case LPQ_QUEUED:
00500                 return 0;
00501         case LPQ_PAUSED:
00502                 return RAP_QUEUE_STATUS_PAUSED;
00503         }
00504         return RAP_QUEUE_STATUS_ERROR;
00505 }
00506 
00507 static void fill_printjob_info(connection_struct *conn, int snum, int uLevel,
00508                                struct pack_desc *desc,
00509                                print_queue_struct *queue, int n)
00510 {
00511         time_t t = queue->time;
00512 
00513         /* the client expects localtime */
00514         t -= get_time_zone(t);
00515 
00516         PACKI(desc,"W",pjobid_to_rap(lp_const_servicename(snum),queue->job)); /* uJobId */
00517         if (uLevel == 1) {
00518                 PACKS(desc,"B21",queue->fs_user); /* szUserName */
00519                 PACKS(desc,"B","");             /* pad */
00520                 PACKS(desc,"B16","");   /* szNotifyName */
00521                 PACKS(desc,"B10","PM_Q_RAW"); /* szDataType */
00522                 PACKS(desc,"z","");             /* pszParms */
00523                 PACKI(desc,"W",n+1);            /* uPosition */
00524                 PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */
00525                 PACKS(desc,"z","");             /* pszStatus */
00526                 PACKI(desc,"D",t); /* ulSubmitted */
00527                 PACKI(desc,"D",queue->size); /* ulSize */
00528                 PACKS(desc,"z",queue->fs_file); /* pszComment */
00529         }
00530         if (uLevel == 2 || uLevel == 3 || uLevel == 4) {
00531                 PACKI(desc,"W",queue->priority);                /* uPriority */
00532                 PACKS(desc,"z",queue->fs_user); /* pszUserName */
00533                 PACKI(desc,"W",n+1);            /* uPosition */
00534                 PACKI(desc,"W",printj_status(queue->status)); /* fsStatus */
00535                 PACKI(desc,"D",t); /* ulSubmitted */
00536                 PACKI(desc,"D",queue->size); /* ulSize */
00537                 PACKS(desc,"z","Samba");        /* pszComment */
00538                 PACKS(desc,"z",queue->fs_file); /* pszDocument */
00539                 if (uLevel == 3) {
00540                         PACKS(desc,"z","");     /* pszNotifyName */
00541                         PACKS(desc,"z","PM_Q_RAW"); /* pszDataType */
00542                         PACKS(desc,"z","");     /* pszParms */
00543                         PACKS(desc,"z","");     /* pszStatus */
00544                         PACKS(desc,"z",SERVICE(snum)); /* pszQueue */
00545                         PACKS(desc,"z","lpd");  /* pszQProcName */
00546                         PACKS(desc,"z","");     /* pszQProcParms */
00547                         PACKS(desc,"z","NULL"); /* pszDriverName */
00548                         PackDriverData(desc);   /* pDriverData */
00549                         PACKS(desc,"z","");     /* pszPrinterName */
00550                 } else if (uLevel == 4) {   /* OS2 */
00551                         PACKS(desc,"z","");       /* pszSpoolFileName  */
00552                         PACKS(desc,"z","");       /* pszPortName       */
00553                         PACKS(desc,"z","");       /* pszStatus         */
00554                         PACKI(desc,"D",0);        /* ulPagesSpooled    */
00555                         PACKI(desc,"D",0);        /* ulPagesSent       */
00556                         PACKI(desc,"D",0);        /* ulPagesPrinted    */
00557                         PACKI(desc,"D",0);        /* ulTimePrinted     */
00558                         PACKI(desc,"D",0);        /* ulExtendJobStatus */
00559                         PACKI(desc,"D",0);        /* ulStartPage       */
00560                         PACKI(desc,"D",0);        /* ulEndPage         */
00561                 }
00562         }
00563 }
00564 
00565 /********************************************************************
00566  Return a driver name given an snum.
00567  Returns True if from tdb, False otherwise.
00568  ********************************************************************/
00569 
00570 static BOOL get_driver_name(int snum, pstring drivername)
00571 {
00572         NT_PRINTER_INFO_LEVEL *info = NULL;
00573         BOOL in_tdb = False;
00574 
00575         get_a_printer (NULL, &info, 2, lp_servicename(snum));
00576         if (info != NULL) {
00577                 pstrcpy( drivername, info->info_2->drivername);
00578                 in_tdb = True;
00579                 free_a_printer(&info, 2);
00580         }
00581 
00582         return in_tdb;
00583 }
00584 
00585 /********************************************************************
00586  Respond to the DosPrintQInfo command with a level of 52
00587  This is used to get printer driver information for Win9x clients
00588  ********************************************************************/
00589 static void fill_printq_info_52(connection_struct *conn, int snum, 
00590                                 struct pack_desc* desc, int count )
00591 {
00592         int                             i;
00593         fstring                         location;
00594         NT_PRINTER_DRIVER_INFO_LEVEL    driver;
00595         NT_PRINTER_INFO_LEVEL           *printer = NULL;
00596 
00597         ZERO_STRUCT(driver);
00598 
00599         if ( !W_ERROR_IS_OK(get_a_printer( NULL, &printer, 2, lp_servicename(snum))) ) {
00600                 DEBUG(3,("fill_printq_info_52: Failed to lookup printer [%s]\n", 
00601                         lp_servicename(snum)));
00602                 goto err;
00603         }
00604 
00605         if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, 
00606                 "Windows 4.0", 0)) )
00607         {
00608                 DEBUG(3,("fill_printq_info_52: Failed to lookup driver [%s]\n", 
00609                         printer->info_2->drivername));
00610                 goto err;
00611         }
00612 
00613         trim_string(driver.info_3->driverpath, "\\print$\\WIN40\\0\\", 0);
00614         trim_string(driver.info_3->datafile, "\\print$\\WIN40\\0\\", 0);
00615         trim_string(driver.info_3->helpfile, "\\print$\\WIN40\\0\\", 0);
00616 
00617         PACKI(desc, "W", 0x0400);                     /* don't know */
00618         PACKS(desc, "z", driver.info_3->name);        /* long printer name */
00619         PACKS(desc, "z", driver.info_3->driverpath);  /* Driverfile Name */
00620         PACKS(desc, "z", driver.info_3->datafile);    /* Datafile name */
00621         PACKS(desc, "z", driver.info_3->monitorname); /* language monitor */
00622 
00623         fstrcpy(location, "\\\\%L\\print$\\WIN40\\0");
00624         standard_sub_basic( "", "", location, sizeof(location)-1 );
00625         PACKS(desc,"z", location);                          /* share to retrieve files */
00626 
00627         PACKS(desc,"z", driver.info_3->defaultdatatype);    /* default data type */
00628         PACKS(desc,"z", driver.info_3->helpfile);           /* helpfile name */
00629         PACKS(desc,"z", driver.info_3->driverpath);               /* driver name */
00630 
00631         DEBUG(3,("Printer Driver Name: %s:\n",driver.info_3->name));
00632         DEBUG(3,("Driver: %s:\n",driver.info_3->driverpath));
00633         DEBUG(3,("Data File: %s:\n",driver.info_3->datafile));
00634         DEBUG(3,("Language Monitor: %s:\n",driver.info_3->monitorname));
00635         DEBUG(3,("Driver Location: %s:\n",location));
00636         DEBUG(3,("Data Type: %s:\n",driver.info_3->defaultdatatype));
00637         DEBUG(3,("Help File: %s:\n",driver.info_3->helpfile));
00638         PACKI(desc,"N",count);                     /* number of files to copy */
00639 
00640         for ( i=0; i<count && driver.info_3->dependentfiles && *driver.info_3->dependentfiles[i]; i++) 
00641         {
00642                 trim_string(driver.info_3->dependentfiles[i], "\\print$\\WIN40\\0\\", 0);
00643                 PACKS(desc,"z",driver.info_3->dependentfiles[i]);         /* driver files to copy */
00644                 DEBUG(3,("Dependent File: %s:\n",driver.info_3->dependentfiles[i]));
00645         }
00646 
00647         /* sanity check */
00648         if ( i != count )
00649                 DEBUG(3,("fill_printq_info_52: file count specified by client [%d] != number of dependent files [%i]\n",
00650                         count, i));
00651 
00652         DEBUG(3,("fill_printq_info on <%s> gave %d entries\n", SERVICE(snum),i));
00653 
00654         desc->errcode=NERR_Success;
00655         goto done;
00656 
00657 err:
00658         DEBUG(3,("fill_printq_info: Can't supply driver files\n"));
00659         desc->errcode=NERR_notsupported;
00660 
00661 done:
00662         if ( printer )
00663                 free_a_printer( &printer, 2 );
00664 
00665         if ( driver.info_3 )
00666                 free_a_printer_driver( driver, 3 );
00667 }
00668 
00669 
00670 static void fill_printq_info(connection_struct *conn, int snum, int uLevel,
00671                              struct pack_desc* desc,
00672                              int count, print_queue_struct* queue,
00673                              print_status_struct* status)
00674 {
00675         switch (uLevel) {
00676         case 1:
00677         case 2:
00678                 PACKS(desc,"B13",SERVICE(snum));
00679                 break;
00680         case 3:
00681         case 4:
00682         case 5:
00683                 PACKS(desc,"z",Expand(conn,snum,SERVICE(snum)));
00684                 break;
00685         case 51:
00686                 PACKI(desc,"K",printq_status(status->status));
00687                 break;
00688         }
00689 
00690         if (uLevel == 1 || uLevel == 2) {
00691                 PACKS(desc,"B","");             /* alignment */
00692                 PACKI(desc,"W",5);              /* priority */
00693                 PACKI(desc,"W",0);              /* start time */
00694                 PACKI(desc,"W",0);              /* until time */
00695                 PACKS(desc,"z","");             /* pSepFile */
00696                 PACKS(desc,"z","lpd");  /* pPrProc */
00697                 PACKS(desc,"z",SERVICE(snum)); /* pDestinations */
00698                 PACKS(desc,"z","");             /* pParms */
00699                 if (snum < 0) {
00700                         PACKS(desc,"z","UNKNOWN PRINTER");
00701                         PACKI(desc,"W",LPSTAT_ERROR);
00702                 }
00703                 else if (!status || !status->message[0]) {
00704                         PACKS(desc,"z",Expand(conn,snum,lp_comment(snum)));
00705                         PACKI(desc,"W",LPSTAT_OK); /* status */
00706                 } else {
00707                         PACKS(desc,"z",status->message);
00708                         PACKI(desc,"W",printq_status(status->status)); /* status */
00709                 }
00710                 PACKI(desc,(uLevel == 1 ? "W" : "N"),count);
00711         }
00712 
00713         if (uLevel == 3 || uLevel == 4) {
00714                 pstring drivername;
00715 
00716                 PACKI(desc,"W",5);              /* uPriority */
00717                 PACKI(desc,"W",0);              /* uStarttime */
00718                 PACKI(desc,"W",0);              /* uUntiltime */
00719                 PACKI(desc,"W",5);              /* pad1 */
00720                 PACKS(desc,"z","");             /* pszSepFile */
00721                 PACKS(desc,"z","WinPrint");     /* pszPrProc */
00722                 PACKS(desc,"z",NULL);           /* pszParms */
00723                 PACKS(desc,"z",NULL);           /* pszComment - don't ask.... JRA */
00724                 /* "don't ask" that it's done this way to fix corrupted 
00725                    Win9X/ME printer comments. */
00726                 if (!status) {
00727                         PACKI(desc,"W",LPSTAT_OK); /* fsStatus */
00728                 } else {
00729                         PACKI(desc,"W",printq_status(status->status)); /* fsStatus */
00730                 }
00731                 PACKI(desc,(uLevel == 3 ? "W" : "N"),count);    /* cJobs */
00732                 PACKS(desc,"z",SERVICE(snum)); /* pszPrinters */
00733                 get_driver_name(snum,drivername);
00734                 PACKS(desc,"z",drivername);             /* pszDriverName */
00735                 PackDriverData(desc);   /* pDriverData */
00736         }
00737 
00738         if (uLevel == 2 || uLevel == 4) {
00739                 int i;
00740                 for (i=0;i<count;i++)
00741                         fill_printjob_info(conn,snum,uLevel == 2 ? 1 : 2,desc,&queue[i],i);
00742         }
00743 
00744         if (uLevel==52)
00745                 fill_printq_info_52( conn, snum, desc, count );
00746 }
00747 
00748 /* This function returns the number of files for a given driver */
00749 static int get_printerdrivernumber(int snum)
00750 {
00751         int                             result = 0;
00752         NT_PRINTER_DRIVER_INFO_LEVEL    driver;
00753         NT_PRINTER_INFO_LEVEL           *printer = NULL;
00754 
00755         ZERO_STRUCT(driver);
00756 
00757         if ( !W_ERROR_IS_OK(get_a_printer( NULL, &printer, 2, lp_servicename(snum))) ) {
00758                 DEBUG(3,("get_printerdrivernumber: Failed to lookup printer [%s]\n", 
00759                         lp_servicename(snum)));
00760                 goto done;
00761         }
00762 
00763         if ( !W_ERROR_IS_OK(get_a_printer_driver(&driver, 3, printer->info_2->drivername, 
00764                 "Windows 4.0", 0)) )
00765         {
00766                 DEBUG(3,("get_printerdrivernumber: Failed to lookup driver [%s]\n", 
00767                         printer->info_2->drivername));
00768                 goto done;
00769         }
00770 
00771         /* count the number of files */
00772         while ( driver.info_3->dependentfiles && *driver.info_3->dependentfiles[result] )
00773                         result++;
00774                         \
00775  done:
00776         if ( printer )
00777                 free_a_printer( &printer, 2 );
00778 
00779         if ( driver.info_3 )
00780                 free_a_printer_driver( driver, 3 );
00781 
00782         return result;
00783 }
00784 
00785 static BOOL api_DosPrintQGetInfo(connection_struct *conn, uint16 vuid,
00786                                 char *param, int tpscnt,
00787                                 char *data, int tdscnt,
00788                                 int mdrcnt,int mprcnt,
00789                                 char **rdata,char **rparam,
00790                                 int *rdata_len,int *rparam_len)
00791 {
00792         char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
00793         char *str2 = skip_string(param,tpscnt,str1);
00794         char *p = skip_string(param,tpscnt,str2);
00795         char *QueueName = p;
00796         unsigned int uLevel;
00797         int count=0;
00798         int snum;
00799         char *str3;
00800         struct pack_desc desc;
00801         print_queue_struct *queue=NULL;
00802         print_status_struct status;
00803         char* tmpdata=NULL;
00804 
00805         if (!str1 || !str2 || !p) {
00806                 return False;
00807         }
00808         memset((char *)&status,'\0',sizeof(status));
00809         memset((char *)&desc,'\0',sizeof(desc));
00810 
00811         p = skip_string(param,tpscnt,p);
00812         if (!p) {
00813                 return False;
00814         }
00815         uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
00816         str3 = get_safe_str_ptr(param,tpscnt,p,4);
00817         /* str3 may be null here and is checked in check_printq_info(). */
00818 
00819         /* remove any trailing username */
00820         if ((p = strchr_m(QueueName,'%')))
00821                 *p = 0;
00822  
00823         DEBUG(3,("api_DosPrintQGetInfo uLevel=%d name=%s\n",uLevel,QueueName));
00824  
00825         /* check it's a supported varient */
00826         if (!prefix_ok(str1,"zWrLh"))
00827                 return False;
00828         if (!check_printq_info(&desc,uLevel,str2,str3)) {
00829                 /*
00830                  * Patch from Scott Moomaw <scott@bridgewater.edu>
00831                  * to return the 'invalid info level' error if an
00832                  * unknown level was requested.
00833                  */
00834                 *rdata_len = 0;
00835                 *rparam_len = 6;
00836                 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
00837                 if (!*rparam) {
00838                         return False;
00839                 }
00840                 SSVALS(*rparam,0,ERRunknownlevel);
00841                 SSVAL(*rparam,2,0);
00842                 SSVAL(*rparam,4,0);
00843                 return(True);
00844         }
00845  
00846         snum = find_service(QueueName);
00847         if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
00848                 return False;
00849                 
00850         if (uLevel==52) {
00851                 count = get_printerdrivernumber(snum);
00852                 DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count));
00853         } else {
00854                 count = print_queue_status(snum, &queue,&status);
00855         }
00856 
00857         if (mdrcnt > 0) {
00858                 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
00859                 if (!*rdata) {
00860                         return False;
00861                 }
00862                 desc.base = *rdata;
00863                 desc.buflen = mdrcnt;
00864         } else {
00865                 /*
00866                  * Don't return data but need to get correct length
00867                  * init_package will return wrong size if buflen=0
00868                  */
00869                 desc.buflen = getlen(desc.format);
00870                 desc.base = tmpdata = (char *) SMB_MALLOC (desc.buflen);
00871         }
00872 
00873         if (init_package(&desc,1,count)) {
00874                 desc.subcount = count;
00875                 fill_printq_info(conn,snum,uLevel,&desc,count,queue,&status);
00876         }
00877 
00878         *rdata_len = desc.usedlen;
00879   
00880         /*
00881          * We must set the return code to ERRbuftoosmall
00882          * in order to support lanman style printing with Win NT/2k
00883          * clients       --jerry
00884          */
00885         if (!mdrcnt && lp_disable_spoolss())
00886                 desc.errcode = ERRbuftoosmall;
00887  
00888         *rdata_len = desc.usedlen;
00889         *rparam_len = 6;
00890         *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
00891         if (!*rparam) {
00892                 return False;
00893         }
00894         SSVALS(*rparam,0,desc.errcode);
00895         SSVAL(*rparam,2,0);
00896         SSVAL(*rparam,4,desc.neededlen);
00897   
00898         DEBUG(4,("printqgetinfo: errorcode %d\n",desc.errcode));
00899 
00900         SAFE_FREE(queue);
00901         SAFE_FREE(tmpdata);
00902 
00903         return(True);
00904 }
00905 
00906 /****************************************************************************
00907  View list of all print jobs on all queues.
00908 ****************************************************************************/
00909 
00910 static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid,
00911                                 char *param, int tpscnt,
00912                                 char *data, int tdscnt,
00913                                 int mdrcnt, int mprcnt,
00914                                 char **rdata, char** rparam,
00915                                 int *rdata_len, int *rparam_len)
00916 {
00917         char *param_format = get_safe_str_ptr(param,tpscnt,param,2);
00918         char *output_format1 = skip_string(param,tpscnt,param_format);
00919         char *p = skip_string(param,tpscnt,output_format1);
00920         unsigned int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
00921         char *output_format2 = get_safe_str_ptr(param,tpscnt,p,4);
00922         int services = lp_numservices();
00923         int i, n;
00924         struct pack_desc desc;
00925         print_queue_struct **queue = NULL;
00926         print_status_struct *status = NULL;
00927         int *subcntarr = NULL;
00928         int queuecnt = 0, subcnt = 0, succnt = 0;
00929  
00930         if (!param_format || !output_format1 || !p) {
00931                 return False;
00932         }
00933 
00934         memset((char *)&desc,'\0',sizeof(desc));
00935 
00936         DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
00937  
00938         if (!prefix_ok(param_format,"WrLeh")) {
00939                 return False;
00940         }
00941         if (!check_printq_info(&desc,uLevel,output_format1,output_format2)) {
00942                 /*
00943                  * Patch from Scott Moomaw <scott@bridgewater.edu>
00944                  * to return the 'invalid info level' error if an
00945                  * unknown level was requested.
00946                  */
00947                 *rdata_len = 0;
00948                 *rparam_len = 6;
00949                 *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
00950                 if (!*rparam) {
00951                         return False;
00952                 }
00953                 SSVALS(*rparam,0,ERRunknownlevel);
00954                 SSVAL(*rparam,2,0);
00955                 SSVAL(*rparam,4,0);
00956                 return(True);
00957         }
00958 
00959         for (i = 0; i < services; i++) {
00960                 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
00961                         queuecnt++;
00962                 }
00963         }
00964 
00965         if((queue = SMB_MALLOC_ARRAY(print_queue_struct*, queuecnt)) == NULL) {
00966                 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
00967                 goto err;
00968         }
00969         memset(queue,0,queuecnt*sizeof(print_queue_struct*));
00970         if((status = SMB_MALLOC_ARRAY(print_status_struct,queuecnt)) == NULL) {
00971                 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
00972                 goto err;
00973         }
00974         memset(status,0,queuecnt*sizeof(print_status_struct));
00975         if((subcntarr = SMB_MALLOC_ARRAY(int,queuecnt)) == NULL) {
00976                 DEBUG(0,("api_DosPrintQEnum: malloc fail !\n"));
00977                 goto err;
00978         }
00979 
00980         subcnt = 0;
00981         n = 0;
00982         for (i = 0; i < services; i++) {
00983                 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
00984                         subcntarr[n] = print_queue_status(i, &queue[n],&status[n]);
00985                         subcnt += subcntarr[n];
00986                         n++;
00987                 }
00988         }
00989 
00990         if (mdrcnt > 0) {
00991                 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
00992                 if (!*rdata) {
00993                         goto err;
00994                 }
00995         }
00996         desc.base = *rdata;
00997         desc.buflen = mdrcnt;
00998 
00999         if (init_package(&desc,queuecnt,subcnt)) {
01000                 n = 0;
01001                 succnt = 0;
01002                 for (i = 0; i < services; i++) {
01003                         if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
01004                                 fill_printq_info(conn,i,uLevel,&desc,subcntarr[n],queue[n],&status[n]);
01005                                 n++;
01006                                 if (desc.errcode == NERR_Success) {
01007                                         succnt = n;
01008                                 }
01009                         }
01010                 }
01011         }
01012 
01013         SAFE_FREE(subcntarr);
01014  
01015         *rdata_len = desc.usedlen;
01016         *rparam_len = 8;
01017         *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
01018         if (!*rparam) {
01019                 goto err;
01020         }
01021         SSVALS(*rparam,0,desc.errcode);
01022         SSVAL(*rparam,2,0);
01023         SSVAL(*rparam,4,succnt);
01024         SSVAL(*rparam,6,queuecnt);
01025   
01026         for (i = 0; i < queuecnt; i++) {
01027                 if (queue) {
01028                         SAFE_FREE(queue[i]);
01029                 }
01030         }
01031 
01032         SAFE_FREE(queue);
01033         SAFE_FREE(status);
01034   
01035         return True;
01036 
01037   err:
01038 
01039         SAFE_FREE(subcntarr);
01040         for (i = 0; i < queuecnt; i++) {
01041                 if (queue) {
01042                         SAFE_FREE(queue[i]);
01043                 }
01044         }
01045         SAFE_FREE(queue);
01046         SAFE_FREE(status);
01047 
01048         return False;
01049 }
01050 
01051 /****************************************************************************
01052  Get info level for a server list query.
01053 ****************************************************************************/
01054 
01055 static BOOL check_server_info(int uLevel, char* id)
01056 {
01057         switch( uLevel ) {
01058                 case 0:
01059                         if (strcmp(id,"B16") != 0) {
01060                                 return False;
01061                         }
01062                         break;
01063                 case 1:
01064                         if (strcmp(id,"B16BBDz") != 0) {
01065                                 return False;
01066                         }
01067                         break;
01068                 default: 
01069                         return False;
01070         }
01071         return True;
01072 }
01073 
01074 struct srv_info_struct {
01075         fstring name;
01076         uint32 type;
01077         fstring comment;
01078         fstring domain;
01079         BOOL server_added;
01080 };
01081 
01082 /*******************************************************************
01083  Get server info lists from the files saved by nmbd. Return the
01084  number of entries.
01085 ******************************************************************/
01086 
01087 static int get_server_info(uint32 servertype, 
01088                            struct srv_info_struct **servers,
01089                            const char *domain)
01090 {
01091         int count=0;
01092         int alloced=0;
01093         char **lines;
01094         BOOL local_list_only;
01095         int i;
01096 
01097         lines = file_lines_load(lock_path(SERVER_LIST), NULL, 0);
01098         if (!lines) {
01099                 DEBUG(4,("Can't open %s - %s\n",lock_path(SERVER_LIST),strerror(errno)));
01100                 return 0;
01101         }
01102 
01103         /* request for everything is code for request all servers */
01104         if (servertype == SV_TYPE_ALL) {
01105                 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
01106         }
01107 
01108         local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY);
01109 
01110         DEBUG(4,("Servertype search: %8x\n",servertype));
01111 
01112         for (i=0;lines[i];i++) {
01113                 fstring stype;
01114                 struct srv_info_struct *s;
01115                 const char *ptr = lines[i];
01116                 BOOL ok = True;
01117 
01118                 if (!*ptr) {
01119                         continue;
01120                 }
01121     
01122                 if (count == alloced) {
01123                         alloced += 10;
01124                         *servers = SMB_REALLOC_ARRAY(*servers,struct srv_info_struct, alloced);
01125                         if (!*servers) {
01126                                 DEBUG(0,("get_server_info: failed to enlarge servers info struct!\n"));
01127                                 file_lines_free(lines);
01128                                 return 0;
01129                         }
01130                         memset((char *)((*servers)+count),'\0',sizeof(**servers)*(alloced-count));
01131                 }
01132                 s = &(*servers)[count];
01133     
01134                 if (!next_token(&ptr,s->name, NULL, sizeof(s->name))) {
01135                         continue;
01136                 }
01137                 if (!next_token(&ptr,stype, NULL, sizeof(stype))) {
01138                         continue;
01139                 }
01140                 if (!next_token(&ptr,s->comment, NULL, sizeof(s->comment))) {
01141                         continue;
01142                 }
01143                 if (!next_token(&ptr,s->domain, NULL, sizeof(s->domain))) {
01144                         /* this allows us to cope with an old nmbd */
01145                         fstrcpy(s->domain,lp_workgroup()); 
01146                 }
01147     
01148                 if (sscanf(stype,"%X",&s->type) != 1) { 
01149                         DEBUG(4,("r:host file ")); 
01150                         ok = False; 
01151                 }
01152     
01153                 /* Filter the servers/domains we return based on what was asked for. */
01154 
01155                 /* Check to see if we are being asked for a local list only. */
01156                 if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) {
01157                         DEBUG(4,("r: local list only"));
01158                         ok = False;
01159                 }
01160 
01161                 /* doesn't match up: don't want it */
01162                 if (!(servertype & s->type)) { 
01163                         DEBUG(4,("r:serv type ")); 
01164                         ok = False; 
01165                 }
01166     
01167                 if ((servertype & SV_TYPE_DOMAIN_ENUM) != 
01168                                 (s->type & SV_TYPE_DOMAIN_ENUM)) {
01169                         DEBUG(4,("s: dom mismatch "));
01170                         ok = False;
01171                 }
01172     
01173                 if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM)) {
01174                         ok = False;
01175                 }
01176     
01177                 /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
01178                 s->type &= ~SV_TYPE_LOCAL_LIST_ONLY;
01179 
01180                 if (ok) {
01181                         DEBUG(4,("**SV** %20s %8x %25s %15s\n",
01182                                 s->name, s->type, s->comment, s->domain));
01183                         s->server_added = True;
01184                         count++;
01185                 } else {
01186                         DEBUG(4,("%20s %8x %25s %15s\n",
01187                                 s->name, s->type, s->comment, s->domain));
01188                 }
01189         }
01190   
01191         file_lines_free(lines);
01192         return count;
01193 }
01194 
01195 /*******************************************************************
01196  Fill in a server info structure.
01197 ******************************************************************/
01198 
01199 static int fill_srv_info(struct srv_info_struct *service, 
01200                          int uLevel, char **buf, int *buflen, 
01201                          char **stringbuf, int *stringspace, char *baseaddr)
01202 {
01203         int struct_len;
01204         char* p;
01205         char* p2;
01206         int l2;
01207         int len;
01208  
01209         switch (uLevel) {
01210                 case 0:
01211                         struct_len = 16;
01212                         break;
01213                 case 1:
01214                         struct_len = 26;
01215                         break;
01216                 default:
01217                         return -1;
01218         }
01219  
01220         if (!buf) {
01221                 len = 0;
01222                 switch (uLevel) {
01223                         case 1:
01224                                 len = strlen(service->comment)+1;
01225                                 break;
01226                 }
01227 
01228                 *buflen = struct_len;
01229                 *stringspace = len;
01230                 return struct_len + len;
01231         }
01232   
01233         len = struct_len;
01234         p = *buf;
01235         if (*buflen < struct_len) {
01236                 return -1;
01237         }
01238         if (stringbuf) {
01239                 p2 = *stringbuf;
01240                 l2 = *stringspace;
01241         } else {
01242                 p2 = p + struct_len;
01243                 l2 = *buflen - struct_len;
01244         }
01245         if (!baseaddr) {
01246                 baseaddr = p;
01247         }
01248   
01249         switch (uLevel) {
01250                 case 0:
01251                         push_ascii(p,service->name, MAX_NETBIOSNAME_LEN, STR_TERMINATE);
01252                         break;
01253 
01254                 case 1:
01255                         push_ascii(p,service->name,MAX_NETBIOSNAME_LEN, STR_TERMINATE);
01256                         SIVAL(p,18,service->type);
01257                         SIVAL(p,22,PTR_DIFF(p2,baseaddr));
01258                         len += CopyAndAdvance(&p2,service->comment,&l2);
01259                         break;
01260         }
01261 
01262         if (stringbuf) {
01263                 *buf = p + struct_len;
01264                 *buflen -= struct_len;
01265                 *stringbuf = p2;
01266                 *stringspace = l2;
01267         } else {
01268                 *buf = p2;
01269                 *buflen -= len;
01270         }
01271         return len;
01272 }
01273 
01274 
01275 static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
01276 {
01277         return(strcmp(s1->name,s2->name));
01278 }
01279 
01280 /****************************************************************************
01281  View list of servers available (or possibly domains). The info is
01282  extracted from lists saved by nmbd on the local host.
01283 ****************************************************************************/
01284 
01285 static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid,
01286                                 char *param, int tpscnt,
01287                                 char *data, int tdscnt,
01288                                 int mdrcnt, int mprcnt, char **rdata, 
01289                                 char **rparam, int *rdata_len, int *rparam_len)
01290 {
01291         char *str1 = get_safe_str_ptr(param, tpscnt, param, 2);
01292         char *str2 = skip_string(param,tpscnt,str1);
01293         char *p = skip_string(param,tpscnt,str2);
01294         int uLevel = get_safe_SVAL(param, tpscnt, p, 0, -1);
01295         int buf_len = get_safe_SVAL(param,tpscnt, p, 2, 0);
01296         uint32 servertype = get_safe_IVAL(param,tpscnt,p,4, 0);
01297         char *p2;
01298         int data_len, fixed_len, string_len;
01299         int f_len = 0, s_len = 0;
01300         struct srv_info_struct *servers=NULL;
01301         int counted=0,total=0;
01302         int i,missed;
01303         fstring domain;
01304         BOOL domain_request;
01305         BOOL local_request;
01306 
01307         if (!str1 || !str2 || !p) {
01308                 return False;
01309         }
01310 
01311         /* If someone sets all the bits they don't really mean to set
01312            DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
01313            known servers. */
01314 
01315         if (servertype == SV_TYPE_ALL) {
01316                 servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
01317         }
01318 
01319         /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
01320            any other bit (they may just set this bit on it's own) they 
01321            want all the locally seen servers. However this bit can be 
01322            set on its own so set the requested servers to be 
01323            ALL - DOMAIN_ENUM. */
01324 
01325         if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM)) {
01326                 servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
01327         }
01328 
01329         domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
01330         local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
01331 
01332         p += 8;
01333 
01334         if (!prefix_ok(str1,"WrLehD")) {
01335                 return False;
01336         }
01337         if (!check_server_info(uLevel,str2)) {
01338                 return False;
01339         }
01340   
01341         DEBUG(4, ("server request level: %s %8x ", str2, servertype));
01342         DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
01343         DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
01344 
01345         if (strcmp(str1, "WrLehDz") == 0) {
01346                 if (skip_string(param,tpscnt,p) == NULL) {
01347                         return False;
01348                 }
01349                 pull_ascii_fstring(domain, p);
01350         } else {
01351                 fstrcpy(domain, lp_workgroup());
01352         }
01353 
01354         if (lp_browse_list()) {
01355                 total = get_server_info(servertype,&servers,domain);
01356         }
01357 
01358         data_len = fixed_len = string_len = 0;
01359         missed = 0;
01360 
01361         if (total > 0) {
01362                 qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
01363         }
01364 
01365         {
01366                 char *lastname=NULL;
01367 
01368                 for (i=0;i<total;i++) {
01369                         struct srv_info_struct *s = &servers[i];
01370 
01371                         if (lastname && strequal(lastname,s->name)) {
01372                                 continue;
01373                         }
01374                         lastname = s->name;
01375                         data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
01376                         DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
01377                                 s->name, s->type, s->comment, s->domain));
01378       
01379                         if (data_len <= buf_len) {
01380                                 counted++;
01381                                 fixed_len += f_len;
01382                                 string_len += s_len;
01383                         } else {
01384                                 missed++;
01385                         }
01386                 }
01387         }
01388 
01389         *rdata_len = fixed_len + string_len;
01390         *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
01391         if (!*rdata) {
01392                 return False;
01393         }
01394         memset(*rdata,'\0',*rdata_len);
01395   
01396         p2 = (*rdata) + fixed_len;      /* auxilliary data (strings) will go here */
01397         p = *rdata;
01398         f_len = fixed_len;
01399         s_len = string_len;
01400 
01401         {
01402                 char *lastname=NULL;
01403                 int count2 = counted;
01404 
01405                 for (i = 0; i < total && count2;i++) {
01406                         struct srv_info_struct *s = &servers[i];
01407 
01408                         if (lastname && strequal(lastname,s->name)) {
01409                                 continue;
01410                         }
01411                         lastname = s->name;
01412                         fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
01413                         DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
01414                                 s->name, s->type, s->comment, s->domain));
01415                         count2--;
01416                 }
01417         }
01418   
01419         *rparam_len = 8;
01420         *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
01421         if (!*rparam) {
01422                 return False;
01423         }
01424         SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata));
01425         SSVAL(*rparam,2,0);
01426         SSVAL(*rparam,4,counted);
01427         SSVAL(*rparam,6,counted+missed);
01428 
01429         SAFE_FREE(servers);
01430 
01431         DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
01432                 domain,uLevel,counted,counted+missed));
01433 
01434         return True;
01435 }
01436 
01437 /****************************************************************************
01438   command 0x34 - suspected of being a "Lookup Names" stub api
01439   ****************************************************************************/
01440 
01441 static BOOL api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid,
01442                                 char *param, int tpscnt,
01443                                 char *data, int tdscnt,
01444                                 int mdrcnt, int mprcnt, char **rdata, 
01445                                 char **rparam, int *rdata_len, int *rparam_len)
01446 {
01447         char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
01448         char *str2 = skip_string(param,tpscnt,str1);
01449         char *p = skip_string(param,tpscnt,str2);
01450         int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
01451         int buf_len = get_safe_SVAL(param,tpscnt,p,2,0);
01452         int counted=0;
01453         int missed=0;
01454 
01455         if (!str1 || !str2 || !p) {
01456                 return False;
01457         }
01458 
01459         DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
01460                 str1, str2, p, uLevel, buf_len));
01461 
01462         if (!prefix_ok(str1,"zWrLeh")) {
01463                 return False;
01464         }
01465   
01466         *rdata_len = 0;
01467   
01468         *rparam_len = 8;
01469         *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
01470         if (!*rparam) {
01471                 return False;
01472         }
01473 
01474         SSVAL(*rparam,0,0x08AC); /* informational warning message */
01475         SSVAL(*rparam,2,0);
01476         SSVAL(*rparam,4,counted);
01477         SSVAL(*rparam,6,counted+missed);
01478 
01479         return True;
01480 }
01481 
01482 /****************************************************************************
01483   get info about a share
01484   ****************************************************************************/
01485 
01486 static BOOL check_share_info(int uLevel, char* id)
01487 {
01488         switch( uLevel ) {
01489                 case 0:
01490                         if (strcmp(id,"B13") != 0) {
01491                                 return False;
01492                         }
01493                         break;
01494                 case 1:
01495                         if (strcmp(id,"B13BWz") != 0) {
01496                                 return False;
01497                         }
01498                         break;
01499                 case 2:
01500                         if (strcmp(id,"B13BWzWWWzB9B") != 0) {
01501                                 return False;
01502                         }
01503                         break;
01504                 case 91:
01505                         if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) {
01506                                 return False;
01507                         }
01508                         break;
01509                 default:
01510                         return False;
01511         }
01512         return True;
01513 }
01514 
01515 static int fill_share_info(connection_struct *conn, int snum, int uLevel,
01516                            char** buf, int* buflen,
01517                            char** stringbuf, int* stringspace, char* baseaddr)
01518 {
01519         int struct_len;
01520         char* p;
01521         char* p2;
01522         int l2;
01523         int len;
01524  
01525         switch( uLevel ) {
01526                 case 0:
01527                         struct_len = 13;
01528                         break;
01529                 case 1:
01530                         struct_len = 20;
01531                         break;
01532                 case 2:
01533                         struct_len = 40;
01534                         break;
01535                 case 91:
01536                         struct_len = 68;
01537                         break;
01538                 default:
01539                         return -1;
01540         }
01541   
01542  
01543         if (!buf) {
01544                 len = 0;
01545 
01546                 if (uLevel > 0) {
01547                         len += StrlenExpanded(conn,snum,lp_comment(snum));
01548                 }
01549                 if (uLevel > 1) {
01550                         len += strlen(lp_pathname(snum)) + 1;
01551                 }
01552                 if (buflen) {
01553                         *buflen = struct_len;
01554                 }
01555                 if (stringspace) {
01556                         *stringspace = len;
01557                 }
01558                 return struct_len + len;
01559         }
01560   
01561         len = struct_len;
01562         p = *buf;
01563         if ((*buflen) < struct_len) {
01564                 return -1;
01565         }
01566 
01567         if (stringbuf) {
01568                 p2 = *stringbuf;
01569                 l2 = *stringspace;
01570         } else {
01571                 p2 = p + struct_len;
01572                 l2 = (*buflen) - struct_len;
01573         }
01574 
01575         if (!baseaddr) {
01576                 baseaddr = p;
01577         }
01578   
01579         push_ascii(p,lp_servicename(snum),13, STR_TERMINATE);
01580   
01581         if (uLevel > 0) {
01582                 int type;
01583 
01584                 SCVAL(p,13,0);
01585                 type = STYPE_DISKTREE;
01586                 if (lp_print_ok(snum)) {
01587                         type = STYPE_PRINTQ;
01588                 }
01589                 if (strequal("IPC",lp_fstype(snum))) {
01590                         type = STYPE_IPC;
01591                 }
01592                 SSVAL(p,14,type);               /* device type */
01593                 SIVAL(p,16,PTR_DIFF(p2,baseaddr));
01594                 len += CopyExpanded(conn,snum,&p2,lp_comment(snum),&l2);
01595         }
01596   
01597         if (uLevel > 1) {
01598                 SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
01599                 SSVALS(p,22,-1);                /* max uses */
01600                 SSVAL(p,24,1); /* current uses */
01601                 SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
01602                 len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
01603                 memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
01604         }
01605   
01606         if (uLevel > 2) {
01607                 memset(p+40,0,SHPWLEN+2);
01608                 SSVAL(p,50,0);
01609                 SIVAL(p,52,0);
01610                 SSVAL(p,56,0);
01611                 SSVAL(p,58,0);
01612                 SIVAL(p,60,0);
01613                 SSVAL(p,64,0);
01614                 SSVAL(p,66,0);
01615         }
01616        
01617         if (stringbuf) {
01618                 (*buf) = p + struct_len;
01619                 (*buflen) -= struct_len;
01620                 (*stringbuf) = p2;
01621                 (*stringspace) = l2;
01622         } else {
01623                 (*buf) = p2;
01624                 (*buflen) -= len;
01625         }
01626 
01627         return len;
01628 }
01629 
01630 static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid,
01631                                 char *param, int tpscnt,
01632                                 char *data, int tdscnt,
01633                                 int mdrcnt,int mprcnt,
01634                                 char **rdata,char **rparam,
01635                                 int *rdata_len,int *rparam_len)
01636 {
01637         char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
01638         char *str2 = skip_string(param,tpscnt,str1);
01639         char *netname = skip_string(param,tpscnt,str2);
01640         char *p = skip_string(param,tpscnt,netname);
01641         int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
01642         int snum;
01643   
01644         if (!str1 || !str2 || !netname || !p) {
01645                 return False;
01646         }
01647 
01648         snum = find_service(netname);
01649         if (snum < 0) {
01650                 return False;
01651         }
01652   
01653         /* check it's a supported varient */
01654         if (!prefix_ok(str1,"zWrLh")) {
01655                 return False;
01656         }
01657         if (!check_share_info(uLevel,str2)) {
01658                 return False;
01659         }
01660  
01661         *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
01662         if (!*rdata) {
01663                 return False;
01664         }
01665         p = *rdata;
01666         *rdata_len = fill_share_info(conn,snum,uLevel,&p,&mdrcnt,0,0,0);
01667         if (*rdata_len < 0) {
01668                 return False;
01669         }
01670  
01671         *rparam_len = 6;
01672         *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
01673         if (!*rparam) {
01674                 return False;
01675         }
01676         SSVAL(*rparam,0,NERR_Success);
01677         SSVAL(*rparam,2,0);             /* converter word */
01678         SSVAL(*rparam,4,*rdata_len);
01679  
01680         return True;
01681 }
01682 
01683 /****************************************************************************
01684   View the list of available shares.
01685 
01686   This function is the server side of the NetShareEnum() RAP call.
01687   It fills the return buffer with share names and share comments.
01688   Note that the return buffer normally (in all known cases) allows only
01689   twelve byte strings for share names (plus one for a nul terminator).
01690   Share names longer than 12 bytes must be skipped.
01691  ****************************************************************************/
01692 
01693 static BOOL api_RNetShareEnum( connection_struct *conn, uint16 vuid,
01694                                 char *param, int tpscnt,
01695                                 char *data, int tdscnt,
01696                                 int                mdrcnt,
01697                                 int                mprcnt,
01698                                 char             **rdata,
01699                                 char             **rparam,
01700                                 int               *rdata_len,
01701                                 int               *rparam_len )
01702 {
01703         char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
01704         char *str2 = skip_string(param,tpscnt,str1);
01705         char *p = skip_string(param,tpscnt,str2);
01706         int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
01707         int buf_len = get_safe_SVAL(param,tpscnt,p,2,0);
01708         char *p2;
01709         int count = 0;
01710         int total=0,counted=0;
01711         BOOL missed = False;
01712         int i;
01713         int data_len, fixed_len, string_len;
01714         int f_len = 0, s_len = 0;
01715  
01716         if (!str1 || !str2 || !p) {
01717                 return False;
01718         }
01719 
01720         if (!prefix_ok(str1,"WrLeh")) {
01721                 return False;
01722         }
01723         if (!check_share_info(uLevel,str2)) {
01724                 return False;
01725         }
01726   
01727         /* Ensure all the usershares are loaded. */
01728         become_root();
01729         count = load_usershare_shares();
01730         unbecome_root();
01731 
01732         data_len = fixed_len = string_len = 0;
01733         for (i=0;i<count;i++) {
01734                 fstring servicename_dos;
01735                 if (!(lp_browseable(i) && lp_snum_ok(i))) {
01736                         continue;
01737                 }
01738                 push_ascii_fstring(servicename_dos, lp_servicename(i));
01739                 /* Maximum name length = 13. */
01740                 if( lp_browseable( i ) && lp_snum_ok( i ) && (strlen(servicename_dos) < 13)) {
01741                         total++;
01742                         data_len += fill_share_info(conn,i,uLevel,0,&f_len,0,&s_len,0);
01743                         if (data_len <= buf_len) {
01744                                 counted++;
01745                                 fixed_len += f_len;
01746                                 string_len += s_len;
01747                         } else {
01748                                 missed = True;
01749                         }
01750                 }
01751         }
01752 
01753         *rdata_len = fixed_len + string_len;
01754         *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
01755         if (!*rdata) {
01756                 return False;
01757         }
01758         memset(*rdata,0,*rdata_len);
01759   
01760         p2 = (*rdata) + fixed_len;      /* auxiliary data (strings) will go here */
01761         p = *rdata;
01762         f_len = fixed_len;
01763         s_len = string_len;
01764 
01765         for( i = 0; i < count; i++ ) {
01766                 fstring servicename_dos;
01767                 if (!(lp_browseable(i) && lp_snum_ok(i))) {
01768                         continue;
01769                 }
01770 
01771                 push_ascii_fstring(servicename_dos, lp_servicename(i));
01772                 if (lp_browseable(i) && lp_snum_ok(i) && (strlen(servicename_dos) < 13)) {
01773                         if (fill_share_info( conn,i,uLevel,&p,&f_len,&p2,&s_len,*rdata ) < 0) {
01774                                 break;
01775                         }
01776                 }
01777         }
01778   
01779         *rparam_len = 8;
01780         *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
01781         if (!*rparam) {
01782                 return False;
01783         }
01784         SSVAL(*rparam,0,missed ? ERRmoredata : NERR_Success);
01785         SSVAL(*rparam,2,0);
01786         SSVAL(*rparam,4,counted);
01787         SSVAL(*rparam,6,total);
01788   
01789         DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
01790                 counted,total,uLevel,
01791                 buf_len,*rdata_len,mdrcnt));
01792 
01793         return True;
01794 }
01795 
01796 /****************************************************************************
01797   Add a share
01798   ****************************************************************************/
01799 
01800 static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid,
01801                                 char *param, int tpscnt,
01802                                 char *data, int tdscnt,
01803                                 int mdrcnt,int mprcnt,
01804                                 char **rdata,char **rparam,
01805                                 int *rdata_len,int *rparam_len)
01806 {
01807         char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
01808         char *str2 = skip_string(param,tpscnt,str1);
01809         char *p = skip_string(param,tpscnt,str2);
01810         int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
01811         fstring sharename;
01812         fstring comment;
01813         pstring pathname;
01814         char *command, *cmdname;
01815         unsigned int offset;
01816         int snum;
01817         int res = ERRunsup;
01818   
01819         if (!str1 || !str2 || !p) {
01820                 return False;
01821         }
01822 
01823         /* check it's a supported varient */
01824         if (!prefix_ok(str1,RAP_WShareAdd_REQ)) {
01825                 return False;
01826         }
01827         if (!check_share_info(uLevel,str2)) {
01828                 return False;
01829         }
01830         if (uLevel != 2) {
01831                 return False;
01832         }
01833 
01834         /* Do we have a string ? */
01835         if (skip_string(data,mdrcnt,data) == NULL) {
01836                 return False;
01837         }
01838         pull_ascii_fstring(sharename,data);
01839         snum = find_service(sharename);
01840         if (snum >= 0) { /* already exists */
01841                 res = ERRfilexists;
01842                 goto error_exit;
01843         }
01844 
01845         if (mdrcnt < 28) {
01846                 return False;
01847         }
01848 
01849         /* only support disk share adds */
01850         if (SVAL(data,14)!=STYPE_DISKTREE) {
01851                 return False;
01852         }
01853 
01854         offset = IVAL(data, 16);
01855         if (offset >= mdrcnt) {
01856                 res = ERRinvalidparam;
01857                 goto error_exit;
01858         }
01859 
01860         /* Do we have a string ? */
01861         if (skip_string(data,mdrcnt,data+offset) == NULL) {
01862                 return False;
01863         }
01864         pull_ascii_fstring(comment, offset? (data+offset) : "");
01865 
01866         offset = IVAL(data, 26);
01867 
01868         if (offset >= mdrcnt) {
01869                 res = ERRinvalidparam;
01870                 goto error_exit;
01871         }
01872 
01873         /* Do we have a string ? */
01874         if (skip_string(data,mdrcnt,data+offset) == NULL) {
01875                 return False;
01876         }
01877         pull_ascii_pstring(pathname, offset? (data+offset) : "");
01878 
01879         string_replace(sharename, '"', ' ');
01880         string_replace(pathname, '"', ' ');
01881         string_replace(comment, '"', ' ');
01882 
01883         cmdname = lp_add_share_cmd();
01884 
01885         if (!cmdname || *cmdname == '\0') {
01886                 return False;
01887         }
01888 
01889         asprintf(&command, "%s \"%s\" \"%s\" \"%s\" \"%s\"",
01890                 lp_add_share_cmd(), dyn_CONFIGFILE, sharename, pathname, comment);
01891 
01892         if (command) {
01893                 DEBUG(10,("api_RNetShareAdd: Running [%s]\n", command ));
01894 
01895                 if ((res = smbrun(command, NULL)) != 0) {
01896                         DEBUG(1,("api_RNetShareAdd: Running [%s] returned (%d)\n", command, res ));
01897                         SAFE_FREE(command);
01898                         res = ERRnoaccess;
01899                         goto error_exit;
01900                 } else {
01901                         SAFE_FREE(command);
01902                         message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
01903                 }
01904         } else {
01905                 return False;
01906         }
01907 
01908         *rparam_len = 6;
01909         *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
01910         if (!*rparam) {
01911                 return False;
01912         }
01913         SSVAL(*rparam,0,NERR_Success);
01914         SSVAL(*rparam,2,0);             /* converter word */
01915         SSVAL(*rparam,4,*rdata_len);
01916         *rdata_len = 0;
01917   
01918         return True;
01919 
01920   error_exit:
01921 
01922         *rparam_len = 4;
01923         *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
01924         if (!*rparam) {
01925                 return False;
01926         }
01927         *rdata_len = 0;
01928         SSVAL(*rparam,0,res);
01929         SSVAL(*rparam,2,0);
01930         return True;
01931 }
01932 
01933 /****************************************************************************
01934   view list of groups available
01935   ****************************************************************************/
01936 
01937 static BOOL api_RNetGroupEnum(connection_struct *conn,uint16 vuid,
01938                                 char *param, int tpscnt,
01939                                 char *data, int tdscnt,
01940                                 int mdrcnt,int mprcnt,
01941                                 char **rdata,char **rparam,
01942                                 int *rdata_len,int *rparam_len)
01943 {
01944         int i;
01945         int errflags=0;
01946         int resume_context, cli_buf_size;
01947         char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
01948         char *str2 = skip_string(param,tpscnt,str1);
01949         char *p = skip_string(param,tpscnt,str2);
01950 
01951         struct pdb_search *search;
01952         struct samr_displayentry *entries;
01953 
01954         int num_entries;
01955  
01956         if (!str1 || !str2 || !p) {
01957                 return False;
01958         }
01959 
01960         if (strcmp(str1,"WrLeh") != 0) {
01961                 return False;
01962         }
01963 
01964         /* parameters  
01965          * W-> resume context (number of users to skip)
01966          * r -> return parameter pointer to receive buffer 
01967          * L -> length of receive buffer
01968          * e -> return parameter number of entries
01969          * h -> return parameter total number of users
01970          */
01971 
01972         if (strcmp("B21",str2) != 0) {
01973                 return False;
01974         }
01975 
01976         /* get list of domain groups SID_DOMAIN_GRP=2 */
01977         become_root();
01978         search = pdb_search_groups();
01979         unbecome_root();
01980 
01981         if (search == NULL) {
01982                 DEBUG(3,("api_RNetGroupEnum:failed to get group list"));
01983                 return False;
01984         }
01985 
01986         resume_context = get_safe_SVAL(param,tpscnt,p,0,-1);
01987         cli_buf_size= get_safe_SVAL(param,tpscnt,p,2,0);
01988         DEBUG(10,("api_RNetGroupEnum:resume context: %d, client buffer size: "
01989                   "%d\n", resume_context, cli_buf_size));
01990 
01991         become_root();
01992         num_entries = pdb_search_entries(search, resume_context, 0xffffffff,
01993                                          &entries);
01994         unbecome_root();
01995 
01996         *rdata_len = cli_buf_size;
01997         *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
01998         if (!*rdata) {
01999                 return False;
02000         }
02001 
02002         p = *rdata;
02003 
02004         for(i=0; i<num_entries; i++) {
02005                 fstring name;
02006                 fstrcpy(name, entries[i].account_name);
02007                 if( ((PTR_DIFF(p,*rdata)+21) <= *rdata_len) ) {
02008                         /* truncate the name at 21 chars. */
02009                         memcpy(p, name, 21); 
02010                         DEBUG(10,("adding entry %d group %s\n", i, p));
02011                         p += 21;
02012                         p += 5; /* Both NT4 and W2k3SP1 do padding here.
02013                                    No idea why... */
02014                 } else {
02015                         /* set overflow error */
02016                         DEBUG(3,("overflow on entry %d group %s\n", i, name));
02017                         errflags=234;
02018                         break;
02019                 }
02020         }
02021 
02022         pdb_search_destroy(search);
02023 
02024         *rdata_len = PTR_DIFF(p,*rdata);
02025 
02026         *rparam_len = 8;
02027         *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
02028         if (!*rparam) {
02029                 return False;
02030         }
02031         SSVAL(*rparam, 0, errflags);
02032         SSVAL(*rparam, 2, 0);           /* converter word */
02033         SSVAL(*rparam, 4, i);   /* is this right?? */
02034         SSVAL(*rparam, 6, resume_context+num_entries);  /* is this right?? */
02035 
02036         return(True);
02037 }
02038 
02039 /*******************************************************************
02040  Get groups that a user is a member of.
02041 ******************************************************************/
02042 
02043 static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid,
02044                                 char *param, int tpscnt,
02045                                 char *data, int tdscnt,
02046                                 int mdrcnt,int mprcnt,
02047                                 char **rdata,char **rparam,
02048                                 int *rdata_len,int *rparam_len)
02049 {
02050         char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
02051         char *str2 = skip_string(param,tpscnt,str1);
02052         char *UserName = skip_string(param,tpscnt,str2);
02053         char *p = skip_string(param,tpscnt,UserName);
02054         int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
02055         const char *level_string;
02056         int count=0;
02057         struct samu *sampw = NULL;
02058         BOOL ret = False;
02059         DOM_SID *sids;
02060         gid_t *gids;
02061         size_t num_groups;
02062         size_t i;
02063         NTSTATUS result;
02064         DOM_SID user_sid;
02065         enum lsa_SidType type;
02066         TALLOC_CTX *mem_ctx;
02067 
02068         if (!str1 || !str2 || !UserName || !p) {
02069                 return False;
02070         }
02071 
02072         *rparam_len = 8;
02073         *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
02074         if (!*rparam) {
02075                 return False;
02076         }
02077   
02078         /* check it's a supported varient */
02079         
02080         if ( strcmp(str1,"zWrLeh") != 0 )
02081                 return False;
02082                 
02083         switch( uLevel ) {
02084                 case 0:
02085                         level_string = "B21";
02086                         break;
02087                 default:
02088                         return False;
02089         }
02090 
02091         if (strcmp(level_string,str2) != 0)
02092                 return False;
02093 
02094         *rdata_len = mdrcnt + 1024;
02095         *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
02096         if (!*rdata) {
02097                 return False;
02098         }
02099         SSVAL(*rparam,0,NERR_Success);
02100         SSVAL(*rparam,2,0);             /* converter word */
02101 
02102         p = *rdata;
02103 
02104         mem_ctx = talloc_new(NULL);
02105         if (mem_ctx == NULL) {
02106                 DEBUG(0, ("talloc_new failed\n"));
02107                 return False;
02108         }
02109 
02110         if ( !(sampw = samu_new(mem_ctx)) ) {
02111                 DEBUG(0, ("samu_new() failed!\n"));
02112                 TALLOC_FREE(mem_ctx);
02113                 return False;
02114         }
02115 
02116         /* Lookup the user information; This should only be one of 
02117            our accounts (not remote domains) */
02118 
02119         become_root();                                  /* ROOT BLOCK */
02120 
02121         if (!lookup_name(mem_ctx, UserName, LOOKUP_NAME_ALL,
02122                          NULL, NULL, &user_sid, &type)) {
02123                 DEBUG(10, ("lookup_name(%s) failed\n", UserName));
02124                 goto done;
02125         }
02126 
02127         if (type != SID_NAME_USER) {
02128                 DEBUG(10, ("%s is a %s, not a user\n", UserName,
02129                            sid_type_lookup(type)));
02130                 goto done;
02131         }
02132 
02133         if ( !pdb_getsampwsid(sampw, &user_sid) ) {
02134                 DEBUG(10, ("pdb_getsampwsid(%s) failed for user %s\n",
02135                            sid_string_static(&user_sid), UserName));
02136                 goto done;
02137         }
02138 
02139         gids = NULL;
02140         sids = NULL;
02141         num_groups = 0;
02142 
02143         result = pdb_enum_group_memberships(mem_ctx, sampw,
02144                                             &sids, &gids, &num_groups);
02145 
02146         if (!NT_STATUS_IS_OK(result)) {
02147                 DEBUG(10, ("pdb_enum_group_memberships failed for %s\n",
02148                            UserName));
02149                 goto done;
02150         }
02151 
02152         for (i=0; i<num_groups; i++) {
02153 
02154                 const char *grp_name;
02155         
02156                 if ( lookup_sid(mem_ctx, &sids[i], NULL, &grp_name, NULL) ) {
02157                         pstrcpy(p, grp_name);
02158                         p += 21; 
02159                         count++;
02160                 }
02161         }
02162 
02163         *rdata_len = PTR_DIFF(p,*rdata);
02164 
02165         SSVAL(*rparam,4,count); /* is this right?? */
02166         SSVAL(*rparam,6,count); /* is this right?? */
02167 
02168         ret = True;
02169 
02170 done:
02171         unbecome_root();                                /* END ROOT BLOCK */
02172 
02173         TALLOC_FREE(mem_ctx);
02174 
02175         return ret;
02176 }
02177 
02178 /*******************************************************************
02179  Get all users.
02180 ******************************************************************/
02181 
02182 static BOOL api_RNetUserEnum(connection_struct *conn, uint16 vuid,
02183                                 char *param, int tpscnt,
02184                                 char *data, int tdscnt,
02185                                 int mdrcnt,int mprcnt,
02186                                 char **rdata,char **rparam,
02187                                 int *rdata_len,int *rparam_len)
02188 {
02189         int count_sent=0;
02190         int num_users=0;
02191         int errflags=0;
02192         int i, resume_context, cli_buf_size;
02193         struct pdb_search *search;
02194         struct samr_displayentry *users;
02195 
02196         char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
02197         char *str2 = skip_string(param,tpscnt,str1);
02198         char *p = skip_string(param,tpscnt,str2);
02199 
02200         if (!str1 || !str2 || !p) {
02201                 return False;
02202         }
02203 
02204         if (strcmp(str1,"WrLeh") != 0)
02205                 return False;
02206         /* parameters
02207           * W-> resume context (number of users to skip)
02208           * r -> return parameter pointer to receive buffer
02209           * L -> length of receive buffer
02210           * e -> return parameter number of entries
02211           * h -> return parameter total number of users
02212           */
02213   
02214         resume_context = get_safe_SVAL(param,tpscnt,p,0,-1);
02215         cli_buf_size= get_safe_SVAL(param,tpscnt,p,2,0);
02216         DEBUG(10,("api_RNetUserEnum:resume context: %d, client buffer size: %d\n",
02217                         resume_context, cli_buf_size));
02218 
02219         *rparam_len = 8;
02220         *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
02221         if (!*rparam) {
02222                 return False;
02223         }
02224 
02225         /* check it's a supported varient */
02226         if (strcmp("B21",str2) != 0)
02227                 return False;
02228 
02229         *rdata_len = cli_buf_size;
02230         *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
02231         if (!*rdata) {
02232                 return False;
02233         }
02234 
02235         p = *rdata;
02236 
02237         become_root();
02238         search = pdb_search_users(ACB_NORMAL);
02239         unbecome_root();
02240         if (search == NULL) {
02241                 DEBUG(0, ("api_RNetUserEnum:unable to open sam database.\n"));
02242                 return False;
02243         }
02244 
02245         become_root();
02246         num_users = pdb_search_entries(search, resume_context, 0xffffffff,
02247                                        &users);
02248         unbecome_root();
02249 
02250         errflags=NERR_Success;
02251 
02252         for (i=0; i<num_users; i++) {
02253                 const char *name = users[i].account_name;
02254                 
02255                 if(((PTR_DIFF(p,*rdata)+21)<=*rdata_len)&&(strlen(name)<=21)) {
02256                         pstrcpy(p,name); 
02257                         DEBUG(10,("api_RNetUserEnum:adding entry %d username "
02258                                   "%s\n",count_sent,p));
02259                         p += 21; 
02260                         count_sent++; 
02261                 } else {
02262                         /* set overflow error */
02263                         DEBUG(10,("api_RNetUserEnum:overflow on entry %d "
02264                                   "username %s\n",count_sent,name));
02265                         errflags=234;
02266                         break;
02267                 }
02268         }
02269 
02270         pdb_search_destroy(search);
02271 
02272         *rdata_len = PTR_DIFF(p,*rdata);
02273 
02274         SSVAL(*rparam,0,errflags);
02275         SSVAL(*rparam,2,0);           /* converter word */
02276         SSVAL(*rparam,4,count_sent);  /* is this right?? */
02277         SSVAL(*rparam,6,num_users); /* is this right?? */
02278 
02279         return True;
02280 }
02281 
02282 /****************************************************************************
02283  Get the time of day info.
02284 ****************************************************************************/
02285 
02286 static BOOL api_NetRemoteTOD(connection_struct *conn,uint16 vuid,
02287                                 char *param, int tpscnt,
02288                                 char *data, int tdscnt,
02289                                 int mdrcnt,int mprcnt,
02290                                 char **rdata,char **rparam,
02291                                 int *rdata_len,int *rparam_len)
02292 {
02293         struct tm *t;
02294         time_t unixdate = time(NULL);
02295         char *p;
02296 
02297         *rparam_len = 4;
02298         *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
02299         if (!*rparam) {
02300                 return False;
02301         }
02302 
02303         *rdata_len = 21;
02304         *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
02305         if (!*rdata) {
02306                 return False;
02307         }
02308 
02309         SSVAL(*rparam,0,NERR_Success);
02310         SSVAL(*rparam,2,0);             /* converter word */
02311 
02312         p = *rdata;
02313 
02314         srv_put_dos_date3(p,0,unixdate); /* this is the time that is looked at
02315                                             by NT in a "net time" operation,
02316                                             it seems to ignore the one below */
02317 
02318         /* the client expects to get localtime, not GMT, in this bit 
02319                 (I think, this needs testing) */
02320         t = localtime(&unixdate);
02321         if (!t) {
02322                 return False;
02323         }
02324 
02325         SIVAL(p,4,0);           /* msecs ? */
02326         SCVAL(p,8,t->tm_hour);
02327         SCVAL(p,9,t->tm_min);
02328         SCVAL(p,10,t->tm_sec);
02329         SCVAL(p,11,0);          /* hundredths of seconds */
02330         SSVALS(p,12,get_time_zone(unixdate)/60); /* timezone in minutes from GMT */
02331         SSVAL(p,14,10000);              /* timer interval in 0.0001 of sec */
02332         SCVAL(p,16,t->tm_mday);
02333         SCVAL(p,17,t->tm_mon + 1);
02334         SSVAL(p,18,1900+t->tm_year);
02335         SCVAL(p,20,t->tm_wday);
02336 
02337         return True;
02338 }
02339 
02340 /****************************************************************************
02341  Set the user password.
02342 *****************************************************************************/
02343 
02344 static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid,
02345                                 char *param, int tpscnt,
02346                                 char *data, int tdscnt,
02347                                 int mdrcnt,int mprcnt,
02348                                 char **rdata,char **rparam,
02349                                 int *rdata_len,int *rparam_len)
02350 {
02351         char *np = get_safe_str_ptr(param,tpscnt,param,2);
02352         char *p = NULL;
02353         fstring user;
02354         fstring pass1,pass2;
02355 
02356         /* Skip 2 strings. */
02357         p = skip_string(param,tpscnt,np);
02358         p = skip_string(param,tpscnt,p);
02359 
02360         if (!np || !p) {
02361                 return False;
02362         }
02363 
02364         /* Do we have a string ? */
02365         if (skip_string(param,tpscnt,p) == NULL) {
02366                 return False;
02367         }
02368         pull_ascii_fstring(user,p);
02369 
02370         p = skip_string(param,tpscnt,p);
02371         if (!p) {
02372                 return False;
02373         }
02374 
02375         memset(pass1,'\0',sizeof(pass1));
02376         memset(pass2,'\0',sizeof(pass2));
02377         /*
02378          * We use 31 here not 32 as we're checking
02379          * the last byte we want to access is safe.
02380          */
02381         if (!is_offset_safe(param,tpscnt,p,31)) {
02382                 return False;
02383         }
02384         memcpy(pass1,p,16);
02385         memcpy(pass2,p+16,16);
02386 
02387         *rparam_len = 4;
02388         *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
02389         if (!*rparam) {
02390                 return False;
02391         }
02392 
02393         *rdata_len = 0;
02394 
02395         SSVAL(*rparam,0,NERR_badpass);
02396         SSVAL(*rparam,2,0);             /* converter word */
02397 
02398         DEBUG(3,("Set password for <%s>\n",user));
02399 
02400         /*
02401          * Attempt to verify the old password against smbpasswd entries
02402          * Win98 clients send old and new password in plaintext for this call.
02403          */
02404 
02405         {
02406                 auth_serversupplied_info *server_info = NULL;
02407                 DATA_BLOB password = data_blob(pass1, strlen(pass1)+1);
02408 
02409                 if (NT_STATUS_IS_OK(check_plaintext_password(user,password,&server_info))) {
02410 
02411                         become_root();
02412                         if (NT_STATUS_IS_OK(change_oem_password(server_info->sam_account, pass1, pass2, False, NULL))) {
02413                                 SSVAL(*rparam,0,NERR_Success);
02414                         }
02415                         unbecome_root();
02416 
02417                         TALLOC_FREE(server_info);
02418                 }
02419                 data_blob_clear_free(&password);
02420         }
02421 
02422         /*
02423          * If the plaintext change failed, attempt
02424          * the old encrypted method. NT will generate this
02425          * after trying the samr method. Note that this
02426          * method is done as a last resort as this
02427          * password change method loses the NT password hash
02428          * and cannot change the UNIX password as no plaintext
02429          * is received.
02430          */
02431 
02432         if(SVAL(*rparam,0) != NERR_Success) {
02433                 struct samu *hnd = NULL;
02434 
02435                 if (check_lanman_password(user,(unsigned char *)pass1,(unsigned char *)pass2, &hnd)) {
02436                         become_root();
02437                         if (change_lanman_password(hnd,(uchar *)pass2)) {
02438                                 SSVAL(*rparam,0,NERR_Success);
02439                         }
02440                         unbecome_root();
02441                         TALLOC_FREE(hnd);
02442                 }
02443         }
02444 
02445         memset((char *)pass1,'\0',sizeof(fstring));
02446         memset((char *)pass2,'\0',sizeof(fstring));      
02447          
02448         return(True);
02449 }
02450 
02451 /****************************************************************************
02452   Set the user password (SamOEM version - gets plaintext).
02453 ****************************************************************************/
02454 
02455 static BOOL api_SamOEMChangePassword(connection_struct *conn,uint16 vuid,
02456                                 char *param, int tpscnt,
02457                                 char *data, int tdscnt,
02458                                 int mdrcnt,int mprcnt,
02459                                 char **rdata,char **rparam,
02460                                 int *rdata_len,int *rparam_len)
02461 {
02462         fstring user;
02463         char *p = get_safe_str_ptr(param,tpscnt,param,2);
02464         *rparam_len = 2;
02465         *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
02466         if (!*rparam) {
02467                 return False;
02468         }
02469 
02470         if (!p) {
02471                 return False;
02472         }
02473         *rdata_len = 0;
02474 
02475         SSVAL(*rparam,0,NERR_badpass);
02476 
02477         /*
02478          * Check the parameter definition is correct.
02479          */
02480 
02481         /* Do we have a string ? */
02482         if (skip_string(param,tpscnt,p) == 0) {
02483                 return False;
02484         }
02485         if(!strequal(p, "zsT")) {
02486                 DEBUG(0,("api_SamOEMChangePassword: Invalid parameter string %s\n", p));
02487                 return False;
02488         }
02489         p = skip_string(param, tpscnt, p);
02490         if (!p) {
02491                 return False;
02492         }
02493 
02494         /* Do we have a string ? */
02495         if (skip_string(param,tpscnt,p) == 0) {
02496                 return False;
02497         }
02498         if(!strequal(p, "B516B16")) {
02499                 DEBUG(0,("api_SamOEMChangePassword: Invalid data parameter string %s\n", p));
02500                 return False;
02501         }
02502         p = skip_string(param,tpscnt,p);
02503         if (!p) {
02504                 return False;
02505         }
02506         /* Do we have a string ? */
02507         if (skip_string(param,tpscnt,p) == 0) {
02508                 return False;
02509         }
02510         p += pull_ascii_fstring(user,p);
02511 
02512         DEBUG(3,("api_SamOEMChangePassword: Change password for <%s>\n",user));
02513 
02514         /*
02515          * Pass the user through the NT -> unix user mapping
02516          * function.
02517          */
02518 
02519         (void)map_username(user);
02520 
02521         if (NT_STATUS_IS_OK(pass_oem_change(user, (uchar*) data, (uchar *)&data[516], NULL, NULL, NULL))) {
02522                 SSVAL(*rparam,0,NERR_Success);
02523         }
02524 
02525         return(True);
02526 }
02527 
02528 /****************************************************************************
02529   delete a print job
02530   Form: <W> <> 
02531   ****************************************************************************/
02532 
02533 static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid,
02534                                 char *param, int tpscnt,
02535                                 char *data, int tdscnt,
02536                                 int mdrcnt,int mprcnt,
02537                                 char **rdata,char **rparam,
02538                                 int *rdata_len,int *rparam_len)
02539 {
02540         int function = get_safe_SVAL(param,tpscnt,param,0,0);
02541         char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
02542         char *str2 = skip_string(param,tpscnt,str1);
02543         char *p = skip_string(param,tpscnt,str2);
02544         uint32 jobid;
02545         int snum;
02546         fstring sharename;
02547         int errcode;
02548         WERROR werr = WERR_OK;
02549 
02550         if (!str1 || !str2 || !p) {
02551                 return False;
02552         }
02553         /*
02554          * We use 1 here not 2 as we're checking
02555          * the last byte we want to access is safe.
02556          */
02557         if (!is_offset_safe(param,tpscnt,p,1)) {
02558                 return False;
02559         }
02560         if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
02561                 return False;
02562 
02563         /* check it's a supported varient */
02564         if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
02565                 return(False);
02566 
02567         *rparam_len = 4;
02568         *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);       
02569         if (!*rparam) {
02570                 return False;
02571         }
02572         *rdata_len = 0;
02573 
02574         if (!print_job_exists(sharename, jobid)) {
02575                 errcode = NERR_JobNotFound;
02576                 goto out;
02577         }
02578 
02579         snum = lp_servicenumber( sharename);
02580         if (snum == -1) {
02581                 errcode = NERR_DestNotFound;
02582                 goto out;
02583         }
02584 
02585         errcode = NERR_notsupported;
02586         
02587         switch (function) {
02588         case 81:                /* delete */ 
02589                 if (print_job_delete(&current_user, snum, jobid, &werr)) 
02590                         errcode = NERR_Success;
02591                 break;
02592         case 82:                /* pause */
02593                 if (print_job_pause(&current_user, snum, jobid, &werr)) 
02594                         errcode = NERR_Success;
02595                 break;
02596         case 83:                /* resume */
02597                 if (print_job_resume(&current_user, snum, jobid, &werr)) 
02598                         errcode = NERR_Success;
02599                 break;
02600         }
02601 
02602         if (!W_ERROR_IS_OK(werr))
02603                 errcode = W_ERROR_V(werr);
02604         
02605  out:
02606         SSVAL(*rparam,0,errcode);       
02607         SSVAL(*rparam,2,0);             /* converter word */
02608 
02609         return(True);
02610 }
02611 
02612 /****************************************************************************
02613   Purge a print queue - or pause or resume it.
02614   ****************************************************************************/
02615 
02616 static BOOL api_WPrintQueueCtrl(connection_struct *conn,uint16 vuid,
02617                                 char *param, int tpscnt,
02618                                 char *data, int tdscnt,
02619                                 int mdrcnt,int mprcnt,
02620                                 char **rdata,char **rparam,
02621                                 int *rdata_len,int *rparam_len)
02622 {
02623         int function = get_safe_SVAL(param,tpscnt,param,0,0);
02624         char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
02625         char *str2 = skip_string(param,tpscnt,str1);
02626         char *QueueName = skip_string(param,tpscnt,str2);
02627         int errcode = NERR_notsupported;
02628         int snum;
02629         WERROR werr = WERR_OK;
02630 
02631         if (!str1 || !str2 || !QueueName) {
02632                 return False;
02633         }
02634 
02635         /* check it's a supported varient */
02636         if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
02637                 return(False);
02638 
02639         *rparam_len = 4;
02640         *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
02641         if (!*rparam) {
02642                 return False;
02643         }
02644         *rdata_len = 0;
02645 
02646         if (skip_string(param,tpscnt,QueueName) == NULL) {
02647                 return False;
02648         }
02649         snum = print_queue_snum(QueueName);
02650 
02651         if (snum == -1) {
02652                 errcode = NERR_JobNotFound;
02653                 goto out;
02654         }
02655 
02656         switch (function) {
02657         case 74: /* Pause queue */
02658                 if (print_queue_pause(&current_user, snum, &werr)) errcode = NERR_Success;
02659                 break;
02660         case 75: /* Resume queue */
02661                 if (print_queue_resume(&current_user, snum, &werr)) errcode = NERR_Success;
02662                 break;
02663         case 103: /* Purge */
02664                 if (print_queue_purge(&current_user, snum, &werr)) errcode = NERR_Success;
02665                 break;
02666         }
02667 
02668         if (!W_ERROR_IS_OK(werr)) errcode = W_ERROR_V(werr);
02669 
02670  out:
02671         SSVAL(*rparam,0,errcode);
02672         SSVAL(*rparam,2,0);             /* converter word */
02673 
02674         return(True);
02675 }
02676 
02677 /****************************************************************************
02678   set the property of a print job (undocumented?)
02679   ? function = 0xb -> set name of print job
02680   ? function = 0x6 -> move print job up/down
02681   Form: <WWsTP> <WWzWWDDzzzzzzzzzzlz> 
02682   or   <WWsTP> <WB21BB16B10zWWzDDz> 
02683 ****************************************************************************/
02684 
02685 static int check_printjob_info(struct pack_desc* desc,
02686                                int uLevel, char* id)
02687 {
02688         desc->subformat = NULL;
02689         switch( uLevel ) {
02690         case 0: desc->format = "W"; break;
02691         case 1: desc->format = "WB21BB16B10zWWzDDz"; break;
02692         case 2: desc->format = "WWzWWDDzz"; break;
02693         case 3: desc->format = "WWzWWDDzzzzzzzzzzlz"; break;
02694         case 4: desc->format = "WWzWWDDzzzzzDDDDDDD"; break;
02695         default:
02696                 DEBUG(0,("check_printjob_info: invalid level %d\n",
02697                         uLevel ));
02698                 return False;
02699         }
02700         if (id == NULL || strcmp(desc->format,id) != 0) {
02701                 DEBUG(0,("check_printjob_info: invalid format %s\n",
02702                         id ? id : "<NULL>" ));
02703                 return False;
02704         }
02705         return True;
02706 }
02707 
02708 static BOOL api_PrintJobInfo(connection_struct *conn, uint16 vuid,
02709                                 char *param, int tpscnt,
02710                                 char *data, int tdscnt,
02711                                 int mdrcnt,int mprcnt,
02712                                 char **rdata,char **rparam,
02713                                 int *rdata_len,int *rparam_len)
02714 {
02715         struct pack_desc desc;
02716         char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
02717         char *str2 = skip_string(param,tpscnt,str1);
02718         char *p = skip_string(param,tpscnt,str2);
02719         uint32 jobid;
02720         fstring sharename;
02721         int uLevel = get_safe_SVAL(param,tpscnt,p,2,-1);
02722         int function = get_safe_SVAL(param,tpscnt,p,4,-1);
02723         int place, errcode;
02724 
02725         if (!str1 || !str2 || !p) {
02726                 return False;
02727         }
02728         /*
02729          * We use 1 here not 2 as we're checking
02730          * the last byte we want to access is safe.
02731          */
02732         if (!is_offset_safe(param,tpscnt,p,1)) {
02733                 return False;
02734         }
02735         if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
02736                 return False;
02737         *rparam_len = 4;
02738         *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
02739         if (!*rparam) {
02740                 return False;
02741         }
02742 
02743         if (!share_defined(sharename)) {
02744                 DEBUG(0,("api_PrintJobInfo: sharen [%s] not defined\n",
02745                          sharename));
02746                 return False;
02747         }
02748   
02749         *rdata_len = 0;
02750         
02751         /* check it's a supported varient */
02752         if ((strcmp(str1,"WWsTP")) || 
02753             (!check_printjob_info(&desc,uLevel,str2)))
02754                 return(False);
02755 
02756         if (!print_job_exists(sharename, jobid)) {
02757                 errcode=NERR_JobNotFound;
02758                 goto out;
02759         }
02760 
02761         errcode = NERR_notsupported;
02762 
02763         switch (function) {
02764         case 0x6:
02765                 /* change job place in the queue, 
02766                    data gives the new place */
02767                 place = SVAL(data,0);
02768                 if (print_job_set_place(sharename, jobid, place)) {
02769                         errcode=NERR_Success;
02770                 }
02771                 break;
02772 
02773         case 0xb:   
02774                 /* change print job name, data gives the name */
02775                 if (print_job_set_name(sharename, jobid, data)) {
02776                         errcode=NERR_Success;
02777                 }
02778                 break;
02779 
02780         default:
02781                 return False;
02782         }
02783 
02784  out:
02785         SSVALS(*rparam,0,errcode);
02786         SSVAL(*rparam,2,0);             /* converter word */
02787         
02788         return(True);
02789 }
02790 
02791 
02792 /****************************************************************************
02793  Get info about the server.
02794 ****************************************************************************/
02795 
02796 static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid,
02797                                 char *param, int tpscnt,
02798                                 char *data, int tdscnt,
02799                                 int mdrcnt,int mprcnt,
02800                                 char **rdata,char **rparam,
02801                                 int *rdata_len,int *rparam_len)
02802 {
02803         char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
02804         char *str2 = skip_string(param,tpscnt,str1);
02805         char *p = skip_string(param,tpscnt,str2);
02806         int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
02807         char *p2;
02808         int struct_len;
02809 
02810         if (!str1 || !str2 || !p) {
02811                 return False;
02812         }
02813 
02814         DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
02815 
02816         /* check it's a supported varient */
02817         if (!prefix_ok(str1,"WrLh")) {
02818                 return False;
02819         }
02820 
02821         switch( uLevel ) {
02822                 case 0:
02823                         if (strcmp(str2,"B16") != 0) {
02824                                 return False;
02825                         }
02826                         struct_len = 16;
02827                         break;
02828                 case 1:
02829                         if (strcmp(str2,"B16BBDz") != 0) {
02830                                 return False;
02831                         }
02832                         struct_len = 26;
02833                         break;
02834                 case 2:
02835                         if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")!= 0) {
02836                                 return False;
02837                         }
02838                         struct_len = 134;
02839                         break;
02840                 case 3:
02841                         if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz") != 0) {
02842                                 return False;
02843                         }
02844                         struct_len = 144;
02845                         break;
02846                 case 20:
02847                         if (strcmp(str2,"DN") != 0) {
02848                                 return False;
02849                         }
02850                         struct_len = 6;
02851                         break;
02852                 case 50:
02853                         if (strcmp(str2,"B16BBDzWWzzz") != 0) {
02854                                 return False;
02855                         }
02856                         struct_len = 42;
02857                         break;
02858                 default:
02859                         return False;
02860         }
02861 
02862         *rdata_len = mdrcnt;
02863         *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
02864         if (!*rdata) {
02865                 return False;
02866         }
02867 
02868         p = *rdata;
02869         p2 = p + struct_len;
02870         if (uLevel != 20) {
02871                 srvstr_push(NULL, p,global_myname(),16, 
02872                         STR_ASCII|STR_UPPER|STR_TERMINATE);
02873         }
02874         p += 16;
02875         if (uLevel > 0) {
02876                 struct srv_info_struct *servers=NULL;
02877                 int i,count;
02878                 pstring comment;
02879                 uint32 servertype= lp_default_server_announce();
02880 
02881                 push_ascii(comment,lp_serverstring(), MAX_SERVER_STRING_LENGTH,STR_TERMINATE);
02882 
02883                 if ((count=get_server_info(SV_TYPE_ALL,&servers,lp_workgroup()))>0) {
02884                         for (i=0;i<count;i++) {
02885                                 if (strequal(servers[i].name,global_myname())) {
02886                                         servertype = servers[i].type;
02887                                         push_ascii(comment,servers[i].comment,sizeof(pstring),STR_TERMINATE);
02888                                 }
02889                         }
02890                 }
02891 
02892                 SAFE_FREE(servers);
02893 
02894                 SCVAL(p,0,lp_major_announce_version());
02895                 SCVAL(p,1,lp_minor_announce_version());
02896                 SIVAL(p,2,servertype);
02897 
02898                 if (mdrcnt == struct_len) {
02899                         SIVAL(p,6,0);
02900                 } else {
02901                         SIVAL(p,6,PTR_DIFF(p2,*rdata));
02902                         standard_sub_advanced(lp_servicename(SNUM(conn)), conn->user,
02903                                               conn->connectpath, conn->gid,
02904                                               get_current_username(),
02905                                               current_user_info.domain,
02906                                               comment, sizeof(comment));
02907                         StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
02908                         p2 = skip_string(*rdata,*rdata_len,p2);
02909                         if (!p2) {
02910                                 return False;
02911                         }
02912                 }
02913         }
02914 
02915         if (uLevel > 1) {
02916                 return False;           /* not yet implemented */
02917         }
02918 
02919         *rdata_len = PTR_DIFF(p2,*rdata);
02920 
02921         *rparam_len = 6;
02922         *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
02923         if (!*rparam) {
02924                 return False;
02925         }
02926         SSVAL(*rparam,0,NERR_Success);
02927         SSVAL(*rparam,2,0);             /* converter word */
02928         SSVAL(*rparam,4,*rdata_len);
02929 
02930         return True;
02931 }
02932 
02933 /****************************************************************************
02934  Get info about the server.
02935 ****************************************************************************/
02936 
02937 static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid,
02938                                 char *param, int tpscnt,
02939                                 char *data, int tdscnt,
02940                                 int mdrcnt,int mprcnt,
02941                                 char **rdata,char **rparam,
02942                                 int *rdata_len,int *rparam_len)
02943 {
02944         char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
02945         char *str2 = skip_string(param,tpscnt,str1);
02946         char *p = skip_string(param,tpscnt,str2);
02947         char *p2;
02948         int level = get_safe_SVAL(param,tpscnt,p,0,-1);
02949 
02950         if (!str1 || !str2 || !p) {
02951                 return False;
02952         }
02953 
02954         DEBUG(4,("NetWkstaGetInfo level %d\n",level));
02955 
02956         *rparam_len = 6;
02957         *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
02958         if (!*rparam) {
02959                 return False;
02960         }
02961 
02962         /* check it's a supported varient */
02963         if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz"))) {
02964                 return False;
02965         }
02966 
02967         *rdata_len = mdrcnt + 1024;
02968         *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
02969         if (!*rdata) {
02970                 return False;
02971         }
02972 
02973         SSVAL(*rparam,0,NERR_Success);
02974         SSVAL(*rparam,2,0);             /* converter word */
02975 
02976         p = *rdata;
02977         p2 = get_safe_ptr(*rdata,*rdata_len,p,22);
02978         if (!p2) {
02979                 return False;
02980         }
02981 
02982         SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
02983         pstrcpy(p2,get_local_machine_name());
02984         strupper_m(p2);
02985         p2 = skip_string(*rdata,*rdata_len,p2);
02986         if (!p2) {
02987                 return False;
02988         }
02989         p += 4;
02990 
02991         SIVAL(p,0,PTR_DIFF(p2,*rdata));
02992         pstrcpy(p2,current_user_info.smb_name);
02993         p2 = skip_string(*rdata,*rdata_len,p2);
02994         if (!p2) {
02995                 return False;
02996         }
02997         p += 4;
02998 
02999         SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
03000         pstrcpy(p2,lp_workgroup());
03001         strupper_m(p2);
03002         p2 = skip_string(*rdata,*rdata_len,p2);
03003         if (!p2) {
03004                 return False;
03005         }
03006         p += 4;
03007 
03008         SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
03009         SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
03010         p += 2;
03011 
03012         SIVAL(p,0,PTR_DIFF(p2,*rdata));
03013         pstrcpy(p2,lp_workgroup());     /* don't know.  login domain?? */
03014         p2 = skip_string(*rdata,*rdata_len,p2);
03015         if (!p2) {
03016                 return False;
03017         }
03018         p += 4;
03019 
03020         SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
03021         pstrcpy(p2,"");
03022         p2 = skip_string(*rdata,*rdata_len,p2);
03023         if (!p2) {
03024                 return False;
03025         }
03026         p += 4;
03027 
03028         *rdata_len = PTR_DIFF(p2,*rdata);
03029 
03030         SSVAL(*rparam,4,*rdata_len);
03031 
03032         return True;
03033 }
03034 
03035 /****************************************************************************
03036   get info about a user
03037 
03038     struct user_info_11 {
03039         char                usri11_name[21];  0-20 
03040         char                usri11_pad;       21 
03041         char                *usri11_comment;  22-25 
03042         char            *usri11_usr_comment;  26-29
03043         unsigned short      usri11_priv;      30-31
03044         unsigned long       usri11_auth_flags; 32-35
03045         long                usri11_password_age; 36-39
03046         char                *usri11_homedir; 40-43
03047         char            *usri11_parms; 44-47
03048         long                usri11_last_logon; 48-51
03049         long                usri11_last_logoff; 52-55
03050         unsigned short      usri11_bad_pw_count; 56-57
03051         unsigned short      usri11_num_logons; 58-59
03052         char                *usri11_logon_server; 60-63
03053         unsigned short      usri11_country_code; 64-65
03054         char            *usri11_workstations; 66-69
03055         unsigned long       usri11_max_storage; 70-73
03056         unsigned short      usri11_units_per_week; 74-75
03057         unsigned char       *usri11_logon_hours; 76-79
03058         unsigned short      usri11_code_page; 80-81
03059     };
03060 
03061 where:
03062 
03063   usri11_name specifies the user name for which information is retireved
03064 
03065   usri11_pad aligns the next data structure element to a word boundary
03066 
03067   usri11_comment is a null terminated ASCII comment
03068 
03069   usri11_user_comment is a null terminated ASCII comment about the user
03070 
03071   usri11_priv specifies the level of the privilege assigned to the user.
03072        The possible values are:
03073 
03074 Name             Value  Description
03075 USER_PRIV_GUEST  0      Guest privilege
03076 USER_PRIV_USER   1      User privilege
03077 USER_PRV_ADMIN   2      Administrator privilege
03078 
03079   usri11_auth_flags specifies the account operator privileges. The
03080        possible values are:
03081 
03082 Name            Value   Description
03083 AF_OP_PRINT     0       Print operator
03084 
03085 
03086 Leach, Naik                                        [Page 28]
03087 
03088 
03089 
03090 INTERNET-DRAFT   CIFS Remote Admin Protocol     January 10, 1997
03091 
03092 
03093 AF_OP_COMM      1       Communications operator
03094 AF_OP_SERVER    2       Server operator
03095 AF_OP_ACCOUNTS  3       Accounts operator
03096 
03097 
03098   usri11_password_age specifies how many seconds have elapsed since the
03099        password was last changed.
03100 
03101   usri11_home_dir points to a null terminated ASCII string that contains
03102        the path name of the user's home directory.
03103 
03104   usri11_parms points to a null terminated ASCII string that is set
03105        aside for use by applications.
03106 
03107   usri11_last_logon specifies the time when the user last logged on.
03108        This value is stored as the number of seconds elapsed since
03109        00:00:00, January 1, 1970.
03110 
03111   usri11_last_logoff specifies the time when the user last logged off.
03112        This value is stored as the number of seconds elapsed since
03113        00:00:00, January 1, 1970. A value of 0 means the last logoff
03114        time is unknown.
03115 
03116   usri11_bad_pw_count specifies the number of incorrect passwords
03117        entered since the last successful logon.
03118 
03119   usri11_log1_num_logons specifies the number of times this user has
03120        logged on. A value of -1 means the number of logons is unknown.
03121 
03122   usri11_logon_server points to a null terminated ASCII string that
03123        contains the name of the server to which logon requests are sent.
03124        A null string indicates logon requests should be sent to the
03125        domain controller.
03126 
03127   usri11_country_code specifies the country code for the user's language
03128        of choice.
03129 
03130   usri11_workstations points to a null terminated ASCII string that
03131        contains the names of workstations the user may log on from.
03132        There may be up to 8 workstations, with the names separated by
03133        commas. A null strings indicates there are no restrictions.
03134 
03135   usri11_max_storage specifies the maximum amount of disk space the user
03136        can occupy. A value of 0xffffffff indicates there are no
03137        restrictions.
03138 
03139   usri11_units_per_week specifies the equal number of time units into
03140        which a week is divided. This value must be equal to 168.
03141 
03142   usri11_logon_hours points to a 21 byte (168 bits) string that
03143        specifies the time during which the user can log on. Each bit
03144        represents one unique hour in a week. The first bit (bit 0, word
03145        0) is Sunday, 0:00 to 0:59, the second bit (bit 1, word 0) is
03146 
03147 
03148 
03149 Leach, Naik                                        [Page 29]
03150 
03151 
03152 
03153 INTERNET-DRAFT   CIFS Remote Admin Protocol     January 10, 1997
03154 
03155 
03156        Sunday, 1:00 to 1:59 and so on. A null pointer indicates there
03157        are no restrictions.
03158 
03159   usri11_code_page specifies the code page for the user's language of
03160        choice
03161 
03162 All of the pointers in this data structure need to be treated
03163 specially. The  pointer is a 32 bit pointer. The higher 16 bits need
03164 to be ignored. The converter word returned in the parameters section
03165 needs to be subtracted from the lower 16 bits to calculate an offset
03166 into the return buffer where this ASCII string resides.
03167 
03168 There is no auxiliary data in the response.
03169 
03170   ****************************************************************************/
03171 
03172 #define usri11_name           0 
03173 #define usri11_pad            21
03174 #define usri11_comment        22
03175 #define usri11_usr_comment    26
03176 #define usri11_full_name      30
03177 #define usri11_priv           34
03178 #define usri11_auth_flags     36
03179 #define usri11_password_age   40
03180 #define usri11_homedir        44
03181 #define usri11_parms          48
03182 #define usri11_last_logon     52
03183 #define usri11_last_logoff    56
03184 #define usri11_bad_pw_count   60
03185 #define usri11_num_logons     62
03186 #define usri11_logon_server   64
03187 #define usri11_country_code   68
03188 #define usri11_workstations   70
03189 #define usri11_max_storage    74
03190 #define usri11_units_per_week 78
03191 #define usri11_logon_hours    80
03192 #define usri11_code_page      84
03193 #define usri11_end            86
03194 
03195 #define USER_PRIV_GUEST 0
03196 #define USER_PRIV_USER 1
03197 #define USER_PRIV_ADMIN 2
03198 
03199 #define AF_OP_PRINT     0 
03200 #define AF_OP_COMM      1
03201 #define AF_OP_SERVER    2
03202 #define AF_OP_ACCOUNTS  3
03203 
03204 
03205 static BOOL api_RNetUserGetInfo(connection_struct *conn, uint16 vuid,
03206                                 char *param, int tpscnt,
03207                                 char *data, int tdscnt,
03208                                 int mdrcnt,int mprcnt,
03209                                 char **rdata,char **rparam,
03210                                 int *rdata_len,int *rparam_len)
03211 {
03212         char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
03213         char *str2 = skip_string(param,tpscnt,str1);
03214         char *UserName = skip_string(param,tpscnt,str2);
03215         char *p = skip_string(param,tpscnt,UserName);
03216         int uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
03217         char *p2;
03218         const char *level_string;
03219 
03220         /* get NIS home of a previously validated user - simeon */
03221         /* With share level security vuid will always be zero.
03222            Don't depend on vuser being non-null !!. JRA */
03223         user_struct *vuser = get_valid_user_struct(vuid);
03224         if(vuser != NULL) {
03225                 DEBUG(3,("  Username of UID %d is %s\n", (int)vuser->uid, 
03226                         vuser->user.unix_name));
03227         }
03228 
03229         if (!str1 || !str2 || !UserName || !p) {
03230                 return False;
03231         }
03232 
03233         *rparam_len = 6;
03234         *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
03235         if (!*rparam) {
03236                 return False;
03237         }
03238 
03239         DEBUG(4,("RNetUserGetInfo level=%d\n", uLevel));
03240   
03241         /* check it's a supported variant */
03242         if (strcmp(str1,"zWrLh") != 0) {
03243                 return False;
03244         }
03245         switch( uLevel ) {
03246                 case 0: level_string = "B21"; break;
03247                 case 1: level_string = "B21BB16DWzzWz"; break;
03248                 case 2: level_string = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
03249                 case 10: level_string = "B21Bzzz"; break;
03250                 case 11: level_string = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
03251                 default: return False;
03252         }
03253 
03254         if (strcmp(level_string,str2) != 0) {
03255                 return False;
03256         }
03257 
03258         *rdata_len = mdrcnt + 1024;
03259         *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
03260         if (!*rdata) {
03261                 return False;
03262         }
03263 
03264         SSVAL(*rparam,0,NERR_Success);
03265         SSVAL(*rparam,2,0);             /* converter word */
03266 
03267         p = *rdata;
03268         p2 = get_safe_ptr(*rdata,*rdata_len,p,usri11_end);
03269         if (!p2) {
03270                 return False;
03271         }
03272 
03273         memset(p,0,21); 
03274         fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
03275 
03276         if (uLevel > 0) {
03277                 SCVAL(p,usri11_pad,0); /* padding - 1 byte */
03278                 *p2 = 0;
03279         }
03280 
03281         if (uLevel >= 10) {
03282                 SIVAL(p,usri11_comment,PTR_DIFF(p2,p)); /* comment */
03283                 pstrcpy(p2,"Comment");
03284                 p2 = skip_string(*rdata,*rdata_len,p2);
03285                 if (!p2) {
03286                         return False;
03287                 }
03288 
03289                 SIVAL(p,usri11_usr_comment,PTR_DIFF(p2,p)); /* user_comment */
03290                 pstrcpy(p2,"UserComment");
03291                 p2 = skip_string(*rdata,*rdata_len,p2);
03292                 if (!p2) {
03293                         return False;
03294                 }
03295 
03296                 /* EEK! the cifsrap.txt doesn't have this in!!!! */
03297                 SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
03298                 pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName));
03299                 p2 = skip_string(*rdata,*rdata_len,p2);
03300                 if (!p2) {
03301                         return False;
03302                 }
03303         }
03304 
03305         if (uLevel == 11) {
03306                 /* modelled after NTAS 3.51 reply */
03307                 SSVAL(p,usri11_priv,conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER); 
03308                 SIVAL(p,usri11_auth_flags,AF_OP_PRINT);         /* auth flags */
03309                 SIVALS(p,usri11_password_age,-1);               /* password age */
03310                 SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
03311                 pstrcpy(p2, vuser && vuser->homedir ? vuser->homedir : "");
03312                 p2 = skip_string(*rdata,*rdata_len,p2);
03313                 if (!p2) {
03314                         return False;
03315                 }
03316                 SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
03317                 pstrcpy(p2,"");
03318                 p2 = skip_string(*rdata,*rdata_len,p2);
03319                 if (!p2) {
03320                         return False;
03321                 }
03322                 SIVAL(p,usri11_last_logon,0);           /* last logon */
03323                 SIVAL(p,usri11_last_logoff,0);          /* last logoff */
03324                 SSVALS(p,usri11_bad_pw_count,-1);       /* bad pw counts */
03325                 SSVALS(p,usri11_num_logons,-1);         /* num logons */
03326                 SIVAL(p,usri11_logon_server,PTR_DIFF(p2,p)); /* logon server */
03327                 pstrcpy(p2,"\\\\*");
03328                 p2 = skip_string(*rdata,*rdata_len,p2);
03329                 if (!p2) {
03330                         return False;
03331                 }
03332                 SSVAL(p,usri11_country_code,0);         /* country code */
03333 
03334                 SIVAL(p,usri11_workstations,PTR_DIFF(p2,p)); /* workstations */
03335                 pstrcpy(p2,"");
03336                 p2 = skip_string(*rdata,*rdata_len,p2);
03337                 if (!p2) {
03338                         return False;
03339                 }
03340 
03341                 SIVALS(p,usri11_max_storage,-1);                /* max storage */
03342                 SSVAL(p,usri11_units_per_week,168);             /* units per week */
03343                 SIVAL(p,usri11_logon_hours,PTR_DIFF(p2,p)); /* logon hours */
03344 
03345                 /* a simple way to get logon hours at all times. */
03346                 memset(p2,0xff,21);
03347                 SCVAL(p2,21,0);           /* fix zero termination */
03348                 p2 = skip_string(*rdata,*rdata_len,p2);
03349                 if (!p2) {
03350                         return False;
03351                 }
03352 
03353                 SSVAL(p,usri11_code_page,0);            /* code page */
03354         }
03355 
03356         if (uLevel == 1 || uLevel == 2) {
03357                 memset(p+22,' ',16);    /* password */
03358                 SIVALS(p,38,-1);                /* password age */
03359                 SSVAL(p,42,
03360                 conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
03361                 SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
03362                 pstrcpy(p2, vuser && vuser->homedir ? vuser->homedir : "");
03363                 p2 = skip_string(*rdata,*rdata_len,p2);
03364                 if (!p2) {
03365                         return False;
03366                 }
03367                 SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
03368                 *p2++ = 0;
03369                 SSVAL(p,52,0);          /* flags */
03370                 SIVAL(p,54,PTR_DIFF(p2,*rdata));                /* script_path */
03371                 pstrcpy(p2,vuser && vuser->logon_script ? vuser->logon_script : "");
03372                 p2 = skip_string(*rdata,*rdata_len,p2);
03373                 if (!p2) {
03374                         return False;
03375                 }
03376                 if (uLevel == 2) {
03377                         SIVAL(p,60,0);          /* auth_flags */
03378                         SIVAL(p,64,PTR_DIFF(p2,*rdata)); /* full_name */
03379                         pstrcpy(p2,((vuser != NULL) ? vuser->user.full_name : UserName));
03380                         p2 = skip_string(*rdata,*rdata_len,p2);
03381                         if (!p2) {
03382                                 return False;
03383                         }
03384                         SIVAL(p,68,0);          /* urs_comment */
03385                         SIVAL(p,72,PTR_DIFF(p2,*rdata)); /* parms */
03386                         pstrcpy(p2,"");
03387                         p2 = skip_string(*rdata,*rdata_len,p2);
03388                         if (!p2) {
03389                                 return False;
03390                         }
03391                         SIVAL(p,76,0);          /* workstations */
03392                         SIVAL(p,80,0);          /* last_logon */
03393                         SIVAL(p,84,0);          /* last_logoff */
03394                         SIVALS(p,88,-1);                /* acct_expires */
03395                         SIVALS(p,92,-1);                /* max_storage */
03396                         SSVAL(p,96,168);        /* units_per_week */
03397                         SIVAL(p,98,PTR_DIFF(p2,*rdata)); /* logon_hours */
03398                         memset(p2,-1,21);
03399                         p2 += 21;
03400                         SSVALS(p,102,-1);       /* bad_pw_count */
03401                         SSVALS(p,104,-1);       /* num_logons */
03402                         SIVAL(p,106,PTR_DIFF(p2,*rdata)); /* logon_server */
03403                         {
03404                                 pstring tmp;
03405                                 pstrcpy(tmp, "\\\\%L");
03406                                 standard_sub_basic("", "", tmp, sizeof(tmp));
03407                                 pstrcpy(p2, tmp);
03408                         }
03409                         p2 = skip_string(*rdata,*rdata_len,p2);
03410                         if (!p2) {
03411                                 return False;
03412                         }
03413                         SSVAL(p,110,49);        /* country_code */
03414                         SSVAL(p,112,860);       /* code page */
03415                 }
03416         }
03417 
03418         *rdata_len = PTR_DIFF(p2,*rdata);
03419 
03420         SSVAL(*rparam,4,*rdata_len);    /* is this right?? */
03421 
03422         return(True);
03423 }
03424 
03425 static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid,
03426                                 char *param, int tpscnt,
03427                                 char *data, int tdscnt,
03428                                 int mdrcnt,int mprcnt,
03429                                 char **rdata,char **rparam,
03430                                 int *rdata_len,int *rparam_len)
03431 {
03432         char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
03433         char *str2 = skip_string(param,tpscnt,str1);
03434         char *p = skip_string(param,tpscnt,str2);
03435         int uLevel;
03436         struct pack_desc desc;
03437         char* name;
03438                 /* With share level security vuid will always be zero.
03439                    Don't depend on vuser being non-null !!. JRA */
03440         user_struct *vuser = get_valid_user_struct(vuid);
03441 
03442         if (!str1 || !str2 || !p) {
03443                 return False;
03444         }
03445 
03446         if(vuser != NULL) {
03447                 DEBUG(3,("  Username of UID %d is %s\n", (int)vuser->uid, 
03448                         vuser->user.unix_name));
03449         }
03450 
03451         uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
03452         name = get_safe_str_ptr(param,tpscnt,p,2);
03453         if (!name) {
03454                 return False;
03455         }
03456 
03457         memset((char *)&desc,'\0',sizeof(desc));
03458 
03459         DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
03460 
03461         /* check it's a supported varient */
03462         if (strcmp(str1,"OOWb54WrLh") != 0) {
03463                 return False;
03464         }
03465         if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) {
03466                 return False;
03467         }
03468         if (mdrcnt > 0) {
03469                 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
03470                 if (!*rdata) {
03471                         return False;
03472                 }
03473         }
03474 
03475         desc.base = *rdata;
03476         desc.buflen = mdrcnt;
03477         desc.subformat = NULL;
03478         desc.format = str2;
03479   
03480         if (init_package(&desc,1,0)) {
03481                 PACKI(&desc,"W",0);             /* code */
03482                 PACKS(&desc,"B21",name);        /* eff. name */
03483                 PACKS(&desc,"B","");            /* pad */
03484                 PACKI(&desc,"W", conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
03485                 PACKI(&desc,"D",0);             /* auth flags XXX */
03486                 PACKI(&desc,"W",0);             /* num logons */
03487                 PACKI(&desc,"W",0);             /* bad pw count */
03488                 PACKI(&desc,"D",0);             /* last logon */
03489                 PACKI(&desc,"D",-1);            /* last logoff */
03490                 PACKI(&desc,"D",-1);            /* logoff time */
03491                 PACKI(&desc,"D",-1);            /* kickoff time */
03492                 PACKI(&desc,"D",0);             /* password age */
03493                 PACKI(&desc,"D",0);             /* password can change */
03494                 PACKI(&desc,"D",-1);            /* password must change */
03495 
03496                 {
03497                         fstring mypath;
03498                         fstrcpy(mypath,"\\\\");
03499                         fstrcat(mypath,get_local_machine_name());
03500                         strupper_m(mypath);
03501                         PACKS(&desc,"z",mypath); /* computer */
03502                 }
03503 
03504                 PACKS(&desc,"z",lp_workgroup());/* domain */
03505                 PACKS(&desc,"z", vuser && vuser->logon_script ? vuser->logon_script :""); /* script path */
03506                 PACKI(&desc,"D",0x00000000);            /* reserved */
03507         }
03508 
03509         *rdata_len = desc.usedlen;
03510         *rparam_len = 6;
03511         *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
03512         if (!*rparam) {
03513                 return False;
03514         }
03515         SSVALS(*rparam,0,desc.errcode);
03516         SSVAL(*rparam,2,0);
03517         SSVAL(*rparam,4,desc.neededlen);
03518 
03519         DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
03520 
03521         return True;
03522 }
03523 
03524 /****************************************************************************
03525  api_WAccessGetUserPerms
03526 ****************************************************************************/
03527 
03528 static BOOL api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid,
03529                                 char *param, int tpscnt,
03530                                 char *data, int tdscnt,
03531                                 int mdrcnt,int mprcnt,
03532                                 char **rdata,char **rparam,
03533                                 int *rdata_len,int *rparam_len)
03534 {
03535         char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
03536         char *str2 = skip_string(param,tpscnt,str1);
03537         char *user = skip_string(param,tpscnt,str2);
03538         char *resource = skip_string(param,tpscnt,user);
03539 
03540         if (!str1 || !str2 || !user || !resource) {
03541                 return False;
03542         }
03543 
03544         if (skip_string(param,tpscnt,resource) == NULL) {
03545                 return False;
03546         }
03547         DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
03548 
03549         /* check it's a supported varient */
03550         if (strcmp(str1,"zzh") != 0) {
03551                 return False;
03552         }
03553         if (strcmp(str2,"") != 0) {
03554                 return False;
03555         }
03556 
03557         *rparam_len = 6;
03558         *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
03559         if (!*rparam) {
03560                 return False;
03561         }
03562         SSVALS(*rparam,0,0);            /* errorcode */
03563         SSVAL(*rparam,2,0);             /* converter word */
03564         SSVAL(*rparam,4,0x7f);  /* permission flags */
03565 
03566         return True;
03567 }
03568 
03569 /****************************************************************************
03570   api_WPrintJobEnumerate
03571   ****************************************************************************/
03572 
03573 static BOOL api_WPrintJobGetInfo(connection_struct *conn, uint16 vuid,
03574                                 char *param, int tpscnt,
03575                                 char *data, int tdscnt,
03576                                 int mdrcnt,int mprcnt,
03577                                 char **rdata,char **rparam,
03578                                 int *rdata_len,int *rparam_len)
03579 {
03580         char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
03581         char *str2 = skip_string(param,tpscnt,str1);
03582         char *p = skip_string(param,tpscnt,str2);
03583         int uLevel;
03584         int count;
03585         int i;
03586         int snum;
03587         fstring sharename;
03588         uint32 jobid;
03589         struct pack_desc desc;
03590         print_queue_struct *queue=NULL;
03591         print_status_struct status;
03592         char *tmpdata=NULL;
03593 
03594         if (!str1 || !str2 || !p) {
03595                 return False;
03596         }
03597 
03598         uLevel = get_safe_SVAL(param,tpscnt,p,2,-1);
03599 
03600         memset((char *)&desc,'\0',sizeof(desc));
03601         memset((char *)&status,'\0',sizeof(status));
03602 
03603         DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
03604 
03605         /* check it's a supported varient */
03606         if (strcmp(str1,"WWrLh") != 0) {
03607                 return False;
03608         }
03609         if (!check_printjob_info(&desc,uLevel,str2)) {
03610                 return False;
03611         }
03612 
03613         if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid)) {
03614                 return False;
03615         }
03616 
03617         snum = lp_servicenumber( sharename);
03618         if (snum < 0 || !VALID_SNUM(snum)) {
03619                 return(False);
03620         }
03621 
03622         count = print_queue_status(snum,&queue,&status);
03623         for (i = 0; i < count; i++) {
03624                 if (queue[i].job == jobid) {
03625                         break;
03626                 }
03627         }
03628 
03629         if (mdrcnt > 0) {
03630                 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
03631                 if (!*rdata) {
03632                         return False;
03633                 }
03634                 desc.base = *rdata;
03635                 desc.buflen = mdrcnt;
03636         } else {
03637                 /*
03638                  * Don't return data but need to get correct length
03639                  *  init_package will return wrong size if buflen=0
03640                  */
03641                 desc.buflen = getlen(desc.format);
03642                 desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen );
03643         }
03644 
03645         if (init_package(&desc,1,0)) {
03646                 if (i < count) {
03647                         fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
03648                         *rdata_len = desc.usedlen;
03649                 } else {
03650                         desc.errcode = NERR_JobNotFound;
03651                         *rdata_len = 0;
03652                 }
03653         }
03654 
03655         *rparam_len = 6;
03656         *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
03657         if (!*rparam) {
03658                 return False;
03659         }
03660         SSVALS(*rparam,0,desc.errcode);
03661         SSVAL(*rparam,2,0);
03662         SSVAL(*rparam,4,desc.neededlen);
03663 
03664         SAFE_FREE(queue);
03665         SAFE_FREE(tmpdata);
03666 
03667         DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
03668 
03669         return True;
03670 }
03671 
03672 static BOOL api_WPrintJobEnumerate(connection_struct *conn, uint16 vuid,
03673                                 char *param, int tpscnt,
03674                                 char *data, int tdscnt,
03675                                 int mdrcnt,int mprcnt,
03676                                 char **rdata,char **rparam,
03677                                 int *rdata_len,int *rparam_len)
03678 {
03679         char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
03680         char *str2 = skip_string(param,tpscnt,str1);
03681         char *p = skip_string(param,tpscnt,str2);
03682         char *name = p;
03683         int uLevel;
03684         int count;
03685         int i, succnt=0;
03686         int snum;
03687         struct pack_desc desc;
03688         print_queue_struct *queue=NULL;
03689         print_status_struct status;
03690 
03691         if (!str1 || !str2 || !p) {
03692                 return False;
03693         }
03694 
03695         memset((char *)&desc,'\0',sizeof(desc));
03696         memset((char *)&status,'\0',sizeof(status));
03697 
03698         p = skip_string(param,tpscnt,p);
03699         if (!p) {
03700                 return False;
03701         }
03702         uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
03703 
03704         DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
03705 
03706         /* check it's a supported variant */
03707         if (strcmp(str1,"zWrLeh") != 0) {
03708                 return False;
03709         }
03710     
03711         if (uLevel > 2) {
03712                 return False;   /* defined only for uLevel 0,1,2 */
03713         }
03714     
03715         if (!check_printjob_info(&desc,uLevel,str2)) { 
03716                 return False;
03717         }
03718 
03719         snum = find_service(name);
03720         if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) ) {
03721                 return False;
03722         }
03723 
03724         count = print_queue_status(snum,&queue,&status);
03725         if (mdrcnt > 0) {
03726                 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
03727                 if (!*rdata) {
03728                         return False;
03729                 }
03730         }
03731         desc.base = *rdata;
03732         desc.buflen = mdrcnt;
03733 
03734         if (init_package(&desc,count,0)) {
03735                 succnt = 0;
03736                 for (i = 0; i < count; i++) {
03737                         fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
03738                         if (desc.errcode == NERR_Success) {
03739                                 succnt = i+1;
03740                         }
03741                 }
03742         }
03743 
03744         *rdata_len = desc.usedlen;
03745 
03746         *rparam_len = 8;
03747         *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
03748         if (!*rparam) {
03749                 return False;
03750         }
03751         SSVALS(*rparam,0,desc.errcode);
03752         SSVAL(*rparam,2,0);
03753         SSVAL(*rparam,4,succnt);
03754         SSVAL(*rparam,6,count);
03755 
03756         SAFE_FREE(queue);
03757 
03758         DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
03759 
03760         return True;
03761 }
03762 
03763 static int check_printdest_info(struct pack_desc* desc,
03764                                 int uLevel, char* id)
03765 {
03766         desc->subformat = NULL;
03767         switch( uLevel ) {
03768                 case 0:
03769                         desc->format = "B9";
03770                         break;
03771                 case 1:
03772                         desc->format = "B9B21WWzW";
03773                         break;
03774                 case 2:
03775                         desc->format = "z";
03776                         break;
03777                 case 3:
03778                         desc->format = "zzzWWzzzWW";
03779                         break;
03780                 default:
03781                         DEBUG(0,("check_printdest_info: invalid level %d\n",
03782                                 uLevel));
03783                         return False;
03784         }
03785         if (id == NULL || strcmp(desc->format,id) != 0) {
03786                 DEBUG(0,("check_printdest_info: invalid string %s\n", 
03787                         id ? id : "<NULL>" ));
03788                 return False;
03789         }
03790         return True;
03791 }
03792 
03793 static void fill_printdest_info(connection_struct *conn, int snum, int uLevel,
03794                                 struct pack_desc* desc)
03795 {
03796         char buf[100];
03797 
03798         strncpy(buf,SERVICE(snum),sizeof(buf)-1);
03799         buf[sizeof(buf)-1] = 0;
03800         strupper_m(buf);
03801 
03802         if (uLevel <= 1) {
03803                 PACKS(desc,"B9",buf);   /* szName */
03804                 if (uLevel == 1) {
03805                         PACKS(desc,"B21","");   /* szUserName */
03806                         PACKI(desc,"W",0);              /* uJobId */
03807                         PACKI(desc,"W",0);              /* fsStatus */
03808                         PACKS(desc,"z","");     /* pszStatus */
03809                         PACKI(desc,"W",0);              /* time */
03810                 }
03811         }
03812 
03813         if (uLevel == 2 || uLevel == 3) {
03814                 PACKS(desc,"z",buf);            /* pszPrinterName */
03815                 if (uLevel == 3) {
03816                         PACKS(desc,"z","");     /* pszUserName */
03817                         PACKS(desc,"z","");     /* pszLogAddr */
03818                         PACKI(desc,"W",0);              /* uJobId */
03819                         PACKI(desc,"W",0);              /* fsStatus */
03820                         PACKS(desc,"z","");     /* pszStatus */
03821                         PACKS(desc,"z","");     /* pszComment */
03822                         PACKS(desc,"z","NULL"); /* pszDrivers */
03823                         PACKI(desc,"W",0);              /* time */
03824                         PACKI(desc,"W",0);              /* pad1 */
03825                 }
03826         }
03827 }
03828 
03829 static BOOL api_WPrintDestGetInfo(connection_struct *conn, uint16 vuid,
03830                                 char *param, int tpscnt,
03831                                 char *data, int tdscnt,
03832                                 int mdrcnt,int mprcnt,
03833                                 char **rdata,char **rparam,
03834                                 int *rdata_len,int *rparam_len)
03835 {
03836         char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
03837         char *str2 = skip_string(param,tpscnt,str1);
03838         char *p = skip_string(param,tpscnt,str2);
03839         char* PrinterName = p;
03840         int uLevel;
03841         struct pack_desc desc;
03842         int snum;
03843         char *tmpdata=NULL;
03844 
03845         if (!str1 || !str2 || !p) {
03846                 return False;
03847         }
03848 
03849         memset((char *)&desc,'\0',sizeof(desc));
03850 
03851         p = skip_string(param,tpscnt,p);
03852         if (!p) {
03853                 return False;
03854         }
03855         uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
03856 
03857         DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
03858 
03859         /* check it's a supported varient */
03860         if (strcmp(str1,"zWrLh") != 0) {
03861                 return False;
03862         }
03863         if (!check_printdest_info(&desc,uLevel,str2)) {
03864                 return False;
03865         }
03866 
03867         snum = find_service(PrinterName);
03868         if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) ) {
03869                 *rdata_len = 0;
03870                 desc.errcode = NERR_DestNotFound;
03871                 desc.neededlen = 0;
03872         } else {
03873                 if (mdrcnt > 0) {
03874                         *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
03875                         if (!*rdata) {
03876                                 return False;
03877                         }
03878                         desc.base = *rdata;
03879                         desc.buflen = mdrcnt;
03880                 } else {
03881                         /*
03882                          * Don't return data but need to get correct length
03883                          * init_package will return wrong size if buflen=0
03884                          */
03885                         desc.buflen = getlen(desc.format);
03886                         desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen );
03887                 }
03888                 if (init_package(&desc,1,0)) {
03889                         fill_printdest_info(conn,snum,uLevel,&desc);
03890                 }
03891                 *rdata_len = desc.usedlen;
03892         }
03893 
03894         *rparam_len = 6;
03895         *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
03896         if (!*rparam) {
03897                 return False;
03898         }
03899         SSVALS(*rparam,0,desc.errcode);
03900         SSVAL(*rparam,2,0);
03901         SSVAL(*rparam,4,desc.neededlen);
03902 
03903         DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
03904         SAFE_FREE(tmpdata);
03905 
03906         return True;
03907 }
03908 
03909 static BOOL api_WPrintDestEnum(connection_struct *conn, uint16 vuid,
03910                                 char *param, int tpscnt,
03911                                 char *data, int tdscnt,
03912                                 int mdrcnt,int mprcnt,
03913                                 char **rdata,char **rparam,
03914                                 int *rdata_len,int *rparam_len)
03915 {
03916         char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
03917         char *str2 = skip_string(param,tpscnt,str1);
03918         char *p = skip_string(param,tpscnt,str2);
03919         int uLevel;
03920         int queuecnt;
03921         int i, n, succnt=0;
03922         struct pack_desc desc;
03923         int services = lp_numservices();
03924 
03925         if (!str1 || !str2 || !p) {
03926                 return False;
03927         }
03928 
03929         memset((char *)&desc,'\0',sizeof(desc));
03930 
03931         uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
03932 
03933         DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
03934 
03935         /* check it's a supported varient */
03936         if (strcmp(str1,"WrLeh") != 0) {
03937                 return False;
03938         }
03939         if (!check_printdest_info(&desc,uLevel,str2)) {
03940                 return False;
03941         }
03942 
03943         queuecnt = 0;
03944         for (i = 0; i < services; i++) {
03945                 if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
03946                         queuecnt++;
03947                 }
03948         }
03949 
03950         if (mdrcnt > 0) {
03951                 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
03952                 if (!*rdata) {
03953                         return False;
03954                 }
03955         }
03956 
03957         desc.base = *rdata;
03958         desc.buflen = mdrcnt;
03959         if (init_package(&desc,queuecnt,0)) {    
03960                 succnt = 0;
03961                 n = 0;
03962                 for (i = 0; i < services; i++) {
03963                         if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
03964                                 fill_printdest_info(conn,i,uLevel,&desc);
03965                                 n++;
03966                                 if (desc.errcode == NERR_Success) {
03967                                         succnt = n;
03968                                 }
03969                         }
03970                 }
03971         }
03972 
03973         *rdata_len = desc.usedlen;
03974 
03975         *rparam_len = 8;
03976         *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
03977         if (!*rparam) {
03978                 return False;
03979         }
03980         SSVALS(*rparam,0,desc.errcode);
03981         SSVAL(*rparam,2,0);
03982         SSVAL(*rparam,4,succnt);
03983         SSVAL(*rparam,6,queuecnt);
03984 
03985         DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
03986 
03987         return True;
03988 }
03989 
03990 static BOOL api_WPrintDriverEnum(connection_struct *conn, uint16 vuid,
03991                                 char *param, int tpscnt,
03992                                 char *data, int tdscnt,
03993                                 int mdrcnt,int mprcnt,
03994                                 char **rdata,char **rparam,
03995                                 int *rdata_len,int *rparam_len)
03996 {
03997         char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
03998         char *str2 = skip_string(param,tpscnt,str1);
03999         char *p = skip_string(param,tpscnt,str2);
04000         int uLevel;
04001         int succnt;
04002         struct pack_desc desc;
04003 
04004         if (!str1 || !str2 || !p) {
04005                 return False;
04006         }
04007 
04008         memset((char *)&desc,'\0',sizeof(desc));
04009 
04010         uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
04011 
04012         DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
04013 
04014         /* check it's a supported varient */
04015         if (strcmp(str1,"WrLeh") != 0) {
04016                 return False;
04017         }
04018         if (uLevel != 0 || strcmp(str2,"B41") != 0) {
04019                 return False;
04020         }
04021 
04022         if (mdrcnt > 0) {
04023                 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
04024                 if (!*rdata) {
04025                         return False;
04026                 }
04027         }
04028         desc.base = *rdata;
04029         desc.buflen = mdrcnt;
04030         if (init_package(&desc,1,0)) {
04031                 PACKS(&desc,"B41","NULL");
04032         }
04033 
04034         succnt = (desc.errcode == NERR_Success ? 1 : 0);
04035 
04036         *rdata_len = desc.usedlen;
04037 
04038         *rparam_len = 8;
04039         *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
04040         if (!*rparam) {
04041                 return False;
04042         }
04043         SSVALS(*rparam,0,desc.errcode);
04044         SSVAL(*rparam,2,0);
04045         SSVAL(*rparam,4,succnt);
04046         SSVAL(*rparam,6,1);
04047 
04048         DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
04049 
04050         return True;
04051 }
04052 
04053 static BOOL api_WPrintQProcEnum(connection_struct *conn, uint16 vuid,
04054                                 char *param, int tpscnt,
04055                                 char *data, int tdscnt,
04056                                 int mdrcnt,int mprcnt,
04057                                 char **rdata,char **rparam,
04058                                 int *rdata_len,int *rparam_len)
04059 {
04060         char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
04061         char *str2 = skip_string(param,tpscnt,str1);
04062         char *p = skip_string(param,tpscnt,str2);
04063         int uLevel;
04064         int succnt;
04065         struct pack_desc desc;
04066 
04067         if (!str1 || !str2 || !p) {
04068                 return False;
04069         }
04070         memset((char *)&desc,'\0',sizeof(desc));
04071 
04072         uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
04073 
04074         DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
04075 
04076         /* check it's a supported varient */
04077         if (strcmp(str1,"WrLeh") != 0) {
04078                 return False;
04079         }
04080         if (uLevel != 0 || strcmp(str2,"B13") != 0) {
04081                 return False;
04082         }
04083 
04084         if (mdrcnt > 0) {
04085                 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
04086                 if (!*rdata) {
04087                         return False;
04088                 }
04089         }
04090         desc.base = *rdata;
04091         desc.buflen = mdrcnt;
04092         desc.format = str2;
04093         if (init_package(&desc,1,0)) {
04094                 PACKS(&desc,"B13","lpd");
04095         }
04096 
04097         succnt = (desc.errcode == NERR_Success ? 1 : 0);
04098 
04099         *rdata_len = desc.usedlen;
04100 
04101         *rparam_len = 8;
04102         *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
04103         if (!*rparam) {
04104                 return False;
04105         }
04106         SSVALS(*rparam,0,desc.errcode);
04107         SSVAL(*rparam,2,0);
04108         SSVAL(*rparam,4,succnt);
04109         SSVAL(*rparam,6,1);
04110 
04111         DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
04112 
04113         return True;
04114 }
04115 
04116 static BOOL api_WPrintPortEnum(connection_struct *conn, uint16 vuid,
04117                                 char *param, int tpscnt,
04118                                 char *data, int tdscnt,
04119                                 int mdrcnt,int mprcnt,
04120                                 char **rdata,char **rparam,
04121                                 int *rdata_len,int *rparam_len)
04122 {
04123         char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
04124         char *str2 = skip_string(param,tpscnt,str1);
04125         char *p = skip_string(param,tpscnt,str2);
04126         int uLevel;
04127         int succnt;
04128         struct pack_desc desc;
04129 
04130         if (!str1 || !str2 || !p) {
04131                 return False;
04132         }
04133 
04134         memset((char *)&desc,'\0',sizeof(desc));
04135 
04136         uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
04137 
04138         DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
04139 
04140         /* check it's a supported varient */
04141         if (strcmp(str1,"WrLeh") != 0) {
04142                 return False;
04143         }
04144         if (uLevel != 0 || strcmp(str2,"B9") != 0) {
04145                 return False;
04146         }
04147 
04148         if (mdrcnt > 0) {
04149                 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
04150                 if (!*rdata) {
04151                         return False;
04152                 }
04153         }
04154         memset((char *)&desc,'\0',sizeof(desc));
04155         desc.base = *rdata;
04156         desc.buflen = mdrcnt;
04157         desc.format = str2;
04158         if (init_package(&desc,1,0)) {
04159                 PACKS(&desc,"B13","lp0");
04160         }
04161 
04162         succnt = (desc.errcode == NERR_Success ? 1 : 0);
04163 
04164         *rdata_len = desc.usedlen;
04165 
04166         *rparam_len = 8;
04167         *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
04168         if (!*rparam) {
04169                 return False;
04170         }
04171         SSVALS(*rparam,0,desc.errcode);
04172         SSVAL(*rparam,2,0);
04173         SSVAL(*rparam,4,succnt);
04174         SSVAL(*rparam,6,1);
04175 
04176         DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
04177 
04178         return True;
04179 }
04180 
04181 /****************************************************************************
04182  List open sessions
04183  ****************************************************************************/
04184 
04185 static BOOL api_RNetSessionEnum(connection_struct *conn, uint16 vuid,
04186                                 char *param, int tpscnt,
04187                                 char *data, int tdscnt,
04188                                 int mdrcnt,int mprcnt,
04189                                 char **rdata,char **rparam,
04190                                 int *rdata_len,int *rparam_len)
04191 
04192 {
04193         char *str1 = get_safe_str_ptr(param,tpscnt,param,2);
04194         char *str2 = skip_string(param,tpscnt,str1);
04195         char *p = skip_string(param,tpscnt,str2);
04196         int uLevel;
04197         struct pack_desc desc;
04198         struct sessionid *session_list = NULL;
04199         int i, num_sessions;
04200 
04201         if (!str1 || !str2 || !p) {
04202                 return False;
04203         }
04204 
04205         memset((char *)&desc,'\0',sizeof(desc));
04206 
04207         uLevel = get_safe_SVAL(param,tpscnt,p,0,-1);
04208 
04209         DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel));
04210         DEBUG(7,("RNetSessionEnum req string=%s\n",str1));
04211         DEBUG(7,("RNetSessionEnum ret string=%s\n",str2));
04212 
04213         /* check it's a supported varient */
04214         if (strcmp(str1,RAP_NetSessionEnum_REQ) != 0) {
04215                 return False;
04216         }
04217         if (uLevel != 2 || strcmp(str2,RAP_SESSION_INFO_L2) != 0) {
04218                 return False;
04219         }
04220 
04221         num_sessions = list_sessions(&session_list);
04222 
04223         if (mdrcnt > 0) {
04224                 *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
04225                 if (!*rdata) {
04226                         SAFE_FREE(session_list);
04227                         return False;
04228                 }
04229         }
04230         memset((char *)&desc,'\0',sizeof(desc));
04231         desc.base = *rdata;
04232         desc.buflen = mdrcnt;
04233         desc.format = str2;
04234         if (!init_package(&desc,num_sessions,0)) {
04235                 SAFE_FREE(session_list);
04236                 return False;
04237         }
04238 
04239         for(i=0; i<num_sessions; i++) {
04240                 PACKS(&desc, "z", session_list[i].remote_machine);
04241                 PACKS(&desc, "z", session_list[i].username);
04242                 PACKI(&desc, "W", 1); /* num conns */
04243                 PACKI(&desc, "W", 0); /* num opens */
04244                 PACKI(&desc, "W", 1); /* num users */
04245                 PACKI(&desc, "D", 0); /* session time */
04246                 PACKI(&desc, "D", 0); /* idle time */
04247                 PACKI(&desc, "D", 0); /* flags */
04248                 PACKS(&desc, "z", "Unknown Client"); /* client type string */
04249         }
04250 
04251         *rdata_len = desc.usedlen;
04252 
04253         *rparam_len = 8;
04254         *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
04255         if (!*rparam) {
04256                 SAFE_FREE(session_list);
04257                 return False;
04258         }
04259         SSVALS(*rparam,0,desc.errcode);
04260         SSVAL(*rparam,2,0); /* converter */
04261         SSVAL(*rparam,4,num_sessions); /* count */
04262 
04263         DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc.errcode));
04264 
04265         SAFE_FREE(session_list);
04266         return True;
04267 }
04268 
04269 
04270 /****************************************************************************
04271  The buffer was too small.
04272  ****************************************************************************/
04273 
04274 static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param, char *data,
04275                          int mdrcnt, int mprcnt,
04276                          char **rdata, char **rparam,
04277                          int *rdata_len, int *rparam_len)
04278 {
04279         *rparam_len = MIN(*rparam_len,mprcnt);
04280         *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
04281         if (!*rparam) {
04282                 return False;
04283         }
04284 
04285         *rdata_len = 0;
04286 
04287         SSVAL(*rparam,0,NERR_BufTooSmall);
04288 
04289         DEBUG(3,("Supplied buffer too small in API command\n"));
04290 
04291         return True;
04292 }
04293 
04294 /****************************************************************************
04295  The request is not supported.
04296  ****************************************************************************/
04297 
04298 static BOOL api_Unsupported(connection_struct *conn, uint16 vuid,
04299                                 char *param, int tpscnt,
04300                                 char *data, int tdscnt,
04301                                 int mdrcnt, int mprcnt,
04302                                 char **rdata, char **rparam,
04303                                 int *rdata_len, int *rparam_len)
04304 {
04305         *rparam_len = 4;
04306         *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
04307         if (!*rparam) {
04308                 return False;
04309         }
04310 
04311         *rdata_len = 0;
04312 
04313         SSVAL(*rparam,0,NERR_notsupported);
04314         SSVAL(*rparam,2,0);             /* converter word */
04315 
04316         DEBUG(3,("Unsupported API command\n"));
04317 
04318         return True;
04319 }
04320 
04321 static const struct {
04322         const char *name;
04323         int id;
04324         BOOL (*fn)(connection_struct *, uint16,
04325                         char *, int,
04326                         char *, int,
04327                         int,int,char **,char **,int *,int *);
04328         BOOL auth_user;         /* Deny anonymous access? */
04329 } api_commands[] = {
04330         {"RNetShareEnum",       RAP_WshareEnum,         api_RNetShareEnum, True},
04331         {"RNetShareGetInfo",    RAP_WshareGetInfo,      api_RNetShareGetInfo},
04332         {"RNetShareAdd",        RAP_WshareAdd,          api_RNetShareAdd},
04333         {"RNetSessionEnum",     RAP_WsessionEnum,       api_RNetSessionEnum, True},
04334         {"RNetServerGetInfo",   RAP_WserverGetInfo,     api_RNetServerGetInfo},
04335         {"RNetGroupEnum",       RAP_WGroupEnum,         api_RNetGroupEnum, True},
04336         {"RNetGroupGetUsers", RAP_WGroupGetUsers,       api_RNetGroupGetUsers, True},
04337         {"RNetUserEnum",        RAP_WUserEnum,          api_RNetUserEnum, True},
04338         {"RNetUserGetInfo",     RAP_WUserGetInfo,       api_RNetUserGetInfo},
04339         {"NetUserGetGroups",    RAP_WUserGetGroups,     api_NetUserGetGroups},
04340         {"NetWkstaGetInfo",     RAP_WWkstaGetInfo,      api_NetWkstaGetInfo},
04341         {"DosPrintQEnum",       RAP_WPrintQEnum,        api_DosPrintQEnum, True},
04342         {"DosPrintQGetInfo",    RAP_WPrintQGetInfo,     api_DosPrintQGetInfo},
04343         {"WPrintQueuePause",  RAP_WPrintQPause, api_WPrintQueueCtrl},
04344         {"WPrintQueueResume", RAP_WPrintQContinue,      api_WPrintQueueCtrl},
04345         {"WPrintJobEnumerate",RAP_WPrintJobEnum,        api_WPrintJobEnumerate},
04346         {"WPrintJobGetInfo",    RAP_WPrintJobGetInfo,   api_WPrintJobGetInfo},
04347         {"RDosPrintJobDel",     RAP_WPrintJobDel,       api_RDosPrintJobDel},
04348         {"RDosPrintJobPause",   RAP_WPrintJobPause,     api_RDosPrintJobDel},
04349         {"RDosPrintJobResume",RAP_WPrintJobContinue,    api_RDosPrintJobDel},
04350         {"WPrintDestEnum",      RAP_WPrintDestEnum,     api_WPrintDestEnum},
04351         {"WPrintDestGetInfo",   RAP_WPrintDestGetInfo,  api_WPrintDestGetInfo},
04352         {"NetRemoteTOD",        RAP_NetRemoteTOD,       api_NetRemoteTOD},
04353         {"WPrintQueuePurge",    RAP_WPrintQPurge,       api_WPrintQueueCtrl},
04354         {"NetServerEnum",       RAP_NetServerEnum2,     api_RNetServerEnum}, /* anon OK */
04355         {"WAccessGetUserPerms",RAP_WAccessGetUserPerms,api_WAccessGetUserPerms},
04356         {"SetUserPassword",     RAP_WUserPasswordSet2,  api_SetUserPassword},
04357         {"WWkstaUserLogon",     RAP_WWkstaUserLogon,    api_WWkstaUserLogon},
04358         {"PrintJobInfo",        RAP_WPrintJobSetInfo,   api_PrintJobInfo},
04359         {"WPrintDriverEnum",    RAP_WPrintDriverEnum,   api_WPrintDriverEnum},
04360         {"WPrintQProcEnum",     RAP_WPrintQProcessorEnum,api_WPrintQProcEnum},
04361         {"WPrintPortEnum",      RAP_WPrintPortEnum,     api_WPrintPortEnum},
04362         {"SamOEMChangePassword",RAP_SamOEMChgPasswordUser2_P,api_SamOEMChangePassword}, /* anon OK */
04363         {NULL,          -1,     api_Unsupported}
04364         /*  The following RAP calls are not implemented by Samba:
04365 
04366         RAP_WFileEnum2 - anon not OK 
04367         */
04368 };
04369 
04370 
04371 /****************************************************************************
04372  Handle remote api calls
04373  ****************************************************************************/
04374 
04375 int api_reply(connection_struct *conn,uint16 vuid,char *outbuf,char *data,char *params,
04376                      int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
04377 {
04378         int api_command;
04379         char *rdata = NULL;
04380         char *rparam = NULL;
04381         const char *name1 = NULL;
04382         const char *name2 = NULL;
04383         int rdata_len = 0;
04384         int rparam_len = 0;
04385         BOOL reply=False;
04386         int i;
04387 
04388         if (!params) {
04389                 DEBUG(0,("ERROR: NULL params in api_reply()\n"));
04390                 return 0;
04391         }
04392 
04393         if (tpscnt < 2) {
04394                 return 0;
04395         }
04396         api_command = SVAL(params,0);
04397         /* Is there a string at position params+2 ? */
04398         if (skip_string(params,tpscnt,params+2)) {
04399                 name1 = params + 2;
04400         } else {
04401                 name1 = "";
04402         }
04403         name2 = skip_string(params,tpscnt,params+2);
04404         if (!name2) {
04405                 name2 = "";
04406         }
04407 
04408         DEBUG(3,("Got API command %d of form <%s> <%s> (tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
04409                 api_command,
04410                 name1,
04411                 name2,
04412                 tdscnt,tpscnt,mdrcnt,mprcnt));
04413 
04414         for (i=0;api_commands[i].name;i++) {
04415                 if (api_commands[i].id == api_command && api_commands[i].fn) {
04416                         DEBUG(3,("Doing %s\n",api_commands[i].name));
04417                         break;
04418                 }
04419         }
04420 
04421         /* Check whether this api call can be done anonymously */
04422 
04423         if (api_commands[i].auth_user && lp_restrict_anonymous()) {
04424                 user_struct *user = get_valid_user_struct(vuid);
04425 
04426                 if (!user || user->guest) {
04427                         return ERROR_NT(NT_STATUS_ACCESS_DENIED);
04428                 }
04429         }
04430 
04431         rdata = (char *)SMB_MALLOC(1024);
04432         if (rdata) {
04433                 memset(rdata,'\0',1024);
04434         }
04435 
04436         rparam = (char *)SMB_MALLOC(1024);
04437         if (rparam) {
04438                 memset(rparam,'\0',1024);
04439         }
04440 
04441         if(!rdata || !rparam) {
04442                 DEBUG(0,("api_reply: malloc fail !\n"));
04443                 SAFE_FREE(rdata);
04444                 SAFE_FREE(rparam);
04445                 return -1;
04446         }
04447 
04448         reply = api_commands[i].fn(conn,
04449                                 vuid,
04450                                 params,tpscnt,  /* params + length */
04451                                 data,tdscnt,    /* data + length */
04452                                 mdrcnt,mprcnt,
04453                                 &rdata,&rparam,&rdata_len,&rparam_len);
04454 
04455 
04456         if (rdata_len > mdrcnt || rparam_len > mprcnt) {
04457                 reply = api_TooSmall(conn,vuid,params,data,mdrcnt,mprcnt,
04458                                         &rdata,&rparam,&rdata_len,&rparam_len);
04459         }
04460 
04461         /* if we get False back then it's actually unsupported */
04462         if (!reply) {
04463                 reply = api_Unsupported(conn,vuid,params,tpscnt,data,tdscnt,mdrcnt,mprcnt,
04464                         &rdata,&rparam,&rdata_len,&rparam_len);
04465         }
04466 
04467         /* If api_Unsupported returns false we can't return anything. */
04468         if (reply) {
04469                 send_trans_reply(outbuf, rparam, rparam_len, rdata, rdata_len, False);
04470         }
04471 
04472         SAFE_FREE(rdata);
04473         SAFE_FREE(rparam);
04474         return -1;
04475 }

Sambaに対してSat Aug 29 21:23:24 2009に生成されました。  doxygen 1.4.7