Example #1
0
File: open.c Project: jophxy/samba
static BOOL check_share_mode(connection_struct *conn, share_mode_entry *share, int share_mode, uint32 desired_access,
			     const char *fname, BOOL fcbopen, int *flags)
{
	int deny_mode = GET_DENY_MODE(share_mode);
	int old_open_mode = GET_OPEN_MODE(share->share_mode);
	int old_deny_mode = GET_DENY_MODE(share->share_mode);

	/*
	 * share modes = false means don't bother to check for
	 * DENY mode conflict. This is a *really* bad idea :-). JRA.
	 */

	if(!lp_share_modes(SNUM(conn)))
		return True;

	/*
	 * Don't allow any opens once the delete on close flag has been
	 * set.
	 */

	if (GET_DELETE_ON_CLOSE_FLAG(share->share_mode)) {
		DEBUG(5,("check_share_mode: Failing open on file %s as delete on close flag is set.\n",
			fname ));
		/* Use errno to map to correct error. */
		unix_ERR_class = SMB_SUCCESS;
		unix_ERR_code = 0;
		unix_ERR_ntstatus = NT_STATUS_OK;
		return False;
	}

	/* this is a nasty hack, but necessary until we rewrite our open
	   handling to use a NTCreateX call as the basic call.
	   NT may open a file with neither read nor write access, and in
		   this case it expects the open not to conflict with any
		   existing deny modes. This happens (for example) during a
		   "xcopy /o" where the second file descriptor is used for
		   ACL sets
		   (tridge)
	*/

	/*
	 * This is a bit wierd - the test for desired access not having the
	 * critical bits seems seems odd. Firstly, if both opens have no
	 * critical bits then always ignore. Then check the "allow delete"
	 * then check for either. This probably isn't quite right yet but
	 * gets us much closer. JRA.
	 */

	/*
	 * If desired_access doesn't contain READ_DATA,WRITE_DATA,APPEND_DATA or EXECUTE
	 * and the existing desired_acces then share modes don't conflict.
	 */

	if ( !(desired_access & (FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_EXECUTE)) &&
		!(share->desired_access & (FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_EXECUTE)) ) {

		/*
		 * Wrinkle discovered by smbtorture....
		 * If both are non-io open and requester is asking for delete and current open has delete access
		 * but neither open has allowed file share delete then deny.... this is very strange and
		 * seems to be the only case in which non-io opens conflict. JRA.
		 */

		if ((desired_access & DELETE_ACCESS) && (share->desired_access & DELETE_ACCESS) && 
				(!GET_ALLOW_SHARE_DELETE(share->share_mode) || !GET_ALLOW_SHARE_DELETE(share_mode))) {
			DEBUG(5,("check_share_mode: Failing open on file %s as delete access requests conflict.\n",
				fname ));
			unix_ERR_class = ERRDOS;
			unix_ERR_code = ERRbadshare;
			unix_ERR_ntstatus = NT_STATUS_SHARING_VIOLATION;

			return False;
		}

		DEBUG(5,("check_share_mode: Allowing open on file %s as both desired access (0x%x) \
and existing desired access (0x%x) are non-data opens\n", 
			fname, (unsigned int)desired_access, (unsigned int)share->desired_access ));
		return True;
	}

	/*
	 * If delete access was requested and the existing share mode doesn't have
	 * ALLOW_SHARE_DELETE then deny.
	 */

	if ((desired_access & DELETE_ACCESS) && !GET_ALLOW_SHARE_DELETE(share->share_mode)) {
		DEBUG(5,("check_share_mode: Failing open on file %s as delete access requested and allow share delete not set.\n",
			fname ));
		unix_ERR_class = ERRDOS;
		unix_ERR_code = ERRbadshare;
		unix_ERR_ntstatus = NT_STATUS_SHARING_VIOLATION;

		return False;
	}

	/*
	 * The inverse of the above.
	 * If delete access was granted and the new share mode doesn't have
	 * ALLOW_SHARE_DELETE then deny.
	 */

	if ((share->desired_access & DELETE_ACCESS) && !GET_ALLOW_SHARE_DELETE(share_mode)) {
		DEBUG(5,("check_share_mode: Failing open on file %s as delete access granted and allow share delete not requested.\n",
			fname ));
		unix_ERR_class = ERRDOS;
		unix_ERR_code = ERRbadshare;
		unix_ERR_ntstatus = NT_STATUS_SHARING_VIOLATION;

		return False;
	}

	/*
	 * If desired_access doesn't contain READ_DATA,WRITE_DATA,APPEND_DATA or EXECUTE
	 * then share modes don't conflict. Likewise with existing desired access.
	 */

	if ( !(desired_access & (FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_EXECUTE)) ||
		!(share->desired_access & (FILE_READ_DATA|FILE_WRITE_DATA|FILE_APPEND_DATA|FILE_EXECUTE)) ) {
		DEBUG(5,("check_share_mode: Allowing open on file %s as desired access (0x%x) doesn't conflict with\
existing desired access (0x%x).\n", fname, (unsigned int)desired_access, (unsigned int)share->desired_access ));
		return True;
	}
Example #2
0
static void print_share_mode(share_mode_entry *e, char *fname)
{
    static int count;
    if (count==0) {
        d_printf("Locked files:\n");
        d_printf("Pid    DenyMode   Access      R/W        Oplock           Name\n");
        d_printf("--------------------------------------------------------------\n");
    }
    count++;

    if (Ucrit_checkPid(e->pid)) {
        d_printf("%-5d  ",(int)e->pid);
        switch (GET_DENY_MODE(e->share_mode)) {
        case DENY_NONE:
            d_printf("DENY_NONE  ");
            break;
        case DENY_ALL:
            d_printf("DENY_ALL   ");
            break;
        case DENY_DOS:
            d_printf("DENY_DOS   ");
            break;
        case DENY_READ:
            d_printf("DENY_READ  ");
            break;
        case DENY_WRITE:
            printf("DENY_WRITE ");
            break;
        case DENY_FCB:
            d_printf("DENY_FCB ");
            break;
        }
        d_printf("0x%-8x  ",(unsigned int)e->desired_access);
        switch (e->share_mode&0xF) {
        case 0:
            d_printf("RDONLY     ");
            break;
        case 1:
            d_printf("WRONLY     ");
            break;
        case 2:
            d_printf("RDWR       ");
            break;
        }

        if((e->op_type &
                (EXCLUSIVE_OPLOCK|BATCH_OPLOCK)) ==
                (EXCLUSIVE_OPLOCK|BATCH_OPLOCK))
            d_printf("EXCLUSIVE+BATCH ");
        else if (e->op_type & EXCLUSIVE_OPLOCK)
            d_printf("EXCLUSIVE       ");
        else if (e->op_type & BATCH_OPLOCK)
            d_printf("BATCH           ");
        else if (e->op_type & LEVEL_II_OPLOCK)
            d_printf("LEVEL_II        ");
        else
            d_printf("NONE            ");

        d_printf(" %s   %s",fname,
                 asctime(LocalTime((time_t *)&e->time.tv_sec)));
    }
}