summaryrefslogtreecommitdiff
path: root/source/smbd
diff options
context:
space:
mode:
authorLuke Leighton <lkcl@samba.org>2000-02-06 05:17:28 +0000
committerLuke Leighton <lkcl@samba.org>2000-02-06 05:17:28 +0000
commitcf34c0bec59dfd8b83edf3e111e925ccd3db1226 (patch)
treec68c44f0f3c93c46845e6fd4183b99328d4154d5 /source/smbd
parent28aa3f66138b8be02d8198537b0e524b4b6b417b (diff)
downloadsamba-cf34c0bec59dfd8b83edf3e111e925ccd3db1226.tar.gz
this is probably one of THE most reluctant commits i've ever made.
it's far-reaching, and necessary. this adds a vuser_struct tdb database, with a key [smbd's pid, vuid]. smbd uses it in every instance of standard_sub() and standard_sub_vuser(). that's almost every single SMB call for any IPC$ access. the next stage is to remove sesssetup_user, probably sessetup_user_list too, and review all occurences of standard_sub_basic used by smbd because if they use standard_sub_basic() they might be expecting to read sesssetup_user, and if they do _that_, they should be using standard_sub_vuser() instead. all i wanted was a means to get vuids across to msrpc daemons.
Diffstat (limited to 'source/smbd')
-rw-r--r--source/smbd/lanman.c128
-rw-r--r--source/smbd/open.c4
-rw-r--r--source/smbd/oplock.c2
-rw-r--r--source/smbd/password.c266
-rw-r--r--source/smbd/process.c10
-rw-r--r--source/smbd/reply.c19
-rw-r--r--source/smbd/service.c56
-rw-r--r--source/smbd/uid.c35
8 files changed, 327 insertions, 193 deletions
diff --git a/source/smbd/lanman.c b/source/smbd/lanman.c
index 84387bd178d..37b71f9b159 100644
--- a/source/smbd/lanman.c
+++ b/source/smbd/lanman.c
@@ -1,12 +1,14 @@
-/*
+ /*
Unix SMB/Netbios implementation.
Version 1.9.
Inter-process communication and named pipe handling
- Copyright (C) Andrew Tridgell 1992-1998
+ Copyright (C) Andrew Tridgell 1992-2000
SMB Version handling
- Copyright (C) John H Terpstra 1995-1998
-
+ Copyright (C) John H Terpstra 1995-2000
+
+ Copyright (C) Luke Kenneth Casson Leighton 1996-2000
+
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
the Free Software Foundation; either version 2 of the License, or
@@ -73,17 +75,21 @@ static BOOL api_TooSmall(connection_struct *conn,uint16 vuid, char *param,char *
int *rdata_len,int *rparam_len);
-static int CopyExpanded(connection_struct *conn, uint16 vuid,
+static int CopyExpanded(connection_struct *conn, const vuser_key *key,
int snum, char** dst, char* src, int* n)
{
pstring buf;
int l;
+ user_struct *vuser;
if (!src || !dst || !n || !(*dst)) return(0);
StrnCpy(buf,src,sizeof(buf)/2);
string_sub(buf,"%S",lp_servicename(snum));
- standard_sub(conn,get_valid_user_struct(vuid), buf);
+ vuser = get_valid_user_struct(key);
+ standard_sub(conn,vuser, buf);
+ vuid_free_user_struct(vuser);
+ safe_free(vuser);
StrnCpy(*dst,buf,*n);
l = strlen(*dst) + 1;
(*dst) += l;
@@ -103,23 +109,29 @@ static int CopyAndAdvance(char** dst, char* src, int* n)
}
static int StrlenExpanded(connection_struct *conn,
- uint16 vuid, int snum, char* s)
+ const vuser_key *key, int snum, char* s)
{
+ user_struct *vuser;
pstring buf;
if (!s) return(0);
StrnCpy(buf,s,sizeof(buf)/2);
string_sub(buf,"%S",lp_servicename(snum));
- standard_sub(conn,get_valid_user_struct(vuid), buf);
+ vuser = get_valid_user_struct(key);
+ standard_sub(conn,vuser, buf);
+ vuid_free_user_struct(vuser);
+ safe_free(vuser);
return strlen(buf) + 1;
}
-static char* Expand(connection_struct *conn, uint16 vuid, int snum, char* s)
+static char* Expand(connection_struct *conn, const vuser_key *key, int snum, char* s)
{
+ user_struct *vuser;
static pstring buf;
if (!s) return(NULL);
StrnCpy(buf,s,sizeof(buf)/2);
string_sub(buf,"%S",lp_servicename(snum));
- standard_sub(conn,get_valid_user_struct(vuid), buf);
+ vuser = get_valid_user_struct(key);
+ standard_sub(conn,vuser, buf);
return &buf[0];
}
@@ -446,7 +458,7 @@ static void fill_printjob_info(connection_struct *conn,
}
}
-static void fill_printq_info(connection_struct *conn, uint16 vuid,
+static void fill_printq_info(connection_struct *conn, const vuser_key *key,
int snum, int uLevel,
struct pack_desc* desc,
int count, print_queue_struct* queue,
@@ -460,7 +472,7 @@ static void fill_printq_info(connection_struct *conn, uint16 vuid,
case 3:
case 4:
case 5:
- PACKS(desc,"z",Expand(conn,vuid, snum,SERVICE(snum)));
+ PACKS(desc,"z",Expand(conn,key, snum,SERVICE(snum)));
break;
}
@@ -478,7 +490,7 @@ static void fill_printq_info(connection_struct *conn, uint16 vuid,
PACKI(desc,"W",LPSTAT_ERROR);
}
else if (!status || !status->message[0]) {
- PACKS(desc,"z",Expand(conn,vuid, snum,lp_comment(snum)));
+ PACKS(desc,"z",Expand(conn,key, snum,lp_comment(snum)));
PACKI(desc,"W",LPSTAT_OK); /* status */
} else {
PACKS(desc,"z",status->message);
@@ -495,7 +507,7 @@ static void fill_printq_info(connection_struct *conn, uint16 vuid,
PACKS(desc,"z","WinPrint"); /* pszPrProc */
PACKS(desc,"z",""); /* pszParms */
if (!status || !status->message[0]) {
- PACKS(desc,"z",Expand(conn,vuid, snum,lp_comment(snum))); /* pszComment */
+ PACKS(desc,"z",Expand(conn,key, snum,lp_comment(snum))); /* pszComment */
PACKI(desc,"W",LPSTAT_OK); /* fsStatus */
} else {
PACKS(desc,"z",status->message); /* pszComment */
@@ -686,6 +698,7 @@ static BOOL api_DosPrintQGetInfo(connection_struct *conn,
struct pack_desc desc;
print_queue_struct *queue=NULL;
print_status_struct status;
+ vuser_key key = { conn->smbd_pid, vuid };
bzero(&status,sizeof(status));
bzero(&desc,sizeof(desc));
@@ -718,7 +731,7 @@ static BOOL api_DosPrintQGetInfo(connection_struct *conn,
count = get_printerdrivernumber(snum);
DEBUG(3,("api_DosPrintQGetInfo: Driver files count: %d\n",count));
} else {
- count = get_printqueue(snum, conn,vuid,&queue,&status);
+ count = get_printqueue(snum, conn,&key,&queue,&status);
}
if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
@@ -726,7 +739,7 @@ static BOOL api_DosPrintQGetInfo(connection_struct *conn,
desc.buflen = mdrcnt;
if (init_package(&desc,1,count)) {
desc.subcount = count;
- fill_printq_info(conn,vuid,snum,uLevel,&desc,count,queue,&status);
+ fill_printq_info(conn,&key,snum,uLevel,&desc,count,queue,&status);
} else if (uLevel == 0) {
/*
* This is a *disgusting* hack.
@@ -785,6 +798,7 @@ static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid, char* param,
print_status_struct *status = NULL;
int* subcntarr = NULL;
int queuecnt, subcnt=0, succnt=0;
+ vuser_key key = { conn->smbd_pid, vuid };
bzero(&desc,sizeof(desc));
@@ -816,7 +830,7 @@ static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid, char* param,
n = 0;
for (i = 0; i < services; i++)
if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
- subcntarr[n] = get_printqueue(i, conn, vuid, &queue[n],&status[n]);
+ subcntarr[n] = get_printqueue(i, conn, &key, &queue[n],&status[n]);
subcnt += subcntarr[n];
n++;
}
@@ -830,7 +844,7 @@ static BOOL api_DosPrintQEnum(connection_struct *conn, uint16 vuid, char* param,
succnt = 0;
for (i = 0; i < services; i++)
if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
- fill_printq_info(conn,vuid, i,uLevel,&desc,subcntarr[n],queue[n],&status[n]);
+ fill_printq_info(conn,&key, i,uLevel,&desc,subcntarr[n],queue[n],&status[n]);
n++;
if (desc.errcode == NERR_Success) succnt = n;
}
@@ -1269,7 +1283,7 @@ static BOOL check_share_info(int uLevel, char* id)
return True;
}
-static int fill_share_info(connection_struct *conn, uint16 vuid,
+static int fill_share_info(connection_struct *conn, const vuser_key *key,
int snum, int uLevel,
char** buf, int* buflen,
char** stringbuf, int* stringspace, char* baseaddr)
@@ -1292,7 +1306,7 @@ static int fill_share_info(connection_struct *conn, uint16 vuid,
if (!buf)
{
len = 0;
- if (uLevel > 0) len += StrlenExpanded(conn,vuid,snum,lp_comment(snum));
+ if (uLevel > 0) len += StrlenExpanded(conn,key,snum,lp_comment(snum));
if (uLevel > 1) len += strlen(lp_pathname(snum)) + 1;
if (buflen) *buflen = struct_len;
if (stringspace) *stringspace = len;
@@ -1325,7 +1339,7 @@ static int fill_share_info(connection_struct *conn, uint16 vuid,
if (strequal("IPC$",lp_servicename(snum))) type = STYPE_IPC;
SSVAL(p,14,type); /* device type */
SIVAL(p,16,PTR_DIFF(p2,baseaddr));
- len += CopyExpanded(conn,vuid, snum,&p2,lp_comment(snum),&l2);
+ len += CopyExpanded(conn,key, snum,&p2,lp_comment(snum),&l2);
}
if (uLevel > 1)
@@ -1376,6 +1390,7 @@ static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid, char *para
char *p = skip_string(netname,1);
int uLevel = SVAL(p,0);
int snum = find_service(netname);
+ vuser_key key = { conn->smbd_pid, vuid };
if (snum < 0) return False;
@@ -1385,7 +1400,7 @@ static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid, char *para
*rdata = REALLOC(*rdata,mdrcnt);
p = *rdata;
- *rdata_len = fill_share_info(conn,vuid,snum,uLevel,&p,&mdrcnt,0,0,0);
+ *rdata_len = fill_share_info(conn,&key,snum,uLevel,&p,&mdrcnt,0,0,0);
if (*rdata_len < 0) return False;
*rparam_len = 6;
@@ -1417,6 +1432,7 @@ static BOOL api_RNetShareEnum(connection_struct *conn,uint16 vuid, char *param,c
int i;
int data_len, fixed_len, string_len;
int f_len = 0, s_len = 0;
+ vuser_key key = { conn->smbd_pid, vuid };
if (!prefix_ok(str1,"WrLeh")) return False;
if (!check_share_info(uLevel,str2)) return False;
@@ -1426,7 +1442,7 @@ static BOOL api_RNetShareEnum(connection_struct *conn,uint16 vuid, char *param,c
if (lp_browseable(i) && lp_snum_ok(i))
{
total++;
- data_len += fill_share_info(conn,vuid,i,uLevel,0,&f_len,0,&s_len,0);
+ data_len += fill_share_info(conn,&key,i,uLevel,0,&f_len,0,&s_len,0);
if (data_len <= buf_len)
{
counted++;
@@ -1446,7 +1462,7 @@ static BOOL api_RNetShareEnum(connection_struct *conn,uint16 vuid, char *param,c
s_len = string_len;
for (i = 0; i < count;i++)
if (lp_browseable(i) && lp_snum_ok(i))
- if (fill_share_info(conn,vuid,i,uLevel,&p,&f_len,&p2,&s_len,*rdata) < 0)
+ if (fill_share_info(conn,&key,i,uLevel,&p,&f_len,&p2,&s_len,*rdata) < 0)
break;
*rparam_len = 8;
@@ -1659,6 +1675,7 @@ static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char *param
char *p = skip_string(str2,1);
int jobid, snum;
int i, count;
+ vuser_key key = { conn->smbd_pid, vuid };
printjob_decode(SVAL(p,0), &snum, &jobid);
@@ -1677,7 +1694,7 @@ static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char *param
{
print_queue_struct *queue=NULL;
lpq_reset(snum);
- count = get_printqueue(snum,conn,vuid,&queue,NULL);
+ count = get_printqueue(snum,conn,&key,&queue,NULL);
for (i=0;i<count;i++)
if ((queue[i].job&0xFF) == jobid)
@@ -1685,13 +1702,13 @@ static BOOL api_RDosPrintJobDel(connection_struct *conn,uint16 vuid, char *param
switch (function) {
case 81: /* delete */
DEBUG(3,("Deleting queue entry %d\n",queue[i].job));
- del_printqueue(conn,vuid,snum,queue[i].job);
+ del_printqueue(conn,&key,snum,queue[i].job);
break;
case 82: /* pause */
case 83: /* resume */
DEBUG(3,("%s queue entry %d\n",
(function==82?"pausing":"resuming"),queue[i].job));
- status_printjob(conn,vuid,snum,queue[i].job,
+ status_printjob(conn,&key,snum,queue[i].job,
(function==82?LPQ_PAUSED:LPQ_QUEUED));
break;
}
@@ -1722,6 +1739,7 @@ static BOOL api_WPrintQueuePurge(connection_struct *conn,uint16 vuid, char *para
char *str2 = skip_string(str1,1);
char *QueueName = skip_string(str2,1);
int snum;
+ vuser_key key = { conn->smbd_pid, vuid };
/* check it's a supported varient */
if (!(strcsequal(str1,"z") && strcsequal(str2,"")))
@@ -1750,17 +1768,19 @@ static BOOL api_WPrintQueuePurge(connection_struct *conn,uint16 vuid, char *para
switch (function) {
case 74: /* Pause queue */
case 75: /* Resume queue */
- status_printqueue(conn,vuid,snum,(function==74?LPSTAT_STOPPED:LPSTAT_OK));
+ {
+ status_printqueue(conn,&key,snum,(function==74?LPSTAT_STOPPED:LPSTAT_OK));
DEBUG(3,("Print queue %s, queue=%s\n",
(function==74?"pause":"resume"),QueueName));
break;
+ }
case 103: /* Purge */
{
print_queue_struct *queue=NULL;
int i, count;
- count = get_printqueue(snum,conn,vuid,&queue,NULL);
+ count = get_printqueue(snum,conn,&key,&queue,NULL);
for (i = 0; i < count; i++)
- del_printqueue(conn,vuid,snum,queue[i].job);
+ del_printqueue(conn,&key,snum,queue[i].job);
if (queue) free(queue);
DEBUG(3,("Print queue purge, queue=%s\n",QueueName));
@@ -1810,6 +1830,7 @@ static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,cha
int i;
char *s = data;
files_struct *fsp;
+ vuser_key key = { conn->smbd_pid, vuid };
printjob_decode(SVAL(p,0), &snum, &jobid);
@@ -1831,7 +1852,7 @@ static BOOL api_PrintJobInfo(connection_struct *conn,uint16 vuid,char *param,cha
int count;
lpq_reset(snum);
- count = get_printqueue(snum,conn,vuid,&queue,NULL);
+ count = get_printqueue(snum,conn,&key,&queue,NULL);
for (i=0;i<count;i++) /* find job */
if ((queue[i].job&0xFF) == jobid) break;
@@ -1916,6 +1937,7 @@ static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *par
int uLevel = SVAL(p,0);
char *p2;
int struct_len;
+ vuser_key key = { conn->smbd_pid, vuid };
DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
@@ -1987,10 +2009,14 @@ static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *par
if (mdrcnt == struct_len) {
SIVAL(p,6,0);
} else {
+ user_struct *vuser = get_valid_user_struct(&key);
SIVAL(p,6,PTR_DIFF(p2,*rdata));
- standard_sub(conn,get_valid_user_struct(vuid), comment);
+ standard_sub(conn,vuser, comment);
StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
p2 = skip_string(p2,1);
+ vuid_free_user_struct(vuser);
+ safe_free(vuser);
+
}
}
if (uLevel > 1)
@@ -2261,11 +2287,12 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param
char *p = skip_string(UserName,1);
int uLevel = SVAL(p,0);
char *p2;
+ vuser_key key = { conn->smbd_pid, vuid };
/* get NIS home of a previously validated user - simeon */
/* With share level security vuid will always be zero.
Don't depend on vuser being non-null !!. JRA */
- user_struct *vuser = get_valid_user_struct(vuid);
+ user_struct *vuser = get_valid_user_struct(&key);
if (vuser != NULL)
DEBUG(3,(" Username of UID %d is %s\n", (int)vuser->uid, vuser->name));
@@ -2283,10 +2310,20 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param
case 2: p2 = "B21BB16DWzzWzDzzzzDDDDWb21WWzWW"; break;
case 10: p2 = "B21Bzzz"; break;
case 11: p2 = "B21BzzzWDDzzDDWWzWzDWb21W"; break;
- default: return False;
+ default:
+ {
+ vuid_free_user_struct(vuser);
+ safe_free(vuser);
+ return False;
+ }
}
- if (strcmp(p2,str2) != 0) return False;
+ if (strcmp(p2,str2) != 0)
+ {
+ vuid_free_user_struct(vuser);
+ safe_free(vuser);
+ return False;
+ }
*rdata_len = mdrcnt + 1024;
*rdata = REALLOC(*rdata,*rdata_len);
@@ -2327,7 +2364,7 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param
SIVAL(p,usri11_auth_flags,AF_OP_PRINT); /* auth flags */
SIVALS(p,usri11_password_age,-1); /* password age */
SIVAL(p,usri11_homedir,PTR_DIFF(p2,p)); /* home dir */
- pstrcpy(p2, lp_logon_path(vuid));
+ pstrcpy(p2, lp_logon_path(&key));
p2 = skip_string(p2,1);
SIVAL(p,usri11_parms,PTR_DIFF(p2,p)); /* parms */
pstrcpy(p2,"");
@@ -2363,7 +2400,7 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param
SSVAL(p,42,
conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
SIVAL(p,44,PTR_DIFF(p2,*rdata)); /* home dir */
- pstrcpy(p2,lp_logon_path(vuid));
+ pstrcpy(p2,lp_logon_path(&key));
p2 = skip_string(p2,1);
SIVAL(p,48,PTR_DIFF(p2,*rdata)); /* comment */
*p2++ = 0;
@@ -2403,6 +2440,9 @@ static BOOL api_RNetUserGetInfo(connection_struct *conn,uint16 vuid, char *param
SSVAL(*rparam,4,*rdata_len); /* is this right?? */
+ vuid_free_user_struct(vuser);
+ safe_free(vuser);
+
return(True);
}
@@ -2468,6 +2508,7 @@ static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param
struct pack_desc desc;
char* name;
char* logon_script;
+ vuser_key key = { conn->smbd_pid, vuid };
uLevel = SVAL(p,0);
name = p + 2;
@@ -2487,6 +2528,7 @@ static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param
if (init_package(&desc,1,0))
{
+ user_struct *vuser = get_valid_user_struct(&key);
PACKI(&desc,"W",0); /* code */
PACKS(&desc,"B21",name); /* eff. name */
PACKS(&desc,"B",""); /* pad */
@@ -2513,8 +2555,10 @@ static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param
/* 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(vuid);
- standard_sub( conn, get_valid_user_struct(vuid), logon_script );
+ logon_script = lp_logon_script(&key);
+ standard_sub( conn, vuser, logon_script );
+ vuid_free_user_struct(vuser);
+ safe_free(vuser);
PACKS(&desc,"z", logon_script); /* script path */
/* End of JHT mods */
@@ -2580,6 +2624,7 @@ static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *para
struct pack_desc desc;
print_queue_struct *queue=NULL;
print_status_struct status;
+ vuser_key key = { conn->smbd_pid, vuid };
uLevel = SVAL(p,2);
@@ -2596,7 +2641,7 @@ static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *para
if (snum < 0 || !VALID_SNUM(snum)) return(False);
- count = get_printqueue(snum,conn,vuid,&queue,&status);
+ count = get_printqueue(snum,conn,&key,&queue,&status);
for (i = 0; i < count; i++) {
if ((queue[i].job & 0xFF) == job) break;
}
@@ -2643,6 +2688,7 @@ static BOOL api_WPrintJobEnumerate(connection_struct *conn,uint16 vuid, char *pa
struct pack_desc desc;
print_queue_struct *queue=NULL;
print_status_struct status;
+ vuser_key key = { conn->smbd_pid, vuid };
bzero(&desc,sizeof(desc));
bzero(&status,sizeof(status));
@@ -2668,7 +2714,7 @@ static BOOL api_WPrintJobEnumerate(connection_struct *conn,uint16 vuid, char *pa
if (snum < 0 || !VALID_SNUM(snum)) return(False);
- count = get_printqueue(snum,conn,vuid,&queue,&status);
+ count = get_printqueue(snum,conn,&key,&queue,&status);
if (mdrcnt > 0) *rdata = REALLOC(*rdata,mdrcnt);
desc.base = *rdata;
desc.buflen = mdrcnt;
diff --git a/source/smbd/open.c b/source/smbd/open.c
index fe20d95ef8b..7608a25d80f 100644
--- a/source/smbd/open.c
+++ b/source/smbd/open.c
@@ -501,7 +501,7 @@ static void open_file(files_struct *fsp,connection_struct *conn,
conn->num_files_open++;
fsp->mode = sbuf->st_mode;
GetTimeOfDay(&fsp->open_time);
- fsp->vuid = current_user.vuid;
+ fsp->vuid = current_user.key.vuid;
fsp->size = 0;
fsp->pos = -1;
fsp->open = True;
@@ -1063,7 +1063,7 @@ int open_directory(files_struct *fsp,connection_struct *conn,
conn->num_files_open++;
fsp->mode = 0;
GetTimeOfDay(&fsp->open_time);
- fsp->vuid = current_user.vuid;
+ fsp->vuid = current_user.key.vuid;
fsp->size = 0;
fsp->pos = -1;
fsp->open = True;
diff --git a/source/smbd/oplock.c b/source/smbd/oplock.c
index 99fe7a69fab..1850c8c9d9a 100644
--- a/source/smbd/oplock.c
+++ b/source/smbd/oplock.c
@@ -697,7 +697,7 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval)
* user, then unbecome the user whilst we're doing this.
*/
saved_conn = fsp->conn;
- saved_vuid = current_user.vuid;
+ saved_vuid = current_user.key.vuid;
dos_GetWd(saved_dir);
unbecome_user();
/* Save the chain fnum. */
diff --git a/source/smbd/password.c b/source/smbd/password.c
index 2141525bc09..005e36c9b85 100644
--- a/source/smbd/password.c
+++ b/source/smbd/password.c
@@ -192,16 +192,18 @@ static char *validate_group(char *group,char *password,int pwlen,int snum,
/****************************************************************************
check for authority to login to a service with a given username/password
****************************************************************************/
-BOOL authorise_login(int snum,char *user, char *domain,
+BOOL authorise_login(int snum, char *user, char *domain,
char *password, int pwlen,
- BOOL *guest,BOOL *force,uint16 vuid)
+ BOOL *guest,BOOL *force,
+ const vuser_key *key)
{
- BOOL ok = False;
-
- *guest = False;
-
+ BOOL ok = False;
+
+ DEBUG(0,("authorise_login: TODO. split function, it's 6 levels!\n"));
+ *guest = False;
+
#if DEBUG_PASSWORD
- DEBUG(100,("checking authorisation on user=%s pass=%s\n",user,password));
+ DEBUG(100,("checking authorisation on user=%s pass=%s\n",user,password));
#endif
/* there are several possibilities:
@@ -216,136 +218,154 @@ BOOL authorise_login(int snum,char *user, char *domain,
if the service is guest_only then steps 1 to 5 are skipped
*/
- if (GUEST_ONLY(snum)) *force = True;
-
- if (!(GUEST_ONLY(snum) && GUEST_OK(snum)))
- {
+ if (GUEST_ONLY(snum)) *force = True;
- user_struct *vuser = get_valid_user_struct(vuid);
-
- /* check the given username and password */
- if (!ok && (*user) && user_ok(user,snum)) {
- ok = password_ok(user,domain, password, pwlen, NULL, 0, NULL, &vuser->usr);
- if (ok) DEBUG(3,("ACCEPTED: given username password ok\n"));
- }
+ if (!(GUEST_ONLY(snum) && GUEST_OK(snum)))
+ {
+ user_struct *vuser = get_valid_user_struct(key);
- /* check for a previously registered guest username */
- if (!ok && (vuser != 0) && vuser->guest) {
- if (user_ok(vuser->name,snum) &&
- password_ok(vuser->name, domain, password, pwlen, NULL, 0, NULL, &vuser->usr)) {
- fstrcpy(user, vuser->name);
- vuser->guest = False;
- DEBUG(3,("ACCEPTED: given password with registered user %s\n", user));
- ok = True;
- }
- }
+ /* check the given username and password */
+ if (!ok && (*user) && user_ok(user,snum))
+ {
+ ok = password_ok(user,domain, password, pwlen, NULL, 0, NULL, &vuser->usr);
+ if (ok) DEBUG(3,("ACCEPTED: given username password ok\n"));
+ }
+ /* check for a previously registered guest username */
+ if (!ok && (vuser != 0) && vuser->guest)
+ {
+ if (user_ok(vuser->name,snum) &&
+ password_ok(vuser->name, domain, password, pwlen, NULL, 0, NULL, &vuser->usr))
+ {
+ fstrcpy(user, vuser->name);
+ vuser->guest = False;
+ DEBUG(3,("ACCEPTED: given password with registered user %s\n", user));
+ ok = True;
+ }
+ }
- /* now check the list of session users */
- if (!ok)
- {
- char *auser;
- char *user_list = strdup(session_users);
- if (!user_list) return False;
- for (auser=strtok(user_list,LIST_SEP);
- !ok && auser;
- auser = strtok(NULL,LIST_SEP))
- {
- fstring user2;
- fstrcpy(user2,auser);
- if (!user_ok(user2,snum)) continue;
-
- if (password_ok(user2, domain, password, pwlen, NULL, 0, NULL,
- &vuser->usr))
- {
- ok = True;
- fstrcpy(user,user2);
- DEBUG(3,("ACCEPTED: session list username and given password ok\n"));
- }
- }
- free(user_list);
- }
+ /* now check the list of session users */
+ if (!ok)
+ {
+ char *auser;
+ char *user_list = strdup(session_users);
+ if (!user_list)
+ {
+ vuid_free_user_struct(vuser);
+ safe_free(vuser);
+ return False;
+ }
+
+ for (auser=strtok(user_list,LIST_SEP);
+ !ok && auser;
+ auser = strtok(NULL,LIST_SEP))
+ {
+ fstring user2;
+ fstrcpy(user2,auser);
+ if (!user_ok(user2,snum)) continue;
+
+ if (password_ok(user2, domain, password, pwlen, NULL, 0, NULL,
+ &vuser->usr))
+ {
+ ok = True;
+ fstrcpy(user,user2);
+ DEBUG(3,("ACCEPTED: session list username and given password ok\n"));
+ }
+ }
+ free(user_list);
+ }
- /* check for a previously validated username/password pair */
- if (!ok && (!lp_revalidate(snum) || lp_security() > SEC_SHARE) &&
- (vuser != 0) && !vuser->guest &&
- user_ok(vuser->name,snum)) {
- fstrcpy(user,vuser->name);
- *guest = False;
- DEBUG(3,("ACCEPTED: validated uid ok as non-guest\n"));
- ok = True;
- }
+ /* check for a previously validated username/password pair */
+ if (!ok && (!lp_revalidate(snum) || lp_security() > SEC_SHARE) &&
+ (vuser != 0) && !vuser->guest &&
+ user_ok(vuser->name,snum))
+ {
+ fstrcpy(user,vuser->name);
+ *guest = False;
+ DEBUG(3,("ACCEPTED: validated uid ok as non-guest\n"));
+ ok = True;
+ }
- /* check for a rhosts entry */
- if (!ok && user_ok(user,snum) && check_hosts_equiv(user)) {
- ok = True;
- DEBUG(3,("ACCEPTED: hosts equiv or rhosts entry\n"));
- }
+ /* check for a rhosts entry */
+ if (!ok && user_ok(user,snum) && check_hosts_equiv(user))
+ {
+ ok = True;
+ DEBUG(3,("ACCEPTED: hosts equiv or rhosts entry\n"));
+ }
- /* check the user= fields and the given password */
- if (!ok && lp_username(snum)) {
- char *auser;
- pstring user_list;
- StrnCpy(user_list,lp_username(snum),sizeof(pstring));
+ /* check the user= fields and the given password */
+ if (!ok && lp_username(snum))
+ {
+ char *auser;
+ pstring user_list;
+ StrnCpy(user_list,lp_username(snum),sizeof(pstring));
+
+ string_sub(user_list,"%S",lp_servicename(snum));
+
+ for (auser=strtok(user_list,LIST_SEP);
+ auser && !ok;
+ auser = strtok(NULL,LIST_SEP))
+ {
+ if (*auser == '@')
+ {
+ auser = validate_group(auser+1,password,pwlen,snum, &vuser->usr);
+ if (auser)
+ {
+ ok = True;
+ fstrcpy(user,auser);
+ DEBUG(3,("ACCEPTED: group username and given password ok\n"));
+ }
+ }
+ else
+ {
+ fstring user2;
+ fstrcpy(user2,auser);
+ if (user_ok(user2,snum) &&
+ password_ok(user2,domain,password,pwlen,NULL, 0,
+ NULL, &vuser->usr))
+ {
+ ok = True;
+ fstrcpy(user,user2);
+ DEBUG(3,("ACCEPTED: user list username and given password ok\n"));
+ }
+ }
+ }
+ }
+
+ if (vuser != NULL)
+ {
+ tdb_store_vuid(key, vuser);
+ }
+ vuid_free_user_struct(vuser);
+ safe_free(vuser);
- string_sub(user_list,"%S",lp_servicename(snum));
-
- for (auser=strtok(user_list,LIST_SEP);
- auser && !ok;
- auser = strtok(NULL,LIST_SEP))
- {
- if (*auser == '@')
- {
- auser = validate_group(auser+1,password,pwlen,snum, &vuser->usr);
- if (auser)
- {
- ok = True;
- fstrcpy(user,auser);
- DEBUG(3,("ACCEPTED: group username and given password ok\n"));
- }
- }
- else
- {
- fstring user2;
- fstrcpy(user2,auser);
- if (user_ok(user2,snum) &&
- password_ok(user2,domain,password,pwlen,NULL, 0,
- NULL, &vuser->usr))
- {
- ok = True;
- fstrcpy(user,user2);
- DEBUG(3,("ACCEPTED: user list username and given password ok\n"));
- }
- }
- }
- }
- } /* not guest only */
+ } /* not guest only */
- /* check for a normal guest connection */
- if (!ok && GUEST_OK(snum))
- {
- fstring guestname;
- StrnCpy(guestname,lp_guestaccount(snum),sizeof(guestname)-1);
- if (Get_Pwnam(guestname,True))
+ /* check for a normal guest connection */
+ if (!ok && GUEST_OK(snum))
{
- fstrcpy(user,guestname);
- ok = True;
- DEBUG(3,("ACCEPTED: guest account and guest ok\n"));
+ fstring guestname;
+ StrnCpy(guestname,lp_guestaccount(snum),sizeof(guestname)-1);
+ if (Get_Pwnam(guestname,True))
+ {
+ fstrcpy(user,guestname);
+ ok = True;
+ DEBUG(3,("ACCEPTED: guest account and guest ok\n"));
+ }
+ else
+ DEBUG(0,("Invalid guest account %s??\n",guestname));
+ *guest = True;
+ *force = True;
}
- else
- DEBUG(0,("Invalid guest account %s??\n",guestname));
- *guest = True;
- *force = True;
- }
- if (ok && !user_ok(user,snum))
- {
- DEBUG(0,("rejected invalid user %s\n",user));
- ok = False;
- }
+ if (ok && !user_ok(user,snum))
+ {
+ DEBUG(0,("rejected invalid user %s\n",user));
+ ok = False;
+ }
- return(ok);
+ return(ok);
}
diff --git a/source/smbd/process.c b/source/smbd/process.c
index d391914f600..e95135a484a 100644
--- a/source/smbd/process.c
+++ b/source/smbd/process.c
@@ -435,14 +435,20 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize
* move it unless you know what you're doing... :-).
* JRA.
*/
- if (session_tag != last_session_tag) {
+ if (session_tag != last_session_tag)
+ {
user_struct *vuser = NULL;
+ vuser_key key = { pid, session_tag };
last_session_tag = session_tag;
if(session_tag != UID_FIELD_INVALID)
- vuser = get_valid_user_struct(session_tag);
+ vuser = get_valid_user_struct(&key);
if(vuser != NULL)
+ {
pstrcpy( sesssetup_user, vuser->requested_name);
+ vuid_free_user_struct(vuser);
+ safe_free(vuser);
+ }
}
/* does this protocol need to be run as root? */
diff --git a/source/smbd/reply.c b/source/smbd/reply.c
index cee776351a6..51842b9462f 100644
--- a/source/smbd/reply.c
+++ b/source/smbd/reply.c
@@ -384,6 +384,7 @@ static int session_trust_account(connection_struct *conn,
if (last_challenge(last_chal))
{
NET_USER_INFO_3 info3;
+ ZERO_STRUCT(info3);
status = check_domain_security(user, domain,
last_chal,
(uchar *)smb_passwd, smb_passlen,
@@ -426,6 +427,8 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int
BOOL doencrypt = SMBENCRYPT();
char *domain = "";
+ ZERO_STRUCT(info3);
+
*smb_apasswd = 0;
*smb_ntpasswd = 0;
@@ -693,7 +696,7 @@ user %s attempted down-level SMB connection\n", user));
/* register the name and uid as being validated, so further connections
to a uid can get through without a password, on the same VC */
- sess_vuid = register_vuid(uid,gid,user,sesssetup_user,guest,&info3);
+ sess_vuid = register_vuid(getpid(), uid,gid,user,sesssetup_user,guest,&info3);
SSVAL(outbuf,smb_uid,sess_vuid);
SSVAL(inbuf,smb_uid,sess_vuid);
@@ -1450,9 +1453,14 @@ int reply_open_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
{
uint16 vuid = SVAL(inbuf,smb_uid);
- user_struct *vuser = get_valid_user_struct(vuid);
+ vuser_key key;
+ user_struct *vuser = NULL;
+ key.pid = conn != NULL ? conn->smbd_pid : getpid();
+ key.vuid = vuid;
+ vuser = get_valid_user_struct(&key);
- if(vuser == 0) {
+ if (vuser == 0)
+ {
DEBUG(3,("ulogoff, vuser id %d does not map to user.\n", vuid));
}
@@ -1462,7 +1470,7 @@ int reply_ulogoffX(connection_struct *conn, char *inbuf,char *outbuf,int length,
file_close_user(vuid);
}
- invalidate_vuid(vuid);
+ invalidate_vuid(&key);
set_message(outbuf,2,0,True);
@@ -2764,6 +2772,7 @@ int reply_printqueue(connection_struct *conn,
int max_count = SVAL(inbuf,smb_vwv0);
int start_index = SVAL(inbuf,smb_vwv1);
uint16 vuid = SVAL(inbuf,smb_uid);
+ vuser_key key = { conn->smbd_pid, vuid };
/* we used to allow the client to get the cnum wrong, but that
is really quite gross and only worked when there was only
@@ -2783,7 +2792,7 @@ int reply_printqueue(connection_struct *conn,
{
print_queue_struct *queue = NULL;
char *p = smb_buf(outbuf) + 3;
- int count = get_printqueue(SNUM(conn), conn, vuid, &queue,NULL);
+ int count = get_printqueue(SNUM(conn), conn, &key, &queue,NULL);
int num_to_get = ABS(max_count);
int first = (max_count>0?start_index:start_index+max_count+1);
int i;
diff --git a/source/smbd/service.c b/source/smbd/service.c
index 8a0ba725b09..a251cfcfa63 100644
--- a/source/smbd/service.c
+++ b/source/smbd/service.c
@@ -202,6 +202,10 @@ connection_struct *make_connection(char *service,char *user,
BOOL force = False;
extern int Client;
connection_struct *conn;
+ vuser_key key;
+
+ key.pid = getpid();
+ key.vuid = vuid;
strlower(service);
@@ -224,9 +228,12 @@ connection_struct *make_connection(char *service,char *user,
return(make_connection(user,user,domain,password,
pwlen,dev,vuid,ecode));
- if(lp_security() != SEC_SHARE) {
- if (validated_username(vuid)) {
- pstrcpy(user,validated_username(vuid));
+ if(lp_security() != SEC_SHARE)
+ {
+ fstring user_name;
+ if (validated_username(&key, user_name, sizeof(user_name)))
+ {
+ pstrcpy(user, user_name);
return(make_connection(user,user,domain,password,pwlen,dev,vuid,ecode));
}
} else {
@@ -273,7 +280,7 @@ connection_struct *make_connection(char *service,char *user,
add_session_user(service);
/* shall we let them in? */
- if (!authorise_login(snum,user,domain,password,pwlen,&guest,&force,vuid))
+ if (!authorise_login(snum,user,domain,password,pwlen,&guest,&force,&key))
{
DEBUG( 2, ( "Invalid username/password for %s\n", service ) );
*ecode = ERRbadpw;
@@ -411,8 +418,11 @@ connection_struct *make_connection(char *service,char *user,
{
pstring s;
+ user_struct *vuser = get_valid_user_struct(&key);
pstrcpy(s,lp_pathname(snum));
- standard_sub(conn,get_valid_user_struct(vuid), s);
+ standard_sub(conn,vuser, s);
+ vuid_free_user_struct(vuser);
+ safe_free(vuser);
string_set(&conn->connectpath,s);
DEBUG(3,("Connect path is %s\n",s));
}
@@ -444,10 +454,14 @@ connection_struct *make_connection(char *service,char *user,
} /* IS_IPC */
/* execute any "root preexec = " line */
- if (*lp_rootpreexec(SNUM(conn))) {
+ if (*lp_rootpreexec(SNUM(conn)))
+ {
pstring cmd;
+ user_struct *vuser = get_valid_user_struct(&key);
pstrcpy(cmd,lp_rootpreexec(SNUM(conn)));
- standard_sub(conn,get_valid_user_struct(vuid), cmd);
+ standard_sub(conn,vuser, cmd);
+ vuid_free_user_struct(vuser);
+ safe_free(vuser);
DEBUG(5,("cmd=%s\n",cmd));
smbrun(cmd,NULL,False);
}
@@ -499,10 +513,14 @@ connection_struct *make_connection(char *service,char *user,
add_session_user(user);
/* execute any "preexec = " line */
- if (*lp_preexec(SNUM(conn))) {
+ if (*lp_preexec(SNUM(conn)))
+ {
pstring cmd;
+ user_struct *vuser = get_valid_user_struct(&key);
pstrcpy(cmd,lp_preexec(SNUM(conn)));
- standard_sub(conn,get_valid_user_struct(vuid), cmd);
+ standard_sub(conn,vuser, cmd);
+ vuid_free_user_struct(vuser);
+ safe_free(vuser);
smbrun(cmd,NULL,False);
}
@@ -522,7 +540,7 @@ connection_struct *make_connection(char *service,char *user,
dbgtext( "connect to service %s ", lp_servicename(SNUM(conn)));
dbgtext( "as user %s ", user );
dbgtext( "(uid=%d, gid=%d) ", (int)conn->uid, (int)conn->gid );
- dbgtext( "(pid %d)\n", (int)getpid() );
+ dbgtext( "(pid %d)\n", (int)key.pid );
}
/* Invoke make connection hook */
@@ -576,6 +594,8 @@ close a cnum
****************************************************************************/
void close_cnum(connection_struct *conn, uint16 vuid)
{
+ vuser_key key = { conn->smbd_pid, vuid };
+
DirCacheFlush(SNUM(conn));
unbecome_user();
@@ -612,20 +632,28 @@ void close_cnum(connection_struct *conn, uint16 vuid)
/* execute any "postexec = " line */
if (*lp_postexec(SNUM(conn)) &&
- become_user(conn, vuid)) {
+ become_user(conn, vuid))
+ {
+ user_struct *vuser = get_valid_user_struct(&key);
pstring cmd;
pstrcpy(cmd,lp_postexec(SNUM(conn)));
- standard_sub(conn,get_valid_user_struct(vuid), cmd);
+ standard_sub(conn,vuser, cmd);
+ vuid_free_user_struct(vuser);
+ safe_free(vuser);
smbrun(cmd,NULL,False);
unbecome_user();
}
unbecome_user();
/* execute any "root postexec = " line */
- if (*lp_rootpostexec(SNUM(conn))) {
+ if (*lp_rootpostexec(SNUM(conn)))
+ {
+ user_struct *vuser = get_valid_user_struct(&key);
pstring cmd;
pstrcpy(cmd,lp_rootpostexec(SNUM(conn)));
- standard_sub(conn,get_valid_user_struct(vuid), cmd);
+ standard_sub(conn,vuser, cmd);
+ vuid_free_user_struct(vuser);
+ safe_free(vuser);
smbrun(cmd,NULL,False);
}
diff --git a/source/smbd/uid.c b/source/smbd/uid.c
index bbaf73eef06..6b05cfda2f4 100644
--- a/source/smbd/uid.c
+++ b/source/smbd/uid.c
@@ -30,7 +30,17 @@ extern struct current_user current_user;
****************************************************************************/
BOOL become_user(connection_struct *conn, uint16 vuid)
{
- user_struct *vuser = get_valid_user_struct(vuid);
+ vuser_key key;
+ key.pid = getpid();
+ key.vuid = vuid;
+ return become_userk(conn, &key);
+}
+/****************************************************************************
+ Become the user of a connection number.
+****************************************************************************/
+BOOL become_userk(connection_struct *conn, const vuser_key *key)
+{
+ user_struct *vuser = NULL;
int snum;
gid_t gid = -1;
uid_t uid = -1;
@@ -55,13 +65,21 @@ BOOL become_user(connection_struct *conn, uint16 vuid)
(current_user.uid == conn->uid))
{
DEBUG(4,("Skipping become_user - already user\n"));
+
return(True);
}
- else if ((current_user.conn == conn) &&
- (vuser != NULL) && (current_user.vuid == vuid) &&
+
+ vuser = get_valid_user_struct(key);
+
+ if ((current_user.conn == conn) &&
+ (vuser != NULL) &&
+ (current_user.key.vuid == key->vuid) &&
+ (current_user.key.pid == key->pid) &&
(current_user.uid == vuser->uid))
{
DEBUG(4,("Skipping become_user - already user\n"));
+ vuid_free_user_struct(vuser);
+ safe_free(vuser);
return(True);
}
@@ -70,7 +88,11 @@ BOOL become_user(connection_struct *conn, uint16 vuid)
snum = SNUM(conn);
if((vuser != NULL) && !check_vuser_ok(&conn->uid_cache, vuser, snum))
+ {
+ vuid_free_user_struct(vuser);
+ safe_free(vuser);
return False;
+ }
if (conn->force_user ||
lp_security() == SEC_SHARE ||
@@ -81,7 +103,7 @@ BOOL become_user(connection_struct *conn, uint16 vuid)
ngroups = conn->ngroups;
} else {
if (!vuser) {
- DEBUG(2,("Invalid vuid used %d\n",vuid));
+ DEBUG(2,("Invalid vuid used %d\n",key->vuid));
return(False);
}
uid = vuser->uid;
@@ -118,7 +140,10 @@ BOOL become_user(connection_struct *conn, uint16 vuid)
}
}
- return become_unix_sec_ctx(vuid, conn, uid, gid, ngroups, groups);
+ vuid_free_user_struct(vuser);
+ safe_free(vuser);
+
+ return become_unix_sec_ctx(key, conn, uid, gid, ngroups, groups);
}
/****************************************************************************