Пример #1
0
smb_sdrc_t
smb_com_nt_create_andx(struct smb_request *sr)
{
	struct open_param	*op = &sr->arg.open;
	unsigned char		DirFlag;
	smb_attr_t		attr;
	smb_node_t		*node;
	int rc;

	if ((op->create_options & FILE_DELETE_ON_CLOSE) &&
	    !(op->desired_access & DELETE)) {
		smbsr_error(sr, NT_STATUS_INVALID_PARAMETER,
		    ERRDOS, ERRbadaccess);
		return (SDRC_ERROR);
	}

	if (op->create_disposition > FILE_MAXIMUM_DISPOSITION) {
		smbsr_error(sr, NT_STATUS_INVALID_PARAMETER,
		    ERRDOS, ERRbadaccess);
		return (SDRC_ERROR);
	}

	if (op->dattr & FILE_FLAG_WRITE_THROUGH)
		op->create_options |= FILE_WRITE_THROUGH;

	if (op->dattr & FILE_FLAG_DELETE_ON_CLOSE)
		op->create_options |= FILE_DELETE_ON_CLOSE;

	if (op->dattr & FILE_FLAG_BACKUP_SEMANTICS)
		op->create_options |= FILE_OPEN_FOR_BACKUP_INTENT;

	if (op->create_options & FILE_OPEN_FOR_BACKUP_INTENT)
		sr->user_cr = smb_user_getprivcred(sr->uid_user);

	if (op->rootdirfid == 0) {
		op->fqi.fq_dnode = sr->tid_tree->t_snode;
	} else {
		op->dir = smb_ofile_lookup_by_fid(sr->tid_tree,
		    (uint16_t)op->rootdirfid);
		if (op->dir == NULL) {
			smbsr_error(sr, NT_STATUS_INVALID_HANDLE,
			    ERRDOS, ERRbadfid);
			return (SDRC_ERROR);
		}
		op->fqi.fq_dnode = op->dir->f_node;
	}

	op->op_oplock_levelII = B_TRUE;

	if (smb_common_open(sr) != NT_STATUS_SUCCESS)
		return (SDRC_ERROR);

	switch (sr->tid_tree->t_res_type & STYPE_MASK) {
	case STYPE_DISKTREE:
	case STYPE_PRINTQ:
		if (op->create_options & FILE_DELETE_ON_CLOSE)
			smb_ofile_set_delete_on_close(sr->fid_ofile);

		node = sr->fid_ofile->f_node;
		DirFlag = smb_node_is_dir(node) ? 1 : 0;
		if (smb_node_getattr(sr, node, &attr) != 0) {
			smbsr_error(sr, NT_STATUS_INTERNAL_ERROR,
			    ERRDOS, ERROR_INTERNAL_ERROR);
			return (SDRC_ERROR);
		}

		rc = smbsr_encode_result(sr, 34, 0, "bb.wbwlTTTTlqqwwbw",
		    34,
		    sr->andx_com,
		    0x67,
		    op->op_oplock_level,
		    sr->smb_fid,
		    op->action_taken,
		    &attr.sa_crtime,
		    &attr.sa_vattr.va_atime,
		    &attr.sa_vattr.va_mtime,
		    &attr.sa_vattr.va_ctime,
		    op->dattr & FILE_ATTRIBUTE_MASK,
		    attr.sa_allocsz,
		    attr.sa_vattr.va_size,
		    op->ftype,
		    op->devstate,
		    DirFlag,
		    0);
		break;

	case STYPE_IPC:
		rc = smbsr_encode_result(sr, 34, 0, "bb.wbwlqqqqlqqwwbw",
		    34,
		    sr->andx_com,
		    0x67,
		    0,
		    sr->smb_fid,
		    op->action_taken,
		    0LL,
		    0LL,
		    0LL,
		    0LL,
		    FILE_ATTRIBUTE_NORMAL,
		    0x1000LL,
		    0LL,
		    op->ftype,
		    op->devstate,
		    0,
		    0);
		break;

	default:
		smbsr_error(sr, NT_STATUS_INVALID_DEVICE_REQUEST,
		    ERRDOS, ERROR_INVALID_FUNCTION);
		return (SDRC_ERROR);
	}

	return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR);
}
Пример #2
0
smb_sdrc_t
smb_nt_transact_create(smb_request_t *sr, smb_xa_t *xa)
{
	struct open_param *op = &sr->arg.open;
	uint8_t			DirFlag;
	smb_attr_t		attr;
	smb_ofile_t		*of;
	int			rc;

	if ((op->create_options & FILE_DELETE_ON_CLOSE) &&
	    !(op->desired_access & DELETE)) {
		smbsr_error(sr, NT_STATUS_INVALID_PARAMETER,
		    ERRDOS, ERRbadaccess);
		return (SDRC_ERROR);
	}

	if (op->create_disposition > FILE_MAXIMUM_DISPOSITION) {
		smbsr_error(sr, NT_STATUS_INVALID_PARAMETER,
		    ERRDOS, ERRbadaccess);
		return (SDRC_ERROR);
	}

	if (op->dattr & FILE_FLAG_WRITE_THROUGH)
		op->create_options |= FILE_WRITE_THROUGH;

	if (op->dattr & FILE_FLAG_DELETE_ON_CLOSE)
		op->create_options |= FILE_DELETE_ON_CLOSE;

	if (op->dattr & FILE_FLAG_BACKUP_SEMANTICS)
		op->create_options |= FILE_OPEN_FOR_BACKUP_INTENT;

	if (op->create_options & FILE_OPEN_FOR_BACKUP_INTENT)
		sr->user_cr = smb_user_getprivcred(sr->uid_user);

	if (op->rootdirfid == 0) {
		op->fqi.fq_dnode = sr->tid_tree->t_snode;
	} else {
		op->dir = smb_ofile_lookup_by_fid(sr, (uint16_t)op->rootdirfid);
		if (op->dir == NULL) {
			smbsr_error(sr, NT_STATUS_INVALID_HANDLE,
			    ERRDOS, ERRbadfid);
			return (SDRC_ERROR);
		}
		op->fqi.fq_dnode = op->dir->f_node;
	}

	op->op_oplock_levelII = B_TRUE;

	if (smb_common_open(sr) != NT_STATUS_SUCCESS)
		return (SDRC_ERROR);

	/*
	 * NB: after the above smb_common_open() success,
	 * we have a handle allocated (sr->fid_ofile).
	 * If we don't return success, we must close it.
	 */
	of = sr->fid_ofile;

	switch (sr->tid_tree->t_res_type & STYPE_MASK) {
	case STYPE_DISKTREE:
	case STYPE_PRINTQ:
		if (op->create_options & FILE_DELETE_ON_CLOSE)
			smb_ofile_set_delete_on_close(of);

		DirFlag = smb_node_is_dir(of->f_node) ? 1 : 0;
		bzero(&attr, sizeof (attr));
		attr.sa_mask = SMB_AT_ALL;
		rc = smb_node_getattr(sr, of->f_node, of->f_cr, of, &attr);
		if (rc != 0) {
			smbsr_errno(sr, rc);
			goto errout;
		}

		(void) smb_mbc_encodef(&xa->rep_param_mb, "b.wllTTTTlqqwwb",
		    op->op_oplock_level,
		    sr->smb_fid,
		    op->action_taken,
		    0,	/* EaErrorOffset */
		    &attr.sa_crtime,
		    &attr.sa_vattr.va_atime,
		    &attr.sa_vattr.va_mtime,
		    &attr.sa_vattr.va_ctime,
		    op->dattr & FILE_ATTRIBUTE_MASK,
		    attr.sa_allocsz,
		    attr.sa_vattr.va_size,
		    op->ftype,
		    op->devstate,
		    DirFlag);
		break;

	case STYPE_IPC:
		bzero(&attr, sizeof (smb_attr_t));
		(void) smb_mbc_encodef(&xa->rep_param_mb, "b.wllTTTTlqqwwb",
		    0,
		    sr->smb_fid,
		    op->action_taken,
		    0,	/* EaErrorOffset */
		    &attr.sa_crtime,
		    &attr.sa_vattr.va_atime,
		    &attr.sa_vattr.va_mtime,
		    &attr.sa_vattr.va_ctime,
		    op->dattr,
		    0x1000LL,
		    0LL,
		    op->ftype,
		    op->devstate,
		    0);
		break;

	default:
		smbsr_error(sr, NT_STATUS_INVALID_DEVICE_REQUEST,
		    ERRDOS, ERROR_INVALID_FUNCTION);
		goto errout;
	}
	return (SDRC_SUCCESS);

errout:
	smb_ofile_close(of, 0);
	return (SDRC_ERROR);
}