Exemple #1
0
int smb_delete_user_group(const char *unix_group, const char *unix_user)
{
	char *del_script = NULL;
	int ret = -1;

	/* defer to scripts */

	if ( *lp_deluserfromgroup_script() ) {
		TALLOC_CTX *ctx = talloc_tos();

		del_script = talloc_strdup(ctx,
				lp_deluserfromgroup_script());
		if (!del_script) {
			return -1;
		}
		del_script = talloc_string_sub(ctx,
				del_script, "%g", unix_group);
		if (!del_script) {
			return -1;
		}
		del_script = talloc_string_sub(ctx,
				del_script, "%u", unix_user);
		if (!del_script) {
			return -1;
		}
		ret = smbrun(del_script,NULL);
		DEBUG(ret ? 0 : 3,("smb_delete_user_group: Running the command `%s' gave %d\n",del_script,ret));
		if (ret == 0) {
			smb_nscd_flush_group_cache();
		}
		return ret;
	}

	return -1;
}
Exemple #2
0
static WERROR keyname_to_path(TALLOC_CTX *mem_ctx, const char *keyname,
			      char **path)
{
	char *tmp_path = NULL;

	if ((keyname == NULL) || (path == NULL)) {
		return WERR_INVALID_PARAM;
	}

	tmp_path = talloc_asprintf(mem_ctx, "\\%s", keyname);
	if (tmp_path == NULL) {
		DEBUG(0, ("talloc_asprintf failed!\n"));
		return WERR_NOMEM;
	}

	tmp_path = talloc_string_sub(mem_ctx, tmp_path, "\\", "/");
	if (tmp_path == NULL) {
		DEBUG(0, ("talloc_string_sub_failed!\n"));
		return WERR_NOMEM;
	}

	*path = tmp_path;

	return WERR_OK;
}
Exemple #3
0
static int regdb_normalize_keynames_fn(struct db_record *rec,
				       void *private_data)
{
	TALLOC_CTX *mem_ctx = talloc_tos();
	const char *keyname;
	NTSTATUS status;
	TDB_DATA key;
	TDB_DATA value;
	struct db_context *db = (struct db_context *)private_data;

	key = dbwrap_record_get_key(rec);
	if (key.dptr == NULL || key.dsize == 0) {
		return 0;
	}

	value = dbwrap_record_get_value(rec);

	if (db == NULL) {
		DEBUG(0, ("regdb_normalize_keynames_fn: ERROR: "
			  "NULL db context handed in via private_data\n"));
		return 1;
	}

	if (strncmp((const char *)key.dptr, REGDB_VERSION_KEYNAME,
	    strlen(REGDB_VERSION_KEYNAME)) == 0)
	{
		return 0;
	}

	keyname = strchr((const char *)key.dptr, '/');
	if (keyname) {
		keyname = talloc_string_sub(mem_ctx,
					    (const char *)key.dptr,
					    "/",
					    "\\");

		DEBUG(2, ("regdb_normalize_keynames_fn: Convert %s to %s\n",
			  (const char *)key.dptr,
			  keyname));

		/* Delete the original record and store the normalized key */
		status = dbwrap_record_delete(rec);
		if (!NT_STATUS_IS_OK(status)) {
			DEBUG(0,("regdb_normalize_keynames_fn: "
				 "tdb_delete for [%s] failed!\n",
				 (const char *)key.dptr));
			return 1;
		}

		status = dbwrap_store_bystring(db, keyname, value, TDB_REPLACE);
		if (!NT_STATUS_IS_OK(status)) {
			DEBUG(0,("regdb_normalize_keynames_fn: "
				 "failed to store new record for [%s]!\n",
				 keyname));
			return 1;
		}
	}

	return 0;
}
Exemple #4
0
int smb_create_group(const char *unix_group, gid_t *new_gid)
{
	char *add_script = NULL;
	int 	ret = -1;
	int 	fd = 0;

	*new_gid = 0;

	/* defer to scripts */

	if ( *lp_addgroup_script() ) {
		TALLOC_CTX *ctx = talloc_tos();

		add_script = talloc_strdup(ctx,
					lp_addgroup_script());
		if (!add_script) {
			return -1;
		}
		add_script = talloc_string_sub(ctx,
				add_script, "%g", unix_group);
		if (!add_script) {
			return -1;
		}

		ret = smbrun(add_script, &fd);
		DEBUG(ret ? 0 : 3,("smb_create_group: Running the command `%s' gave %d\n",add_script,ret));
		if (ret == 0) {
			smb_nscd_flush_group_cache();
		}
		if (ret != 0)
			return ret;

		if (fd != 0) {
			fstring output;

			*new_gid = 0;
			if (read(fd, output, sizeof(output)) > 0) {
				*new_gid = (gid_t)strtoul(output, NULL, 10);
			}

			close(fd);
		}

	}

	if (*new_gid == 0) {
		struct group *grp = getgrnam(unix_group);

		if (grp != NULL)
			*new_gid = grp->gr_gid;
	}

	return ret;
}
Exemple #5
0
static NTSTATUS log_nt_token(struct security_token *token)
{
	TALLOC_CTX *frame = talloc_stackframe();
	char *command;
	char *group_sidstr;
	size_t i;

	if ((lp_log_nt_token_command() == NULL) ||
	    (strlen(lp_log_nt_token_command()) == 0)) {
		TALLOC_FREE(frame);
		return NT_STATUS_OK;
	}

	group_sidstr = talloc_strdup(frame, "");
	for (i=1; i<token->num_sids; i++) {
		group_sidstr = talloc_asprintf(
			frame, "%s %s", group_sidstr,
			sid_string_talloc(frame, &token->sids[i]));
	}

	command = talloc_string_sub(
		frame, lp_log_nt_token_command(),
		"%s", sid_string_talloc(frame, &token->sids[0]));
	command = talloc_string_sub(frame, command, "%t", group_sidstr);

	if (command == NULL) {
		TALLOC_FREE(frame);
		return NT_STATUS_NO_MEMORY;
	}

	DEBUG(8, ("running command: [%s]\n", command));
	if (smbrun(command, NULL) != 0) {
		DEBUG(0, ("Could not log NT token\n"));
		TALLOC_FREE(frame);
		return NT_STATUS_ACCESS_DENIED;
	}

	TALLOC_FREE(frame);
	return NT_STATUS_OK;
}
Exemple #6
0
NTSTATUS gpo_explode_filesyspath(TALLOC_CTX *mem_ctx,
                                 const char *cache_dir,
				 const char *file_sys_path,
				 char **server,
				 char **service,
				 char **nt_path,
				 char **unix_path)
{
	char *path = NULL;

	*server = NULL;
	*service = NULL;
	*nt_path = NULL;
	*unix_path = NULL;

	if (!file_sys_path) {
		return NT_STATUS_OK;
	}

	if (!next_token_talloc(mem_ctx, &file_sys_path, server, "\\")) {
		return NT_STATUS_INVALID_PARAMETER;
	}
	NT_STATUS_HAVE_NO_MEMORY(*server);

	if (!next_token_talloc(mem_ctx, &file_sys_path, service, "\\")) {
		return NT_STATUS_INVALID_PARAMETER;
	}
	NT_STATUS_HAVE_NO_MEMORY(*service);

	if ((*nt_path = talloc_asprintf(mem_ctx, "\\%s", file_sys_path))
		== NULL) {
		return NT_STATUS_NO_MEMORY;
	}
	NT_STATUS_HAVE_NO_MEMORY(*nt_path);

	if ((path = talloc_asprintf(mem_ctx,
					"%s/%s",
					cache_dir,
					file_sys_path)) == NULL) {
		return NT_STATUS_NO_MEMORY;
	}
	path = talloc_string_sub(mem_ctx, path, "\\", "/");
	if (!path) {
		return NT_STATUS_NO_MEMORY;
	}

	*unix_path = talloc_strdup(mem_ctx, path);
	NT_STATUS_HAVE_NO_MEMORY(*unix_path);

	talloc_free(path);
	return NT_STATUS_OK;
}
static int regdb_normalize_keynames_fn(struct db_record *rec,
				       void *private_data)
{
	TALLOC_CTX *mem_ctx = talloc_tos();
	const char *keyname;
	NTSTATUS status;

	if (rec->key.dptr == NULL || rec->key.dsize == 0) {
		return 0;
	}

	keyname = strchr((const char *) rec->key.dptr, '/');
	if (keyname) {
		struct db_record new_rec;

		keyname = talloc_string_sub(mem_ctx,
					    (const char *) rec->key.dptr,
					    "/",
					    "\\");

		DEBUG(2, ("regdb_normalize_keynames_fn: Convert %s to %s\n",
			  (const char *) rec->key.dptr,
			  keyname));

		new_rec.value = rec->value;
		new_rec.key = string_term_tdb_data(keyname);
		new_rec.private_data = rec->private_data;

		/* Delete the original record and store the normalized key */
		status = rec->delete_rec(rec);
		if (!NT_STATUS_IS_OK(status)) {
			DEBUG(0,("regdb_normalize_keynames_fn: "
				 "tdb_delete for [%s] failed!\n",
				 rec->key.dptr));
			return 1;
		}

		status = rec->store(&new_rec, new_rec.value, TDB_REPLACE);
		if (!NT_STATUS_IS_OK(status)) {
			DEBUG(0,("regdb_normalize_keynames_fn: "
				 "failed to store new record for [%s]!\n",
				 keyname));
			return 1;
		}
	}

	return 0;
}
/**
 * Split path into hive name and subkeyname
 * normalizations performed:
 *  - if the path contains no '\\' characters,
 *    assume that the legacy format of using '/'
 *    as a separator is used and  convert '/' to '\\'
 *  - strip trailing '\\' chars
 */
