Fix bug 7104 - "wide links" and "unix extensions" are incompatible.
[samba.git] / source3 / smbd / service.c
index 8ae13b14f368bf5b0f13954432598d3e12a2d0c8..8039d16586eb164f576f4c4def3a919aac6feff1 100644 (file)
@@ -56,7 +56,12 @@ bool set_conn_connectpath(connection_struct *conn, const char *connectpath)
        const char *s = connectpath;
         bool start_of_name_component = true;
 
-       destname = SMB_STRDUP(connectpath);
+       if (connectpath == NULL || connectpath[0] == '\0') {
+               return false;
+       }
+
+       /* Allocate for strlen + '\0' + possible leading '/' */
+       destname = SMB_MALLOC(strlen(connectpath) + 2);
        if (!destname) {
                return false;
        }
@@ -182,8 +187,8 @@ bool set_current_service(connection_struct *conn, uint16 flags, bool do_chdir)
        if (do_chdir &&
            vfs_ChDir(conn,conn->connectpath) != 0 &&
            vfs_ChDir(conn,conn->origpath) != 0) {
-               DEBUG(0,("chdir (%s) failed\n",
-                        conn->connectpath));
+                DEBUG(((errno!=EACCES)?0:3),("chdir (%s) failed, reason: %s\n",
+                         conn->connectpath, strerror(errno)));
                return(False);
        }
 
