#include "lib/param/loadparm.h"
#include "messages.h"
#include "lib/afs/afs_funcs.h"
+#include "lib/util_path.h"
static bool canonicalize_connect_path(connection_struct *conn)
{
bool ret;
- char *resolved_name = SMB_VFS_REALPATH(conn,conn->connectpath);
- if (!resolved_name) {
+ struct smb_filename con_fname = { .base_name = conn->connectpath };
+ struct smb_filename *resolved_fname = SMB_VFS_REALPATH(conn, talloc_tos(),
+ &con_fname);
+ if (resolved_fname == NULL) {
return false;
}
- ret = set_conn_connectpath(conn,resolved_name);
- SAFE_FREE(resolved_name);
+ ret = set_conn_connectpath(conn,resolved_fname->base_name);
+ TALLOC_FREE(resolved_fname);
return ret;
}
/****************************************************************************
Ensure when setting connectpath it is a canonicalized (no ./ // or ../)
absolute path stating in / and not ending in /.
- Observent people will notice a similarity between this and check_path_syntax :-).
****************************************************************************/
bool set_conn_connectpath(connection_struct *conn, const char *connectpath)
{
char *destname;
- char *d;
- const char *s = connectpath;
- bool start_of_name_component = true;
if (connectpath == NULL || connectpath[0] == '\0') {
return false;
}
- /* Allocate for strlen + '\0' + possible leading '/' */
- destname = (char *)talloc_size(conn, strlen(connectpath) + 2);
- if (!destname) {
+ destname = canonicalize_absolute_path(conn, connectpath);
+ if (destname == NULL) {
return false;
}
- d = destname;
-
- *d++ = '/'; /* Always start with root. */
-
- while (*s) {
- if (*s == '/') {
- /* Eat multiple '/' */
- while (*s == '/') {
- s++;
- }
- if ((d > destname + 1) && (*s != '\0')) {
- *d++ = '/';
- }
- start_of_name_component = True;
- continue;
- }
-
- if (start_of_name_component) {
- if ((s[0] == '.') && (s[1] == '.') && (s[2] == '/' || s[2] == '\0')) {
- /* Uh oh - "/../" or "/..\0" ! */
-
- /* Go past the ../ or .. */
- if (s[2] == '/') {
- s += 3;
- } else {
- s += 2; /* Go past the .. */
- }
-
- /* If we just added a '/' - delete it */
- if ((d > destname) && (*(d-1) == '/')) {
- *(d-1) = '\0';
- d--;
- }
-
- /* Are we at the start ? Can't go back further if so. */
- if (d <= destname) {
- *d++ = '/'; /* Can't delete root */
- continue;
- }
- /* Go back one level... */
- /* Decrement d first as d points to the *next* char to write into. */
- for (d--; d > destname; d--) {
- if (*d == '/') {
- break;
- }
- }
- /* We're still at the start of a name component, just the previous one. */
- continue;
- } else if ((s[0] == '.') && ((s[1] == '\0') || s[1] == '/')) {
- /* Component of pathname can't be "." only - skip the '.' . */
- if (s[1] == '/') {
- s += 2;
- } else {
- s++;
- }
- continue;
- }
- }
-
- if (!(*s & 0x80)) {
- *d++ = *s++;
- } else {
- size_t siz;
- /* Get the size of the next MB character. */
- next_codepoint(s,&siz);
- switch(siz) {
- case 5:
- *d++ = *s++;
- /*fall through*/
- case 4:
- *d++ = *s++;
- /*fall through*/
- case 3:
- *d++ = *s++;
- /*fall through*/
- case 2:
- *d++ = *s++;
- /*fall through*/
- case 1:
- *d++ = *s++;
- break;
- default:
- break;
- }
- }
- start_of_name_component = false;
- }
- *d = '\0';
-
- /* And must not end in '/' */
- if (d > destname + 1 && (*(d-1) == '/')) {
- *(d-1) = '\0';
- }
DEBUG(10,("set_conn_connectpath: service %s, connectpath = %s\n",
lp_servicename(talloc_tos(), SNUM(conn)), destname ));
talloc_free(conn->connectpath);
conn->connectpath = destname;
- /* Ensure conn->cwd is initialized - start as conn->connectpath. */
- TALLOC_FREE(conn->cwd);
- conn->cwd = talloc_strdup(conn, conn->connectpath);
- if (!conn->cwd) {
+ /*
+ * Ensure conn->cwd_fname is initialized.
+ * start as conn->connectpath.
+ */
+ TALLOC_FREE(conn->cwd_fname);
+ conn->cwd_fname = synthetic_smb_fname(conn,
+ conn->connectpath,
+ NULL,
+ NULL,
+ 0);
+ if (conn->cwd_fname == NULL) {
return false;
}
return true;
snum = SNUM(conn);
- if (do_chdir &&
- vfs_ChDir(conn,conn->connectpath) != 0 &&
- vfs_ChDir(conn,conn->origpath) != 0) {
- DEBUG(((errno!=EACCES)?0:3),("chdir (%s) failed, reason: %s\n",
- conn->connectpath, strerror(errno)));
- return(False);
+ {
+ struct smb_filename connectpath_fname = {
+ .base_name = conn->connectpath
+ };
+ struct smb_filename origpath_fname = {
+ .base_name = conn->origpath
+ };
+
+ if (do_chdir &&
+ vfs_ChDir(conn, &connectpath_fname) != 0 &&
+ vfs_ChDir(conn, &origpath_fname) != 0) {
+ DEBUG(((errno!=EACCES)?0:3),
+ ("chdir (%s) failed, reason: %s\n",
+ conn->connectpath, strerror(errno)));
+ return(False);
+ }
}
if ((conn == last_conn) && (last_flags == flags)) {
}
sconn->notify_ctx = notify_init(sconn, sconn->msg_ctx, sconn->ev_ctx,
- notify_callback);
+ sconn, notify_callback);
if (sconn->notify_ctx == NULL) {
return NT_STATUS_NO_MEMORY;
}
return status;
}
+ status = messaging_register(sconn->msg_ctx, sconn,
+ MSG_SMB_NOTIFY_STARTED,
+ smbd_notifyd_restarted);
+ if (!NT_STATUS_IS_OK(status)) {
+ DBG_DEBUG("messaging_register failed: %s\n",
+ nt_errstr(status));
+ messaging_deregister(sconn->msg_ctx,
+ MSG_SMB_NOTIFY_CANCEL_DELETED, sconn);
+ TALLOC_FREE(sconn->notify_ctx);
+ return status;
+ }
+
return NT_STATUS_OK;
}
conn->short_case_preserve = lp_short_preserve_case(snum);
conn->encrypt_level = lp_smb_encrypt(snum);
+ if (conn->encrypt_level > SMB_SIGNING_OFF) {
+ if (lp_smb_encrypt(-1) == SMB_SIGNING_OFF) {
+ if (conn->encrypt_level == SMB_SIGNING_REQUIRED) {
+ DBG_ERR("Service [%s] requires encryption, but "
+ "it is disabled globally!\n",
+ lp_servicename(talloc_tos(), snum));
+ status = NT_STATUS_ACCESS_DENIED;
+ goto err_root_exit;
+ }
+ conn->encrypt_level = SMB_SIGNING_OFF;
+ }
+ }
conn->veto_list = NULL;
conn->hide_list = NULL;
conn->session_info->info->domain_name,
lp_root_preexec(talloc_tos(), snum));
DEBUG(5,("cmd=%s\n",cmd));
- ret = smbrun(cmd,NULL);
+ ret = smbrun(cmd, NULL, NULL);
TALLOC_FREE(cmd);
if (ret != 0 && lp_root_preexec_close(snum)) {
DEBUG(1,("root preexec gave %d - failing "
conn->session_info->unix_info->sanitized_username,
conn->session_info->info->domain_name,
lp_preexec(talloc_tos(), snum));
- ret = smbrun(cmd,NULL);
+ ret = smbrun(cmd, NULL, NULL);
TALLOC_FREE(cmd);
if (ret != 0 && lp_preexec_close(snum)) {
DEBUG(1,("preexec gave %d - failing connection\n",
void close_cnum(connection_struct *conn, uint64_t vuid)
{
+ char rootpath[2] = { '/', '\0'};
+ struct smb_filename root_fname = { .base_name = rootpath };
+
file_close_conn(conn);
if (!IS_IPC(conn)) {
lp_servicename(talloc_tos(), SNUM(conn))));
/* make sure we leave the directory available for unmount */
- vfs_ChDir(conn, "/");
+ vfs_ChDir(conn, &root_fname);
/* Call VFS disconnect hook */
SMB_VFS_DISCONNECT(conn);
conn->session_info->unix_info->sanitized_username,
conn->session_info->info->domain_name,
lp_postexec(talloc_tos(), SNUM(conn)));
- smbrun(cmd,NULL);
+ smbrun(cmd, NULL, NULL);
TALLOC_FREE(cmd);
change_to_root_user();
}
conn->session_info->unix_info->sanitized_username,
conn->session_info->info->domain_name,
lp_root_postexec(talloc_tos(), SNUM(conn)));
- smbrun(cmd,NULL);
+ smbrun(cmd, NULL, NULL);
TALLOC_FREE(cmd);
}