Esempio n. 1
0
File: clidfs.c Progetto: ekohl/samba
static bool cli_dfs_check_error(struct cli_state *cli, NTSTATUS expected,
				NTSTATUS status)
{
	/* only deal with DS when we negotiated NT_STATUS codes and UNICODE */

	if (!(cli_state_capabilities(cli) & CAP_UNICODE)) {
		return false;
	}
	if (!(cli_state_capabilities(cli) & CAP_STATUS32)) {
		return false;
	}
	if (NT_STATUS_EQUAL(status, expected)) {
		return true;
	}
	return false;
}
Esempio n. 2
0
int
SMBC_fstatvfs_ctx(SMBCCTX *context,
                  SMBCFILE *file,
                  struct statvfs *st)
{
        unsigned long flags = 0;
	uint32 fs_attrs = 0;
	struct cli_state *cli = file->srv->cli;

        /* Initialize all fields (at least until we actually use them) */
        memset(st, 0, sizeof(*st));

        /*
         * The state of each flag is such that the same bits are unset as
         * would typically be unset on a local file system on a POSIX OS. Thus
         * the bit is on, for example, only for case-insensitive file systems
         * since most POSIX file systems are case sensitive and fstatvfs()
         * would typically return zero in these bits on such a local file
         * system.
         */

        /* See if the server has UNIX CIFS support */
        if (! SERVER_HAS_UNIX_CIFS(cli)) {
                uint64_t total_allocation_units;
                uint64_t caller_allocation_units;
                uint64_t actual_allocation_units;
                uint64_t sectors_per_allocation_unit;
                uint64_t bytes_per_sector;
		NTSTATUS status;

                /* Nope. If size data is available... */
		status = cli_get_fs_full_size_info(cli,
						   &total_allocation_units,
						   &caller_allocation_units,
						   &actual_allocation_units,
						   &sectors_per_allocation_unit,
						   &bytes_per_sector);
		if (NT_STATUS_IS_OK(status)) {

                        /* ... then provide it */
                        st->f_bsize =
                                (unsigned long) bytes_per_sector;
#if HAVE_FRSIZE
                        st->f_frsize =
                                (unsigned long) sectors_per_allocation_unit;
#endif
                        st->f_blocks =
                                (fsblkcnt_t) total_allocation_units;
                        st->f_bfree =
                                (fsblkcnt_t) actual_allocation_units;
                }

                flags |= SMBC_VFS_FEATURE_NO_UNIXCIFS;
        } else {
                uint32 optimal_transfer_size;
                uint32 block_size;
                uint64_t total_blocks;
                uint64_t blocks_available;
                uint64_t user_blocks_available;
                uint64_t total_file_nodes;
                uint64_t free_file_nodes;
                uint64_t fs_identifier;
		NTSTATUS status;

                /* Has UNIXCIFS. If POSIX filesystem info is available... */
		status = cli_get_posix_fs_info(cli,
					       &optimal_transfer_size,
					       &block_size,
					       &total_blocks,
					       &blocks_available,
					       &user_blocks_available,
					       &total_file_nodes,
					       &free_file_nodes,
					       &fs_identifier);
		if (NT_STATUS_IS_OK(status)) {

                        /* ... then what's provided here takes precedence. */
                        st->f_bsize =
                                (unsigned long) block_size;
                        st->f_blocks =
                                (fsblkcnt_t) total_blocks;
                        st->f_bfree =
                                (fsblkcnt_t) blocks_available;
                        st->f_bavail =
                                (fsblkcnt_t) user_blocks_available;
                        st->f_files =
                                (fsfilcnt_t) total_file_nodes;
                        st->f_ffree =
                                (fsfilcnt_t) free_file_nodes;
#if HAVE_FSID_INT
                        st->f_fsid =
                                (unsigned long) fs_identifier;
#endif
                }
        }

        /* See if the share is case sensitive */
        if (!NT_STATUS_IS_OK(cli_get_fs_attr_info(cli, &fs_attrs))) {
                /*
                 * We can't determine the case sensitivity of
                 * the share. We have no choice but to use the
                 * user-specified case sensitivity setting.
                 */
                if (! smbc_getOptionCaseSensitive(context)) {
                        flags |= SMBC_VFS_FEATURE_CASE_INSENSITIVE;
                }
        } else {
                if (! (fs_attrs & FILE_CASE_SENSITIVE_SEARCH)) {
                        flags |= SMBC_VFS_FEATURE_CASE_INSENSITIVE;
                }
        }