WERROR split_hive_key(TALLOC_CTX *ctx, const char *path, char **hivename,
		      char **subkeyname)
{
	char *p;
	const char *tmp_subkeyname;

	if ((path == NULL) || (hivename == NULL) || (subkeyname == NULL)) {
		return WERR_INVALID_PARAM;
	}

	if (strlen(path) == 0) {
		return WERR_INVALID_PARAM;
	}

	if (strchr(path, '\\') == NULL) {
		*hivename = talloc_string_sub(ctx, path, "/", "\\");
	} else {
		*hivename = talloc_strdup(ctx, path);
	}

	if (*hivename == NULL) {
		return WERR_NOMEM;
	}

	/* strip trailing '\\' chars */
	p = strrchr(*hivename, '\\');
	while ((p != NULL) && (p[1] == '\0')) {
		*p = '\0';
		p = strrchr(*hivename, '\\');
	}

	p = strchr(*hivename, '\\');

	if ((p == NULL) || (*p == '\0')) {
		/* just the hive - no subkey given */
		tmp_subkeyname = "";
	} else {
		*p = '\0';
		tmp_subkeyname = p+1;
	}
	*subkeyname = talloc_strdup(ctx, tmp_subkeyname);
	if (*subkeyname == NULL) {
		return WERR_NOMEM;
	}

	return WERR_OK;
}
Exemple #9
0
int smb_set_primary_group(const char *unix_group, const char* unix_user)
{
	char *add_script = NULL;
	int ret = -1;

	/* defer to scripts */

	if ( *lp_setprimarygroup_script() ) {
		TALLOC_CTX *ctx = talloc_tos();

		add_script = talloc_strdup(ctx,
				lp_setprimarygroup_script());
		if (!add_script) {
			return -1;
		}
		add_script = talloc_all_string_sub(ctx,
				add_script, "%g", unix_group);
		if (!add_script) {
			return -1;
		}
		add_script = talloc_string_sub(ctx,
				add_script, "%u", unix_user);
		if (!add_script) {
			return -1;
		}
		ret = smbrun(add_script,NULL);
		flush_pwnam_cache();
		DEBUG(ret ? 0 : 3,("smb_set_primary_group: "
			 "Running the command `%s' gave %d\n",add_script,ret));
		if (ret == 0) {
			smb_nscd_flush_group_cache();
		}
		return ret;
	}

	return -1;
}
Exemple #10
0
static NTSTATUS find_forced_user(connection_struct *conn, BOOL vuser_is_guest, fstring username)
{
	int snum = conn->params->service;
	char *fuser, *found_username;
	NTSTATUS result;

	if (!(fuser = talloc_string_sub(conn->mem_ctx, lp_force_user(snum), "%S",
					lp_servicename(snum)))) {
		return NT_STATUS_NO_MEMORY;
	}

	result = create_token_from_username(conn->mem_ctx, fuser, vuser_is_guest,
					    &conn->uid, &conn->gid, &found_username,
					    &conn->nt_user_token);
	if (!NT_STATUS_IS_OK(result)) {
		return result;
	}

	fstrcpy(username, found_username);

	TALLOC_FREE(fuser);
	TALLOC_FREE(found_username);
	return NT_STATUS_OK;
}
Exemple #11
0
/****************************************************************************
 Run a given print command
 a null terminated list of value/substitute pairs is provided
 for local substitution strings
****************************************************************************/
static int print_run_command(int snum, const char* printername, bool do_sub,
                             const char *command, int *outfd, ...)
{
    char *syscmd;
    char *arg;
    int ret;
    TALLOC_CTX *ctx = talloc_tos();
    va_list ap;
    va_start(ap, outfd);

    /* check for a valid system printername and valid command to run */

    if ( !printername || !*printername ) {
        va_end(ap);
        return -1;
    }

    if (!command || !*command) {
        va_end(ap);
        return -1;
    }

    syscmd = talloc_strdup(ctx, command);
    if (!syscmd) {
        va_end(ap);
        return -1;
    }

    while ((arg = va_arg(ap, char *))) {
        char *value = va_arg(ap,char *);
        syscmd = talloc_string_sub(ctx, syscmd, arg, value);
        if (!syscmd) {
            va_end(ap);
            return -1;
        }
    }
    va_end(ap);

    syscmd = talloc_string_sub(ctx, syscmd, "%p", printername);
    if (!syscmd) {
        return -1;
    }

    if (do_sub && snum != -1) {
        syscmd = talloc_sub_advanced(ctx,
                                     lp_servicename(talloc_tos(), snum),
                                     current_user_info.unix_name,
                                     "",
                                     current_user.ut.gid,
                                     get_current_username(),
                                     current_user_info.domain,
                                     syscmd);
        if (!syscmd) {
            return -1;
        }
    }

    ret = smbrun_no_sanitize(syscmd,outfd);

    DEBUG(3,("Running the command `%s' gave %d\n",syscmd,ret));

    return ret;
}
Exemple #12
0
static int generic_job_submit(int snum, struct printjob *pjob,
                              enum printing_types printing_type,
                              char *lpq_cmd)
{
    int ret = -1;
    char *current_directory = NULL;
    char *print_directory = NULL;
    char *wd = NULL;
    char *p = NULL;
    char *jobname = NULL;
    TALLOC_CTX *ctx = talloc_tos();
    fstring job_page_count, job_size;
    print_queue_struct *q;
    print_status_struct status;

    /* we print from the directory path to give the best chance of
           parsing the lpq output */
    wd = sys_getwd();
    if (!wd) {
        return -1;
    }

    current_directory = talloc_strdup(ctx, wd);
    SAFE_FREE(wd);

    if (!current_directory) {
        return -1;
    }
    print_directory = talloc_strdup(ctx, pjob->filename);
    if (!print_directory) {
        return -1;
    }
    p = strrchr_m(print_directory,'/');
    if (!p) {
        return -1;
    }
    *p++ = 0;

    if (chdir(print_directory) != 0) {
        return -1;
    }

    jobname = talloc_strdup(ctx, pjob->jobname);
    if (!jobname) {
        ret = -1;
        goto out;
    }
    jobname = talloc_string_sub(ctx, jobname, "'", "_");
    if (!jobname) {
        ret = -1;
        goto out;
    }
    slprintf(job_page_count, sizeof(job_page_count)-1, "%d", pjob->page_count);
    slprintf(job_size, sizeof(job_size)-1, "%lu", (unsigned long)pjob->size);

    /* send it to the system spooler */
    ret = print_run_command(snum, lp_printername(talloc_tos(), snum), True,
                            lp_print_command(talloc_tos(), snum), NULL,
                            "%s", p,
                            "%J", jobname,
                            "%f", p,
                            "%z", job_size,
                            "%c", job_page_count,
                            NULL);
    if (ret != 0) {
        ret = -1;
        goto out;
    }

    /*
     * check the queue for the newly submitted job, this allows us to
     * determine the backend job identifier (sysjob).
     */
    pjob->sysjob = -1;
    ret = generic_queue_get(lp_printername(talloc_tos(), snum),
                            printing_type, lpq_cmd, &q, &status);
    if (ret > 0) {
        int i;
        for (i = 0; i < ret; i++) {
            if (strcmp(q[i].fs_file, p) == 0) {
                pjob->sysjob = q[i].sysjob;
                DEBUG(5, ("new job %u (%s) matches sysjob %d\n",
                          pjob->jobid, jobname, pjob->sysjob));
                break;
            }
        }
        SAFE_FREE(q);
        ret = 0;
    }
    if (pjob->sysjob == -1) {
        DEBUG(2, ("failed to get sysjob for job %u (%s), tracking as "
                  "Unix job\n", pjob->jobid, jobname));
    }


out:

    if (chdir(current_directory) == -1) {
        smb_panic("chdir failed in generic_job_submit");
    }
    TALLOC_FREE(current_directory);
    return ret;
}
Exemple #13
0
connection_struct *make_connection_snum(struct smbd_server_connection *sconn,
					int snum, user_struct *vuser,
					DATA_BLOB password,
					const char *pdev,
					NTSTATUS *pstatus)
{
	connection_struct *conn;
	struct smb_filename *smb_fname_cpath = NULL;
	fstring dev;
	int ret;
	char addr[INET6_ADDRSTRLEN];
	bool on_err_call_dis_hook = false;
	NTSTATUS status;

	fstrcpy(dev, pdev);

	if (NT_STATUS_IS_ERR(*pstatus = share_sanity_checks(snum, dev))) {
		return NULL;
	}	

	conn = conn_new(sconn);
	if (!conn) {
		DEBUG(0,("Couldn't find free connection.\n"));
		*pstatus = NT_STATUS_INSUFFICIENT_RESOURCES;
		return NULL;
	}

	conn->params->service = snum;

	status = create_connection_server_info(sconn,
		conn, snum, vuser ? vuser->server_info : NULL, password,
		&conn->server_info);

	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(1, ("create_connection_server_info failed: %s\n",
			  nt_errstr(status)));
		*pstatus = status;
		conn_free(conn);
		return NULL;
	}

	if ((lp_guest_only(snum)) || (lp_security() == SEC_SHARE)) {
		conn->force_user = true;
	}

	add_session_user(sconn, conn->server_info->unix_name);

	safe_strcpy(conn->client_address,
			client_addr(get_client_fd(),addr,sizeof(addr)), 
			sizeof(conn->client_address)-1);
	conn->num_files_open = 0;
	conn->lastused = conn->lastused_count = time(NULL);
	conn->used = True;
	conn->printer = (strncmp(dev,"LPT",3) == 0);
	conn->ipc = ( (strncmp(dev,"IPC",3) == 0) ||
		      ( lp_enable_asu_support() && strequal(dev,"ADMIN$")) );

	/* Case options for the share. */
	if (lp_casesensitive(snum) == Auto) {
		/* We will be setting this per packet. Set to be case
		 * insensitive for now. */
		conn->case_sensitive = False;
	} else {
		conn->case_sensitive = (bool)lp_casesensitive(snum);
	}

	conn->case_preserve = lp_preservecase(snum);
	conn->short_case_preserve = lp_shortpreservecase(snum);

	conn->encrypt_level = lp_smb_encrypt(snum);

	conn->veto_list = NULL;
	conn->hide_list = NULL;
	conn->veto_oplock_list = NULL;
	conn->aio_write_behind_list = NULL;

	conn->read_only = lp_readonly(SNUM(conn));
	conn->admin_user = False;

	if (*lp_force_user(snum)) {

		/*
		 * Replace conn->server_info with a completely faked up one
		 * from the username we are forced into :-)
		 */

		char *fuser;
		struct auth_serversupplied_info *forced_serverinfo;

		fuser = talloc_string_sub(conn, lp_force_user(snum), "%S",
					  lp_servicename(snum));
		if (fuser == NULL) {
			conn_free(conn);
			*pstatus = NT_STATUS_NO_MEMORY;
			return NULL;
		}

		status = make_serverinfo_from_username(
			conn, fuser, conn->server_info->guest,
			&forced_serverinfo);
		if (!NT_STATUS_IS_OK(status)) {
			conn_free(conn);
			*pstatus = status;
			return NULL;
		}

		TALLOC_FREE(conn->server_info);
		conn->server_info = forced_serverinfo;

		conn->force_user = True;
		DEBUG(3,("Forced user %s\n", fuser));
	}

	/*
	 * If force group is true, then override
	 * any groupid stored for the connecting user.
	 */

	if (*lp_force_group(snum)) {

		status = find_forced_group(
			conn->force_user, snum, conn->server_info->unix_name,
			&conn->server_info->ptok->user_sids[1],
			&conn->server_info->utok.gid);

		if (!NT_STATUS_IS_OK(status)) {
			conn_free(conn);
			*pstatus = status;
			return NULL;
		}

		/*
		 * We need to cache this gid, to use within
 		 * change_to_user() separately from the conn->server_info
 		 * struct. We only use conn->server_info directly if
 		 * "force_user" was set.
 		 */
		conn->force_group_gid = conn->server_info->utok.gid;
	}

	conn->vuid = (vuser != NULL) ? vuser->vuid : UID_FIELD_INVALID;

	{
		char *s = talloc_sub_advanced(talloc_tos(),
					lp_servicename(SNUM(conn)),
					conn->server_info->unix_name,
					conn->connectpath,
					conn->server_info->utok.gid,
					conn->server_info->sanitized_username,
					pdb_get_domain(conn->server_info->sam_account),
					lp_pathname(snum));
		if (!s) {
			conn_free(conn);
			*pstatus = NT_STATUS_NO_MEMORY;
			return NULL;
		}

		if (!set_conn_connectpath(conn,s)) {
			TALLOC_FREE(s);
			conn_free(conn);
			*pstatus = NT_STATUS_NO_MEMORY;
			return NULL;
		}
		DEBUG(3,("Connect path is '%s' for service [%s]\n",s,
			 lp_servicename(snum)));
		TALLOC_FREE(s);
	}

	/*
	 * New code to check if there's a share security descripter
	 * added from NT server manager. This is done after the
	 * smb.conf checks are done as we need a uid and token. JRA.
	 *
	 */

	{
		bool can_write = False;

		can_write = share_access_check(conn->server_info->ptok,
					       lp_servicename(snum),
					       FILE_WRITE_DATA);

		if (!can_write) {
			if (!share_access_check(conn->server_info->ptok,
						lp_servicename(snum),
						FILE_READ_DATA)) {
				/* No access, read or write. */
				DEBUG(0,("make_connection: connection to %s "
					 "denied due to security "
					 "descriptor.\n",
					  lp_servicename(snum)));
				conn_free(conn);
				*pstatus = NT_STATUS_ACCESS_DENIED;
				return NULL;
			} else {
				conn->read_only = True;
			}
		}
	}
	/* Initialise VFS function pointers */

	if (!smbd_vfs_init(conn)) {
		DEBUG(0, ("vfs_init failed for service %s\n",
			  lp_servicename(snum)));
		conn_free(conn);
		*pstatus = NT_STATUS_BAD_NETWORK_NAME;
		return NULL;
	}

	/*
	 * If widelinks are disallowed we need to canonicalise the connect
	 * path here to ensure we don't have any symlinks in the
	 * connectpath. We will be checking all paths on this connection are
	 * below this directory. We must do this after the VFS init as we
	 * depend on the realpath() pointer in the vfs table. JRA.
	 */
	if (!lp_widelinks(snum)) {
		if (!canonicalize_connect_path(conn)) {
			DEBUG(0, ("canonicalize_connect_path failed "
			"for service %s, path %s\n",
				lp_servicename(snum),
				conn->connectpath));
			conn_free(conn);
			*pstatus = NT_STATUS_BAD_NETWORK_NAME;
			return NULL;
		}
	}

	if ((!conn->printer) && (!conn->ipc)) {
		conn->notify_ctx = notify_init(conn, server_id_self(),
					       smbd_messaging_context(),
					       smbd_event_context(),
					       conn);
	}

