diff options
Diffstat (limited to 'source3/smbd')
-rw-r--r-- | source3/smbd/close.c | 2 | ||||
-rw-r--r-- | source3/smbd/ipc.c | 27 | ||||
-rw-r--r-- | source3/smbd/password.c | 10 | ||||
-rw-r--r-- | source3/smbd/uid.c | 124 |
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 || |