summaryrefslogtreecommitdiff
path: root/source3/smbd
diff options
context:
space:
mode:
Diffstat (limited to 'source3/smbd')
-rw-r--r--source3/smbd/close.c2
-rw-r--r--source3/smbd/ipc.c27
-rw-r--r--source3/smbd/password.c10
-rw-r--r--source3/smbd/uid.c124
4 files changed, 127 insertions, 36 deletions
diff --git a/source3/smbd/close.c b/source3/smbd/close.c
index 024a3c03e4..c37c2ceab2 100644
--- a/source3/smbd/close.c
+++ b/source3/smbd/close.c
@@ -129,7 +129,7 @@ void close_file(files_struct *fsp, BOOL normal_close)
/* NT uses smbclose to start a print - weird */
if (normal_close && fsp->print_file)
- print_file(conn, fsp);
+ print_file(conn, SNUM(conn), fsp);
/* check for magic scripts */
if (normal_close) {
diff --git a/source3/smbd/ipc.c b/source3/smbd/ipc.c
index a3e7932529..eeb367bcb5 100644
--- a/source3/smbd/ipc.c
+++ b/source3/smbd/ipc.c
@@ -3118,21 +3118,14 @@ static BOOL api_WPrintPortEnum(connection_struct *conn,uint16 vuid, char *param,
}
static void api_rpc_trans_reply(char *outbuf,
- pipes_struct *p,
- prs_struct *pd)
+ pipes_struct *p)
{
- send_trans_reply(outbuf, p->rhdr.data, NULL, NULL, 0, p->file_offset);
+ send_trans_reply(outbuf, p->rsmb_pdu.data, NULL, NULL, 0, p->file_offset);
- if (mem_buf_len(p->rhdr.data) <= p->file_offset)
+ if (mem_buf_len(p->rsmb_pdu.data) <= p->file_offset)
{
/* all of data was sent: no need to wait for SMBreadX calls */
- mem_free_data(p->rhdr .data);
- mem_free_data(p->rfault .data);
- mem_free_data(p->rdata .data);
- mem_free_data(p->rdata_i.data);
- mem_free_data(p->rauth .data);
- mem_free_data(p->rverf .data);
- mem_free_data(p->rntlm .data);
+ mem_free_data(p->rsmb_pdu.data);
}
}
@@ -3221,14 +3214,9 @@ static int api_fd_reply(connection_struct *conn,uint16 vuid,char *outbuf,
uint16 pnum;
uint16 subcommand;
pipes_struct *p = NULL;
- prs_struct pd;
DEBUG(5,("api_fd_reply\n"));
- /* make a static data parsing structure from the api_fd_reply data */
- prs_init(&pd, 0, 4, 0, True);
- mem_create(pd.data, data, 0, tdscnt, 0, False);
-
/* First find out the name of this file. */
if (suwcnt != 2)
{
@@ -3257,11 +3245,10 @@ static int api_fd_reply(connection_struct *conn,uint16 vuid,char *outbuf,
{
case 0x26:
{
- /* dce/rpc command */
- reply = rpc_command(p, &pd);
+ reply = rpc_to_smb(p, data, tdscnt);
if (reply)
{
- api_rpc_trans_reply(outbuf, p, &pd);
+ api_rpc_trans_reply(outbuf, p);
}
break;
}
@@ -3284,8 +3271,6 @@ static int api_fd_reply(connection_struct *conn,uint16 vuid,char *outbuf,
DEBUG(1,("api_fd_reply: INVALID PIPE HANDLE: %x\n", pnum));
}
- mem_free_data(pd.data);
-
if (!reply)
{
return api_no_reply(outbuf, mdrcnt);
diff --git a/source3/smbd/password.c b/source3/smbd/password.c
index 240ec30c3f..91f727701c 100644
--- a/source3/smbd/password.c
+++ b/source3/smbd/password.c
@@ -221,14 +221,14 @@ BOOL authorise_login(int snum,char *user,char *password, int pwlen,
/* check the given username and password */
if (!ok && (*user) && user_ok(user,snum)) {
- ok = password_ok(user,password, pwlen, NULL, vuser->dc.user_sess_key);
+ ok = password_ok(user,password, pwlen, NULL, vuser->user_sess_key);
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, password, pwlen, NULL, vuser->dc.user_sess_key)) {
+ password_ok(vuser->name, password, pwlen, NULL, vuser->user_sess_key)) {
fstrcpy(user, vuser->name);
vuser->guest = False;
DEBUG(3,("ACCEPTED: given password with registered user %s\n", user));
@@ -252,7 +252,7 @@ BOOL authorise_login(int snum,char *user,char *password, int pwlen,
fstrcpy(user2,auser);
if (!user_ok(user2,snum)) continue;
- if (password_ok(user2,password, pwlen, NULL, vuser->dc.user_sess_key)) {
+ if (password_ok(user2,password, pwlen, NULL, vuser->user_sess_key)) {
ok = True;
fstrcpy(user,user2);
DEBUG(3,("ACCEPTED: session list username and given password ok\n"));
@@ -291,7 +291,7 @@ BOOL authorise_login(int snum,char *user,char *password, int pwlen,
{
if (*auser == '@')
{
- auser = validate_group(auser+1,password,pwlen,snum, vuser->dc.user_sess_key);
+ auser = validate_group(auser+1,password,pwlen,snum, vuser->user_sess_key);
if (auser)
{
ok = True;
@@ -304,7 +304,7 @@ BOOL authorise_login(int snum,char *user,char *password, int pwlen,
fstring user2;
fstrcpy(user2,auser);
if (user_ok(user2,snum) &&
- password_ok(user2,password,pwlen,NULL, vuser->dc.user_sess_key))
+ password_ok(user2,password,pwlen,NULL, vuser->user_sess_key))
{
ok = True;
fstrcpy(user,user2);
diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c
index 92565b7507..3501879d5f 100644
--- a/source3/smbd/uid.c
+++ b/source3/smbd/uid.c
@@ -25,6 +25,7 @@ extern int DEBUGLEVEL;
static uid_t initial_uid;
static gid_t initial_gid;
+static struct uid_cache vcache;
/* what user is current? */
extern struct current_user current_user;
@@ -54,6 +55,8 @@ void init_uid(void)
current_user.conn = NULL;
current_user.vuid = UID_FIELD_INVALID;
+ vcache.entries = 0;
+
dos_ChDir(OriginalDir);
}
@@ -192,19 +195,19 @@ BOOL become_guest(void)
/*******************************************************************
check if a username is OK
********************************************************************/
-static BOOL check_user_ok(connection_struct *conn, user_struct *vuser,int snum)
+static BOOL check_vuser_ok(struct uid_cache *cache, user_struct *vuser,int snum)
{
int i;
- for (i=0;i<conn->uid_cache.entries;i++)
- if (conn->uid_cache.list[i] == vuser->uid) return(True);
+ for (i=0;i<cache->entries;i++)
+ if (cache->list[i] == vuser->uid) return(True);
if (!user_ok(vuser->name,snum)) return(False);
- i = conn->uid_cache.entries % UID_CACHE_SIZE;
- conn->uid_cache.list[i] = vuser->uid;
+ i = cache->entries % UID_CACHE_SIZE;
+ cache->list[i] = vuser->uid;
- if (conn->uid_cache.entries < UID_CACHE_SIZE)
- conn->uid_cache.entries++;
+ if (cache->entries < UID_CACHE_SIZE)
+ cache->entries++;
return(True);
}
@@ -213,11 +216,114 @@ static BOOL check_user_ok(connection_struct *conn, user_struct *vuser,int snum)
/****************************************************************************
become the user of a connection number
****************************************************************************/
+BOOL become_vuser(uint16 vuid)
+{
+ user_struct *vuser = get_valid_user_struct(vuid);
+ gid_t gid;
+ uid_t uid;
+
+ unbecome_vuser();
+
+ if((vuser != NULL) && !check_vuser_ok(&vcache, vuser, -1))
+ return False;
+
+ if ( vuser != 0 &&
+ current_user.vuid == vuid &&
+ current_user.uid == vuser->uid)
+ {
+ DEBUG(4,("Skipping become_vuser - already user\n"));
+ return(True);
+ }
+ uid = vuser->uid;
+ gid = vuser->gid;
+ current_user.ngroups = vuser->n_groups;
+ current_user.groups = vuser->groups;
+
+ if (initial_uid == 0)
+ {
+ if (!become_gid(gid)) return(False);
+
+#ifdef HAVE_SETGROUPS
+ /* groups stuff added by ih/wreu */
+ if (current_user.ngroups > 0)
+ {
+ if (setgroups(current_user.ngroups,
+ current_user.groups)<0) {
+ DEBUG(0,("setgroups call failed!\n"));
+ }
+ }
+#endif
+
+ if (!become_uid(uid)) return(False);
+ }
+
+ current_user.conn = NULL;
+ current_user.vuid = vuid;
+
+ DEBUG(5,("become_vuser uid=(%d,%d) gid=(%d,%d)\n",
+ (int)getuid(),(int)geteuid(),(int)getgid(),(int)getegid()));
+
+ return(True);
+}
+
+/****************************************************************************
+ unbecome a user
+****************************************************************************/
+BOOL unbecome_vuser(void)
+{
+ dos_ChDir(OriginalDir);
+
+ if (initial_uid == 0)
+ {
+#ifdef HAVE_SETRESUID
+ setresuid(-1,getuid(),-1);
+ setresgid(-1,getgid(),-1);
+#else
+ if (seteuid(initial_uid) != 0)
+ setuid(initial_uid);
+ setgid(initial_gid);
+#endif
+ }
+
+#ifdef NO_EID
+ if (initial_uid == 0)
+ DEBUG(2,("Running with no EID\n"));
+ initial_uid = getuid();
+ initial_gid = getgid();
+#else
+ if (geteuid() != initial_uid) {
+ DEBUG(0,("Warning: You appear to have a trapdoor uid system\n"));
+ initial_uid = geteuid();
+ }
+ if (getegid() != initial_gid) {
+ DEBUG(0,("Warning: You appear to have a trapdoor gid system\n"));
+ initial_gid = getegid();
+ }
+#endif
+
+ current_user.uid = initial_uid;
+ current_user.gid = initial_gid;
+
+ if (dos_ChDir(OriginalDir) != 0)
+ DEBUG( 0, ( "chdir(%s) failed in unbecome_vuser\n", OriginalDir ) );
+
+ DEBUG(5,("unbecome_vuser now uid=(%d,%d) gid=(%d,%d)\n",
+ (int)getuid(),(int)geteuid(),(int)getgid(),(int)getegid()));
+
+ current_user.conn = NULL;
+ current_user.vuid = UID_FIELD_INVALID;
+
+ return(True);
+}
+
+/****************************************************************************
+ become the user of a connection number
+****************************************************************************/
BOOL become_user(connection_struct *conn, uint16 vuid)
{
user_struct *vuser = get_valid_user_struct(vuid);
int snum;
- gid_t gid;
+ gid_t gid;
uid_t uid;
/*
@@ -247,7 +353,7 @@ BOOL become_user(connection_struct *conn, uint16 vuid)
snum = SNUM(conn);
- if((vuser != NULL) && !check_user_ok(conn, vuser, snum))
+ if((vuser != NULL) && !check_vuser_ok(&conn->uid_cache, vuser, snum))
return False;
if (conn->force_user ||