@@ -259,7 +264,7 @@ int add_home_service(const char *service, const char *username, const char *home
 {
        int iHomeService;
 
-       if (!service || !homedir)
+       if (!service || !homedir || homedir[0] == '\0')
                return -1;
 
        if ((iHomeService = lp_servicenumber(HOMES_NAME)) < 0) {
@@ -630,33 +635,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
@@ -700,7 +678,7 @@ connection_struct *make_connection_snum(struct smbd_server_connection *sconn,
                DEBUG(1, ("create_connection_server_info failed: %s\n",
                          nt_errstr(status)));
                *pstatus = status;
-               conn_free(sconn, conn);
+               conn_free(conn);
                return NULL;
        }
 
@@ -719,7 +697,6 @@ connection_struct *make_connection_snum(struct smbd_server_connection *sconn,
        conn->printer = (strncmp(dev,"LPT",3) == 0);
        conn->ipc = ( (strncmp(dev,"IPC",3) == 0) ||
                      ( lp_enable_asu_support() && strequal(dev,"ADMIN$")) );
-       conn->dirptr = NULL;
 
        /* Case options for the share. */
        if (lp_casesensitive(snum) == Auto) {
@@ -739,7 +716,6 @@ connection_struct *make_connection_snum(struct smbd_server_connection *sconn,
        conn->hide_list = NULL;
        conn->veto_oplock_list = NULL;
        conn->aio_write_behind_list = NULL;
-       string_set(&conn->dirpath,"");
 
        conn->read_only = lp_readonly(SNUM(conn));
        conn->admin_user = False;
@@ -757,7 +733,7 @@ connection_struct *make_connection_snum(struct smbd_server_connection *sconn,
                fuser = talloc_string_sub(conn, lp_force_user(snum), "%S",
                                          lp_servicename(snum));
                if (fuser == NULL) {
-                       conn_free(sconn, conn);
+                       conn_free(conn);
                        *pstatus = NT_STATUS_NO_MEMORY;
                        return NULL;
                }
@@ -766,7 +742,7 @@ connection_struct *make_connection_snum(struct smbd_server_connection *sconn,
                        conn, fuser, conn->server_info->guest,
                        &forced_serverinfo);
                if (!NT_STATUS_IS_OK(status)) {
-                       conn_free(sconn, conn);
+                       conn_free(conn);
                        *pstatus = status;
                        return NULL;
                }
@@ -791,7 +767,7 @@ connection_struct *make_connection_snum(struct smbd_server_connection *sconn,
                        &conn->server_info->utok.gid);
 
                if (!NT_STATUS_IS_OK(status)) {
-                       conn_free(sconn, conn);
+                       conn_free(conn);
                        *pstatus = status;
                        return NULL;
                }
@@ -817,14 +793,14 @@ connection_struct *make_connection_snum(struct smbd_server_connection *sconn,
                                        pdb_get_domain(conn->server_info->sam_account),
                                        lp_pathname(snum));
                if (!s) {
-                       conn_free(sconn, conn);
+                       conn_free(conn);
                        *pstatus = NT_STATUS_NO_MEMORY;
                        return NULL;
                }
 
                if (!set_conn_connectpath(conn,s)) {
                        TALLOC_FREE(s);
-                       conn_free(sconn, conn);
+                       conn_free(conn);
                        *pstatus = NT_STATUS_NO_MEMORY;
                        return NULL;
                }
@@ -856,7 +832,7 @@ connection_struct *make_connection_snum(struct smbd_server_connection *sconn,
                                         "denied due to security "
                                         "descriptor.\n",
                                          lp_servicename(snum)));
-                               conn_free(sconn, conn);
+                               conn_free(conn);
                                *pstatus = NT_STATUS_ACCESS_DENIED;
                                return NULL;
                        } else {
@@ -869,7 +845,7 @@ connection_struct *make_connection_snum(struct smbd_server_connection *sconn,
        if (!smbd_vfs_init(conn)) {
                DEBUG(0, ("vfs_init failed for service %s\n",
                          lp_servicename(snum)));
-               conn_free(sconn, conn);
+               conn_free(conn);
                *pstatus = NT_STATUS_BAD_NETWORK_NAME;
                return NULL;
        }
@@ -887,71 +863,18 @@ connection_struct *make_connection_snum(struct smbd_server_connection *sconn,
                        "for service %s, path %s\n",
                                lp_servicename(snum),
                                conn->connectpath));
-                       conn_free(sconn, conn);
+                       conn_free(conn);
                        *pstatus = NT_STATUS_BAD_NETWORK_NAME;
                        return NULL;
                }
        }
 
        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: */ 
        /*
@@ -964,7 +887,7 @@ nonotify:
 
                DEBUG(1, ("Max connections (%d) exceeded for %s\n",
                          lp_max_connections(snum), lp_servicename(snum)));
-               conn_free(sconn, conn);
+               conn_free(conn);
                *pstatus = NT_STATUS_INSUFFICIENT_RESOURCES;
                return NULL;
        }  
@@ -974,7 +897,7 @@ nonotify:
         */
        if (!claim_connection(conn, lp_servicename(snum), 0)) {
                DEBUG(1, ("Could not store connections entry\n"));
-               conn_free(sconn, conn);
+               conn_free(conn);
                *pstatus = NT_STATUS_INTERNAL_DB_ERROR;
                return NULL;
        }  
@@ -998,7 +921,7 @@ nonotify:
                        DEBUG(1,("root preexec gave %d - failing "
                                 "connection\n", ret));
                        yield_connection(conn, lp_servicename(snum));
-                       conn_free(sconn, conn);
+                       conn_free(conn);
                        *pstatus = NT_STATUS_ACCESS_DENIED;
                        return NULL;
                }
@@ -1009,7 +932,7 @@ nonotify:
                /* No point continuing if they fail the basic checks */
                DEBUG(0,("Can't become connected user!\n"));
                yield_connection(conn, lp_servicename(snum));
-               conn_free(sconn, conn);
+               conn_free(conn);
                *pstatus = NT_STATUS_LOGON_FAILURE;
                return NULL;
        }
@@ -1116,12 +1039,20 @@ nonotify:
        }
 #endif
 
+       if (lp_unix_extensions() && lp_widelinks(snum)) {
+               DEBUG(0,("Share '%s' has wide links and unix extensions enabled. "
+                       "These parameters are incompatible. "
+                       "Disabling wide links for this share.\n",
+                       lp_servicename(snum) ));
+               lp_do_parameter(snum, "wide links", "False");
+       }
+
        /* Figure out the characteristics of the underlying filesystem. This
         * assumes that all the filesystem mounted withing a share path have
         * the same characteristics, which is likely but not guaranteed.
         */
 
-       conn->fs_capabilities = SMB_VFS_FS_CAPABILITIES(conn);
+       conn->fs_capabilities = SMB_VFS_FS_CAPABILITIES(conn, &conn->ts_res);
 
        /*
         * Print out the 'connected as' stuff here as we need
@@ -1152,7 +1083,7 @@ nonotify:
                SMB_VFS_DISCONNECT(conn);
        }
        yield_connection(conn, lp_servicename(snum));
-       conn_free(sconn, conn);
+       conn_free(conn);
        return NULL;
 }
 
@@ -1271,7 +1202,7 @@ connection_struct *make_connection(struct smbd_server_connection *sconn,
                        return NULL;
                }
 
-               DEBUG(0,("%s (%s) couldn't find service %s\n",
+               DEBUG(3,("%s (%s) couldn't find service %s\n",
                        get_remote_machine_name(),
                        client_addr(get_client_fd(),addr,sizeof(addr)),
                        service));
@@ -1299,8 +1230,7 @@ connection_struct *make_connection(struct smbd_server_connection *sconn,
  Close a cnum.
 ****************************************************************************/
 
-void close_cnum(struct smbd_server_connection *sconn,
-               connection_struct *conn, uint16 vuid)
+void close_cnum(connection_struct *conn, uint16 vuid)
 {
        file_close_conn(conn);
 
@@ -1354,5 +1284,5 @@ void close_cnum(struct smbd_server_connection *sconn,
                TALLOC_FREE(cmd);
        }
 
-       conn_free(sconn, conn);
+       conn_free(conn);
 }