        /* See if DFS is supported */
	if ((cli_state_capabilities(cli) & CAP_DFS) &&  cli->dfsroot) {
                flags |= SMBC_VFS_FEATURE_DFS;
        }

#if HAVE_STATVFS_F_FLAG
        st->f_flag = flags;
#elif HAVE_STATVFS_F_FLAGS
        st->f_flags = flags;
#endif

        return 0;
}
Esempio n. 3
0
/*
 * Get info from an SMB server on a file. Use a qpathinfo call first
 * and if that fails, use getatr, as Win95 sometimes refuses qpathinfo
 */
bool
SMBC_getatr(SMBCCTX * context,
            SMBCSRV *srv,
            const char *path,
            uint16 *mode,
            off_t *size,
            struct timespec *create_time_ts,
            struct timespec *access_time_ts,
            struct timespec *write_time_ts,
            struct timespec *change_time_ts,
            SMB_INO_T *ino)
{
	char *fixedpath = NULL;
	char *targetpath = NULL;
	struct cli_state *targetcli = NULL;
	time_t write_time;
	TALLOC_CTX *frame = talloc_stackframe();
	NTSTATUS status;

	if (!context || !context->internal->initialized) {
		errno = EINVAL;
		TALLOC_FREE(frame);
 		return False;
 	}

	/* path fixup for . and .. */
	if (strequal(path, ".") || strequal(path, "..")) {
		fixedpath = talloc_strdup(frame, "\\");
		if (!fixedpath) {
			errno = ENOMEM;
			TALLOC_FREE(frame);
			return False;
		}
	} else {
		fixedpath = talloc_strdup(frame, path);
		if (!fixedpath) {
			errno = ENOMEM;
			TALLOC_FREE(frame);
			return False;
		}
		trim_string(fixedpath, NULL, "\\..");
		trim_string(fixedpath, NULL, "\\.");
	}
	DEBUG(4,("SMBC_getatr: sending qpathinfo\n"));

	status = cli_resolve_path(frame, "", context->internal->auth_info,
				  srv->cli, fixedpath,
				  &targetcli, &targetpath);
	if (!NT_STATUS_IS_OK(status)) {
		d_printf("Couldn't resolve %s\n", path);
                errno = ENOENT;
		TALLOC_FREE(frame);
		return False;
	}

	if (!srv->no_pathinfo2 &&
            NT_STATUS_IS_OK(cli_qpathinfo2(targetcli, targetpath,
                           create_time_ts,
                           access_time_ts,
                           write_time_ts,
                           change_time_ts,
			   size, mode, ino))) {
		TALLOC_FREE(frame);
		return True;
        }

	/* if this is NT then don't bother with the getatr */
	if (cli_state_capabilities(targetcli) & CAP_NT_SMBS) {
                errno = EPERM;
		TALLOC_FREE(frame);
                return False;
        }

	if (NT_STATUS_IS_OK(cli_getatr(targetcli, targetpath, mode, size, &write_time))) {
                struct timespec w_time_ts;

                w_time_ts = convert_time_t_to_timespec(write_time);
                if (write_time_ts != NULL) {
			*write_time_ts = w_time_ts;
                }
                if (create_time_ts != NULL) {
                        *create_time_ts = w_time_ts;
                }
                if (access_time_ts != NULL) {
                        *access_time_ts = w_time_ts;
                }
                if (change_time_ts != NULL) {
                        *change_time_ts = w_time_ts;
                }
		srv->no_pathinfo2 = True;
		TALLOC_FREE(frame);
		return True;
	}

        errno = EPERM;
	TALLOC_FREE(frame);
	return False;
}
Esempio n. 4
0
File: clidfs.c Progetto: ekohl/samba
static NTSTATUS do_connect(TALLOC_CTX *ctx,
					const char *server,
					const char *share,
					const struct user_auth_info *auth_info,
					bool show_sessetup,
					bool force_encrypt,
					int max_protocol,
					int port,
					int name_type,
					struct cli_state **pcli)
{
	struct cli_state *c = NULL;
	char *servicename;
	char *sharename;
	char *newserver, *newshare;
	const char *username;
	const char *password;
	NTSTATUS status;
	int flags = 0;

	/* make a copy so we don't modify the global string 'service' */
	servicename = talloc_strdup(ctx,share);
	if (!servicename) {
		return NT_STATUS_NO_MEMORY;
	}
	sharename = servicename;
	if (*sharename == '\\') {
		sharename += 2;
		if (server == NULL) {
			server = sharename;
		}
		sharename = strchr_m(sharename,'\\');
		if (!sharename) {
			return NT_STATUS_NO_MEMORY;
		}
		*sharename = 0;
		sharename++;
	}
	if (server == NULL) {
		return NT_STATUS_INVALID_PARAMETER;
	}

