summaryrefslogtreecommitdiff
path: root/source/smbd/ipc.c
diff options
context:
space:
mode:
Diffstat (limited to 'source/smbd/ipc.c')
-rw-r--r--source/smbd/ipc.c365
1 files changed, 234 insertions, 131 deletions
diff --git a/source/smbd/ipc.c b/source/smbd/ipc.c
index 8852e57e8b6..78a98077694 100644
--- a/source/smbd/ipc.c
+++ b/source/smbd/ipc.c
@@ -24,8 +24,6 @@
*/
#include "includes.h"
-#include "loadparm.h"
-#include "pcap.h"
#ifdef CHECK_TYPES
#undef CHECK_TYPES
@@ -61,8 +59,21 @@ extern fstring local_machine;
#define SNLEN 15 /* service name length */
#define QNLEN 12 /* queue name maximum length */
+#define MAJOR_VERSION 4
+#define MINOR_VERSION 0
+
extern int Client;
+static BOOL api_Unsupported(int cnum,int uid, char *param,char *data,
+ int mdrcnt,int mprcnt,
+ char **rdata,char **rparam,
+ int *rdata_len,int *rparam_len);
+static BOOL api_TooSmall(int cnum,int uid, char *param,char *data,
+ int mdrcnt,int mprcnt,
+ char **rdata,char **rparam,
+ int *rdata_len,int *rparam_len);
+
+
static int CopyExpanded(int cnum, int snum, char** dst, char* src, int* n)
{
pstring buf;
@@ -189,12 +200,6 @@ static void send_trans_reply(char *outbuf,char *data,char *param,uint16 *setup,
}
}
-
-
-/****************************************************************************
- get a print queue
- ****************************************************************************/
-
struct pack_desc {
char* format; /* formatstring for structure */
char* subformat; /* subformat for structure */
@@ -418,6 +423,11 @@ static void PACKS(struct pack_desc* desc,char *t,char *v)
PACK(desc,t,v);
}
+
+/****************************************************************************
+ get a print queue
+ ****************************************************************************/
+
static void PackDriverData(struct pack_desc* desc)
{
char drivdata[4+4+32];
@@ -467,7 +477,7 @@ static void fill_printjob_info(int cnum, int snum, int uLevel,
time_t t = queue->time;
/* the client expects localtime */
- t += GMT_TO_LOCAL*TimeDiff(t);
+ t -= TimeDiff(t);
PACKI(desc,"W",((snum%0xFF)<<8) | (queue->job%0xFF)); /* uJobId */
if (uLevel == 1) {
@@ -479,7 +489,7 @@ static void fill_printjob_info(int cnum, int snum, int uLevel,
PACKI(desc,"W",n+1); /* uPosition */
PACKI(desc,"W",queue->status); /* fsStatus */
PACKS(desc,"z",""); /* pszStatus */
- PACKI(desc,"D",queue->time); /* ulSubmitted */
+ PACKI(desc,"D",t); /* ulSubmitted */
PACKI(desc,"D",queue->size); /* ulSize */
PACKS(desc,"z",queue->file); /* pszComment */
}
@@ -488,7 +498,7 @@ static void fill_printjob_info(int cnum, int snum, int uLevel,
PACKS(desc,"z",queue->user); /* pszUserName */
PACKI(desc,"W",n+1); /* uPosition */
PACKI(desc,"W",queue->status); /* fsStatus */
- PACKI(desc,"D",queue->time); /* ulSubmitted */
+ PACKI(desc,"D",t); /* ulSubmitted */
PACKI(desc,"D",queue->size); /* ulSize */
PACKS(desc,"z","Samba"); /* pszComment */
PACKS(desc,"z",queue->file); /* pszDocument */
@@ -545,7 +555,7 @@ static void fill_printq_info(int cnum, int snum, int uLevel,
PACKI(desc,"W",0); /* uUntiltime */
PACKI(desc,"W",5); /* pad1 */
PACKS(desc,"z",""); /* pszSepFile */
- PACKS(desc,"z","lpd"); /* pszPrProc */
+ PACKS(desc,"z","WinPrint"); /* pszPrProc */
PACKS(desc,"z",""); /* pszParms */
if (!status || !status->message[0]) {
PACKS(desc,"z",Expand(cnum,snum,lp_comment(snum))); /* pszComment */
@@ -556,7 +566,7 @@ static void fill_printq_info(int cnum, int snum, int uLevel,
}
PACKI(desc,(uLevel == 3 ? "W" : "N"),count); /* cJobs */
PACKS(desc,"z",SERVICE(snum)); /* pszPrinters */
- PACKS(desc,"z","NULL"); /* pszDriverName */
+ PACKS(desc,"z",lp_printerdriver(snum)); /* pszDriverName */
PackDriverData(desc); /* pDriverData */
}
if (uLevel == 2 || uLevel == 4) {
@@ -593,6 +603,7 @@ static BOOL api_DosPrintQGetInfo(int cnum,int uid, char *param,char *data,
cbBuf = SVAL(p,2);
str3 = p + 4;
+ /* remove any trailing username */
if ((p = strchr(QueueName,'%'))) *p = 0;
DEBUG(3,("PrintQueue uLevel=%d name=%s\n",uLevel,QueueName));
@@ -662,7 +673,7 @@ static BOOL api_DosPrintQEnum(int cnum, int uid, char* param, char* data,
DEBUG(3,("DosPrintQEnum uLevel=%d\n",uLevel));
- if (prefix_ok(param_format,"WrLeh")) return False;
+ if (!prefix_ok(param_format,"WrLeh")) return False;
if (!check_printq_info(&desc,uLevel,output_format1,output_format2))
return False;
queuecnt = 0;
@@ -737,58 +748,23 @@ static BOOL check_server_info(int uLevel, char* id)
return True;
}
-/* used for server information: client, nameserv and ipc */
struct srv_info_struct
{
fstring name;
uint32 type;
fstring comment;
- fstring domain; /* used ONLY in ipc.c NOT namework.c */
- BOOL server_added; /* used ONLY in ipc.c NOT namework.c */
+ fstring domain;
+ BOOL server_added;
};
-/*******************************************************************
- filter out unwanted server info
- ******************************************************************/
-static BOOL filter_server_info(struct srv_info_struct *server,
- char *domain)
-{
- if (*domain)
- return(strequal(domain, server->domain));
-
- return (True); /* be indiscriminate: get all servers! */
-}
-
-/*******************************************************************
- find server in the files saved by nmbd. Return True if we find it.
- ******************************************************************/
-static BOOL find_server(struct srv_info_struct *servers, int num_servers,
- char *domain, char *name)
-{
- int count;
-
- if (!servers || num_servers == 0) return (False);
-
- for (count = 0; count < num_servers; count++) {
- struct srv_info_struct *s;
-
- s = &servers[count];
-
- if (strequal(name, s->name)) {
- StrnCpy(domain, s->domain, sizeof(pstring)-1);
- return (True);
- }
- }
- return (False);
-}
-
/*******************************************************************
get server info lists from the files saved by nmbd. Return the
number of entries
******************************************************************/
static int get_server_info(uint32 servertype,
- struct srv_info_struct **servers)
+ struct srv_info_struct **servers,
+ char *domain)
{
FILE *f;
pstring fname;
@@ -807,18 +783,23 @@ static int get_server_info(uint32 servertype,
DEBUG(4,("Can't open %s - %s\n",fname,strerror(errno)));
return(0);
}
+
+ /* request for everything is code for request all servers */
if (servertype == SV_TYPE_ALL) servertype &= ~SV_TYPE_DOMAIN_ENUM;
+ DEBUG(4,("Servertype search: %8x\n",servertype));
+
while (!feof(f))
{
fstring stype;
struct srv_info_struct *s;
char *ptr = line;
+ BOOL ok = True;
*ptr = 0;
fgets(line,sizeof(line)-1,f);
if (!*line) continue;
-
+
if (count == alloced) {
alloced += 10;
(*servers) = (struct srv_info_struct *)
@@ -827,36 +808,58 @@ static int get_server_info(uint32 servertype,
bzero((char *)((*servers)+count),sizeof(**servers)*(alloced-count));
}
s = &(*servers)[count];
-
- s->server_added = True;
-
+
if (!next_token(&ptr,s->name , NULL)) continue;
if (!next_token(&ptr,stype , NULL)) continue;
if (!next_token(&ptr,s->comment, NULL)) continue;
if (!next_token(&ptr,s->domain , NULL)) {
- /* this allows us to cop with an old nmbd */
- strcpy(s->domain,my_workgroup());
+ /* this allows us to cope with an old nmbd */
+ strcpy(s->domain,lp_workgroup());
}
-
- if (sscanf(stype,"%X",&s->type) != 1) continue;
-
+
+ if (sscanf(stype,"%X",&s->type) != 1) {
+ DEBUG(4,("r:host file "));
+ ok = False;
+ }
+
/* doesn't match up: don't want it */
- if (!(servertype & s->type)) continue;
-
- /* server entry is a domain, we haven't asked for domains: don't want it */
- if ((s->type&SV_TYPE_DOMAIN_ENUM) && !(servertype&SV_TYPE_DOMAIN_ENUM))
- continue;
-
- DEBUG(4,("Server %20s %8x %25s %15s\n",
- s->name, stype, s->comment, s->domain));
-
- count++;
+ if (!(servertype & s->type)) {
+ DEBUG(4,("r:serv type "));
+ ok = False;
+ }
+
+ if ((servertype & SV_TYPE_DOMAIN_ENUM) !=
+ (s->type & SV_TYPE_DOMAIN_ENUM))
+ {
+ DEBUG(4,("s: dom mismatch "));
+ ok = False;
+ }
+
+ if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM))
+ {
+ ok = False;
+ }
+
+ if (ok)
+ {
+ DEBUG(4,("**SV** %20s %8x %25s %15s\n",
+ s->name, s->type, s->comment, s->domain));
+
+ s->server_added = True;
+ count++;
+ }
+ else
+ {
+ DEBUG(4,("%20s %8x %25s %15s\n",
+ s->name, s->type, s->comment, s->domain));
+ }
}
-
+
fclose(f);
return(count);
}
+
/*******************************************************************
fill in a server info structure
******************************************************************/
@@ -936,6 +939,11 @@ static int fill_srv_info(struct srv_info_struct *service,
}
+static BOOL srv_comp(struct srv_info_struct *s1,struct srv_info_struct *s2)
+{
+ return(strcmp(s1->name,s2->name));
+}
+
/****************************************************************************
view list of servers available (or possibly domains). The info is
extracted from lists saved by nmbd on the local host
@@ -957,51 +965,47 @@ static BOOL api_RNetServerEnum(int cnum, int uid, char *param, char *data,
int counted=0,total=0;
int i;
fstring domain;
- BOOL domain_request = (servertype & SV_TYPE_DOMAIN_ENUM) &&
- !(servertype == SV_TYPE_ALL);
+ BOOL domain_request;
+ BOOL local_request = servertype & SV_TYPE_LOCAL_LIST_ONLY;
+
+ if (servertype == SV_TYPE_ALL) servertype &= ~SV_TYPE_DOMAIN_ENUM;
+
+ domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
- domain[0] = 0;
p += 8;
if (!prefix_ok(str1,"WrLehD")) return False;
if (!check_server_info(uLevel,str2)) return False;
- DEBUG(4, ("server request level: %s\n", str2));
+ DEBUG(4, ("server request level: %s %8x ", str2, servertype));
+ DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
+ DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
- if (strcmp(str1, "WrLehDO") == 0)
- {
- /* asking for servers. we will have to work out which workgroup was
- requested, as we maintain lists for multiple workgroups */
- }
- else if (strcmp(str1, "WrLehDz") == 0)
- {
- /* asking for a specific workgroup */
+ if (strcmp(str1, "WrLehDz") == 0) {
StrnCpy(domain, p, sizeof(fstring)-1);
+ } else {
+ StrnCpy(domain, lp_workgroup(), sizeof(fstring)-1);
}
if (lp_browse_list())
- {
- total = get_server_info(servertype,&servers);
- }
-
- if (!domain[0] && !domain_request) {
- extern fstring remote_machine;
- /* must be a server request with an assumed domain. find a domain */
-
- if (find_server(servers, total, domain, remote_machine)) {
- DEBUG(4, ("No domain specified: using %s for %s\n",
- domain, remote_machine));
- } else {
- /* default to soemthing sensible */
- strcpy(domain,my_workgroup());
- }
- }
+ total = get_server_info(servertype,&servers,domain);
data_len = fixed_len = string_len = 0;
- for (i=0;i<total;i++)
- if (filter_server_info(&servers[i],domain)) {
- data_len += fill_srv_info(&servers[i],uLevel,0,&f_len,0,&s_len,0);
+ qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
+
+ {
+ char *lastname=NULL;
+
+ for (i=0;i<total;i++)
+ {
+ struct srv_info_struct *s = &servers[i];
+ if (lastname && strequal(lastname,s->name)) continue;
+ lastname = s->name;
+ data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
+ DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
+ s->name, s->type, s->comment, s->domain));
+
if (data_len <= buf_len)
{
counted++;
@@ -1009,6 +1013,7 @@ static BOOL api_RNetServerEnum(int cnum, int uid, char *param, char *data,
string_len += s_len;
}
}
+ }
*rdata_len = fixed_len + string_len;
*rdata = REALLOC(*rdata,*rdata_len);
@@ -1020,13 +1025,18 @@ static BOOL api_RNetServerEnum(int cnum, int uid, char *param, char *data,
s_len = string_len;
{
+ char *lastname=NULL;
int count2 = counted;
- for (i = 0; i < total && count2;i++) {
- if (filter_server_info(&servers[i],domain)) {
- fill_srv_info(&servers[i],uLevel,&p,&f_len,&p2,&s_len,*rdata);
+ for (i = 0; i < total && count2;i++)
+ {
+ struct srv_info_struct *s = &servers[i];
+ if (lastname && strequal(lastname,s->name)) continue;
+ lastname = s->name;
+ fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
+ DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
+ s->name, s->type, s->comment, s->domain));
count2--;
}
- }
}
*rparam_len = 8;
@@ -1289,7 +1299,7 @@ static BOOL api_NetRemoteTOD(int cnum,int uid, char *param,char *data,
/* the client expects to get localtime, not GMT, in this bit
(I think, this needs testing) */
- t = LocalTime(&unixdate,GMT_TO_LOCAL);
+ t = LocalTime(&unixdate);
SIVAL(p,4,0); /* msecs ? */
CVAL(p,8) = t->tm_hour;
@@ -1332,14 +1342,16 @@ static BOOL api_SetUserPassword(int cnum,int uid, char *param,char *data,
*rdata_len = 0;
- SSVAL(*rparam,0,NERR_Success);
+ SSVAL(*rparam,0,NERR_badpass);
SSVAL(*rparam,2,0); /* converter word */
DEBUG(3,("Set password for <%s>\n",user));
- if (!password_ok(user,pass1,strlen(pass1),NULL,False) ||
- !chgpasswd(user,pass1,pass2))
- SSVAL(*rparam,0,NERR_badpass);
+ if (password_ok(user,pass1,strlen(pass1),NULL,False) &&
+ chgpasswd(user,pass1,pass2))
+ {
+ SSVAL(*rparam,0,NERR_Success);
+ }
bzero(pass1,sizeof(fstring));
bzero(pass2,sizeof(fstring));
@@ -1551,8 +1563,7 @@ static BOOL api_PrintJobInfo(int cnum,int uid,char *param,char *data,
int l = 0;
while (l<64 && *s)
{
- if (isalnum(*s) || strchr("-._",*s))
- name[l++] = *s;
+ if (issafe(*s)) name[l++] = *s;
s++;
}
name[l] = 0;
@@ -1658,7 +1669,7 @@ static BOOL api_RNetServerGetInfo(int cnum,int uid, char *param,char *data,
strcpy(comment,lp_serverstring());
- if ((count=get_server_info(SV_TYPE_ALL,&servers))>0) {
+ if ((count=get_server_info(SV_TYPE_ALL,&servers,lp_workgroup()))>0) {
for (i=0;i<count;i++)
if (strequal(servers[i].name,local_machine)) {
servertype = servers[i].type;
@@ -1667,9 +1678,10 @@ static BOOL api_RNetServerGetInfo(int cnum,int uid, char *param,char *data,
}
if (servers) free(servers);
- SCVAL(p,0,2); /* version_major */
- SCVAL(p,1,0); /* version_minor */
+ SCVAL(p,0,MAJOR_VERSION);
+ SCVAL(p,1,MINOR_VERSION);
SIVAL(p,2,servertype);
+
if (mdrcnt == struct_len) {
SIVAL(p,6,0);
} else {
@@ -1740,16 +1752,16 @@ static BOOL api_NetWkstaGetInfo(int cnum,int uid, char *param,char *data,
p += 4;
SIVAL(p,0,PTR_DIFF(p2,*rdata));
- strcpy(p2,my_workgroup());
+ strcpy(p2,lp_workgroup());
p2 = skip_string(p2,1);
p += 4;
- SCVAL(p,0,2); /* major version?? */
- SCVAL(p,1,1); /* minor version?? */
+ SCVAL(p,0,MAJOR_VERSION);
+ SCVAL(p,1,MINOR_VERSION);
p += 2;
SIVAL(p,0,PTR_DIFF(p2,*rdata));
- strcpy(p2,my_workgroup()); /* login domain?? */
+ strcpy(p2,lp_workgroup()); /* login domain?? */
p2 = skip_string(p2,1);
p += 4;
@@ -1827,7 +1839,8 @@ static BOOL api_RNetUserGetInfo(int cnum,int uid, char *param,char *data,
p2 = skip_string(p2,1);
}
if (uLevel == 11) { /* modelled after NTAS 3.51 reply */
- SSVAL(p,34,USER_PRIV_USER); /* user privilege */
+ SSVAL(p,34,
+ Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
SIVAL(p,36,0); /* auth flags */
SIVALS(p,40,-1); /* password age */
SIVAL(p,44,PTR_DIFF(p2,p)); /* home dir */
@@ -1862,7 +1875,8 @@ static BOOL api_RNetUserGetInfo(int cnum,int uid, char *param,char *data,
if (uLevel == 1 || uLevel == 2) {
memset(p+22,' ',16); /* password */
SIVALS(p,38,-1); /* password age */
- SSVAL(p,42,USER_PRIV_ADMIN); /* user privilege */
+ SSVAL(p,42,
+ Connections[cnum].admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
strcpy(p2,"\\\\%L\\HOMES");
standard_sub_basic(p2);
@@ -2012,7 +2026,7 @@ static BOOL api_WWkstaUserLogon(int cnum,int uid, char *param,char *data,
strupper(mypath);
PACKS(&desc,"z",mypath); /* computer */
}
- PACKS(&desc,"z",my_workgroup());/* domain */
+ PACKS(&desc,"z",lp_workgroup());/* domain */
PACKS(&desc,"z",lp_logon_script()); /* script path */
PACKI(&desc,"D",0); /* reserved */
}
@@ -2498,6 +2512,92 @@ static BOOL api_WPrintPortEnum(int cnum,int uid, char *param,char *data,
return(True);
}
+
+struct
+{
+ char * name;
+ char * pipename;
+ int subcommand;
+ BOOL (*fn) ();
+} api_fd_commands [] =
+ {
+ { "SetNmdPpHndState", "lsarpc", 1, api_LsarpcSNPHS },
+ { "TransactNmPipe", "lsarpc", 0x26, api_LsarpcTNP },
+ { NULL, NULL, -1, api_Unsupported }
+ };
+
+/****************************************************************************
+ handle remote api calls delivered to a named pipe already opened.
+ ****************************************************************************/
+static int api_fd_reply(int cnum,int uid,char *outbuf,
+ uint16 *setup,char *data,char *params,
+ int suwcnt,int tdscnt,int tpscnt,int mdrcnt,int mprcnt)
+{
+ char *rdata = NULL;
+ char *rparam = NULL;
+ int rdata_len = 0;
+ int rparam_len = 0;
+ BOOL reply=False;
+ int i;
+ int fd;
+ int subcommand;
+
+ /* First find out the name of this file. */
+ if (suwcnt != 2)
+ {
+ DEBUG(0,("Unexpected named pipe transaction.\n"));
+ return(-1);
+ }
+
+ /* Get the file handle and hence the file name. */
+ fd = setup[1];
+ subcommand = setup[0];
+
+ DEBUG(3,("Got API command %d on pipe %s ",subcommand,Files[fd].name));
+ DEBUG(3,("(tdscnt=%d,tpscnt=%d,mdrcnt=%d,mprcnt=%d)\n",
+ tdscnt,tpscnt,mdrcnt,mprcnt));
+
+ for (i=0;api_fd_commands[i].name;i++)
+ if (strequal(api_fd_commands[i].pipename, Files[fd].name) &&
+ api_fd_commands[i].subcommand == subcommand &&
+ api_fd_commands[i].fn)
+ {
+ DEBUG(3,("Doing %s\n",api_fd_commands[i].name));
+ break;
+ }
+
+ rdata = (char *)malloc(1024); if (rdata) bzero(rdata,1024);
+ rparam = (char *)malloc(1024); if (rparam) bzero(rparam,1024);
+
+ reply = api_fd_commands[i].fn(cnum,uid,params,data,mdrcnt,mprcnt,
+ &rdata,&rparam,&rdata_len,&rparam_len);
+
+ if (rdata_len > mdrcnt ||
+ rparam_len > mprcnt)
+ {
+ reply = api_TooSmall(cnum,uid,params,data,mdrcnt,mprcnt,
+ &rdata,&rparam,&rdata_len,&rparam_len);
+ }
+
+
+ /* if we get False back then it's actually unsupported */
+ if (!reply)
+ api_Unsupported(cnum,uid,params,data,mdrcnt,mprcnt,
+ &rdata,&rparam,&rdata_len,&rparam_len);
+
+ /* now send the reply */
+ send_trans_reply(outbuf,rdata,rparam,NULL,rdata_len,rparam_len,0);
+
+ if (rdata)
+ free(rdata);
+ if (rparam)
+ free(rparam);
+
+ return(-1);
+}
+
+
+
/****************************************************************************
the buffer was too small
****************************************************************************/
@@ -2648,6 +2748,10 @@ static int named_pipe(int cnum,int uid, char *outbuf,char *name,
if (strequal(name,"LANMAN"))
return(api_reply(cnum,uid,outbuf,data,params,tdscnt,tpscnt,mdrcnt,mprcnt));
+if (strlen(name) < 1)
+ return(api_fd_reply(cnum,uid,outbuf,setup,data,params,suwcnt,tdscnt,tpscnt,mdrcnt,mprcnt));
+
+
DEBUG(3,("named pipe command on <%s> 0x%X setup1=%d\n",
name,(int)setup[0],(int)setup[1]));
@@ -2717,12 +2821,9 @@ int reply_trans(char *inbuf,char *outbuf)
while (pscnt < tpscnt || dscnt < tdscnt)
{
int pcnt,poff,dcnt,doff,pdisp,ddisp;
-
- receive_smb(Client,inbuf, 0);
- show_msg(inbuf);
-
- /* Ensure this is still a trans packet (sanity check) */
- if(CVAL(inbuf, smb_com) != SMBtrans)
+
+ if (!receive_smb(Client,inbuf, SMB_SECONDARY_WAIT*1000) ||
+ CVAL(inbuf, smb_com) != SMBtrans)
{
DEBUG(2,("Invalid secondary trans2 packet\n"));
if (params) free(params);
@@ -2730,6 +2831,8 @@ int reply_trans(char *inbuf,char *outbuf)
if (setup) free(setup);
return(ERROR(ERRSRV,ERRerror));
}
+
+ show_msg(inbuf);
tpscnt = SVAL(inbuf,smb_vwv0);
tdscnt = SVAL(inbuf,smb_vwv1);