s3: Make smbd aware of permission change of usershare. Since usershare are relatively...
[samba.git] / source3 / smbd / process.c
index f66f114c7b503c6d5c56af8c6bcecc1441d7fea5..5b8a325d2232f8a73e7c645bc119f0cad661610f 100644 (file)
@@ -357,6 +357,7 @@ void init_smb_request(struct smb_request *req,
                        size_t unread_bytes,
                        bool encrypted)
 {
+       struct smbd_server_connection *sconn = smbd_server_conn;
        size_t req_size = smb_len(inbuf) + 4;
        /* Ensure we have at least smb_size bytes. */
        if (req_size < smb_size) {
@@ -377,7 +378,7 @@ void init_smb_request(struct smb_request *req,
        req->buf    = (const uint8_t *)smb_buf(inbuf);
        req->unread_bytes = unread_bytes;
        req->encrypted = encrypted;
-       req->conn = conn_find(req->tid);
+       req->conn = conn_find(sconn,req->tid);
        req->chain_fsp = NULL;
        req->chain_outbuf = NULL;
        smb_init_perfcount_data(&req->pcd);
@@ -1275,7 +1276,7 @@ static connection_struct *switch_message(uint8 type, struct smb_request *req, in
 
                sconn->smb1.sessions.last_session_tag = session_tag;
                if(session_tag != UID_FIELD_INVALID) {
-                       vuser = get_valid_user_struct(session_tag);
+                       vuser = get_valid_user_struct(sconn, session_tag);
                        if (vuser) {
                                set_current_user_info(
                                        vuser->server_info->sanitized_username,
@@ -1285,7 +1286,6 @@ 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,12 +1302,67 @@ 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. */
 
@@ -1968,8 +2023,9 @@ static bool keepalive_fn(const struct timeval *now, void *private_data)
  */
 static bool deadtime_fn(const struct timeval *now, void *private_data)
 {
-       if ((conn_num_open() == 0)
-           || (conn_idle_all(now->tv_sec))) {
+       struct smbd_server_connection *sconn = smbd_server_conn;
+       if ((conn_num_open(sconn) == 0)
+           || (conn_idle_all(sconn, now->tv_sec))) {
                DEBUG( 2, ( "Closing idle connection\n" ) );
                messaging_send(smbd_messaging_context(), procid_self(),
                               MSG_SHUTDOWN, &data_blob_null);
@@ -2101,6 +2157,15 @@ void smbd_process(void)
        messaging_register(smbd_messaging_context(), NULL,
                           MSG_SMB_CLOSE_FILE, msg_close_file);
 
+       /*
+        * Use the default MSG_DEBUG handler to avoid rebroadcasting
+        * MSGs to all child processes
+        */
+       messaging_deregister(smbd_messaging_context(),
+                            MSG_DEBUG, NULL);
+       messaging_register(smbd_messaging_context(), NULL,
+                          MSG_DEBUG, debug_message);
+
        if ((lp_keepalive() != 0)
            && !(event_add_idle(smbd_event_context(), NULL,
                                timeval_set(lp_keepalive(), 0),
@@ -2165,6 +2230,19 @@ void smbd_process(void)
        smbd_server_conn->smb1.sessions.done_sesssetup = false;
        smbd_server_conn->smb1.sessions.max_send = BUFFER_SIZE;
        smbd_server_conn->smb1.sessions.last_session_tag = UID_FIELD_INVALID;
+       /* users from session setup */
+       smbd_server_conn->smb1.sessions.session_userlist = NULL;
+       /* workgroup from session setup. */
+       smbd_server_conn->smb1.sessions.session_workgroup = NULL;
+       /* this holds info on user ids that are already validated for this VC */
+       smbd_server_conn->smb1.sessions.validated_users = NULL;
+       smbd_server_conn->smb1.sessions.next_vuid = VUID_OFFSET;
+       smbd_server_conn->smb1.sessions.num_validated_vuids = 0;
+#ifdef HAVE_NETGROUP
+       smbd_server_conn->smb1.sessions.my_yp_domain = NULL;
+#endif
+
+       conn_init(smbd_server_conn);
 
        smbd_server_conn->smb1.fde = event_add_fd(smbd_event_context(),
                                                  smbd_server_conn,