/* ROOT Activities: */	
	/*
	 * Enforce the max connections parameter.
	 */

	if ((lp_max_connections(snum) > 0)
	    && (count_current_connections(lp_servicename(SNUM(conn)), True) >=
		lp_max_connections(snum))) {

		DEBUG(1, ("Max connections (%d) exceeded for %s\n",
			  lp_max_connections(snum), lp_servicename(snum)));
		conn_free(conn);
		*pstatus = NT_STATUS_INSUFFICIENT_RESOURCES;
		return NULL;
	}  

	/*
	 * Get us an entry in the connections db
	 */
	if (!claim_connection(conn, lp_servicename(snum), 0)) {
		DEBUG(1, ("Could not store connections entry\n"));
		conn_free(conn);
		*pstatus = NT_STATUS_INTERNAL_DB_ERROR;
		return NULL;
	}  

	/* Preexecs are done here as they might make the dir we are to ChDir
	 * to below */
	/* execute any "root preexec = " line */
	if (*lp_rootpreexec(snum)) {
		char *cmd = talloc_sub_advanced(talloc_tos(),
					lp_servicename(SNUM(conn)),
					conn->server_info->unix_name,
					conn->connectpath,
					conn->server_info->utok.gid,
					conn->server_info->sanitized_username,
					pdb_get_domain(conn->server_info->sam_account),
					lp_rootpreexec(snum));
		DEBUG(5,("cmd=%s\n",cmd));
		ret = smbrun(cmd,NULL);
		TALLOC_FREE(cmd);
		if (ret != 0 && lp_rootpreexec_close(snum)) {
			DEBUG(1,("root preexec gave %d - failing "
				 "connection\n", ret));
			yield_connection(conn, lp_servicename(snum));
			conn_free(conn);
			*pstatus = NT_STATUS_ACCESS_DENIED;
			return NULL;
		}
	}