	if (get_cmdline_auth_info_use_kerberos(auth_info)) {
		flags |= CLI_FULL_CONNECTION_USE_KERBEROS;
	}
	if (get_cmdline_auth_info_fallback_after_kerberos(auth_info)) {
		flags |= CLI_FULL_CONNECTION_FALLBACK_AFTER_KERBEROS;
	}
	if (get_cmdline_auth_info_use_ccache(auth_info)) {
		flags |= CLI_FULL_CONNECTION_USE_CCACHE;
	}

	status = cli_connect_nb(
		server, NULL, port, name_type, NULL,
		get_cmdline_auth_info_signing_state(auth_info),
		flags, &c);

	if (!NT_STATUS_IS_OK(status)) {
		d_printf("Connection to %s failed (Error %s)\n",
				server,
				nt_errstr(status));
		return status;
	}

	if (max_protocol == 0) {
		max_protocol = PROTOCOL_NT1;
	}
	DEBUG(4,(" session request ok\n"));

	status = cli_negprot(c, max_protocol);

	if (!NT_STATUS_IS_OK(status)) {
		d_printf("protocol negotiation failed: %s\n",
			 nt_errstr(status));
		cli_shutdown(c);
		return status;
	}

	username = get_cmdline_auth_info_username(auth_info);
	password = get_cmdline_auth_info_password(auth_info);

	status = cli_session_setup(c, username,
				   password, strlen(password),
				   password, strlen(password),
				   lp_workgroup());
	if (!NT_STATUS_IS_OK(status)) {
		/* If a password was not supplied then
		 * try again with a null username. */
		if (password[0] || !username[0] ||
			get_cmdline_auth_info_use_kerberos(auth_info) ||
			!NT_STATUS_IS_OK(status = cli_session_setup(c, "",
				    		"", 0,
						"", 0,
					       lp_workgroup()))) {
			d_printf("session setup failed: %s\n",
				 nt_errstr(status));
			if (NT_STATUS_EQUAL(status,
					    NT_STATUS_MORE_PROCESSING_REQUIRED))
				d_printf("did you forget to run kinit?\n");
			cli_shutdown(c);
			return status;
		}
		d_printf("Anonymous login successful\n");
		status = cli_init_creds(c, "", lp_workgroup(), "");
	} else {
		status = cli_init_creds(c, username, lp_workgroup(), password);
	}

	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(10,("cli_init_creds() failed: %s\n", nt_errstr(status)));
		cli_shutdown(c);
		return status;
	}

	if ( show_sessetup ) {
		if (*c->server_domain) {
			DEBUG(0,("Domain=[%s] OS=[%s] Server=[%s]\n",
				c->server_domain,c->server_os,c->server_type));
		} else if (*c->server_os || *c->server_type) {
			DEBUG(0,("OS=[%s] Server=[%s]\n",
				 c->server_os,c->server_type));
		}
	}
	DEBUG(4,(" session setup ok\n"));

	/* here's the fun part....to support 'msdfs proxy' shares
	   (on Samba or windows) we have to issues a TRANS_GET_DFS_REFERRAL
	   here before trying to connect to the original share.
	   cli_check_msdfs_proxy() will fail if it is a normal share. */

	if ((cli_state_capabilities(c) & CAP_DFS) &&
			cli_check_msdfs_proxy(ctx, c, sharename,
				&newserver, &newshare,
				force_encrypt,
				username,
				password,
				lp_workgroup())) {
		cli_shutdown(c);
		return do_connect(ctx, newserver,
				newshare, auth_info, false,
				force_encrypt, max_protocol,
				port, name_type, pcli);
	}

	/* must be a normal share */

	status = cli_tree_connect(c, sharename, "?????",
				  password, strlen(password)+1);
	if (!NT_STATUS_IS_OK(status)) {
		d_printf("tree connect failed: %s\n", nt_errstr(status));
		cli_shutdown(c);
		return status;
	}

	if (force_encrypt) {
		status = cli_cm_force_encryption(c,
					username,
					password,
					lp_workgroup(),
					sharename);
		if (!NT_STATUS_IS_OK(status)) {
			cli_shutdown(c);
			return status;
		}
	}

	DEBUG(4,(" tconx ok\n"));
	*pcli = c;
	return NT_STATUS_OK;
}