From d57e67f9eb5a6a05f0e173d48e86dd1fe050635e Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 14 Jul 2009 11:25:45 -0700 Subject: Revert this commit : s3: Make smbd aware of permission change of usershare. Since usershare are relatively volatile and non-previledge users must disconnect from smbd and reconnect to it to make share permission in effect. For now. This is a feature request and I think we need to design it a little differently so as not to touch core change_to_user() code. Jeremy. --- source3/include/proto.h | 7 +--- source3/include/smb.h | 6 --- source3/param/loadparm.c | 11 +++++ source3/smbd/conn.c | 1 - source3/smbd/notify_inotify.c | 4 +- source3/smbd/process.c | 58 +------------------------- source3/smbd/service.c | 80 ------------------------------------ source3/smbd/uid.c | 96 +++++++++++-------------------------------- 8 files changed, 39 insertions(+), 224 deletions(-) diff --git a/source3/include/proto.h b/source3/include/proto.h index d141de44cf..0dd1e98c86 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -4296,7 +4296,6 @@ enum usershare_err parse_usershare_file(TALLOC_CTX *ctx, char **pp_comment, SEC_DESC **ppsd, bool *pallow_guest); -bool am_usershare(int iService); int load_usershare_service(const char *servicename); int load_usershare_shares(void); void gfree_loadparm(void); @@ -7064,8 +7063,7 @@ void reply_transs2(struct smb_request *req); bool change_to_guest(void); void conn_clear_vuid_cache(connection_struct *conn, uint16_t vuid); -bool change_to_user_force_recheck(connection_struct *conn, uint16 vuid, - bool recheck, NTSTATUS *pstatus); +bool change_to_user(connection_struct *conn, uint16 vuid); bool change_to_root_user(void); bool become_authenticated_pipe_user(pipes_struct *p); bool unbecome_authenticated_pipe_user(void); @@ -7074,9 +7072,6 @@ void unbecome_root(void); bool become_user(connection_struct *conn, uint16 vuid); bool unbecome_user(void); -#define change_to_user(conn, vuid) \ - change_to_user_force_recheck(conn, vuid, 0, NULL) - /* The following definitions come from smbd/utmp.c */ void sys_utmp_claim(const char *username, const char *hostname, diff --git a/source3/include/smb.h b/source3/include/smb.h index 44216f856a..2e9cf1b54a 100644 --- a/source3/include/smb.h +++ b/source3/include/smb.h @@ -550,7 +550,6 @@ typedef struct connection_struct { unsigned cnum; /* an index passed over the wire */ struct share_params *params; bool force_user; - bool force_recheck_perm; struct vuid_cache vuid_cache; struct dptr_struct *dirptr; bool printer; @@ -1399,11 +1398,6 @@ struct bitmap { #define FILE_NOTIFY_CHANGE_STREAM_NAME 0x00000200 #define FILE_NOTIFY_CHANGE_STREAM_SIZE 0x00000400 #define FILE_NOTIFY_CHANGE_STREAM_WRITE 0x00000800 -#define FILE_NOTIFY_CHANGE_FILE_CONTENT \ - (FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME \ - | FILE_NOTIFY_CHANGE_ATTRIBUTES | FILE_NOTIFY_CHANGE_SIZE \ - | FILE_NOTIFY_CHANGE_CREATION | FILE_NOTIFY_CHANGE_EA \ - | FILE_NOTIFY_CHANGE_SECURITY) #define FILE_NOTIFY_CHANGE_NAME \ (FILE_NOTIFY_CHANGE_FILE_NAME|FILE_NOTIFY_CHANGE_DIR_NAME) diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c index 4415804a2d..5d3ac9207e 100644 --- a/source3/param/loadparm.c +++ b/source3/param/loadparm.c @@ -8740,6 +8740,17 @@ bool am_usershare(int iService) return false; } +/*************************************************************************** +Am I a usershare service? +***************************************************************************/ +bool am_usershare(int iService) +{ + if (iService >= 0) { + return (ServicePtrs[iService]->usershare == USERSHARE_VALID); + } + return false; +} + /*************************************************************************** Checks if a usershare entry has been modified since last load. ***************************************************************************/ diff --git a/source3/smbd/conn.c b/source3/smbd/conn.c index 3ddb4c094f..af6e0919a4 100644 --- a/source3/smbd/conn.c +++ b/source3/smbd/conn.c @@ -155,7 +155,6 @@ find_again: return NULL; } conn->cnum = i; - conn->force_recheck_perm = false; conn->force_group_gid = (gid_t)-1; bitmap_set(sconn->smb1.tcons.bmap, i); diff --git a/source3/smbd/notify_inotify.c b/source3/smbd/notify_inotify.c index b6be69c8fd..26570a2216 100644 --- a/source3/smbd/notify_inotify.c +++ b/source3/smbd/notify_inotify.c @@ -316,9 +316,7 @@ static const struct { {FILE_NOTIFY_CHANGE_LAST_WRITE, IN_ATTRIB}, {FILE_NOTIFY_CHANGE_LAST_ACCESS, IN_ATTRIB}, {FILE_NOTIFY_CHANGE_EA, IN_ATTRIB}, - {FILE_NOTIFY_CHANGE_SECURITY, IN_ATTRIB}, - {FILE_NOTIFY_CHANGE_FILE_CONTENT, IN_MODIFY|IN_DELETE|IN_CREATE|IN_DELETE_SELF - |IN_MOVE_SELF|IN_MOVED_FROM|IN_MOVED_TO}, + {FILE_NOTIFY_CHANGE_SECURITY, IN_ATTRIB} }; static uint32_t inotify_map(struct notify_entry *e) diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 5b8a325d22..b26bc150db 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -1286,6 +1286,7 @@ static connection_struct *switch_message(uint8 type, struct smb_request *req, in } } } + /* Does this call need to be run as the connected user? */ if (flags & AS_USER) { @@ -1302,67 +1303,12 @@ static connection_struct *switch_message(uint8 type, struct smb_request *req, in } return NULL; } -#ifdef HAVE_INOTIFY - if (conn->force_recheck_perm) { - int old; - int iService = -1; - const char *service = NULL; - NTSTATUS status = NT_STATUS_UNSUCCESSFUL; - conn->force_recheck_perm = false; - DEBUG(5, ("switch_message: rechecking permission for connection %x\n", - (unsigned int)conn)); - old = SNUM(conn); - service = lp_servicename(old); - conn->read_only = False; - if (lp_snum_ok(old) && am_usershare(old)) { - iService = load_usershare_service(service); - if (iService < 0 || old != iService) { - /* non-exist service */ - DEBUG(5, ("switch_message: deleting connection %x\n", - (unsigned int)conn)); - DEBUG(5, ("snum %d, sname %s\n", - old, service ? service : "NULL")); - delete_share_security(service); - set_current_service(NULL, 0, True); - close_cnum(smbd_server_conn, conn, conn->vuid); - lp_killservice(old); - reply_nterror(req, NT_STATUS_BAD_NETWORK_NAME); - return NULL; - } - - /* - * Don't have to reauthentication here, but - * need to check share permissions..... - * the vuid cache is a problem.. - */ - - if (!change_to_root_user()) { - smb_panic("cann't change to root user!\n"); - } - - if (!change_to_user_force_recheck(conn, session_tag, - True, &status)) { - reply_nterror(req, status); - remove_deferred_open_smb_message(req->mid); - return conn; - } - } - } else { - NTSTATUS status = NT_STATUS_UNSUCCESSFUL; - if (!change_to_user_force_recheck(conn, session_tag, - False, &status)) { - reply_nterror(req, status); - remove_deferred_open_smb_message(req->mid); - return conn; - } - } -#else + if (!change_to_user(conn,session_tag)) { reply_nterror(req, NT_STATUS_DOS(ERRSRV, ERRbaduid)); remove_deferred_open_smb_message(req->mid); return conn; } -#endif /* All NEED_WRITE and CAN_IPC flags must also have AS_USER. */ diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 8ae13b14f3..0124b2b047 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -630,33 +630,6 @@ static NTSTATUS create_connection_server_info(struct smbd_server_connection *sco return NT_STATUS_ACCESS_DENIED; } -#ifdef HAVE_INOTIFY -static void share_perm_changed(struct sys_notify_context *ctx, - void *ptr, struct notify_event *ev) -{ - connection_struct *conn = talloc_get_type_abort(ptr, connection_struct); - const char *service = NULL; - service = lp_servicename(SNUM(conn)); - if (strequal(ev->path, service)) { - conn->force_recheck_perm = true; - DEBUG(0, ("share_perm_changed: set recheck flag for connection %x\n", - (unsigned int)conn)); - } -} - -struct notify_context { - struct db_context *db_recursive; - struct db_context *db_onelevel; - struct server_id server; - struct messaging_context *messaging_ctx; - struct notify_list *list; - struct notify_array *array; - int seqnum; - struct sys_notify_context *sys_notify_ctx; - TDB_DATA key; -}; -#endif - /**************************************************************************** Make a connection, given the snum to connect to, and the vuser of the @@ -894,64 +867,11 @@ connection_struct *make_connection_snum(struct smbd_server_connection *sconn, } if ((!conn->printer) && (!conn->ipc)) { -#ifdef HAVE_INOTIFY - struct sys_notify_context *sys_ctx = NULL; - struct notify_entry e; - struct inotify_watch_context *w = NULL; -#endif conn->notify_ctx = notify_init(conn, server_id_self(), smbd_messaging_context(), smbd_event_context(), conn); -#ifdef HAVE_INOTIFY - /* - * here is the start of monitoring share permissions change. - * For usershares, we have to watch on both - * get_dyn_STATDIR()/servicename and get_dyn_STATDIR()/share_info.tdb. - * For shares in smb.conf, we just watch on - * get_dyn_STATDIR()/share_info.tdb - */ - if (!conn->notify_ctx) { - DEBUG(1, ("change notify is not enabled??\n")); - goto nonotify; - } - sys_ctx = conn->notify_ctx->sys_notify_ctx; - if (!sys_ctx) { - DEBUG(1, ("change notify: out of memory!!\n")); - *pstatus = NT_STATUS_NO_MEMORY; - conn_free(sconn, conn); - return NULL; - } - ZERO_STRUCT(e); - if (am_usershare(SNUM(conn))) { - const char *usershare_path = lp_usershare_path(); - /* This is usershare service. */ - e.path = talloc_strdup(conn, usershare_path); - } else { - goto nonotify; - /* watch normal shares' permission? */ - } - if (!e.path) { - DEBUG(1, ("setting up usershare notify: out of memory!\n")); - *pstatus = status; - conn_free(sconn, conn); - return NULL; - } - e.path_len = strlen(e.path); - e.filter = FILE_NOTIFY_CHANGE_FILE_CONTENT; - status = inotify_watch(sys_ctx, &e, share_perm_changed, - (void *)conn, (void *)&w); - if (NT_STATUS_IS_ERR(status)) { - DEBUG(1, ("add inotify for usershare permission failed!\n")); - *pstatus = status; - conn_free(sconn, conn); - return NULL; - } -#endif } -#ifdef HAVE_INOTIFY -nonotify: -#endif /* ROOT Activities: */ /* diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 8e5a386a2d..2ec50cd4d8 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -82,17 +82,12 @@ static void free_conn_server_info_if_unused(connection_struct *conn) static bool check_user_ok(connection_struct *conn, uint16_t vuid, const struct auth_serversupplied_info *server_info, - int snum, bool recheck, NTSTATUS *pstatus) + int snum) { bool valid_vuid = (vuid != UID_FIELD_INVALID); unsigned int i; bool readonly_share; bool admin_user; - struct vuid_cache_entry *ent0; - - if (pstatus) { - *pstatus = NT_STATUS_OK; - } if (valid_vuid) { struct vuid_cache_entry *ent; @@ -101,27 +96,18 @@ static bool check_user_ok(connection_struct *conn, ent = &conn->vuid_cache.array[i]; if (ent->vuid == vuid) { free_conn_server_info_if_unused(conn); - ent0 = ent; - if (!recheck) { - conn->server_info = ent->server_info; - conn->read_only = ent->read_only; - conn->admin_user = ent->admin_user; - return(True); - } else { - break; - } + conn->server_info = ent->server_info; + conn->read_only = ent->read_only; + conn->admin_user = ent->admin_user; + return(True); } } } if (!user_ok_token(server_info->unix_name, pdb_get_domain(server_info->sam_account), - server_info->ptok, snum)) { - if (pstatus) { - *pstatus = NT_STATUS_ACCESS_DENIED; - } + server_info->ptok, snum)) return(False); - } readonly_share = is_share_read_only_for_token( server_info->unix_name, @@ -142,9 +128,6 @@ static bool check_user_ok(connection_struct *conn, if (!share_access_check(server_info->ptok, lp_servicename(snum), readonly_share ? FILE_READ_DATA : FILE_WRITE_DATA)) { - if (pstatus) { - *pstatus = NT_STATUS_ACCESS_DENIED; - } return False; } @@ -154,26 +137,13 @@ static bool check_user_ok(connection_struct *conn, NULL, server_info->ptok, lp_admin_users(snum)); if (valid_vuid) { - struct vuid_cache_entry *ent = NULL; - - if (!recheck || i == VUID_CACHE_SIZE) { - /* find a new entry and fill it. */ - ent = &conn->vuid_cache.array[conn->vuid_cache.next_entry]; + struct vuid_cache_entry *ent = + &conn->vuid_cache.array[conn->vuid_cache.next_entry]; - conn->vuid_cache.next_entry = - (conn->vuid_cache.next_entry + 1) % VUID_CACHE_SIZE; + conn->vuid_cache.next_entry = + (conn->vuid_cache.next_entry + 1) % VUID_CACHE_SIZE; - TALLOC_FREE(ent->server_info); - } else if (recheck && (i < VUID_CACHE_SIZE) && (ent0->vuid == vuid)) { - /* she perform forced recheck, replace the old one. */ - ent = ent0; - } else { - /* must not happen */ - DEBUG(0, ("check_user_ok: recheck %s\n", recheck ? "true" : "false")); - DEBUG(0, ("check_user_ok: vuid cache %d -- %d\n", i, VUID_CACHE_SIZE)); - DEBUG(0, ("check_user_ok: vuid %d -- %d\n", ent0->vuid, vuid)); - smb_panic("should not happen"); - } + TALLOC_FREE(ent->server_info); /* * If force_user was set, all server_info's are based on the same @@ -185,9 +155,6 @@ static bool check_user_ok(connection_struct *conn, if (ent->server_info == NULL) { ent->vuid = UID_FIELD_INVALID; - if (pstatus) { - *pstatus = NT_STATUS_NO_MEMORY; - } return false; } @@ -254,8 +221,7 @@ void conn_clear_vuid_cache(connection_struct *conn, uint16_t vuid) stack, but modify the current_user entries. ****************************************************************************/ -bool change_to_user_force_recheck(connection_struct *conn, uint16 vuid, - bool recheck, NTSTATUS *pstatus) +bool change_to_user(connection_struct *conn, uint16 vuid) { const struct auth_serversupplied_info *server_info = NULL; struct smbd_server_connection *sconn = smbd_server_conn; @@ -269,9 +235,6 @@ bool change_to_user_force_recheck(connection_struct *conn, uint16 vuid, if (!conn) { DEBUG(2,("change_to_user: Connection not open\n")); - if (pstatus) { - *pstatus = NT_STATUS_INVALID_HANDLE; - } return(False); } @@ -282,19 +245,17 @@ bool change_to_user_force_recheck(connection_struct *conn, uint16 vuid, * SMB's - this hurts performance - Badly. */ - if (!recheck) { - if((lp_security() == SEC_SHARE) && (current_user.conn == conn) && - (current_user.ut.uid == conn->server_info->utok.uid)) { - DEBUG(4,("change_to_user: Skipping user change - already " - "user\n")); - return(True); - } else if ((current_user.conn == conn) && - (vuser != NULL) && (current_user.vuid == vuid) && - (current_user.ut.uid == vuser->server_info->utok.uid)) { - DEBUG(4,("change_to_user: Skipping user change - already " - "user\n")); - return(True); - } + if((lp_security() == SEC_SHARE) && (current_user.conn == conn) && + (current_user.ut.uid == conn->server_info->utok.uid)) { + DEBUG(4,("change_to_user: Skipping user change - already " + "user\n")); + return(True); + } else if ((current_user.conn == conn) && + (vuser != NULL) && (current_user.vuid == vuid) && + (current_user.ut.uid == vuser->server_info->utok.uid)) { + DEBUG(4,("change_to_user: Skipping user change - already " + "user\n")); + return(True); } snum = SNUM(conn); @@ -305,13 +266,10 @@ bool change_to_user_force_recheck(connection_struct *conn, uint16 vuid, /* Invalid vuid sent - even with security = share. */ DEBUG(2,("change_to_user: Invalid vuid %d used on " "share %s.\n",vuid, lp_servicename(snum) )); - if (pstatus) { - *pstatus = NT_STATUS_ACCESS_VIOLATION; - } return false; } - if (!check_user_ok(conn, vuid, server_info, snum, recheck, pstatus)) { + if (!check_user_ok(conn, vuid, server_info, snum)) { DEBUG(2,("change_to_user: SMB user %s (unix user %s, vuid %d) " "not permitted access to share %s.\n", server_info->sanitized_username, @@ -338,9 +296,6 @@ bool change_to_user_force_recheck(connection_struct *conn, uint16 vuid, } else { DEBUG(2,("change_to_user: Invalid vuid used %d in accessing " "share %s.\n",vuid, lp_servicename(snum) )); - if (pstatus) { - *pstatus = NT_STATUS_DOS(ERRSRV, ERRbaduid); - } return False; } @@ -398,9 +353,6 @@ bool change_to_user_force_recheck(connection_struct *conn, uint16 vuid, DEBUG(5,("change_to_user uid=(%d,%d) gid=(%d,%d)\n", (int)getuid(),(int)geteuid(),(int)getgid(),(int)getegid())); - if (pstatus) { - *pstatus = NT_STATUS_OK; - } return(True); } -- cgit