/* USER Activites: */
	if (!change_to_user(conn, conn->vuid)) {
		/* 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(conn);
		*pstatus = NT_STATUS_LOGON_FAILURE;
		return NULL;
	}

	/* Remember that a different vuid can connect later without these
	 * checks... */
	
	/* Preexecs are done here as they might make the dir we are to ChDir
	 * to below */

	/* execute any "preexec = " line */
	if (*lp_preexec(snum)) {
		char *cmd = talloc_sub_advanced(talloc_tos(),
					lp_servicename(SNUM(conn)),
					conn->server_info->unix_name,
					conn->connectpath,
					conn->server_info->utok.gid,
					conn->server_info->sanitized_username,
					pdb_get_domain(conn->server_info->sam_account),
					lp_preexec(snum));
		ret = smbrun(cmd,NULL);
		TALLOC_FREE(cmd);
		if (ret != 0 && lp_preexec_close(snum)) {
			DEBUG(1,("preexec gave %d - failing connection\n",
				 ret));
			*pstatus = NT_STATUS_ACCESS_DENIED;
			goto err_root_exit;
		}
	}

#ifdef WITH_FAKE_KASERVER
	if (lp_afs_share(snum)) {
		afs_login(conn);
	}
#endif
	
	/* Add veto/hide lists */
	if (!IS_IPC(conn) && !IS_PRINT(conn)) {
		set_namearray( &conn->veto_list, lp_veto_files(snum));
		set_namearray( &conn->hide_list, lp_hide_files(snum));
		set_namearray( &conn->veto_oplock_list, lp_veto_oplocks(snum));
		set_namearray( &conn->aio_write_behind_list,
				lp_aio_write_behind(snum));
	}
	
	/* Invoke VFS make connection hook - do this before the VFS_STAT call
	   to allow any filesystems needing user credentials to initialize
	   themselves. */

	if (SMB_VFS_CONNECT(conn, lp_servicename(snum),
			    conn->server_info->unix_name) < 0) {
		DEBUG(0,("make_connection: VFS make connection failed!\n"));
		*pstatus = NT_STATUS_UNSUCCESSFUL;
		goto err_root_exit;
	}

	/* Any error exit after here needs to call the disconnect hook. */
	on_err_call_dis_hook = true;

	status = create_synthetic_smb_fname(talloc_tos(), conn->connectpath,
					    NULL, NULL, &smb_fname_cpath);
	if (!NT_STATUS_IS_OK(status)) {
		*pstatus = status;
		goto err_root_exit;
	}

	/* win2000 does not check the permissions on the directory
	   during the tree connect, instead relying on permission
	   check during individual operations. To match this behaviour
	   I have disabled this chdir check (tridge) */
	/* the alternative is just to check the directory exists */
	if ((ret = SMB_VFS_STAT(conn, smb_fname_cpath)) != 0 ||
	    !S_ISDIR(smb_fname_cpath->st.st_ex_mode)) {
		if (ret == 0 && !S_ISDIR(smb_fname_cpath->st.st_ex_mode)) {
			DEBUG(0,("'%s' is not a directory, when connecting to "
				 "[%s]\n", conn->connectpath,
				 lp_servicename(snum)));
		} else {
			DEBUG(0,("'%s' does not exist or permission denied "
				 "when connecting to [%s] Error was %s\n",
				 conn->connectpath, lp_servicename(snum),
				 strerror(errno) ));
		}
		*pstatus = NT_STATUS_BAD_NETWORK_NAME;
		goto err_root_exit;
	}

	string_set(&conn->origpath,conn->connectpath);

#if SOFTLINK_OPTIMISATION
	/* resolve any soft links early if possible */
	if (vfs_ChDir(conn,conn->connectpath) == 0) {
		TALLOC_CTX *ctx = talloc_tos();
		char *s = vfs_GetWd(ctx,s);
		if (!s) {
			*status = map_nt_error_from_unix(errno);
			goto err_root_exit;
		}
		if (!set_conn_connectpath(conn,s)) {
			*status = NT_STATUS_NO_MEMORY;
			goto err_root_exit;
		}
		vfs_ChDir(conn,conn->connectpath);
	}
#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->ts_res);

	/*
	 * Print out the 'connected as' stuff here as we need
	 * to know the effective uid and gid we will be using
	 * (at least initially).
	 */

	if( DEBUGLVL( IS_IPC(conn) ? 3 : 1 ) ) {
		dbgtext( "%s (%s) ", get_remote_machine_name(),
			 conn->client_address );
		dbgtext( "%s", srv_is_signing_active(smbd_server_conn) ? "signed " : "");
		dbgtext( "connect to service %s ", lp_servicename(snum) );
		dbgtext( "initially as user %s ",
			 conn->server_info->unix_name );
		dbgtext( "(uid=%d, gid=%d) ", (int)geteuid(), (int)getegid() );
		dbgtext( "(pid %d)\n", (int)sys_getpid() );
	}

	/* we've finished with the user stuff - go back to root */
	change_to_root_user();
	return(conn);

  err_root_exit:
	TALLOC_FREE(smb_fname_cpath);
	change_to_root_user();
	if (on_err_call_dis_hook) {
		/* Call VFS disconnect hook */
		SMB_VFS_DISCONNECT(conn);
	}
	yield_connection(conn, lp_servicename(snum));
	conn_free(conn);
	return NULL;
}
Exemple #14
0
static NTSTATUS find_forced_group(bool force_user,
				  int snum, const char *username,
				  DOM_SID *pgroup_sid,
				  gid_t *pgid)
{
	NTSTATUS result = NT_STATUS_NO_SUCH_GROUP;
	TALLOC_CTX *frame = talloc_stackframe();
	DOM_SID group_sid;
	enum lsa_SidType type;
	char *groupname;
	bool user_must_be_member = False;
	gid_t gid;

	groupname = talloc_strdup(talloc_tos(), lp_force_group(snum));
	if (groupname == NULL) {
		DEBUG(1, ("talloc_strdup failed\n"));
		result = NT_STATUS_NO_MEMORY;
		goto done;
	}

	if (groupname[0] == '+') {
		user_must_be_member = True;
		groupname += 1;
	}

	groupname = talloc_string_sub(talloc_tos(), groupname,
				      "%S", lp_servicename(snum));
	if (groupname == NULL) {
		DEBUG(1, ("talloc_string_sub failed\n"));
		result = NT_STATUS_NO_MEMORY;
		goto done;
	}

	if (!lookup_name_smbconf(talloc_tos(), groupname,
			 LOOKUP_NAME_ALL|LOOKUP_NAME_GROUP,
			 NULL, NULL, &group_sid, &type)) {
		DEBUG(10, ("lookup_name_smbconf(%s) failed\n",
			   groupname));
		goto done;
	}

	if ((type != SID_NAME_DOM_GRP) && (type != SID_NAME_ALIAS) &&
	    (type != SID_NAME_WKN_GRP)) {
		DEBUG(10, ("%s is a %s, not a group\n", groupname,
			   sid_type_lookup(type)));
		goto done;
	}

	if (!sid_to_gid(&group_sid, &gid)) {
		DEBUG(10, ("sid_to_gid(%s) for %s failed\n",
			   sid_string_dbg(&group_sid), groupname));
		goto done;
	}

	/*
	 * If the user has been forced and the forced group starts with a '+',
	 * then we only set the group to be the forced group if the forced
	 * user is a member of that group.  Otherwise, the meaning of the '+'
	 * would be ignored.
	 */

	if (force_user && user_must_be_member) {
		if (user_in_group_sid(username, &group_sid)) {
			sid_copy(pgroup_sid, &group_sid);
			*pgid = gid;
			DEBUG(3,("Forced group %s for member %s\n",
				 groupname, username));
		} else {
			DEBUG(0,("find_forced_group: forced user %s is not a member "
				"of forced group %s. Disallowing access.\n",
				username, groupname ));
			result = NT_STATUS_MEMBER_NOT_IN_GROUP;
			goto done;
		}
	} else {
		sid_copy(pgroup_sid, &group_sid);
		*pgid = gid;
		DEBUG(3,("Forced group %s\n", groupname));
	}

	result = NT_STATUS_OK;
 done:
	TALLOC_FREE(frame);
	return result;
}
Exemple #15
0
static int generic_job_submit(int snum, struct printjob *pjob)
{
	int ret = -1;
	char *current_directory = NULL;
	char *print_directory = NULL;
	char *wd = NULL;
	char *p = NULL;
	char *jobname = NULL;
	TALLOC_CTX *ctx = talloc_tos();
	fstring job_page_count, job_size;

	/* we print from the directory path to give the best chance of
           parsing the lpq output */
	wd = sys_getwd();
	if (!wd) {
		return -1;
	}

	current_directory = talloc_strdup(ctx, wd);
	SAFE_FREE(wd);

	if (!current_directory) {
		return -1;
	}
	print_directory = talloc_strdup(ctx, pjob->filename);
	if (!print_directory) {
		return -1;
	}
	p = strrchr_m(print_directory,'/');
	if (!p) {
		return -1;
	}
	*p++ = 0;

	if (chdir(print_directory) != 0) {
		return -1;
	}

	jobname = talloc_strdup(ctx, pjob->jobname);
	if (!jobname) {
		ret = -1;
		goto out;
	}
	jobname = talloc_string_sub(ctx, jobname, "'", "_");
	if (!jobname) {
		ret = -1;
		goto out;
	}
	slprintf(job_page_count, sizeof(job_page_count)-1, "%d", pjob->page_count);
	slprintf(job_size, sizeof(job_size)-1, "%lu", (unsigned long)pjob->size);

	/* send it to the system spooler */
	ret = print_run_command(snum, lp_printername(snum), True,
			lp_printcommand(snum), NULL,
			"%s", p,
			"%J", jobname,
			"%f", p,
			"%z", job_size,
			"%c", job_page_count,
			NULL);

 out:

	if (chdir(current_directory) == -1) {
		smb_panic("chdir failed in generic_job_submit");
	}
	TALLOC_FREE(current_directory);
        return ret;
}
Exemple #16
0
static bool token_contains_name(TALLOC_CTX *mem_ctx,
				const char *username,
				const char *domain,
				const char *sharename,
				const struct nt_user_token *token,
				const char *name)
{
	const char *prefix;
	DOM_SID sid;
	enum lsa_SidType type;
	struct smbd_server_connection *sconn = smbd_server_conn;

	if (username != NULL) {
		name = talloc_sub_basic(mem_ctx, username, domain, name);
	}
	if (sharename != NULL) {
		name = talloc_string_sub(mem_ctx, name, "%S", sharename);
	}

	if (name == NULL) {
		/* This is too security sensitive, better panic than return a
		 * result that might be interpreted in a wrong way. */
		smb_panic("substitutions failed");
	}
	
	/* check to see is we already have a SID */

	if ( string_to_sid( &sid, name ) ) {
		DEBUG(5,("token_contains_name: Checking for SID [%s] in token\n", name));
		return nt_token_check_sid( &sid, token );
	}

	if (!do_group_checks(&name, &prefix)) {
		if (!lookup_name_smbconf(mem_ctx, name, LOOKUP_NAME_ALL,
				 NULL, NULL, &sid, &type)) {
			DEBUG(5, ("lookup_name %s failed\n", name));
			return False;
		}
		if (type != SID_NAME_USER) {
			DEBUG(5, ("%s is a %s, expected a user\n",
				  name, sid_type_lookup(type)));
			return False;
		}
		return nt_token_check_sid(&sid, token);
	}

	for (/* initialized above */ ; *prefix != '\0'; prefix++) {
		if (*prefix == '+') {
			if (!lookup_name_smbconf(mem_ctx, name,
					 LOOKUP_NAME_ALL|LOOKUP_NAME_GROUP,
					 NULL, NULL, &sid, &type)) {
				DEBUG(5, ("lookup_name %s failed\n", name));
				return False;
			}
			if ((type != SID_NAME_DOM_GRP) &&
			    (type != SID_NAME_ALIAS) &&
			    (type != SID_NAME_WKN_GRP)) {
				DEBUG(5, ("%s is a %s, expected a group\n",
					  name, sid_type_lookup(type)));
				return False;
			}
			if (nt_token_check_sid(&sid, token)) {
				return True;
			}
			continue;
		}
		if (*prefix == '&') {
			if (username) {
				if (user_in_netgroup(sconn, username, name)) {
					return True;
				}
			}
			continue;
		}
		smb_panic("got invalid prefix from do_groups_check");
	}
	return False;
}
Exemple #17
0
NTSTATUS set_conn_force_user_group(connection_struct *conn, int snum)
{
	NTSTATUS status;

	if (*lp_force_user(talloc_tos(), snum)) {

		/*
		 * Replace conn->session_info with a completely faked up one
		 * from the username we are forced into :-)
		 */

		char *fuser;
		char *sanitized_username;
		struct auth_session_info *forced_serverinfo;
		bool guest;

		fuser = talloc_string_sub(conn, lp_force_user(talloc_tos(), snum), "%S",
					  lp_const_servicename(snum));
		if (fuser == NULL) {
			return NT_STATUS_NO_MEMORY;
		}

		guest = security_session_user_level(conn->session_info, NULL) < SECURITY_USER;

		status = make_session_info_from_username(
			conn, fuser,
			guest,
			&forced_serverinfo);
		if (!NT_STATUS_IS_OK(status)) {
			return status;
		}

		/* We don't want to replace the original sanitized_username
		   as it is the original user given in the connect attempt.
		   This is used in '%U' substitutions. */
		sanitized_username = discard_const_p(char,
			forced_serverinfo->unix_info->sanitized_username);
		TALLOC_FREE(sanitized_username);
		forced_serverinfo->unix_info->sanitized_username =
			talloc_move(forced_serverinfo->unix_info,
				&conn->session_info->unix_info->sanitized_username);

		TALLOC_FREE(conn->session_info);
		conn->session_info = forced_serverinfo;

		conn->force_user = true;
		DEBUG(3,("Forced user %s\n", fuser));
	}

	/*
	 * If force group is true, then override
	 * any groupid stored for the connecting user.
	 */

	if (*lp_force_group(talloc_tos(), snum)) {

		status = find_forced_group(
			conn->force_user, snum, conn->session_info->unix_info->unix_name,
			&conn->session_info->security_token->sids[1],
			&conn->session_info->unix_token->gid);

		if (!NT_STATUS_IS_OK(status)) {
			return status;
		}

		/*
		 * We need to cache this gid, to use within
		 * change_to_user() separately from the conn->session_info
		 * struct. We only use conn->session_info directly if
		 * "force_user" was set.
		 */
		conn->force_group_gid = conn->session_info->unix_token->gid;
	}

	return NT_STATUS_OK;
}
Exemple #18
0
bool authorise_login(int snum, fstring user, DATA_BLOB password,
		     bool *guest)
{
	bool ok = False;

#ifdef DEBUG_PASSWORD
	DEBUG(100,("authorise_login: checking authorisation on "
		   "user=%s pass=%s\n", user,password.data));
#endif

	*guest = False;

	/* there are several possibilities:
		1) login as the given user with given password
		2) login as a previously registered username with the given
		   password
		3) login as a session list username with the given password
		4) login as a previously validated user/password pair
		5) login as the "user ="******"user ="******"");

		if (!user_list)
			return(False);

		for (auser = strtok_r(user_list, LIST_SEP, &saveptr);
		     !ok && auser;
		     auser = strtok_r(NULL, LIST_SEP, &saveptr)) {
			fstring user2;
			fstrcpy(user2,auser);
			if (!user_ok(user2,snum))
				continue;

			if (password_ok(user2,password)) {
				ok = True;
				fstrcpy(user,user2);
				DEBUG(3,("authorise_login: ACCEPTED: session "
					 "list username (%s) and given "
					 "password ok\n", user));
			}
		}

		SAFE_FREE(user_list);
	}

	/* check the user= fields and the given password */
	if (!ok && lp_username(snum)) {
		TALLOC_CTX *ctx = talloc_tos();
		char *auser;
		char *user_list = talloc_strdup(ctx, lp_username(snum));
		char *saveptr;

		if (!user_list) {
			goto check_guest;
		}

		user_list = talloc_string_sub(ctx,
				user_list,
				"%S",
				lp_servicename(snum));

		if (!user_list) {
			goto check_guest;
		}

		for (auser = strtok_r(user_list, LIST_SEP, &saveptr);
		     auser && !ok;
		     auser = strtok_r(NULL, LIST_SEP, &saveptr)) {
			if (*auser == '@') {
				auser = validate_group(auser+1,password,snum);
				if (auser) {
					ok = True;
					fstrcpy(user,auser);
					DEBUG(3,("authorise_login: ACCEPTED: "
						 "group username and given "
						 "password ok (%s)\n", user));
				}
			} else {
				fstring user2;
				fstrcpy(user2,auser);
				if (user_ok(user2,snum) &&
				    password_ok(user2,password)) {
					ok = True;
					fstrcpy(user,user2);
					DEBUG(3,("authorise_login: ACCEPTED: "
						 "user list username and "
						 "given password ok (%s)\n",
						 user));
				}
			}
		}
	}

  check_guest:

	/* check for a normal guest connection */
	if (!ok && GUEST_OK(snum)) {
		struct passwd *guest_pw;
		fstring guestname;
		fstrcpy(guestname,lp_guestaccount());
		guest_pw = Get_Pwnam_alloc(talloc_tos(), guestname);
		if (guest_pw != NULL) {
			fstrcpy(user,guestname);
			ok = True;
			DEBUG(3,("authorise_login: ACCEPTED: guest account "
				 "and guest ok (%s)\n",	user));
		} else {
			DEBUG(0,("authorise_login: Invalid guest account "
				 "%s??\n",guestname));
		}
		TALLOC_FREE(guest_pw);
		*guest = True;
	}

	if (ok && !user_ok(user, snum)) {
		DEBUG(0,("authorise_login: rejected invalid user %s\n",user));
		ok = False;
	}

	return(ok);
}
Exemple #19
0
bool afs_login(connection_struct *conn)
{
    DATA_BLOB ticket;
    char *afs_username = NULL;
    char *cell = NULL;
    bool result;
    char *ticket_str = NULL;
    const struct dom_sid *user_sid;
    TALLOC_CTX *ctx = talloc_tos();

    struct ClearToken ct;

    afs_username = talloc_strdup(ctx,
                                 lp_afs_username_map());
    if (!afs_username) {
        return false;
    }

    afs_username = talloc_sub_advanced(ctx,
                                       lp_servicename(SNUM(conn)),
                                       conn->session_info->unix_info->unix_name,
                                       conn->connectpath,
                                       conn->session_info->unix_token->gid,
                                       conn->session_info->unix_info->sanitized_username,
                                       conn->session_info->info->domain_name,
                                       afs_username);
    if (!afs_username) {
        return false;
    }

    user_sid = &conn->session_info->security_token->sids[0];
    afs_username = talloc_string_sub(talloc_tos(),
                                     afs_username,
                                     "%s",
                                     sid_string_tos(user_sid));
    if (!afs_username) {
        return false;
    }

    /* The pts command always generates completely lower-case user
     * names. */
    strlower_m(afs_username);

    cell = strchr(afs_username, '@');

    if (cell == NULL) {
        DEBUG(1, ("AFS username doesn't contain a @, "
                  "could not find cell\n"));
        return false;
    }

    *cell = '\0';
    cell += 1;

    DEBUG(10, ("Trying to log into AFS for user %s@%s\n",
               afs_username, cell));

    if (!afs_createtoken(afs_username, cell, &ticket, &ct))
        return false;

    /* For which Unix-UID do we want to set the token? */
    ct.ViceId = getuid();

    ticket_str = afs_encode_token(cell, ticket, &ct);

    result = afs_settoken_str(ticket_str);

    SAFE_FREE(ticket_str);

    data_blob_free(&ticket);

    return result;
}
Exemple #20
0
static NTSTATUS create_conn_struct_as_root(TALLOC_CTX *ctx,
			    struct tevent_context *ev,
			    struct messaging_context *msg,
			    connection_struct **pconn,
			    int snum,
			    const char *path,
			    const struct auth_session_info *session_info)
{
	connection_struct *conn;
	char *connpath;
	const char *vfs_user;
	struct smbd_server_connection *sconn;
	const char *servicename = lp_const_servicename(snum);

	sconn = talloc_zero(ctx, struct smbd_server_connection);
	if (sconn == NULL) {
		return NT_STATUS_NO_MEMORY;
	}

	sconn->ev_ctx = ev;
	sconn->msg_ctx = msg;
	sconn->sock = -1;
	sconn->smb1.echo_handler.trusted_fd = -1;
	sconn->smb1.echo_handler.socket_lock_fd = -1;

	conn = conn_new(sconn);
	if (conn == NULL) {
		TALLOC_FREE(sconn);
		return NT_STATUS_NO_MEMORY;
	}

	/* Now we have conn, we need to make sconn a child of conn,
	 * for a proper talloc tree */
	talloc_steal(conn, sconn);

	if (snum == -1 && servicename == NULL) {
		servicename = "Unknown Service (snum == -1)";
	}

	connpath = talloc_strdup(conn, path);
	if (!connpath) {
		TALLOC_FREE(conn);
		return NT_STATUS_NO_MEMORY;
	}
	connpath = talloc_string_sub(conn,
				     connpath,
				     "%S",
				     servicename);
	if (!connpath) {
		TALLOC_FREE(conn);
		return NT_STATUS_NO_MEMORY;
	}

	/* needed for smbd_vfs_init() */

	conn->params->service = snum;
	conn->cnum = TID_FIELD_INVALID;

	if (session_info != NULL) {
		conn->session_info = copy_session_info(conn, session_info);
		if (conn->session_info == NULL) {
			DEBUG(0, ("copy_serverinfo failed\n"));
			TALLOC_FREE(conn);
			return NT_STATUS_NO_MEMORY;
		}
		vfs_user = conn->session_info->unix_info->unix_name;
	} else {
		/* use current authenticated user in absence of session_info */
		vfs_user = get_current_username();
	}

	set_conn_connectpath(conn, connpath);

	/*
	 * New code to check if there's a share security descripter
	 * added from NT server manager. This is done after the
	 * smb.conf checks are done as we need a uid and token. JRA.
	 *
	 */
	if (conn->session_info) {
		share_access_check(conn->session_info->security_token,
				   servicename,
				   MAXIMUM_ALLOWED_ACCESS,
				   &conn->share_access);

		if ((conn->share_access & FILE_WRITE_DATA) == 0) {
			if ((conn->share_access & FILE_READ_DATA) == 0) {
				/* No access, read or write. */
				DEBUG(0,("create_conn_struct: connection to %s "
					 "denied due to security "
					 "descriptor.\n",
					 servicename));
				conn_free(conn);
				return NT_STATUS_ACCESS_DENIED;
			} else {
				conn->read_only = true;
			}
		}
	} else {
		conn->share_access = 0;
		conn->read_only = true;
	}

	if (!smbd_vfs_init(conn)) {
		NTSTATUS status = map_nt_error_from_unix(errno);
		DEBUG(0,("create_conn_struct: smbd_vfs_init failed.\n"));
		conn_free(conn);
		return status;
	}

	/* this must be the first filesystem operation that we do */
	if (SMB_VFS_CONNECT(conn, servicename, vfs_user) < 0) {
		DEBUG(0,("VFS connect failed!\n"));
		conn_free(conn);
		return NT_STATUS_UNSUCCESSFUL;
	}

	conn->fs_capabilities = SMB_VFS_FS_CAPABILITIES(conn, &conn->ts_res);
	*pconn = conn;

	return NT_STATUS_OK;
}