ipc.c :
[kai/samba.git] / source3 / smbd / ipc.c
index 6b3953e6c8658449e73f7c225214ea972129425d..6b255dd405ec2e00ebf00a1266a2a7f5d0df15c0 100644 (file)
@@ -1,9 +1,11 @@
-
 /* 
    Unix SMB/Netbios implementation.
    Version 1.9.
    Inter-process communication and named pipe handling
    Copyright (C) Andrew Tridgell 1992-1997
+
+   SMB Version handling
+   Copyright (C) John H Terpstra 1995-1997
    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -438,7 +440,7 @@ static void PackDriverData(struct pack_desc* desc)
 }
 
 static int check_printq_info(struct pack_desc* desc,
-                            int uLevel, char *id1, const char* id2)
+                            int uLevel, char *id1, char *id2)
 {
   desc->subformat = NULL;
   switch( uLevel ) {
@@ -478,7 +480,7 @@ static void fill_printjob_info(int cnum, int snum, int uLevel,
   /* the client expects localtime */
   t -= TimeDiff(t);
 
-  PACKI(desc,"W",((snum%0xFF)<<8) | (queue->job%0xFF)); /* uJobId */
+  PACKI(desc,"W",printjob_encode(snum, queue->job)); /* uJobId */
   if (uLevel == 1) {
     PACKS(desc,"B21",queue->user); /* szUserName */
     PACKS(desc,"B","");                /* pad */
@@ -770,8 +772,9 @@ static int get_server_info(uint32 servertype,
   int count=0;
   int alloced=0;
   pstring line;
+  BOOL local_list_only;
 
-  strcpy(fname,lp_lockdir());
+  pstrcpy(fname,lp_lockdir());
   trim_string(fname,NULL,"/");
   strcat(fname,"/");
   strcat(fname,SERVER_LIST);
@@ -784,7 +787,10 @@ static int get_server_info(uint32 servertype,
   }
 
   /* request for everything is code for request all servers */
-  if (servertype == SV_TYPE_ALL) servertype &= ~SV_TYPE_DOMAIN_ENUM;
+  if (servertype == SV_TYPE_ALL) 
+       servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
+
+  local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY);
 
   DEBUG(4,("Servertype search: %8x\n",servertype));
 
@@ -821,6 +827,14 @@ static int get_server_info(uint32 servertype,
       ok = False; 
     }
     
+       /* Filter the servers/domains we return based on what was asked for. */
+
+       /* Check to see if we are being asked for a local list only. */
+       if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) {
+         DEBUG(4,("r: local list only"));
+         ok = False;
+       }
+
     /* doesn't match up: don't want it */
     if (!(servertype & s->type)) { 
       DEBUG(4,("r:serv type ")); 
@@ -839,6 +853,9 @@ static int get_server_info(uint32 servertype,
        ok = False;
       }
     
+       /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
+       s->type &= ~SV_TYPE_LOCAL_LIST_ONLY;
+
     if (ok)
       {
        DEBUG(4,("**SV** %20s %8x %25s %15s\n",
@@ -965,11 +982,26 @@ static BOOL api_RNetServerEnum(int cnum, uint16 vuid, char *param, char *data,
   int i,missed;
   fstring domain;
   BOOL domain_request;
-  BOOL local_request = servertype & SV_TYPE_LOCAL_LIST_ONLY;
+  BOOL local_request;
+
+  /* If someone sets all the bits they don't really mean to set
+     DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
+     known servers. */
+
+  if (servertype == SV_TYPE_ALL) 
+    servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
 
-  if (servertype == SV_TYPE_ALL) servertype &= ~SV_TYPE_DOMAIN_ENUM;
+  /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
+     any other bit (they may just set this bit on it's own) they 
+     want all the locally seen servers. However this bit can be 
+     set on its own so set the requested servers to be 
+     ALL - DOMAIN_ENUM. */
+
+  if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM)) 
+    servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
 
   domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
+  local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
 
   p += 8;
 
@@ -1042,7 +1074,7 @@ static BOOL api_RNetServerEnum(int cnum, uint16 vuid, char *param, char *data,
   
   *rparam_len = 8;
   *rparam = REALLOC(*rparam,*rparam_len);
-  SSVAL(*rparam,0,NERR_Success);
+  SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERROR_MORE_DATA));
   SSVAL(*rparam,2,0);
   SSVAL(*rparam,4,counted);
   SSVAL(*rparam,6,counted+missed);
@@ -1331,7 +1363,7 @@ static BOOL api_SetUserPassword(int cnum,uint16 vuid, char *param,char *data,
   fstring user;
   fstring pass1,pass2;
 
-  strcpy(user,p);
+  fstrcpy(user,p);
 
   p = skip_string(p,1);
 
@@ -1373,11 +1405,10 @@ static BOOL api_RDosPrintJobDel(int cnum,uint16 vuid, char *param,char *data,
   char *str1 = param+2;
   char *str2 = skip_string(str1,1);
   char *p = skip_string(str2,1);
-  int jobid = (SVAL(p,0)&0xFF); /* the snum and jobid are encoded
-                                  by the print queue api */
-  int snum = (SVAL(p,0)>>8);  
+  int jobid, snum;
   int i, count;
 
+  printjob_decode(SVAL(p,0), &snum, &jobid);
 
   /* check it's a supported varient */
   if (!(strcsequal(str1,"W") && strcsequal(str2,"")))
@@ -1397,7 +1428,7 @@ static BOOL api_RDosPrintJobDel(int cnum,uint16 vuid, char *param,char *data,
       count = get_printqueue(snum,cnum,&queue,NULL);
   
       for (i=0;i<count;i++)
-       if ((queue[i].job%0xFF) == jobid)
+       if ((queue[i].job&0xFF) == jobid)
          {
            switch (function) {
            case 81:            /* delete */ 
@@ -1506,13 +1537,13 @@ static BOOL api_PrintJobInfo(int cnum,uint16 vuid,char *param,char *data,
   char *str1 = param+2;
   char *str2 = skip_string(str1,1);
   char *p = skip_string(str2,1);
-  int jobid = (SVAL(p,0)&0xFF); /* the snum and jobid are encoded
-                                  by the print queue api */
-  int snum = (SVAL(p,0)>>8);
+  int jobid, snum;
   int uLevel = SVAL(p,2);
   int function = SVAL(p,4);    /* what is this ?? */
   int i;
   char *s = data;
+
+  printjob_decode(SVAL(p,0), &snum, &jobid);
    
   *rparam_len = 4;
   *rparam = REALLOC(*rparam,*rparam_len);
@@ -1533,7 +1564,7 @@ static BOOL api_PrintJobInfo(int cnum,uint16 vuid,char *param,char *data,
        lpq_reset(snum);
        count = get_printqueue(snum,cnum,&queue,NULL);
        for (i=0;i<count;i++)   /* find job */
-         if ((queue[i].job%0xFF) == jobid) break;
+         if ((queue[i].job&0xFF) == jobid) break;
            
        if (i==count) {
          desc.errcode=NERR_JobNotFound;
@@ -1665,22 +1696,22 @@ static BOOL api_RNetServerGetInfo(int cnum,uint16 vuid, char *param,char *data,
       struct srv_info_struct *servers=NULL;
       int i,count;
       pstring comment;
-      uint32 servertype=DFLT_SERVER_TYPE;
+      uint32 servertype= lp_default_server_announce();
 
-      strcpy(comment,lp_serverstring());
+      pstrcpy(comment,lp_serverstring());
 
       if ((count=get_server_info(SV_TYPE_ALL,&servers,myworkgroup))>0) {
        for (i=0;i<count;i++)
          if (strequal(servers[i].name,local_machine))
       {
            servertype = servers[i].type;
-           strcpy(comment,servers[i].comment);     
+           pstrcpy(comment,servers[i].comment);            
          }
       }
       if (servers) free(servers);
 
-      SCVAL(p,0,MAJOR_VERSION);
-      SCVAL(p,1,MINOR_VERSION);
+      SCVAL(p,0,lp_major_announce_version());
+      SCVAL(p,1,lp_minor_announce_version());
       SIVAL(p,2,servertype);
 
       if (mdrcnt == struct_len) {
@@ -1760,8 +1791,8 @@ static BOOL api_NetWkstaGetInfo(int cnum,uint16 vuid, char *param,char *data,
   p2 = skip_string(p2,1);
   p += 4;
 
-  SCVAL(p,0,MAJOR_VERSION); /* system version - e.g 4 in 4.1 */
-  SCVAL(p,1,MINOR_VERSION); /* system version - e.g .1 in 4.1 */
+  SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
+  SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
   p += 2;
 
   SIVAL(p,0,PTR_DIFF(p2,*rdata));
@@ -1995,7 +2026,7 @@ static BOOL api_RNetUserGetInfo(int cnum,uint16 vuid, char *param,char *data,
        p2 = p + usri11_end;
 
        memset(p,0,21); 
-       strcpy(p+usri11_name,UserName); /* 21 bytes - user name */
+       fstrcpy(p+usri11_name,UserName); /* 21 bytes - user name */
 
        if (uLevel > 0)
        {
@@ -2012,9 +2043,9 @@ static BOOL api_RNetUserGetInfo(int cnum,uint16 vuid, char *param,char *data,
                strcpy(p2,"UserComment");
                p2 = skip_string(p2,1);
 
-        /* EEK! the cifsrap.txt doesn't have this in!!!! */
+               /* EEK! the cifsrap.txt doesn't have this in!!!! */
                SIVAL(p,usri11_full_name,PTR_DIFF(p2,p)); /* full name */
-        strcpy(p2,vuser->real_name);   /* simeon */
+               strcpy(p2,vuser->real_name);    /* simeon */
                p2 = skip_string(p2,1);
        }
 
@@ -2031,7 +2062,7 @@ static BOOL api_RNetUserGetInfo(int cnum,uint16 vuid, char *param,char *data,
                else
                {
 #if (defined(NETGROUP) && defined(AUTOMOUNT))
-            strcpy(p2, vuser->home_share);
+                       strcpy(p2, vuser->home_share);
 #else
                        strcpy(p2,"\\\\%L\\%U");
 #endif
@@ -2188,6 +2219,7 @@ static BOOL api_WWkstaUserLogon(int cnum,uint16 vuid, char *param,char *data,
   int uLevel;
   struct pack_desc desc;
   char* name;
+  char* logon_script;
 
   uLevel = SVAL(p,0);
   name = p + 2;
@@ -2230,7 +2262,14 @@ static BOOL api_WWkstaUserLogon(int cnum,uint16 vuid, char *param,char *data,
       PACKS(&desc,"z",mypath); /* computer */
     }
     PACKS(&desc,"z",myworkgroup);/* domain */
-    PACKS(&desc,"z",lp_logon_script());                /* script path */
+
+/* JHT - By calling lp_logon_script() and standard_sub() we have */
+/* made sure all macros are fully substituted and available */
+    logon_script = lp_logon_script();
+    standard_sub( cnum, logon_script );
+    PACKS(&desc,"z", logon_script);            /* script path */
+/* End of JHT mods */
+
     PACKI(&desc,"D",0x00000000);               /* reserved */
   }
 
@@ -2285,7 +2324,6 @@ static BOOL api_WPrintJobGetInfo(int cnum,uint16 vuid, char *param,char *data,
   char *str1 = param+2;
   char *str2 = skip_string(str1,1);
   char *p = skip_string(str2,1);
-  int uJobId = SVAL(p,0);
   int uLevel,cbBuf;
   int count;
   int i;
@@ -2301,20 +2339,19 @@ static BOOL api_WPrintJobGetInfo(int cnum,uint16 vuid, char *param,char *data,
   bzero(&desc,sizeof(desc));
   bzero(&status,sizeof(status));
 
-  DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,uJobId));
+  DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
 
   /* check it's a supported varient */
   if (strcmp(str1,"WWrLh") != 0) return False;
   if (!check_printjob_info(&desc,uLevel,str2)) return False;
 
-  snum = (unsigned int)uJobId >> 8; /*## valid serice number??*/
-  job = uJobId & 0xFF;
+  printjob_decode(SVAL(p,0), &snum, &job);
 
   if (snum < 0 || !VALID_SNUM(snum)) return(False);
 
   count = get_printqueue(snum,cnum,&queue,&status);
   for (i = 0; i < count; i++) {
-    if ((queue[i].job % 0xFF) == job) break;
+    if ((queue[i].job & 0xFF) == job) break;
   }
   if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
   desc.base = *rdata;
@@ -2432,7 +2469,8 @@ static void fill_printdest_info(int cnum, int snum, int uLevel,
                                struct pack_desc* desc)
 {
   char buf[100];
-  strcpy(buf,SERVICE(snum));
+  strncpy(buf,SERVICE(snum),sizeof(buf)-1);
+  buf[sizeof(buf)-1] = 0;
   strupper(buf);
   if (uLevel <= 1) {
     PACKS(desc,"B9",buf);      /* szName */
@@ -2725,7 +2763,13 @@ struct
 } api_fd_commands [] =
   {
     { "SetNmdPpHndState",      "lsarpc",       1,      api_LsarpcSNPHS },
+#ifdef NTDOMAIN
+    { "TransactNmPipe",        "lsarpc",       0x26,   api_ntLsarpcTNP },
+    { "TransactNmPipe",        "NETLOGON",     0x26,   api_netlogrpcTNP },
+    { "SetNmdPpHndState",      "NETLOGON",     1,      api_netlogrpcTNP },
+#else
     { "TransactNmPipe",        "lsarpc",       0x26,   api_LsarpcTNP },
+#endif
     { NULL,            NULL,           -1,     (BOOL (*)())api_Unsupported }
   };
 
@@ -2989,7 +3033,11 @@ int reply_trans(char *inbuf,char *outbuf)
   int dsoff = SVAL(inbuf,smb_vwv12);
   int suwcnt = CVAL(inbuf,smb_vwv13);
 
-  StrnCpy(name,smb_buf(inbuf),sizeof(name)-1);
+  fstrcpy(name,smb_buf(inbuf));
+
+  if (dscnt > tdscnt || pscnt > tpscnt) {
+         exit_server("invalid trans parameters\n");
+  }
   
   if (tdscnt)
     {
@@ -3051,6 +3099,10 @@ int reply_trans(char *inbuf,char *outbuf)
       pscnt += pcnt;
       dscnt += dcnt;
 
+      if (dscnt > tdscnt || pscnt > tpscnt) {
+             exit_server("invalid trans parameters\n");
+      }
+
       if (pcnt)
        memcpy(params+pdisp,smb_base(inbuf)+poff,pcnt);
       if (dcnt)