Example #1
0
static DATA_BLOB NTLMv2_generate_client_data(TALLOC_CTX *mem_ctx, const DATA_BLOB *names_blob)
{
	uint8_t client_chal[8];
	DATA_BLOB response = data_blob(NULL, 0);
	uint8_t long_date[8];
	NTTIME nttime;

	unix_to_nt_time(&nttime, time(NULL));

	generate_random_buffer(client_chal, sizeof(client_chal));

	push_nttime(long_date, 0, nttime);

	/* See http://www.ubiqx.org/cifs/SMB.html#SMB.8.5 */

	/* Deliberately ignore return here.. */
	(void)msrpc_gen(mem_ctx, &response, "ddbbdb",
		  0x00000101,     /* Header  */
		  0,              /* 'Reserved'  */
		  long_date, 8,	  /* Timestamp */
		  client_chal, 8, /* client challenge */
		  0,		  /* Unknown */
		  names_blob->data, names_blob->length);	/* End of name list */

	return response;
}
Example #2
0
/*
  return filesystem attribute info
*/
static NTSTATUS svfs_fsattr(struct ntvfs_module_context *ntvfs,
			    struct ntvfs_request *req, union smb_fsattr *fs)
{
	struct stat st;
	struct svfs_private *p = ntvfs->private_data;

	if (fs->generic.level != RAW_FSATTR_GENERIC) {
		return ntvfs_map_fsattr(ntvfs, req, fs);
	}

	if (stat(p->connectpath, &st) == -1) {
		return map_nt_error_from_unix(errno);
	}

	unix_to_nt_time(&fs->generic.out.create_time, st.st_ctime);
	fs->generic.out.fs_attr = 
		FILE_CASE_PRESERVED_NAMES | 
		FILE_CASE_SENSITIVE_SEARCH | 
		FILE_PERSISTENT_ACLS;
	fs->generic.out.max_file_component_length = 255;
	fs->generic.out.serial_number = 1;
	fs->generic.out.fs_type = talloc_strdup(req, "NTFS");
	fs->generic.out.volume_name = talloc_strdup(req, 
						    lp_servicename(req->tcon->service));

	return NT_STATUS_OK;
}
Example #3
0
/*
  construct msDS-User-Account-Control-Computed attr
*/
static int construct_msds_user_account_control_computed(struct ldb_module *module,
							struct ldb_message *msg, enum ldb_scope scope,
							struct ldb_request *parent)
{
	uint32_t userAccountControl;
	uint32_t msDS_User_Account_Control_Computed = 0;
	struct ldb_context *ldb = ldb_module_get_ctx(module);
	NTTIME now;
	struct ldb_dn *nc_root;
	int ret;

	ret = dsdb_find_nc_root(ldb, msg, msg->dn, &nc_root);
	if (ret != 0) {
		ldb_asprintf_errstring(ldb,
				       "Failed to find NC root of DN: %s: %s",
				       ldb_dn_get_linearized(msg->dn),
				       ldb_errstring(ldb_module_get_ctx(module)));
		return ret;
	}
	if (ldb_dn_compare(nc_root, ldb_get_default_basedn(ldb)) != 0) {
		/* Only calculate this on our default NC */
		return 0;
	}
	/* Test account expire time */
	unix_to_nt_time(&now, time(NULL));

	userAccountControl = ldb_msg_find_attr_as_uint(msg,
						       "userAccountControl",
						       0);
	if (!(userAccountControl & _UF_TRUST_ACCOUNTS)) {

		int64_t lockoutTime = ldb_msg_find_attr_as_int64(msg, "lockoutTime", 0);
		if (lockoutTime != 0) {
			int64_t lockoutDuration = samdb_search_int64(ldb,
								     msg, 0, nc_root,
								     "lockoutDuration", NULL);
			if (lockoutDuration >= 0) {
				msDS_User_Account_Control_Computed |= UF_LOCKOUT;
			} else if (lockoutTime - lockoutDuration >= now) {
				msDS_User_Account_Control_Computed |= UF_LOCKOUT;
			}
		}
	}

	if (!(userAccountControl & _UF_NO_EXPIRY_ACCOUNTS)) {
		NTTIME must_change_time
			= get_msds_user_password_expiry_time_computed(module,
								      msg, nc_root);
		/* check for expired password */
		if (must_change_time < now) {
			msDS_User_Account_Control_Computed |= UF_PASSWORD_EXPIRED;
		}
	}

	return samdb_msg_add_int64(ldb,
				   msg->elements, msg,
				   "msDS-User-Account-Control-Computed",
				   msDS_User_Account_Control_Computed);
}
Example #4
0
static PyObject *py_unix2nttime(PyObject *self, PyObject *args)
{
	time_t t;
	NTTIME nt;
	if (!PyArg_ParseTuple(args, "I", &t))
		return NULL;

	unix_to_nt_time(&nt, t);

	return PyInt_FromLong((uint64_t)nt);
}
Example #5
0
static WERROR dsdb_syntax_NTTIME_ldb_to_drsuapi(struct ldb_context *ldb, 
						const struct dsdb_schema *schema,
						const struct dsdb_attribute *attr,
						const struct ldb_message_element *in,
						TALLOC_CTX *mem_ctx,
						struct drsuapi_DsReplicaAttribute *out)
{
	uint32_t i;
	DATA_BLOB *blobs;

	if (attr->attributeID_id == 0xFFFFFFFF) {
		return WERR_FOOBAR;
	}

	out->attid			= attr->attributeID_id;
	out->value_ctr.num_values	= in->num_values;
	out->value_ctr.values		= talloc_array(mem_ctx,
						       struct drsuapi_DsAttributeValue,
						       in->num_values);
	W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);

	blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
	W_ERROR_HAVE_NO_MEMORY(blobs);

	for (i=0; i < in->num_values; i++) {
		NTTIME v;
		time_t t;

		out->value_ctr.values[i].blob	= &blobs[i];

		blobs[i] = data_blob_talloc(blobs, NULL, 8);
		W_ERROR_HAVE_NO_MEMORY(blobs[i].data);

		t = ldb_string_to_time((const char *)in->values[i].data);
		unix_to_nt_time(&v, t);
		v /= 10000000;

		SBVAL(blobs[i].data, 0, v);
	}

	return WERR_OK;
}
Example #6
0
/*
  return filesystem space info
*/
static NTSTATUS svfs_fsinfo(struct ntvfs_module_context *ntvfs,
			    struct ntvfs_request *req, union smb_fsinfo *fs)
{
	struct svfs_private *p = ntvfs->private_data;
	struct stat st;

	if (fs->generic.level != RAW_QFS_GENERIC) {
		return ntvfs_map_fsinfo(ntvfs, req, fs);
	}

	if (sys_fsusage(p->connectpath,
			&fs->generic.out.blocks_free, 
			&fs->generic.out.blocks_total) == -1) {
		return map_nt_error_from_unix(errno);
	}

	fs->generic.out.block_size = 512;

	if (stat(p->connectpath, &st) != 0) {
		return NT_STATUS_DISK_CORRUPT_ERROR;
	}
	
	fs->generic.out.fs_id = st.st_ino;
	unix_to_nt_time(&fs->generic.out.create_time, st.st_ctime);
	fs->generic.out.serial_number = st.st_ino;
	fs->generic.out.fs_attr = 0;
	fs->generic.out.max_file_component_length = 255;
	fs->generic.out.device_type = 0;
	fs->generic.out.device_characteristics = 0;
	fs->generic.out.quota_soft = 0;
	fs->generic.out.quota_hard = 0;
	fs->generic.out.quota_flags = 0;
	fs->generic.out.volume_name = talloc_strdup(req, ntvfs->ctx->config->name);
	fs->generic.out.fs_type = ntvfs->ctx->fs_type;

	return NT_STATUS_OK;
}
Example #7
0
uint32_t _fss_GetShareMapping(struct pipes_struct *p,
			      struct fss_GetShareMapping *r)
{
	NTSTATUS status;
	struct fss_sc_set *sc_set;
	struct fss_sc *sc;
	struct fss_sc_smap *sc_smap;
	char *share;
	struct fssagent_share_mapping_1 *sm_out;

	TALLOC_CTX *tmp_ctx = talloc_new(p->mem_ctx);
	if (tmp_ctx == NULL) {
		return HRES_ERROR_V(HRES_E_OUTOFMEMORY);
	}

	if (!fss_permitted(p)) {
		talloc_free(tmp_ctx);
		return HRES_ERROR_V(HRES_E_ACCESSDENIED);
	}

	sc_set = sc_set_lookup(fss_global.sc_sets, &r->in.ShadowCopySetId);
	if (sc_set == NULL) {
		talloc_free(tmp_ctx);
		return HRES_ERROR_V(HRES_E_INVALIDARG);
	}

	/*
	 * If ShadowCopySet.Status is not "Exposed", the server SHOULD<9> fail
	 * the call with FSRVP_E_BAD_STATE.
	 * <9> If ShadowCopySet.Status is "Started", "Added",
	 * "CreationInProgress", or "Committed", Windows Server 2012 FSRVP
	 * servers return an error value of 0x80042311.
	 */
	if ((sc_set->state == FSS_SC_STARTED)
	 || (sc_set->state == FSS_SC_ADDED)
	 || (sc_set->state == FSS_SC_CREATING)
	 || (sc_set->state == FSS_SC_COMMITED)) {
		talloc_free(tmp_ctx);
		return 0x80042311;	/* documented magic value */
	}

	sc = sc_lookup(sc_set->scs, &r->in.ShadowCopyId);
	if (sc == NULL) {
		talloc_free(tmp_ctx);
		return HRES_ERROR_V(HRES_E_INVALIDARG);
	}

	status = fss_unc_parse(tmp_ctx, r->in.ShareName, NULL, &share);
	if (!NT_STATUS_IS_OK(status)) {
		talloc_free(tmp_ctx);
		return fss_ntstatus_map(status);
	}

	sc_smap = sc_smap_lookup(sc->smaps, share);
	if (sc_smap == NULL) {
		talloc_free(tmp_ctx);
		return HRES_ERROR_V(HRES_E_INVALIDARG);
	}

	if (r->in.Level != 1) {
		talloc_free(tmp_ctx);
		return HRES_ERROR_V(HRES_E_INVALIDARG);
	}

	sm_out = talloc_zero(p->mem_ctx, struct fssagent_share_mapping_1);
	if (sm_out == NULL) {
		talloc_free(tmp_ctx);
		return HRES_ERROR_V(HRES_E_OUTOFMEMORY);
	}
	sm_out->ShadowCopySetId = sc_set->id;
	sm_out->ShadowCopyId = sc->id;
	sm_out->ShareNameUNC = talloc_asprintf(sm_out, "\\\\%s\\%s",
					       lp_netbios_name(),
					       sc_smap->share_name);
	if (sm_out->ShareNameUNC == NULL) {
		talloc_free(sm_out);
		talloc_free(tmp_ctx);
		return HRES_ERROR_V(HRES_E_OUTOFMEMORY);
	}
	sm_out->ShadowCopyShareName = sc_smap->sc_share_name;
	unix_to_nt_time(&sm_out->tstamp, sc->create_ts);
	r->out.ShareMapping->ShareMapping1 = sm_out;
	talloc_free(tmp_ctx);

	/* reset msg sequence timer */
	TALLOC_FREE(fss_global.seq_tmr);
	fss_seq_tout_set(fss_global.mem_ctx, 1800, sc_set, &fss_global.seq_tmr);

	return 0;
}
Example #8
0
NTSTATUS samu_to_SamInfo3(TALLOC_CTX *mem_ctx,
			  struct samu *samu,
			  const char *login_server,
			  struct netr_SamInfo3 **_info3,
			  struct extra_auth_info *extra)
{
	struct netr_SamInfo3 *info3;
	const struct dom_sid *user_sid;
	const struct dom_sid *group_sid;
	struct dom_sid domain_sid;
	struct dom_sid *group_sids;
	uint32_t num_group_sids = 0;
	const char *tmp;
	gid_t *gids;
	NTSTATUS status;
	bool ok;

	user_sid = pdb_get_user_sid(samu);
	group_sid = pdb_get_group_sid(samu);

	if (!user_sid || !group_sid) {
		DEBUG(1, ("Sam account is missing sids!\n"));
		return NT_STATUS_UNSUCCESSFUL;
	}

	info3 = talloc_zero(mem_ctx, struct netr_SamInfo3);
	if (!info3) {
		return NT_STATUS_NO_MEMORY;
	}

	ZERO_STRUCT(domain_sid);

	/* check if this is a "Unix Users" domain user,
	 * we need to handle it in a special way if that's the case */
	if (sid_check_is_in_unix_users(user_sid)) {
		/* in info3 you can only set rids for the user and the
		 * primary group, and the domain sid must be that of
		 * the sam domain.
		 *
		 * Store a completely bogus value here.
		 * The real SID is stored in the extra sids.
		 * Other code will know to look there if (-1) is found
		 */
		info3->base.rid = (uint32_t)(-1);
		sid_copy(&extra->user_sid, user_sid);

		DEBUG(10, ("Unix User found in struct samu. Rid marked as "
			   "special and sid (%s) saved as extra sid\n",
			   sid_string_dbg(user_sid)));
	} else {
		sid_copy(&domain_sid, user_sid);
		sid_split_rid(&domain_sid, &info3->base.rid);
	}

	if (is_null_sid(&domain_sid)) {
		sid_copy(&domain_sid, get_global_sam_sid());
	}

	/* check if this is a "Unix Groups" domain group,
	 * if so we need special handling */
	if (sid_check_is_in_unix_groups(group_sid)) {
		/* in info3 you can only set rids for the user and the
		 * primary group, and the domain sid must be that of
		 * the sam domain.
		 *
		 * Store a completely bogus value here.
		 * The real SID is stored in the extra sids.
		 * Other code will know to look there if (-1) is found
		 */
		info3->base.primary_gid = (uint32_t)(-1);
		sid_copy(&extra->pgid_sid, group_sid);

		DEBUG(10, ("Unix Group found in struct samu. Rid marked as "
			   "special and sid (%s) saved as extra sid\n",
			   sid_string_dbg(group_sid)));

	} else {
		ok = sid_peek_check_rid(&domain_sid, group_sid,
					&info3->base.primary_gid);
		if (!ok) {
			DEBUG(1, ("The primary group domain sid(%s) does not "
				  "match the domain sid(%s) for %s(%s)\n",
				  sid_string_dbg(group_sid),
				  sid_string_dbg(&domain_sid),
				  pdb_get_username(samu),
				  sid_string_dbg(user_sid)));
			TALLOC_FREE(info3);
			return NT_STATUS_UNSUCCESSFUL;
		}
	}

	unix_to_nt_time(&info3->base.last_logon, pdb_get_logon_time(samu));
	unix_to_nt_time(&info3->base.last_logoff, get_time_t_max());
	unix_to_nt_time(&info3->base.acct_expiry, get_time_t_max());
	unix_to_nt_time(&info3->base.last_password_change,
			pdb_get_pass_last_set_time(samu));
	unix_to_nt_time(&info3->base.allow_password_change,
			pdb_get_pass_can_change_time(samu));
	unix_to_nt_time(&info3->base.force_password_change,
			pdb_get_pass_must_change_time(samu));

	tmp = pdb_get_username(samu);
	if (tmp) {
		info3->base.account_name.string	= talloc_strdup(info3, tmp);
		RET_NOMEM(info3->base.account_name.string);
	}
	tmp = pdb_get_fullname(samu);
	if (tmp) {
		info3->base.full_name.string = talloc_strdup(info3, tmp);
		RET_NOMEM(info3->base.full_name.string);
	}
	tmp = pdb_get_logon_script(samu);
	if (tmp) {
		info3->base.logon_script.string = talloc_strdup(info3, tmp);
		RET_NOMEM(info3->base.logon_script.string);
	}
	tmp = pdb_get_profile_path(samu);
	if (tmp) {
		info3->base.profile_path.string	= talloc_strdup(info3, tmp);
		RET_NOMEM(info3->base.profile_path.string);
	}
	tmp = pdb_get_homedir(samu);
	if (tmp) {
		info3->base.home_directory.string = talloc_strdup(info3, tmp);
		RET_NOMEM(info3->base.home_directory.string);
	}
	tmp = pdb_get_dir_drive(samu);
	if (tmp) {
		info3->base.home_drive.string = talloc_strdup(info3, tmp);
		RET_NOMEM(info3->base.home_drive.string);
	}

	info3->base.logon_count	= pdb_get_logon_count(samu);
	info3->base.bad_password_count = pdb_get_bad_password_count(samu);

	info3->base.domain.string = talloc_strdup(info3,
						  pdb_get_domain(samu));
	RET_NOMEM(info3->base.domain.string);

	info3->base.domain_sid = dom_sid_dup(info3, &domain_sid);
	RET_NOMEM(info3->base.domain_sid);

	status = pdb_enum_group_memberships(mem_ctx, samu,
					    &group_sids, &gids,
					    &num_group_sids);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(1, ("Failed to get groups from sam account.\n"));
		TALLOC_FREE(info3);
		return status;
	}

	if (num_group_sids) {
		status = group_sids_to_info3(info3, group_sids, num_group_sids);
		if (!NT_STATUS_IS_OK(status)) {
			TALLOC_FREE(info3);
			return status;
		}
	}

	/* We don't need sids and gids after the conversion */
	TALLOC_FREE(group_sids);
	TALLOC_FREE(gids);
	num_group_sids = 0;

	/* FIXME: should we add other flags ? */
	info3->base.user_flags = NETLOGON_EXTRA_SIDS;

	if (login_server) {
		info3->base.logon_server.string = talloc_strdup(info3, login_server);
		RET_NOMEM(info3->base.logon_server.string);
	}

	info3->base.acct_flags = pdb_get_acct_ctrl(samu);

	*_info3 = info3;
	return NT_STATUS_OK;
}
Example #9
0
/*
  add or modify a rdataset
 */
_PUBLIC_ isc_result_t dlz_addrdataset(const char *name, const char *rdatastr, void *dbdata, void *version)
{
	struct dlz_bind9_data *state = talloc_get_type_abort(dbdata, struct dlz_bind9_data);
	struct dnsp_DnssrvRpcRecord *rec;
	struct ldb_dn *dn;
	isc_result_t result;
	struct ldb_result *res;
	const char *attrs[] = { "dnsRecord", NULL };
	int ret, i;
	struct ldb_message_element *el;
	enum ndr_err_code ndr_err;
	NTTIME t;

	if (state->transaction_token != (void*)version) {
		state->log(ISC_LOG_INFO, "samba_dlz: bad transaction version");
		return ISC_R_FAILURE;
	}

	rec = talloc_zero(state, struct dnsp_DnssrvRpcRecord);
	if (rec == NULL) {
		return ISC_R_NOMEMORY;
	}

	unix_to_nt_time(&t, time(NULL));
	t /= 10*1000*1000; /* convert to seconds (NT time is in 100ns units) */
	t /= 3600;         /* convert to hours */

	rec->rank        = DNS_RANK_ZONE;
	rec->dwSerial    = state->soa_serial;
	rec->dwTimeStamp = (uint32_t)t;

	if (!b9_parse(state, rdatastr, rec)) {
		state->log(ISC_LOG_INFO, "samba_dlz: failed to parse rdataset '%s'", rdatastr);
		talloc_free(rec);
		return ISC_R_FAILURE;
	}

	/* find the DN of the record */
	result = b9_find_name_dn(state, name, rec, &dn);
	if (result != ISC_R_SUCCESS) {
		talloc_free(rec);
		return result;
	}

	/* get any existing records */
	ret = ldb_search(state->samdb, rec, &res, dn, LDB_SCOPE_BASE, attrs, "objectClass=dnsNode");
	if (ret == LDB_ERR_NO_SUCH_OBJECT) {
		result = b9_add_record(state, name, dn, rec);
		talloc_free(rec);
		if (result == ISC_R_SUCCESS) {
			state->log(ISC_LOG_ERROR, "samba_dlz: added %s %s", name, rdatastr);
		}
		return result;
	}

	/* there are existing records. We need to see if this will
	 * replace a record or add to it
	 */
	el = ldb_msg_find_element(res->msgs[0], "dnsRecord");
	if (el == NULL) {
		state->log(ISC_LOG_ERROR, "samba_dlz: no dnsRecord attribute for %s",
			   ldb_dn_get_linearized(dn));
		talloc_free(rec);
		return ISC_R_FAILURE;
	}

	for (i=0; i<el->num_values; i++) {
		struct dnsp_DnssrvRpcRecord rec2;

		ndr_err = ndr_pull_struct_blob(&el->values[i], rec, &rec2,
					       (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnssrvRpcRecord);
		if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
			state->log(ISC_LOG_ERROR, "samba_dlz: failed to parse dnsRecord for %s",
				   ldb_dn_get_linearized(dn));
			talloc_free(rec);
			return ISC_R_FAILURE;
		}

		if (b9_record_match(state, rec, &rec2)) {
			break;
		}
	}
	if (i == el->num_values) {
		/* adding a new value */
		el->values = talloc_realloc(el, el->values, struct ldb_val, el->num_values+1);
		if (el->values == NULL) {
			talloc_free(rec);
			return ISC_R_NOMEMORY;
		}
		el->num_values++;
	}
Example #10
0
/*
  fill in the dos file attributes for a file
*/
NTSTATUS pvfs_fill_dos_info(struct pvfs_state *pvfs, struct pvfs_filename *name,
			    unsigned int flags, int fd)
{
	NTSTATUS status;
	DATA_BLOB lkey;
	NTTIME write_time;

	/* make directories appear as size 0 with 1 link */
	if (S_ISDIR(name->st.st_mode)) {
		name->st.st_size = 0;
		name->st.st_nlink = 1;
	} else if (name->stream_id == 0) {
		name->stream_name = NULL;
	}

	/* for now just use the simple samba mapping */
	unix_to_nt_time(&name->dos.create_time, name->st.st_ctime);
	unix_to_nt_time(&name->dos.access_time, name->st.st_atime);
	unix_to_nt_time(&name->dos.write_time,  name->st.st_mtime);
	unix_to_nt_time(&name->dos.change_time, name->st.st_ctime);
#ifdef HAVE_STAT_TV_NSEC
	name->dos.create_time += name->st.st_ctim.tv_nsec / 100;
	name->dos.access_time += name->st.st_atim.tv_nsec / 100;
	name->dos.write_time  += name->st.st_mtim.tv_nsec / 100;
	name->dos.change_time += name->st.st_ctim.tv_nsec / 100;
#endif
	name->dos.attrib = dos_mode_from_stat(pvfs, &name->st);
	name->dos.alloc_size = pvfs_round_alloc_size(pvfs, name->st.st_size);
	name->dos.nlink = name->st.st_nlink;
	name->dos.ea_size = 4;  /* TODO: Fill this in without hitting the stream bad in pvfs_doseas_load() */
	if (pvfs->ntvfs->ctx->protocol >= PROTOCOL_SMB2_02) {
		/* SMB2 represents a null EA with zero bytes */
		name->dos.ea_size = 0;
	}
	
	name->dos.file_id = (((uint64_t)name->st.st_dev)<<32) | name->st.st_ino;
	name->dos.flags = 0;

	status = pvfs_dosattrib_load(pvfs, name, fd);
	NT_STATUS_NOT_OK_RETURN(status);

	if (flags & PVFS_RESOLVE_NO_OPENDB) {
		return NT_STATUS_OK;
	}

	status = pvfs_locking_key(name, name, &lkey);
	NT_STATUS_NOT_OK_RETURN(status);

	status = odb_get_file_infos(pvfs->odb_context, &lkey,
				    NULL, &write_time);
	data_blob_free(&lkey);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(1,("WARNING: odb_get_file_infos: %s\n", nt_errstr(status)));
		return status;
	}

	if (!null_time(write_time)) {
		name->dos.write_time = write_time;
	}

	return NT_STATUS_OK;
}
Example #11
0
/* basic testing of all RAW_SFILEINFO_* calls
   for each call we test that it succeeds, and where possible test
   for consistency between the calls.
*/
static bool
torture_raw_sfileinfo_base(struct torture_context *torture, struct smbcli_state *cli)
{
    bool ret = true;
    int fnum = -1;
    char *fnum_fname;
    char *fnum_fname_new;
    char *path_fname;
    char *path_fname_new;
    union smb_fileinfo finfo1, finfo2;
    union smb_setfileinfo sfinfo;
    NTSTATUS status, status2;
    const char *call_name;
    time_t basetime = (time(NULL) - 86400) & ~1;
    bool check_fnum;
    int n = time(NULL) % 100;

    asprintf(&path_fname, BASEDIR "\\fname_test_%d.txt", n);
    asprintf(&path_fname_new, BASEDIR "\\fname_test_new_%d.txt", n);
    asprintf(&fnum_fname, BASEDIR "\\fnum_test_%d.txt", n);
    asprintf(&fnum_fname_new, BASEDIR "\\fnum_test_new_%d.txt", n);

    if (!torture_setup_dir(cli, BASEDIR)) {
        return false;
    }

#define RECREATE_FILE(fname) do { \
	if (fnum != -1) smbcli_close(cli->tree, fnum); \
	fnum = create_complex_file(cli, torture, fname); \
	if (fnum == -1) { \
		printf("(%s) ERROR: open of %s failed (%s)\n", \
		       __location__, fname, smbcli_errstr(cli->tree)); \
		ret = false; \
		goto done; \
	}} while (0)

#define RECREATE_BOTH do { \
		RECREATE_FILE(path_fname); \
		smbcli_close(cli->tree, fnum); \
		RECREATE_FILE(fnum_fname); \
	} while (0)

    RECREATE_BOTH;

#define CHECK_CALL_FNUM(call, rightstatus) do { \
	check_fnum = true; \
	call_name = #call; \
	sfinfo.generic.level = RAW_SFILEINFO_ ## call; \
	sfinfo.generic.in.file.fnum = fnum; \
	status = smb_raw_setfileinfo(cli->tree, &sfinfo); \
	if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) { \
                torture_warning(torture, \
			"(%s) %s - %s", __location__, #call, \
                        nt_errstr(status)); \
        } else if (!NT_STATUS_EQUAL(status, rightstatus)) { \
		printf("(%s) %s - %s (should be %s)\n", __location__, #call, \
			nt_errstr(status), nt_errstr(rightstatus)); \
		ret = false; \
	} \
	finfo1.generic.level = RAW_FILEINFO_ALL_INFO; \
	finfo1.generic.in.file.fnum = fnum; \
	status2 = smb_raw_fileinfo(cli->tree, torture, &finfo1); \
	if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) { \
                torture_warning(torture, \
			"(%s) %s - %s", __location__, #call, \
                        nt_errstr(status)); \
        } else if (!NT_STATUS_IS_OK(status2)) { \
		printf("(%s) %s pathinfo - %s\n", __location__, #call, nt_errstr(status)); \
		ret = false; \
	}} while (0)

#define CHECK_CALL_PATH(call, rightstatus) do { \
	check_fnum = false; \
	call_name = #call; \
	sfinfo.generic.level = RAW_SFILEINFO_ ## call; \
	sfinfo.generic.in.file.path = path_fname; \
	status = smb_raw_setpathinfo(cli->tree, &sfinfo); \
	if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) { \
		sfinfo.generic.in.file.path = path_fname_new; \
		status = smb_raw_setpathinfo(cli->tree, &sfinfo); \
	} \
	if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) { \
                torture_warning(torture, \
			"(%s) %s - %s", __location__, #call, \
                        nt_errstr(status)); \
        } else if (!NT_STATUS_EQUAL(status, rightstatus)) { \
		printf("(%s) %s - %s (should be %s)\n", __location__, #call, \
			nt_errstr(status), nt_errstr(rightstatus)); \
		ret = false; \
	} \
	finfo1.generic.level = RAW_FILEINFO_ALL_INFO; \
	finfo1.generic.in.file.path = path_fname; \
	status2 = smb_raw_pathinfo(cli->tree, torture, &finfo1); \
	if (NT_STATUS_EQUAL(status2, NT_STATUS_OBJECT_NAME_NOT_FOUND)) { \
		finfo1.generic.in.file.path = path_fname_new; \
		status2 = smb_raw_pathinfo(cli->tree, torture, &finfo1); \
	} \
	if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_SUPPORTED)) { \
                torture_warning(torture, \
			"(%s) %s - %s", __location__, #call, \
                        nt_errstr(status)); \
        } else if (!NT_STATUS_IS_OK(status2)) { \
		printf("(%s) %s pathinfo - %s\n", __location__, #call, nt_errstr(status2)); \
		ret = false; \
	}} while (0)

#define CHECK1(call) \
	do { if (NT_STATUS_IS_OK(status)) { \
		finfo2.generic.level = RAW_FILEINFO_ ## call; \
		if (check_fnum) { \
			finfo2.generic.in.file.fnum = fnum; \
			status2 = smb_raw_fileinfo(cli->tree, torture, &finfo2); \
		} else { \
			finfo2.generic.in.file.path = path_fname; \
			status2 = smb_raw_pathinfo(cli->tree, torture, &finfo2); \
			if (NT_STATUS_EQUAL(status2, NT_STATUS_OBJECT_NAME_NOT_FOUND)) { \
				finfo2.generic.in.file.path = path_fname_new; \
				status2 = smb_raw_pathinfo(cli->tree, torture, &finfo2); \
			} \
		} \
		if (!NT_STATUS_IS_OK(status2)) { \
			printf("%s - %s\n", #call, nt_errstr(status2)); \
			ret = false; \
		} \
	}} while (0)

#define CHECK_VALUE(call, stype, field, value) do { \
 	CHECK1(call); \
	if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(status2) && finfo2.stype.out.field != value) { \
		printf("(%s) %s - %s/%s should be 0x%x - 0x%x\n", __location__, \
		       call_name, #stype, #field, \
		       (unsigned int)value, (unsigned int)finfo2.stype.out.field); \
		dump_all_info(torture, &finfo1); \
		ret = false; \
	}} while (0)

#define CHECK_TIME(call, stype, field, value) do { \
 	CHECK1(call); \
	if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(status2) && nt_time_to_unix(finfo2.stype.out.field) != value) { \
		printf("(%s) %s - %s/%s should be 0x%x - 0x%x\n", __location__, \
		        call_name, #stype, #field, \
		        (unsigned int)value, \
			(unsigned int)nt_time_to_unix(finfo2.stype.out.field)); \
		printf("\t%s", timestring(torture, value)); \
		printf("\t%s\n", nt_time_string(torture, finfo2.stype.out.field)); \
		dump_all_info(torture, &finfo1); \
		ret = false; \
	}} while (0)

#define CHECK_STR(call, stype, field, value) do { \
 	CHECK1(call); \
	if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(status2) && strcmp(finfo2.stype.out.field, value) != 0) { \
		printf("(%s) %s - %s/%s should be '%s' - '%s'\n", __location__, \
		        call_name, #stype, #field, \
		        value, \
			finfo2.stype.out.field); \
		dump_all_info(torture, &finfo1); \
		ret = false; \
	}} while (0)

#define CHECK_STATUS(status, correct) do { \
	if (!NT_STATUS_EQUAL(status, correct)) { \
		printf("(%s) Incorrect status %s - should be %s\n", \
		       __location__, nt_errstr(status), nt_errstr(correct)); \
		ret = false; \
		goto done; \
	}} while (0)


    printf("Test setattr\n");
    sfinfo.setattr.in.attrib = FILE_ATTRIBUTE_READONLY;
    sfinfo.setattr.in.write_time = basetime;
    CHECK_CALL_PATH(SETATTR, NT_STATUS_OK);
    CHECK_VALUE  (ALL_INFO, all_info, attrib,     FILE_ATTRIBUTE_READONLY);
    CHECK_TIME   (ALL_INFO, all_info, write_time, basetime);

    printf("setting to NORMAL doesn't do anything\n");
    sfinfo.setattr.in.attrib = FILE_ATTRIBUTE_NORMAL;
    sfinfo.setattr.in.write_time = 0;
    CHECK_CALL_PATH(SETATTR, NT_STATUS_OK);
    CHECK_VALUE(ALL_INFO, all_info, attrib,     FILE_ATTRIBUTE_READONLY);
    CHECK_TIME (ALL_INFO, all_info, write_time, basetime);

    printf("a zero write_time means don't change\n");
    sfinfo.setattr.in.attrib = 0;
    sfinfo.setattr.in.write_time = 0;
    CHECK_CALL_PATH(SETATTR, NT_STATUS_OK);
    CHECK_VALUE(ALL_INFO, all_info, attrib,     FILE_ATTRIBUTE_NORMAL);
    CHECK_TIME (ALL_INFO, all_info, write_time, basetime);

    printf("Test setattre\n");
    sfinfo.setattre.in.create_time = basetime + 20;
    sfinfo.setattre.in.access_time = basetime + 30;
    sfinfo.setattre.in.write_time  = basetime + 40;
    CHECK_CALL_FNUM(SETATTRE, NT_STATUS_OK);
    CHECK_TIME(ALL_INFO, all_info, create_time, basetime + 20);
    CHECK_TIME(ALL_INFO, all_info, access_time, basetime + 30);
    CHECK_TIME(ALL_INFO, all_info, write_time,  basetime + 40);

    sfinfo.setattre.in.create_time = 0;
    sfinfo.setattre.in.access_time = 0;
    sfinfo.setattre.in.write_time  = 0;
    CHECK_CALL_FNUM(SETATTRE, NT_STATUS_OK);
    CHECK_TIME(ALL_INFO, all_info, create_time, basetime + 20);
    CHECK_TIME(ALL_INFO, all_info, access_time, basetime + 30);
    CHECK_TIME(ALL_INFO, all_info, write_time,  basetime + 40);

    printf("Test standard level\n");
    sfinfo.standard.in.create_time = basetime + 100;
    sfinfo.standard.in.access_time = basetime + 200;
    sfinfo.standard.in.write_time  = basetime + 300;
    CHECK_CALL_FNUM(STANDARD, NT_STATUS_OK);
    CHECK_TIME(ALL_INFO, all_info, create_time, basetime + 100);
    CHECK_TIME(ALL_INFO, all_info, access_time, basetime + 200);
    CHECK_TIME(ALL_INFO, all_info, write_time,  basetime + 300);

    printf("Test basic_info level\n");
    basetime += 86400;
    unix_to_nt_time(&sfinfo.basic_info.in.create_time, basetime + 100);
    unix_to_nt_time(&sfinfo.basic_info.in.access_time, basetime + 200);
    unix_to_nt_time(&sfinfo.basic_info.in.write_time,  basetime + 300);
    unix_to_nt_time(&sfinfo.basic_info.in.change_time, basetime + 400);
    sfinfo.basic_info.in.attrib = FILE_ATTRIBUTE_READONLY;
    CHECK_CALL_FNUM(BASIC_INFO, NT_STATUS_OK);
    CHECK_TIME(ALL_INFO, all_info, create_time, basetime + 100);
    CHECK_TIME(ALL_INFO, all_info, access_time, basetime + 200);
    CHECK_TIME(ALL_INFO, all_info, write_time,  basetime + 300);
    CHECK_TIME(ALL_INFO, all_info, change_time, basetime + 400);
    CHECK_VALUE(ALL_INFO, all_info, attrib,     FILE_ATTRIBUTE_READONLY);

    printf("a zero time means don't change\n");
    unix_to_nt_time(&sfinfo.basic_info.in.create_time, 0);
    unix_to_nt_time(&sfinfo.basic_info.in.access_time, 0);
    unix_to_nt_time(&sfinfo.basic_info.in.write_time,  0);
    unix_to_nt_time(&sfinfo.basic_info.in.change_time, 0);
    sfinfo.basic_info.in.attrib = 0;
    CHECK_CALL_FNUM(BASIC_INFO, NT_STATUS_OK);
    CHECK_TIME(ALL_INFO, all_info, create_time, basetime + 100);
    CHECK_TIME(ALL_INFO, all_info, access_time, basetime + 200);
    CHECK_TIME(ALL_INFO, all_info, write_time,  basetime + 300);
    CHECK_TIME(ALL_INFO, all_info, change_time, basetime + 400);
    CHECK_VALUE(ALL_INFO, all_info, attrib,     FILE_ATTRIBUTE_READONLY);

    printf("Test basic_information level\n");
    basetime += 86400;
    unix_to_nt_time(&sfinfo.basic_info.in.create_time, basetime + 100);
    unix_to_nt_time(&sfinfo.basic_info.in.access_time, basetime + 200);
    unix_to_nt_time(&sfinfo.basic_info.in.write_time,  basetime + 300);
    unix_to_nt_time(&sfinfo.basic_info.in.change_time, basetime + 400);
    sfinfo.basic_info.in.attrib = FILE_ATTRIBUTE_NORMAL;
    CHECK_CALL_FNUM(BASIC_INFORMATION, NT_STATUS_OK);
    CHECK_TIME(ALL_INFO, all_info, create_time, basetime + 100);
    CHECK_TIME(ALL_INFO, all_info, access_time, basetime + 200);
    CHECK_TIME(ALL_INFO, all_info, write_time,  basetime + 300);
    CHECK_TIME(ALL_INFO, all_info, change_time, basetime + 400);
    CHECK_VALUE(ALL_INFO, all_info, attrib,     FILE_ATTRIBUTE_NORMAL);

    CHECK_CALL_PATH(BASIC_INFORMATION, NT_STATUS_OK);
    CHECK_TIME(ALL_INFO, all_info, create_time, basetime + 100);
    CHECK_TIME(ALL_INFO, all_info, access_time, basetime + 200);
    CHECK_TIME(ALL_INFO, all_info, write_time,  basetime + 300);
    CHECK_TIME(ALL_INFO, all_info, change_time, basetime + 400);
    CHECK_VALUE(ALL_INFO, all_info, attrib,     FILE_ATTRIBUTE_NORMAL);

    torture_comment(torture, "try to change a file to a directory\n");
    sfinfo.basic_info.in.attrib = FILE_ATTRIBUTE_DIRECTORY;
    CHECK_CALL_FNUM(BASIC_INFO, NT_STATUS_INVALID_PARAMETER);

    printf("a zero time means don't change\n");
    unix_to_nt_time(&sfinfo.basic_info.in.create_time, 0);
    unix_to_nt_time(&sfinfo.basic_info.in.access_time, 0);
    unix_to_nt_time(&sfinfo.basic_info.in.write_time,  0);
    unix_to_nt_time(&sfinfo.basic_info.in.change_time, 0);
    sfinfo.basic_info.in.attrib = FILE_ATTRIBUTE_NORMAL;
    CHECK_CALL_FNUM(BASIC_INFORMATION, NT_STATUS_OK);
    CHECK_TIME(ALL_INFO, all_info, create_time, basetime + 100);
    CHECK_TIME(ALL_INFO, all_info, access_time, basetime + 200);
    CHECK_TIME(ALL_INFO, all_info, write_time,  basetime + 300);
    CHECK_TIME(ALL_INFO, all_info, change_time, basetime + 400);
    CHECK_VALUE(ALL_INFO, all_info, attrib,     FILE_ATTRIBUTE_NORMAL);

    CHECK_CALL_PATH(BASIC_INFORMATION, NT_STATUS_OK);
    CHECK_TIME(ALL_INFO, all_info, create_time, basetime + 100);
    CHECK_TIME(ALL_INFO, all_info, access_time, basetime + 200);
    CHECK_TIME(ALL_INFO, all_info, write_time,  basetime + 300);

    /* interesting - w2k3 leaves change_time as current time for 0 change time
       in setpathinfo
      CHECK_TIME(ALL_INFO, all_info, change_time, basetime + 400);
    */
    CHECK_VALUE(ALL_INFO, all_info, attrib,     FILE_ATTRIBUTE_NORMAL);

    printf("Test disposition_info level\n");
    sfinfo.disposition_info.in.delete_on_close = 1;
    CHECK_CALL_FNUM(DISPOSITION_INFO, NT_STATUS_OK);
    CHECK_VALUE(ALL_INFO, all_info, delete_pending, 1);
    CHECK_VALUE(ALL_INFO, all_info, nlink, 0);

    sfinfo.disposition_info.in.delete_on_close = 0;
    CHECK_CALL_FNUM(DISPOSITION_INFO, NT_STATUS_OK);
    CHECK_VALUE(ALL_INFO, all_info, delete_pending, 0);
    CHECK_VALUE(ALL_INFO, all_info, nlink, 1);

    printf("Test disposition_information level\n");
    sfinfo.disposition_info.in.delete_on_close = 1;
    CHECK_CALL_FNUM(DISPOSITION_INFORMATION, NT_STATUS_OK);
    CHECK_VALUE(ALL_INFO, all_info, delete_pending, 1);
    CHECK_VALUE(ALL_INFO, all_info, nlink, 0);

    /* this would delete the file! */
    /*
      CHECK_CALL_PATH(DISPOSITION_INFORMATION, NT_STATUS_OK);
      CHECK_VALUE(ALL_INFO, all_info, delete_pending, 1);
      CHECK_VALUE(ALL_INFO, all_info, nlink, 0);
    */

    sfinfo.disposition_info.in.delete_on_close = 0;
    CHECK_CALL_FNUM(DISPOSITION_INFORMATION, NT_STATUS_OK);
    CHECK_VALUE(ALL_INFO, all_info, delete_pending, 0);
    CHECK_VALUE(ALL_INFO, all_info, nlink, 1);

    CHECK_CALL_PATH(DISPOSITION_INFORMATION, NT_STATUS_OK);
    CHECK_VALUE(ALL_INFO, all_info, delete_pending, 0);
    CHECK_VALUE(ALL_INFO, all_info, nlink, 1);

    printf("Test allocation_info level\n");
    sfinfo.allocation_info.in.alloc_size = 0;
    CHECK_CALL_FNUM(ALLOCATION_INFO, NT_STATUS_OK);
    CHECK_VALUE(ALL_INFO, all_info, size, 0);
    CHECK_VALUE(ALL_INFO, all_info, alloc_size, 0);

    sfinfo.allocation_info.in.alloc_size = 4096;
    CHECK_CALL_FNUM(ALLOCATION_INFO, NT_STATUS_OK);
    CHECK_VALUE(ALL_INFO, all_info, alloc_size, 4096);
    CHECK_VALUE(ALL_INFO, all_info, size, 0);

    RECREATE_BOTH;
    sfinfo.allocation_info.in.alloc_size = 0;
    CHECK_CALL_FNUM(ALLOCATION_INFORMATION, NT_STATUS_OK);
    CHECK_VALUE(ALL_INFO, all_info, size, 0);
    CHECK_VALUE(ALL_INFO, all_info, alloc_size, 0);

    CHECK_CALL_PATH(ALLOCATION_INFORMATION, NT_STATUS_OK);
    CHECK_VALUE(ALL_INFO, all_info, size, 0);
    CHECK_VALUE(ALL_INFO, all_info, alloc_size, 0);

    sfinfo.allocation_info.in.alloc_size = 4096;
    CHECK_CALL_FNUM(ALLOCATION_INFORMATION, NT_STATUS_OK);
    CHECK_VALUE(ALL_INFO, all_info, alloc_size, 4096);
    CHECK_VALUE(ALL_INFO, all_info, size, 0);

    /* setting the allocation size up via setpathinfo seems
       to be broken in w2k3 */
    CHECK_CALL_PATH(ALLOCATION_INFORMATION, NT_STATUS_OK);
    CHECK_VALUE(ALL_INFO, all_info, alloc_size, 0);
    CHECK_VALUE(ALL_INFO, all_info, size, 0);

    printf("Test end_of_file_info level\n");
    sfinfo.end_of_file_info.in.size = 37;
    CHECK_CALL_FNUM(END_OF_FILE_INFO, NT_STATUS_OK);
    CHECK_VALUE(ALL_INFO, all_info, size, 37);

    sfinfo.end_of_file_info.in.size = 7;
    CHECK_CALL_FNUM(END_OF_FILE_INFO, NT_STATUS_OK);
    CHECK_VALUE(ALL_INFO, all_info, size, 7);

    sfinfo.end_of_file_info.in.size = 37;
    CHECK_CALL_FNUM(END_OF_FILE_INFORMATION, NT_STATUS_OK);
    CHECK_VALUE(ALL_INFO, all_info, size, 37);

    CHECK_CALL_PATH(END_OF_FILE_INFORMATION, NT_STATUS_OK);
    CHECK_VALUE(ALL_INFO, all_info, size, 37);

    sfinfo.end_of_file_info.in.size = 7;
    CHECK_CALL_FNUM(END_OF_FILE_INFORMATION, NT_STATUS_OK);
    CHECK_VALUE(ALL_INFO, all_info, size, 7);

    CHECK_CALL_PATH(END_OF_FILE_INFORMATION, NT_STATUS_OK);
    CHECK_VALUE(ALL_INFO, all_info, size, 7);

    printf("Test position_information level\n");
    sfinfo.position_information.in.position = 123456;
    CHECK_CALL_FNUM(POSITION_INFORMATION, NT_STATUS_OK);
    CHECK_VALUE(POSITION_INFORMATION, position_information, position, 123456);

    CHECK_CALL_PATH(POSITION_INFORMATION, NT_STATUS_OK);
    CHECK_VALUE(POSITION_INFORMATION, position_information, position, 0);

    printf("Test mode_information level\n");
    sfinfo.mode_information.in.mode = 2;
    CHECK_CALL_FNUM(MODE_INFORMATION, NT_STATUS_OK);
    CHECK_VALUE(MODE_INFORMATION, mode_information, mode, 2);

    CHECK_CALL_PATH(MODE_INFORMATION, NT_STATUS_OK);
    CHECK_VALUE(MODE_INFORMATION, mode_information, mode, 0);

    sfinfo.mode_information.in.mode = 1;
    CHECK_CALL_FNUM(MODE_INFORMATION, NT_STATUS_INVALID_PARAMETER);
    CHECK_CALL_PATH(MODE_INFORMATION, NT_STATUS_INVALID_PARAMETER);

    sfinfo.mode_information.in.mode = 0;
    CHECK_CALL_FNUM(MODE_INFORMATION, NT_STATUS_OK);
    CHECK_VALUE(MODE_INFORMATION, mode_information, mode, 0);

    CHECK_CALL_PATH(MODE_INFORMATION, NT_STATUS_OK);
    CHECK_VALUE(MODE_INFORMATION, mode_information, mode, 0);

#if 0
    printf("Test unix_basic level\n");
    CHECK_CALL_FNUM(UNIX_BASIC, NT_STATUS_OK);
    CHECK_CALL_PATH(UNIX_BASIC, NT_STATUS_OK);

    printf("Test unix_link level\n");
    CHECK_CALL_FNUM(UNIX_LINK, NT_STATUS_OK);
    CHECK_CALL_PATH(UNIX_LINK, NT_STATUS_OK);
#endif

done:
    smb_raw_exit(cli->session);
    smbcli_close(cli->tree, fnum);
    if (NT_STATUS_IS_ERR(smbcli_unlink(cli->tree, fnum_fname))) {
        printf("Failed to delete %s - %s\n", fnum_fname, smbcli_errstr(cli->tree));
    }
    if (NT_STATUS_IS_ERR(smbcli_unlink(cli->tree, path_fname))) {
        printf("Failed to delete %s - %s\n", path_fname, smbcli_errstr(cli->tree));
    }

    return ret;
}
Example #12
0
/* 
   list files in a directory matching a wildcard pattern
*/
static NTSTATUS svfs_search_first(struct ntvfs_module_context *ntvfs,
				  struct ntvfs_request *req, union smb_search_first *io, 
				  void *search_private, 
				  bool (*callback)(void *, const union smb_search_data *))
{
	struct svfs_dir *dir;
	int i;
	struct svfs_private *p = ntvfs->private_data;
	struct search_state *search;
	union smb_search_data file;
	unsigned int max_count;

	if (io->generic.level != RAW_SEARCH_TRANS2) {
		return NT_STATUS_NOT_SUPPORTED;
	}

	if (io->generic.data_level != RAW_SEARCH_DATA_BOTH_DIRECTORY_INFO) {
		return NT_STATUS_NOT_SUPPORTED;
	}

	search = talloc_zero(p, struct search_state);
	if (!search) {
		return NT_STATUS_NO_MEMORY;
	}

	max_count = io->t2ffirst.in.max_count;

	dir = svfs_list(ntvfs, req, io->t2ffirst.in.pattern);
	if (!dir) {
		return NT_STATUS_FOOBAR;
	}

	search->handle = p->next_search_handle;
	search->dir = dir;

	if (dir->count < max_count) {
		max_count = dir->count;
	}

	for (i=0; i < max_count;i++) {
		ZERO_STRUCT(file);
		unix_to_nt_time(&file.both_directory_info.create_time, dir->files[i].st.st_ctime);
		unix_to_nt_time(&file.both_directory_info.access_time, dir->files[i].st.st_atime);
		unix_to_nt_time(&file.both_directory_info.write_time,  dir->files[i].st.st_mtime);
		unix_to_nt_time(&file.both_directory_info.change_time, dir->files[i].st.st_mtime);
		file.both_directory_info.name.s = dir->files[i].name;
		file.both_directory_info.short_name.s = dir->files[i].name;
		file.both_directory_info.size = dir->files[i].st.st_size;
		file.both_directory_info.attrib = svfs_unix_to_dos_attrib(dir->files[i].st.st_mode);

		if (!callback(search_private, &file)) {
			break;
		}
	}

	search->current_index = i;

	io->t2ffirst.out.count = i;
	io->t2ffirst.out.handle = search->handle;
	io->t2ffirst.out.end_of_search = (i == dir->count) ? 1 : 0;

	/* work out if we are going to keep the search state */
	if ((io->t2ffirst.in.flags & FLAG_TRANS2_FIND_CLOSE) ||
	    ((io->t2ffirst.in.flags & FLAG_TRANS2_FIND_CLOSE_IF_END) && (i == dir->count))) {
		talloc_free(search);
	} else {
		p->next_search_handle++;
		DLIST_ADD(p->search, search);
	}

	return NT_STATUS_OK;
}
Example #13
0
/*
  approximately map a struct stat to a generic fileinfo struct
*/
static NTSTATUS svfs_map_fileinfo(struct ntvfs_module_context *ntvfs,
				  struct ntvfs_request *req, union smb_fileinfo *info, 
				  struct stat *st, const char *unix_path)
{
	struct svfs_dir *dir = NULL;
	char *pattern = NULL;
	int i;
	const char *s, *short_name;

	s = strrchr(unix_path, '/');
	if (s) {
		short_name = s+1;
	} else {
		short_name = "";
	}

	asprintf(&pattern, "%s:*", unix_path);
	
	if (pattern) {
		dir = svfs_list_unix(req, req, pattern);
	}

	unix_to_nt_time(&info->generic.out.create_time, st->st_ctime);
	unix_to_nt_time(&info->generic.out.access_time, st->st_atime);
	unix_to_nt_time(&info->generic.out.write_time,  st->st_mtime);
	unix_to_nt_time(&info->generic.out.change_time, st->st_mtime);
	info->generic.out.alloc_size = st->st_size;
	info->generic.out.size = st->st_size;
	info->generic.out.attrib = svfs_unix_to_dos_attrib(st->st_mode);
	info->generic.out.alloc_size = st->st_blksize * st->st_blocks;
	info->generic.out.nlink = st->st_nlink;
	info->generic.out.directory = S_ISDIR(st->st_mode) ? 1 : 0;
	info->generic.out.file_id = svfs_file_id(st);
	/* REWRITE: TODO stuff in here */
	info->generic.out.delete_pending = 0;
	info->generic.out.ea_size = 0;
	info->generic.out.num_eas = 0;
	info->generic.out.fname.s = talloc_strdup(req, short_name);
	info->generic.out.alt_fname.s = talloc_strdup(req, short_name);
	info->generic.out.compressed_size = 0;
	info->generic.out.format = 0;
	info->generic.out.unit_shift = 0;
	info->generic.out.chunk_shift = 0;
	info->generic.out.cluster_shift = 0;
	
	info->generic.out.access_flags = 0;
	info->generic.out.position = 0;
	info->generic.out.mode = 0;
	info->generic.out.alignment_requirement = 0;
	info->generic.out.reparse_tag = 0;
	info->generic.out.num_streams = 0;
	/* setup a single data stream */
	info->generic.out.num_streams = 1 + (dir?dir->count:0);
	info->generic.out.streams = talloc_array(req, 
						   struct stream_struct,
						   info->generic.out.num_streams);
	if (!info->generic.out.streams) {
		return NT_STATUS_NO_MEMORY;
	}
	info->generic.out.streams[0].size = st->st_size;
	info->generic.out.streams[0].alloc_size = st->st_size;
	info->generic.out.streams[0].stream_name.s = talloc_strdup(req,"::$DATA");

	for (i=0;dir && i<dir->count;i++) {
		s = strchr(dir->files[i].name, ':');
		info->generic.out.streams[1+i].size = dir->files[i].st.st_size;
		info->generic.out.streams[1+i].alloc_size = dir->files[i].st.st_size;
		info->generic.out.streams[1+i].stream_name.s = s?s:dir->files[i].name;
	}

	return NT_STATUS_OK;
}
Example #14
0
/****************************************************************************
 Do a specific test for a SAM_ACCOUNT being valid for this connection
 (ie not disabled, expired and the like).
****************************************************************************/
_PUBLIC_ NTSTATUS authsam_account_ok(TALLOC_CTX *mem_ctx,
				     struct ldb_context *sam_ctx,
				     uint32_t logon_parameters,
				     struct ldb_dn *domain_dn,
				     struct ldb_message *msg,
				     const char *logon_workstation,
				     const char *name_for_logs,
				     bool allow_domain_trust,
				     bool password_change)
{
	uint16_t acct_flags;
	const char *workstation_list;
	NTTIME acct_expiry;
	NTTIME must_change_time;

	NTTIME now;
	DEBUG(4,("authsam_account_ok: Checking SMB password for user %s\n", name_for_logs));

	acct_flags = samdb_result_acct_flags(sam_ctx, mem_ctx, msg, domain_dn);
	
	acct_expiry = samdb_result_account_expires(msg);

	/* Check for when we must change this password, taking the
	 * userAccountControl flags into account */
	must_change_time = samdb_result_force_password_change(sam_ctx, mem_ctx, 
							      domain_dn, msg);

	workstation_list = ldb_msg_find_attr_as_string(msg, "userWorkstations", NULL);

	/* Quit if the account was disabled. */
	if (acct_flags & ACB_DISABLED) {
		DEBUG(2,("authsam_account_ok: Account for user '%s' was disabled.\n", name_for_logs));
		return NT_STATUS_ACCOUNT_DISABLED;
	}

	/* Quit if the account was locked out. */
	if (acct_flags & ACB_AUTOLOCK) {
		DEBUG(2,("authsam_account_ok: Account for user %s was locked out.\n", name_for_logs));
		return NT_STATUS_ACCOUNT_LOCKED_OUT;
	}

	/* Test account expire time */
	unix_to_nt_time(&now, time(NULL));
	if (now > acct_expiry) {
		DEBUG(2,("authsam_account_ok: Account for user '%s' has expired.\n", name_for_logs));
		DEBUG(3,("authsam_account_ok: Account expired at '%s'.\n", 
			 nt_time_string(mem_ctx, acct_expiry)));
		return NT_STATUS_ACCOUNT_EXPIRED;
	}

	/* check for immediate expiry "must change at next logon" (but not if this is a password change request) */
	if ((must_change_time == 0) && !password_change) {
		DEBUG(2,("sam_account_ok: Account for user '%s' password must change!.\n",
			 name_for_logs));
		return NT_STATUS_PASSWORD_MUST_CHANGE;
	}

	/* check for expired password (but not if this is a password change request) */
	if ((must_change_time < now) && !password_change) {
		DEBUG(2,("sam_account_ok: Account for user '%s' password expired!.\n",
			 name_for_logs));
		DEBUG(2,("sam_account_ok: Password expired at '%s' unix time.\n",
			 nt_time_string(mem_ctx, must_change_time)));
		return NT_STATUS_PASSWORD_EXPIRED;
	}

	/* Test workstation. Workstation list is comma separated. */
	if (logon_workstation && workstation_list && *workstation_list) {
		bool invalid_ws = true;
		int i;
		const char **workstations = (const char **)str_list_make(mem_ctx, workstation_list, ",");
		
		for (i = 0; workstations && workstations[i]; i++) {
			DEBUG(10,("sam_account_ok: checking for workstation match '%s' and '%s'\n",
				  workstations[i], logon_workstation));

			if (strequal(workstations[i], logon_workstation)) {
				invalid_ws = false;
				break;
			}
		}

		talloc_free(workstations);

		if (invalid_ws) {
			return NT_STATUS_INVALID_WORKSTATION;
		}
	}
	
	if (!logon_hours_ok(msg, name_for_logs)) {
		return NT_STATUS_INVALID_LOGON_HOURS;
	}
	
	if (!allow_domain_trust) {
		if (acct_flags & ACB_DOMTRUST) {
			DEBUG(2,("sam_account_ok: Domain trust account %s denied by server\n", name_for_logs));
			return NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT;
		}
	}
	if (!(logon_parameters & MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT)) {
		if (acct_flags & ACB_SVRTRUST) {
			DEBUG(2,("sam_account_ok: Server trust account %s denied by server\n", name_for_logs));
			return NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT;
		}
	}
	if (!(logon_parameters & MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT)) {
		/* TODO: this fails with current solaris client. We
		   need to work with Gordon to work out why */
		if (acct_flags & ACB_WSTRUST) {
			DEBUG(4,("sam_account_ok: Wksta trust account %s denied by server\n", name_for_logs));
			return NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT;
		}
	}

	return NT_STATUS_OK;
}
Example #15
0
/**
* @brief Decode a blob containing a NDR envoded PAC structure
*
* @param mem_ctx	  - The memory context
* @param pac_data_blob	  - The data blob containing the NDR encoded data
* @param context	  - The Kerberos Context
* @param service_keyblock - The Service Key used to verify the checksum
* @param client_principal - The client principal
* @param tgs_authtime     - The ticket timestamp
* @param pac_data_out	  - [out] The decoded PAC
*
* @return - A NTSTATUS error code
*/
NTSTATUS kerberos_decode_pac(TALLOC_CTX *mem_ctx,
			     DATA_BLOB pac_data_blob,
			     krb5_context context,
			     const krb5_keyblock *krbtgt_keyblock,
			     const krb5_keyblock *service_keyblock,
			     krb5_const_principal client_principal,
			     time_t tgs_authtime,
			     struct PAC_DATA **pac_data_out)
{
	NTSTATUS status;
	enum ndr_err_code ndr_err;
	krb5_error_code ret;
	DATA_BLOB modified_pac_blob;

	NTTIME tgs_authtime_nttime;
	krb5_principal client_principal_pac = NULL;
	int i;

	struct PAC_SIGNATURE_DATA *srv_sig_ptr = NULL;
	struct PAC_SIGNATURE_DATA *kdc_sig_ptr = NULL;
	struct PAC_SIGNATURE_DATA *srv_sig_wipe = NULL;
	struct PAC_SIGNATURE_DATA *kdc_sig_wipe = NULL;
	struct PAC_LOGON_NAME *logon_name = NULL;
	struct PAC_LOGON_INFO *logon_info = NULL;
	struct PAC_DATA *pac_data = NULL;
	struct PAC_DATA_RAW *pac_data_raw = NULL;

	DATA_BLOB *srv_sig_blob = NULL;
	DATA_BLOB *kdc_sig_blob = NULL;

	bool bool_ret;

	*pac_data_out = NULL;

	pac_data = talloc(mem_ctx, struct PAC_DATA);
	pac_data_raw = talloc(mem_ctx, struct PAC_DATA_RAW);
	kdc_sig_wipe = talloc(mem_ctx, struct PAC_SIGNATURE_DATA);
	srv_sig_wipe = talloc(mem_ctx, struct PAC_SIGNATURE_DATA);
	if (!pac_data_raw || !pac_data || !kdc_sig_wipe || !srv_sig_wipe) {
		return NT_STATUS_NO_MEMORY;
	}

	ndr_err = ndr_pull_struct_blob(&pac_data_blob, pac_data, pac_data,
		       (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA);
	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
		status = ndr_map_error2ntstatus(ndr_err);
		DEBUG(0,("can't parse the PAC: %s\n",
			nt_errstr(status)));
		return status;
	}

	if (pac_data->num_buffers < 4) {
		/* we need logon_ingo, service_key and kdc_key */
		DEBUG(0,("less than 4 PAC buffers\n"));
		return NT_STATUS_INVALID_PARAMETER;
	}

	ndr_err = ndr_pull_struct_blob(
				&pac_data_blob, pac_data_raw, pac_data_raw,
				(ndr_pull_flags_fn_t)ndr_pull_PAC_DATA_RAW);
	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
		status = ndr_map_error2ntstatus(ndr_err);
		DEBUG(0,("can't parse the PAC: %s\n",
			nt_errstr(status)));
		return status;
	}

	if (pac_data_raw->num_buffers < 4) {
		/* we need logon_ingo, service_key and kdc_key */
		DEBUG(0,("less than 4 PAC buffers\n"));
		return NT_STATUS_INVALID_PARAMETER;
	}

	if (pac_data->num_buffers != pac_data_raw->num_buffers) {
		/* we need logon_ingo, service_key and kdc_key */
		DEBUG(0, ("misparse! PAC_DATA has %d buffers while "
			  "PAC_DATA_RAW has %d\n", pac_data->num_buffers,
			  pac_data_raw->num_buffers));
		return NT_STATUS_INVALID_PARAMETER;
	}

	for (i=0; i < pac_data->num_buffers; i++) {
		struct PAC_BUFFER *data_buf = &pac_data->buffers[i];
		struct PAC_BUFFER_RAW *raw_buf = &pac_data_raw->buffers[i];

		if (data_buf->type != raw_buf->type) {
			DEBUG(0, ("misparse! PAC_DATA buffer %d has type "
				  "%d while PAC_DATA_RAW has %d\n", i,
				  data_buf->type, raw_buf->type));
			return NT_STATUS_INVALID_PARAMETER;
		}
		switch (data_buf->type) {
		case PAC_TYPE_LOGON_INFO:
			if (!data_buf->info) {
				break;
			}
			logon_info = data_buf->info->logon_info.info;
			break;
		case PAC_TYPE_SRV_CHECKSUM:
			if (!data_buf->info) {
				break;
			}
			srv_sig_ptr = &data_buf->info->srv_cksum;
			srv_sig_blob = &raw_buf->info->remaining;
			break;
		case PAC_TYPE_KDC_CHECKSUM:
			if (!data_buf->info) {
				break;
			}
			kdc_sig_ptr = &data_buf->info->kdc_cksum;
			kdc_sig_blob = &raw_buf->info->remaining;
			break;
		case PAC_TYPE_LOGON_NAME:
			logon_name = &data_buf->info->logon_name;
			break;
		default:
			break;
		}
	}

	if (!logon_info) {
		DEBUG(0,("PAC no logon_info\n"));
		return NT_STATUS_INVALID_PARAMETER;
	}

	if (!logon_name) {
		DEBUG(0,("PAC no logon_name\n"));
		return NT_STATUS_INVALID_PARAMETER;
	}

	if (!srv_sig_ptr || !srv_sig_blob) {
		DEBUG(0,("PAC no srv_key\n"));
		return NT_STATUS_INVALID_PARAMETER;
	}

	if (!kdc_sig_ptr || !kdc_sig_blob) {
		DEBUG(0,("PAC no kdc_key\n"));
		return NT_STATUS_INVALID_PARAMETER;
	}

	/* Find and zero out the signatures,
	 * as required by the signing algorithm */

	/* We find the data blobs above,
	 * now we parse them to get at the exact portion we should zero */
	ndr_err = ndr_pull_struct_blob(
			kdc_sig_blob, kdc_sig_wipe, kdc_sig_wipe,
			(ndr_pull_flags_fn_t)ndr_pull_PAC_SIGNATURE_DATA);
	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
		status = ndr_map_error2ntstatus(ndr_err);
		DEBUG(0,("can't parse the KDC signature: %s\n",
			nt_errstr(status)));
		return status;
	}

	ndr_err = ndr_pull_struct_blob(
			srv_sig_blob, srv_sig_wipe, srv_sig_wipe,
			(ndr_pull_flags_fn_t)ndr_pull_PAC_SIGNATURE_DATA);
	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
		status = ndr_map_error2ntstatus(ndr_err);
		DEBUG(0,("can't parse the SRV signature: %s\n",
			nt_errstr(status)));
		return status;
	}

	/* Now zero the decoded structure */
	memset(kdc_sig_wipe->signature.data,
		'\0', kdc_sig_wipe->signature.length);
	memset(srv_sig_wipe->signature.data,
		'\0', srv_sig_wipe->signature.length);

	/* and reencode, back into the same place it came from */
	ndr_err = ndr_push_struct_blob(
			kdc_sig_blob, pac_data_raw, kdc_sig_wipe,
			(ndr_push_flags_fn_t)ndr_push_PAC_SIGNATURE_DATA);
	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
		status = ndr_map_error2ntstatus(ndr_err);
		DEBUG(0,("can't repack the KDC signature: %s\n",
			nt_errstr(status)));
		return status;
	}
	ndr_err = ndr_push_struct_blob(
			srv_sig_blob, pac_data_raw, srv_sig_wipe,
			(ndr_push_flags_fn_t)ndr_push_PAC_SIGNATURE_DATA);
	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
		status = ndr_map_error2ntstatus(ndr_err);
		DEBUG(0,("can't repack the SRV signature: %s\n",
			nt_errstr(status)));
		return status;
	}

	/* push out the whole structure, but now with zero'ed signatures */
	ndr_err = ndr_push_struct_blob(
			&modified_pac_blob, pac_data_raw, pac_data_raw,
			(ndr_push_flags_fn_t)ndr_push_PAC_DATA_RAW);
	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
		status = ndr_map_error2ntstatus(ndr_err);
		DEBUG(0,("can't repack the RAW PAC: %s\n",
			nt_errstr(status)));
		return status;
	}

	if (service_keyblock) {
		/* verify by service_key */
		ret = check_pac_checksum(mem_ctx,
					 modified_pac_blob, srv_sig_ptr,
					 context,
					 service_keyblock);
		if (ret) {
			DEBUG(1, ("PAC Decode: Failed to verify the service "
				  "signature: %s\n", error_message(ret)));
			return NT_STATUS_ACCESS_DENIED;
		}

		if (krbtgt_keyblock) {
			/* verify the service key checksum by krbtgt_key */
			ret = check_pac_checksum(mem_ctx,
						 srv_sig_ptr->signature, kdc_sig_ptr,
						 context, krbtgt_keyblock);
			if (ret) {
				DEBUG(1, ("PAC Decode: Failed to verify the KDC signature: %s\n",
					  smb_get_krb5_error_message(context, ret, mem_ctx)));
				return NT_STATUS_ACCESS_DENIED;
			}
		}
	}

	if (tgs_authtime) {
		/* Convert to NT time, so as not to loose accuracy in comparison */
		unix_to_nt_time(&tgs_authtime_nttime, tgs_authtime);

		if (tgs_authtime_nttime != logon_name->logon_time) {
			DEBUG(2, ("PAC Decode: "
				  "Logon time mismatch between ticket and PAC!\n"));
			DEBUG(2, ("PAC Decode: PAC: %s\n",
				  nt_time_string(mem_ctx, logon_name->logon_time)));
			DEBUG(2, ("PAC Decode: Ticket: %s\n",
				  nt_time_string(mem_ctx, tgs_authtime_nttime)));
			return NT_STATUS_ACCESS_DENIED;
		}
	}

	if (client_principal) {
		ret = smb_krb5_parse_name_norealm(context,
						  logon_name->account_name,
						  &client_principal_pac);
		if (ret) {
			DEBUG(2, ("Could not parse name from PAC: [%s]:%s\n",
				  logon_name->account_name, error_message(ret)));
			return NT_STATUS_INVALID_PARAMETER;
		}

		bool_ret = smb_krb5_principal_compare_any_realm(context,
								client_principal,
								client_principal_pac);

		krb5_free_principal(context, client_principal_pac);

		if (!bool_ret) {
			DEBUG(2, ("Name in PAC [%s] does not match principal name "
				  "in ticket\n", logon_name->account_name));
			return NT_STATUS_ACCESS_DENIED;
		}
	}

	DEBUG(3,("Found account name from PAC: %s [%s]\n",
		 logon_info->info3.base.account_name.string,
		 logon_info->info3.base.full_name.string));

	DEBUG(10,("Successfully validated Kerberos PAC\n"));

	if (DEBUGLEVEL >= 10) {
		const char *s;
		s = NDR_PRINT_STRUCT_STRING(mem_ctx, PAC_DATA, pac_data);
		if (s) {
			DEBUGADD(10,("%s\n", s));
		}
	}

	*pac_data_out = pac_data;

	return NT_STATUS_OK;
}
Example #16
0
NTSTATUS samu_to_SamInfo3(TALLOC_CTX *mem_ctx,
			  struct samu *samu,
			  const char *login_server,
			  struct netr_SamInfo3 **_info3,
			  struct extra_auth_info *extra)
{
	struct netr_SamInfo3 *info3;
	const struct dom_sid *user_sid;
	const struct dom_sid *group_sid;
	struct dom_sid domain_sid;
	struct dom_sid *group_sids;
	uint32_t num_group_sids = 0;
	const char *tmp;
	gid_t *gids;
	NTSTATUS status;

	user_sid = pdb_get_user_sid(samu);
	group_sid = pdb_get_group_sid(samu);

	if (!user_sid || !group_sid) {
		DEBUG(1, ("Sam account is missing sids!\n"));
		return NT_STATUS_UNSUCCESSFUL;
	}

	info3 = talloc_zero(mem_ctx, struct netr_SamInfo3);
	if (!info3) {
		return NT_STATUS_NO_MEMORY;
	}

	ZERO_STRUCT(domain_sid);

	status = SamInfo3_handle_sids(pdb_get_username(samu),
				user_sid,
				group_sid,
				info3,
				&domain_sid,
				extra);

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

	unix_to_nt_time(&info3->base.logon_time, pdb_get_logon_time(samu));
	unix_to_nt_time(&info3->base.logoff_time, get_time_t_max());
	unix_to_nt_time(&info3->base.kickoff_time, get_time_t_max());
	unix_to_nt_time(&info3->base.last_password_change,
			pdb_get_pass_last_set_time(samu));
	unix_to_nt_time(&info3->base.allow_password_change,
			pdb_get_pass_can_change_time(samu));
	unix_to_nt_time(&info3->base.force_password_change,
			pdb_get_pass_must_change_time(samu));

	tmp = pdb_get_username(samu);
	if (tmp) {
		info3->base.account_name.string	= talloc_strdup(info3, tmp);
		RET_NOMEM(info3->base.account_name.string);
	}
	tmp = pdb_get_fullname(samu);
	if (tmp) {
		info3->base.full_name.string = talloc_strdup(info3, tmp);
		RET_NOMEM(info3->base.full_name.string);
	}
	tmp = pdb_get_logon_script(samu);
	if (tmp) {
		info3->base.logon_script.string = talloc_strdup(info3, tmp);
		RET_NOMEM(info3->base.logon_script.string);
	}
	tmp = pdb_get_profile_path(samu);
	if (tmp) {
		info3->base.profile_path.string	= talloc_strdup(info3, tmp);
		RET_NOMEM(info3->base.profile_path.string);
	}
	tmp = pdb_get_homedir(samu);
	if (tmp) {
		info3->base.home_directory.string = talloc_strdup(info3, tmp);
		RET_NOMEM(info3->base.home_directory.string);
	}
	tmp = pdb_get_dir_drive(samu);
	if (tmp) {
		info3->base.home_drive.string = talloc_strdup(info3, tmp);
		RET_NOMEM(info3->base.home_drive.string);
	}

	info3->base.logon_count	= pdb_get_logon_count(samu);
	info3->base.bad_password_count = pdb_get_bad_password_count(samu);

	info3->base.logon_domain.string = talloc_strdup(info3,
						  pdb_get_domain(samu));
	RET_NOMEM(info3->base.logon_domain.string);

	info3->base.domain_sid = dom_sid_dup(info3, &domain_sid);
	RET_NOMEM(info3->base.domain_sid);

	status = pdb_enum_group_memberships(mem_ctx, samu,
					    &group_sids, &gids,
					    &num_group_sids);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(1, ("Failed to get groups from sam account.\n"));
		TALLOC_FREE(info3);
		return status;
	}

	if (num_group_sids) {
		status = group_sids_to_info3(info3, group_sids, num_group_sids);
		if (!NT_STATUS_IS_OK(status)) {
			TALLOC_FREE(info3);
			return status;
		}
	}

	/* We don't need sids and gids after the conversion */
	TALLOC_FREE(group_sids);
	TALLOC_FREE(gids);
	num_group_sids = 0;

	/* FIXME: should we add other flags ? */
	info3->base.user_flags = NETLOGON_EXTRA_SIDS;

	if (login_server) {
		info3->base.logon_server.string = talloc_strdup(info3, login_server);
		RET_NOMEM(info3->base.logon_server.string);
	}

	info3->base.acct_flags = pdb_get_acct_ctrl(samu);

	*_info3 = info3;
	return NT_STATUS_OK;
}
Example #17
0
 NTSTATUS kerberos_decode_pac(TALLOC_CTX *mem_ctx,
			      struct smb_iconv_convenience *iconv_convenience,
			      struct PAC_DATA **pac_data_out,
			      DATA_BLOB blob,
			      krb5_context context,
			      const krb5_keyblock *krbtgt_keyblock,
			      const krb5_keyblock *service_keyblock,
			      krb5_const_principal client_principal,
			      time_t tgs_authtime,
			      krb5_error_code *k5ret)
{
	krb5_error_code ret;
	NTSTATUS status;
	enum ndr_err_code ndr_err;
	struct PAC_SIGNATURE_DATA *srv_sig_ptr = NULL;
	struct PAC_SIGNATURE_DATA *kdc_sig_ptr = NULL;
	struct PAC_SIGNATURE_DATA *srv_sig_wipe = NULL;
	struct PAC_SIGNATURE_DATA *kdc_sig_wipe = NULL;
	struct PAC_LOGON_INFO *logon_info = NULL;
	struct PAC_LOGON_NAME *logon_name = NULL;
	struct PAC_DATA *pac_data;
	struct PAC_DATA_RAW *pac_data_raw;

	DATA_BLOB *srv_sig_blob = NULL;
	DATA_BLOB *kdc_sig_blob = NULL;

	DATA_BLOB modified_pac_blob;
	NTTIME tgs_authtime_nttime;
	krb5_principal client_principal_pac;
	int i;

	krb5_clear_error_message(context);

	if (k5ret) {
		*k5ret = KRB5_PARSE_MALFORMED;
	}

	pac_data = talloc(mem_ctx, struct PAC_DATA);
	pac_data_raw = talloc(mem_ctx, struct PAC_DATA_RAW);
	kdc_sig_wipe = talloc(mem_ctx, struct PAC_SIGNATURE_DATA);
	srv_sig_wipe = talloc(mem_ctx, struct PAC_SIGNATURE_DATA);
	if (!pac_data_raw || !pac_data || !kdc_sig_wipe || !srv_sig_wipe) {
		if (k5ret) {
			*k5ret = ENOMEM;
		}
		return NT_STATUS_NO_MEMORY;
	}

	ndr_err = ndr_pull_struct_blob(&blob, pac_data, 
			iconv_convenience, pac_data,
		       (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA);
	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
		status = ndr_map_error2ntstatus(ndr_err);
		DEBUG(0,("can't parse the PAC: %s\n",
			nt_errstr(status)));
		return status;
	}

	if (pac_data->num_buffers < 4) {
		/* we need logon_ingo, service_key and kdc_key */
		DEBUG(0,("less than 4 PAC buffers\n"));
		return NT_STATUS_INVALID_PARAMETER;
	}

	ndr_err = ndr_pull_struct_blob(&blob, pac_data_raw, 
				       iconv_convenience, pac_data_raw,
				       (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA_RAW);
	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
		status = ndr_map_error2ntstatus(ndr_err);
		DEBUG(0,("can't parse the PAC: %s\n",
			nt_errstr(status)));
		return status;
	}

	if (pac_data_raw->num_buffers < 4) {
		/* we need logon_ingo, service_key and kdc_key */
		DEBUG(0,("less than 4 PAC buffers\n"));
		return NT_STATUS_INVALID_PARAMETER;
	}

	if (pac_data->num_buffers != pac_data_raw->num_buffers) {
		/* we need logon_ingo, service_key and kdc_key */
		DEBUG(0,("misparse!  PAC_DATA has %d buffers while PAC_DATA_RAW has %d\n",
			 pac_data->num_buffers, pac_data_raw->num_buffers));
		return NT_STATUS_INVALID_PARAMETER;
	}

	for (i=0; i < pac_data->num_buffers; i++) {
		if (pac_data->buffers[i].type != pac_data_raw->buffers[i].type) {
			DEBUG(0,("misparse!  PAC_DATA buffer %d has type %d while PAC_DATA_RAW has %d\n",
				 i, pac_data->buffers[i].type, pac_data->buffers[i].type));
			return NT_STATUS_INVALID_PARAMETER;
		}
		switch (pac_data->buffers[i].type) {
			case PAC_TYPE_LOGON_INFO:
				if (!pac_data->buffers[i].info) {
					break;
				}
				logon_info = pac_data->buffers[i].info->logon_info.info;
				break;
			case PAC_TYPE_SRV_CHECKSUM:
				if (!pac_data->buffers[i].info) {
					break;
				}
				srv_sig_ptr = &pac_data->buffers[i].info->srv_cksum;
				srv_sig_blob = &pac_data_raw->buffers[i].info->remaining;
				break;
			case PAC_TYPE_KDC_CHECKSUM:
				if (!pac_data->buffers[i].info) {
					break;
				}
				kdc_sig_ptr = &pac_data->buffers[i].info->kdc_cksum;
				kdc_sig_blob = &pac_data_raw->buffers[i].info->remaining;
				break;
			case PAC_TYPE_LOGON_NAME:
				logon_name = &pac_data->buffers[i].info->logon_name;
				break;
			default:
				break;
		}
	}

	if (!logon_info) {
		DEBUG(0,("PAC no logon_info\n"));
		return NT_STATUS_INVALID_PARAMETER;
	}

	if (!logon_name) {
		DEBUG(0,("PAC no logon_name\n"));
		return NT_STATUS_INVALID_PARAMETER;
	}

	if (!srv_sig_ptr || !srv_sig_blob) {
		DEBUG(0,("PAC no srv_key\n"));
		return NT_STATUS_INVALID_PARAMETER;
	}

	if (!kdc_sig_ptr || !kdc_sig_blob) {
		DEBUG(0,("PAC no kdc_key\n"));
		return NT_STATUS_INVALID_PARAMETER;
	}

	/* Find and zero out the signatures, as required by the signing algorithm */

	/* We find the data blobs above, now we parse them to get at the exact portion we should zero */
	ndr_err = ndr_pull_struct_blob(kdc_sig_blob, kdc_sig_wipe, 
				       iconv_convenience, kdc_sig_wipe,
				       (ndr_pull_flags_fn_t)ndr_pull_PAC_SIGNATURE_DATA);
	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
		status = ndr_map_error2ntstatus(ndr_err);
		DEBUG(0,("can't parse the KDC signature: %s\n",
			nt_errstr(status)));
		return status;
	}
	
	ndr_err = ndr_pull_struct_blob(srv_sig_blob, srv_sig_wipe, 
				       iconv_convenience, srv_sig_wipe,
				       (ndr_pull_flags_fn_t)ndr_pull_PAC_SIGNATURE_DATA);
	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
		status = ndr_map_error2ntstatus(ndr_err);
		DEBUG(0,("can't parse the SRV signature: %s\n",
			nt_errstr(status)));
		return status;
	}

	/* Now zero the decoded structure */
	memset(kdc_sig_wipe->signature.data, '\0', kdc_sig_wipe->signature.length);
	memset(srv_sig_wipe->signature.data, '\0', srv_sig_wipe->signature.length);
	
	/* and reencode, back into the same place it came from */
	ndr_err = ndr_push_struct_blob(kdc_sig_blob, pac_data_raw, 
				       iconv_convenience,
				       kdc_sig_wipe,
				       (ndr_push_flags_fn_t)ndr_push_PAC_SIGNATURE_DATA);
	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
		status = ndr_map_error2ntstatus(ndr_err);
		DEBUG(0,("can't repack the KDC signature: %s\n",
			nt_errstr(status)));
		return status;
	}
	ndr_err = ndr_push_struct_blob(srv_sig_blob, pac_data_raw, 
				       iconv_convenience,
				       srv_sig_wipe,
				       (ndr_push_flags_fn_t)ndr_push_PAC_SIGNATURE_DATA);
	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
		status = ndr_map_error2ntstatus(ndr_err);
		DEBUG(0,("can't repack the SRV signature: %s\n",
			nt_errstr(status)));
		return status;
	}

	/* push out the whole structure, but now with zero'ed signatures */
	ndr_err = ndr_push_struct_blob(&modified_pac_blob, pac_data_raw, 
				       iconv_convenience,
				       pac_data_raw,
				       (ndr_push_flags_fn_t)ndr_push_PAC_DATA_RAW);
	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
		status = ndr_map_error2ntstatus(ndr_err);
		DEBUG(0,("can't repack the RAW PAC: %s\n",
			nt_errstr(status)));
		return status;
	}

	/* verify by service_key */
	ret = check_pac_checksum(mem_ctx, 
				 modified_pac_blob, srv_sig_ptr, 
				 context, 
				 service_keyblock);
	if (ret) {
		DEBUG(1, ("PAC Decode: Failed to verify the service signature: %s\n",
			  smb_get_krb5_error_message(context, ret, mem_ctx)));
		if (k5ret) {
			*k5ret = ret;
		}
		return NT_STATUS_ACCESS_DENIED;
	}

	if (krbtgt_keyblock) {
		ret = check_pac_checksum(mem_ctx, 
					    srv_sig_ptr->signature, kdc_sig_ptr, 
					    context, krbtgt_keyblock);
		if (ret) {
			DEBUG(1, ("PAC Decode: Failed to verify the KDC signature: %s\n",
				  smb_get_krb5_error_message(context, ret, mem_ctx)));
			if (k5ret) {
				*k5ret = ret;
			}
			return NT_STATUS_ACCESS_DENIED;
		}
	}

	/* Convert to NT time, so as not to loose accuracy in comparison */
	unix_to_nt_time(&tgs_authtime_nttime, tgs_authtime);

	if (tgs_authtime_nttime != logon_name->logon_time) {
		DEBUG(2, ("PAC Decode: Logon time mismatch between ticket and PAC!\n"));
		DEBUG(2, ("PAC Decode: PAC: %s\n", nt_time_string(mem_ctx, logon_name->logon_time)));
		DEBUG(2, ("PAC Decode: Ticket: %s\n", nt_time_string(mem_ctx, tgs_authtime_nttime)));
		return NT_STATUS_ACCESS_DENIED;
	}

	ret = krb5_parse_name_flags(context, logon_name->account_name, KRB5_PRINCIPAL_PARSE_NO_REALM, 
				    &client_principal_pac);
	if (ret) {
		DEBUG(2, ("Could not parse name from incoming PAC: [%s]: %s\n", 
			  logon_name->account_name, 
			  smb_get_krb5_error_message(context, ret, mem_ctx)));
		if (k5ret) {
			*k5ret = ret;
		}
		return NT_STATUS_INVALID_PARAMETER;
	}

	if (!krb5_principal_compare_any_realm(context, client_principal, client_principal_pac)) {
		DEBUG(2, ("Name in PAC [%s] does not match principal name in ticket\n", 
			  logon_name->account_name));
		return NT_STATUS_ACCESS_DENIED;
	}
	
#if 0
	if (strcasecmp(logon_info->info3.base.account_name.string, 
		       "Administrator")== 0) {
		file_save("tmp_pac_data-admin.dat",blob.data,blob.length);
	}
#endif

	DEBUG(3,("Found account name from PAC: %s [%s]\n",
		 logon_info->info3.base.account_name.string, 
		 logon_info->info3.base.full_name.string));
	*pac_data_out = pac_data;

	return NT_STATUS_OK;
}
Example #18
0
/* basic testing of all SMB2 setinfo calls 
   for each call we test that it succeeds, and where possible test 
   for consistency between the calls. 
*/
bool torture_smb2_setinfo(struct torture_context *tctx)
{
	struct smb2_tree *tree;
	bool ret = true;
	struct smb2_handle handle;
	char *fname;
	union smb_fileinfo finfo2;
	union smb_setfileinfo sfinfo;
	struct security_ace ace;
	struct security_descriptor *sd;
	struct dom_sid *test_sid;
	NTSTATUS status, status2=NT_STATUS_OK;
	const char *call_name;
	time_t basetime = (time(NULL) - 86400) & ~1;
	int n = time(NULL) % 100;
	struct ea_struct ea;
	
	ZERO_STRUCT(handle);
	
	fname = talloc_asprintf(tctx, BASEDIR "fnum_test_%d.txt", n);

	if (!torture_smb2_connection(tctx, &tree)) {
		return false;
	}

#define RECREATE_FILE(fname) do { \
	smb2_util_close(tree, handle); \
	status = smb2_create_complex_file(tree, fname, &handle); \
	if (!NT_STATUS_IS_OK(status)) { \
		torture_result(tctx, TORTURE_FAIL, "(%s) ERROR: open of %s failed (%s)\n", \
		       __location__, fname, nt_errstr(status)); \
		ret = false; \
		goto done; \
	}} while (0)

#define RECREATE_BOTH do { \
		RECREATE_FILE(fname); \
	} while (0)

	RECREATE_BOTH;
	
#define CHECK_CALL(call, rightstatus) do { \
	call_name = #call; \
	sfinfo.generic.level = RAW_SFILEINFO_ ## call; \
	sfinfo.generic.in.file.handle = handle; \
	status = smb2_setinfo_file(tree, &sfinfo); \
	if (!NT_STATUS_EQUAL(status, rightstatus)) { \
		torture_result(tctx, TORTURE_FAIL, "(%s) %s - %s (should be %s)\n", __location__, #call, \
			nt_errstr(status), nt_errstr(rightstatus)); \
		ret = false; \
		goto done; \
	} \
	} while (0)

#define CHECK1(call) \
	do { if (NT_STATUS_IS_OK(status)) { \
		finfo2.generic.level = RAW_FILEINFO_ ## call; \
		finfo2.generic.in.file.handle = handle; \
		status2 = smb2_getinfo_file(tree, tctx, &finfo2); \
		if (!NT_STATUS_IS_OK(status2)) { \
			torture_result(tctx, TORTURE_FAIL, "(%s) %s - %s\n", __location__, #call, nt_errstr(status2)); \
		ret = false; \
		goto done; \
		} \
	}} while (0)

#define CHECK_VALUE(call, stype, field, value) do { \
 	CHECK1(call); \
	if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(status2) && finfo2.stype.out.field != value) { \
		torture_result(tctx, TORTURE_FAIL, "(%s) %s - %s/%s should be 0x%x - 0x%x\n", __location__, \
		       call_name, #stype, #field, \
		       (unsigned int)value, (unsigned int)finfo2.stype.out.field); \
		torture_smb2_all_info(tree, handle); \
		ret = false; \
		goto done; \
	}} while (0)

#define CHECK_TIME(call, stype, field, value) do { \
 	CHECK1(call); \
	if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(status2) && nt_time_to_unix(finfo2.stype.out.field) != value) { \
		torture_result(tctx, TORTURE_FAIL, "(%s) %s - %s/%s should be 0x%x - 0x%x\n", __location__, \
		        call_name, #stype, #field, \
		        (unsigned int)value, \
			(unsigned int)nt_time_to_unix(finfo2.stype.out.field)); \
		torture_warning(tctx, "\t%s", timestring(tctx, value)); \
		torture_warning(tctx, "\t%s\n", nt_time_string(tctx, finfo2.stype.out.field)); \
		torture_smb2_all_info(tree, handle); \
		ret = false; \
		goto done; \
	}} while (0)

#define CHECK_STATUS(status, correct) do { \
	if (!NT_STATUS_EQUAL(status, correct)) { \
		torture_result(tctx, TORTURE_FAIL, "(%s) Incorrect status %s - should be %s\n", \
		       __location__, nt_errstr(status), nt_errstr(correct)); \
		ret = false; \
		goto done; \
	}} while (0)

	torture_smb2_all_info(tree, handle);
	
	torture_comment(tctx, "Test basic_information level\n");
	basetime += 86400;
	unix_to_nt_time(&sfinfo.basic_info.in.create_time, basetime + 100);
	unix_to_nt_time(&sfinfo.basic_info.in.access_time, basetime + 200);
	unix_to_nt_time(&sfinfo.basic_info.in.write_time,  basetime + 300);
	unix_to_nt_time(&sfinfo.basic_info.in.change_time, basetime + 400);
	sfinfo.basic_info.in.attrib = FILE_ATTRIBUTE_READONLY;
	CHECK_CALL(BASIC_INFORMATION, NT_STATUS_OK);
	CHECK_TIME(SMB2_ALL_INFORMATION, all_info2, create_time, basetime + 100);
	CHECK_TIME(SMB2_ALL_INFORMATION, all_info2, access_time, basetime + 200);
	CHECK_TIME(SMB2_ALL_INFORMATION, all_info2, write_time,  basetime + 300);
	CHECK_TIME(SMB2_ALL_INFORMATION, all_info2, change_time, basetime + 400);
	CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, attrib,     FILE_ATTRIBUTE_READONLY);

	torture_comment(tctx, "a zero time means don't change\n");
	unix_to_nt_time(&sfinfo.basic_info.in.create_time, 0);
	unix_to_nt_time(&sfinfo.basic_info.in.access_time, 0);
	unix_to_nt_time(&sfinfo.basic_info.in.write_time,  0);
	unix_to_nt_time(&sfinfo.basic_info.in.change_time, 0);
	sfinfo.basic_info.in.attrib = FILE_ATTRIBUTE_NORMAL;
	CHECK_CALL(BASIC_INFORMATION, NT_STATUS_OK);
	CHECK_TIME(SMB2_ALL_INFORMATION, all_info2, create_time, basetime + 100);
	CHECK_TIME(SMB2_ALL_INFORMATION, all_info2, access_time, basetime + 200);
	CHECK_TIME(SMB2_ALL_INFORMATION, all_info2, write_time,  basetime + 300);
	CHECK_TIME(SMB2_ALL_INFORMATION, all_info2, change_time, basetime + 400);
	CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, attrib,     FILE_ATTRIBUTE_NORMAL);

	torture_comment(tctx, "change the attribute\n");
	sfinfo.basic_info.in.attrib = FILE_ATTRIBUTE_HIDDEN;
	CHECK_CALL(BASIC_INFORMATION, NT_STATUS_OK);
	CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, attrib, FILE_ATTRIBUTE_HIDDEN);

	torture_comment(tctx, "zero attrib means don't change\n");
	sfinfo.basic_info.in.attrib = 0;
	CHECK_CALL(BASIC_INFORMATION, NT_STATUS_OK);
	CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, attrib, FILE_ATTRIBUTE_HIDDEN);

	torture_comment(tctx, "can't change a file to a directory\n");
	sfinfo.basic_info.in.attrib = FILE_ATTRIBUTE_DIRECTORY;
	CHECK_CALL(BASIC_INFORMATION, NT_STATUS_INVALID_PARAMETER);

	torture_comment(tctx, "restore attribute\n");
	sfinfo.basic_info.in.attrib = FILE_ATTRIBUTE_NORMAL;
	CHECK_CALL(BASIC_INFORMATION, NT_STATUS_OK);
	CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, attrib, FILE_ATTRIBUTE_NORMAL);

	torture_comment(tctx, "Test disposition_information level\n");
	sfinfo.disposition_info.in.delete_on_close = 1;
	CHECK_CALL(DISPOSITION_INFORMATION, NT_STATUS_OK);
	CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, delete_pending, 1);
	CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, nlink, 0);

	sfinfo.disposition_info.in.delete_on_close = 0;
	CHECK_CALL(DISPOSITION_INFORMATION, NT_STATUS_OK);
	CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, delete_pending, 0);
	CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, nlink, 1);

	torture_comment(tctx, "Test allocation_information level\n");
	sfinfo.allocation_info.in.alloc_size = 0;
	CHECK_CALL(ALLOCATION_INFORMATION, NT_STATUS_OK);
	CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, size, 0);
	CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, alloc_size, 0);

	sfinfo.allocation_info.in.alloc_size = 4096;
	CHECK_CALL(ALLOCATION_INFORMATION, NT_STATUS_OK);
	CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, alloc_size, 4096);
	CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, size, 0);

	torture_comment(tctx, "Test end_of_file_info level\n");
	sfinfo.end_of_file_info.in.size = 37;
	CHECK_CALL(END_OF_FILE_INFORMATION, NT_STATUS_OK);
	CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, size, 37);

	sfinfo.end_of_file_info.in.size = 7;
	CHECK_CALL(END_OF_FILE_INFORMATION, NT_STATUS_OK);
	CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, size, 7);

	torture_comment(tctx, "Test position_information level\n");
	sfinfo.position_information.in.position = 123456;
	CHECK_CALL(POSITION_INFORMATION, NT_STATUS_OK);
	CHECK_VALUE(POSITION_INFORMATION, position_information, position, 123456);
	CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, position, 123456);

	torture_comment(tctx, "Test mode_information level\n");
	sfinfo.mode_information.in.mode = 2;
	CHECK_CALL(MODE_INFORMATION, NT_STATUS_OK);
	CHECK_VALUE(MODE_INFORMATION, mode_information, mode, 2);
	CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, mode, 2);

	sfinfo.mode_information.in.mode = 1;
	CHECK_CALL(MODE_INFORMATION, NT_STATUS_INVALID_PARAMETER);

	sfinfo.mode_information.in.mode = 0;
	CHECK_CALL(MODE_INFORMATION, NT_STATUS_OK);
	CHECK_VALUE(MODE_INFORMATION, mode_information, mode, 0);

	torture_comment(tctx, "Test sec_desc level\n");
	ZERO_STRUCT(finfo2);
	finfo2.query_secdesc.in.secinfo_flags =
		SECINFO_OWNER |
		SECINFO_GROUP |
		SECINFO_DACL;
 	CHECK1(SEC_DESC);
	sd = finfo2.query_secdesc.out.sd;

	test_sid = dom_sid_parse_talloc(tctx, SID_NT_AUTHENTICATED_USERS);
	ZERO_STRUCT(ace);
	ace.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
	ace.flags = 0;
	ace.access_mask = SEC_STD_ALL;
	ace.trustee = *test_sid;
	status = security_descriptor_dacl_add(sd, &ace);
	CHECK_STATUS(status, NT_STATUS_OK);

	torture_comment(tctx, "add a new ACE to the DACL\n");

	sfinfo.set_secdesc.in.secinfo_flags = finfo2.query_secdesc.in.secinfo_flags;
	sfinfo.set_secdesc.in.sd = sd;
	CHECK_CALL(SEC_DESC, NT_STATUS_OK);
	FAIL_UNLESS(smb2_util_verify_sd(tctx, tree, handle, sd));

	torture_comment(tctx, "remove it again\n");

	status = security_descriptor_dacl_del(sd, test_sid);
	CHECK_STATUS(status, NT_STATUS_OK);

	sfinfo.set_secdesc.in.secinfo_flags = finfo2.query_secdesc.in.secinfo_flags;
	sfinfo.set_secdesc.in.sd = sd;
	CHECK_CALL(SEC_DESC, NT_STATUS_OK);
	FAIL_UNLESS(smb2_util_verify_sd(tctx, tree, handle, sd));

	torture_comment(tctx, "Check zero length EA's behavior\n");

	/* Set a new EA. */
	sfinfo.full_ea_information.in.eas.num_eas = 1;
	ea.flags = 0;
	ea.name.private_length = 6;
	ea.name.s = "NewEA";
	ea.value = data_blob_string_const("testme");
	sfinfo.full_ea_information.in.eas.eas = &ea;
	CHECK_CALL(FULL_EA_INFORMATION, NT_STATUS_OK);

	/* Does it still exist ? */
	finfo2.generic.level = RAW_FILEINFO_SMB2_ALL_EAS;
	finfo2.generic.in.file.handle = handle;
	finfo2.all_eas.in.continue_flags = 1;
	status2 = smb2_getinfo_file(tree, tctx, &finfo2);
	if (!NT_STATUS_IS_OK(status2)) {
		torture_result(tctx, TORTURE_FAIL, "(%s) %s - %s\n", __location__,
			"SMB2_ALL_EAS", nt_errstr(status2));
		ret = false;
		goto done;
	}

	/* Note on Windows EA name is returned capitalized. */
	if (!find_returned_ea(&finfo2, "NewEA", "testme")) {
		torture_result(tctx, TORTURE_FAIL, "(%s) Missing EA 'NewEA'\n", __location__);
		ret = false;
	}

	/* Now zero it out (should delete it) */
	sfinfo.full_ea_information.in.eas.num_eas = 1;
	ea.flags = 0;
	ea.name.private_length = 6;
	ea.name.s = "NewEA";
	ea.value = data_blob_null;
	sfinfo.full_ea_information.in.eas.eas = &ea;
	CHECK_CALL(FULL_EA_INFORMATION, NT_STATUS_OK);

	/* Does it still exist ? */
	finfo2.generic.level = RAW_FILEINFO_SMB2_ALL_EAS;
	finfo2.generic.in.file.handle = handle;
	finfo2.all_eas.in.continue_flags = 1;
	status2 = smb2_getinfo_file(tree, tctx, &finfo2);
	if (!NT_STATUS_IS_OK(status2)) {
		torture_result(tctx, TORTURE_FAIL, "(%s) %s - %s\n", __location__,
			"SMB2_ALL_EAS", nt_errstr(status2));
		ret = false;
		goto done;
	}

	if (find_returned_ea(&finfo2, "NewEA", NULL)) {
		torture_result(tctx, TORTURE_FAIL, "(%s) EA 'NewEA' should be deleted\n", __location__);
		ret = false;
	}

	/* Set a zero length EA. */
	sfinfo.full_ea_information.in.eas.num_eas = 1;
	ea.flags = 0;
	ea.name.private_length = 6;
	ea.name.s = "ZeroEA";
	ea.value = data_blob_null;
	sfinfo.full_ea_information.in.eas.eas = &ea;
	CHECK_CALL(FULL_EA_INFORMATION, NT_STATUS_OK);

	/* Does it still exist ? */
	finfo2.generic.level = RAW_FILEINFO_SMB2_ALL_EAS;
	finfo2.generic.in.file.handle = handle;
	finfo2.all_eas.in.continue_flags = 1;
	status2 = smb2_getinfo_file(tree, tctx, &finfo2);
	if (!NT_STATUS_IS_OK(status2)) {
		torture_result(tctx, TORTURE_FAIL, "(%s) %s - %s\n", __location__,
			"SMB2_ALL_EAS", nt_errstr(status2));
		ret = false;
		goto done;
	}

	/* Over SMB2 ZeroEA should not exist. */
	if (!find_returned_ea(&finfo2, "EAONE", "VALUE1")) {
		torture_result(tctx, TORTURE_FAIL, "(%s) Missing EA 'EAONE'\n", __location__);
		ret = false;
	}
	if (!find_returned_ea(&finfo2, "SECONDEA", "ValueTwo")) {
		torture_result(tctx, TORTURE_FAIL, "(%s) Missing EA 'SECONDEA'\n", __location__);
		ret = false;
	}
	if (find_returned_ea(&finfo2, "ZeroEA", NULL)) {
		torture_result(tctx, TORTURE_FAIL, "(%s) Found null EA 'ZeroEA'\n", __location__);
		ret = false;
	}

done:
	status = smb2_util_close(tree, handle);
	if (NT_STATUS_IS_ERR(status)) {
		torture_warning(tctx, "Failed to delete %s - %s\n", fname, nt_errstr(status));
	}
	smb2_util_unlink(tree, fname);

	return ret;
}
Example #19
0
/*
  open a file
*/
static NTSTATUS svfs_open(struct ntvfs_module_context *ntvfs,
			  struct ntvfs_request *req, union smb_open *io)
{
	struct svfs_private *p = ntvfs->private_data;
	char *unix_path;
	struct stat st;
	int fd, flags;
	struct svfs_file *f;
	int create_flags, rdwr_flags;
	bool readonly;
	NTSTATUS status;
	struct ntvfs_handle *handle;
	
	if (io->generic.level != RAW_OPEN_GENERIC) {
		return ntvfs_map_open(ntvfs, req, io);
	}

	readonly = share_bool_option(ntvfs->ctx->config, SHARE_READONLY, SHARE_READONLY_DEFAULT);
	if (readonly) {
		create_flags = 0;
		rdwr_flags = O_RDONLY;
	} else {
		create_flags = O_CREAT;
		rdwr_flags = O_RDWR;
	}

	unix_path = svfs_unix_path(ntvfs, req, io->ntcreatex.in.fname);

	switch (io->generic.in.open_disposition) {
	case NTCREATEX_DISP_SUPERSEDE:
	case NTCREATEX_DISP_OVERWRITE_IF:
		flags = create_flags | O_TRUNC;
		break;
	case NTCREATEX_DISP_OPEN:
	case NTCREATEX_DISP_OVERWRITE:
		flags = 0;
		break;
	case NTCREATEX_DISP_CREATE:
		flags = create_flags | O_EXCL;
		break;
	case NTCREATEX_DISP_OPEN_IF:
		flags = create_flags;
		break;
	default:
		flags = 0;
		break;
	}
	
	flags |= rdwr_flags;

	if (io->generic.in.create_options & NTCREATEX_OPTIONS_DIRECTORY) {
		flags = O_RDONLY | O_DIRECTORY;
		if (readonly) {
			goto do_open;
		}
		switch (io->generic.in.open_disposition) {
		case NTCREATEX_DISP_CREATE:
			if (mkdir(unix_path, 0755) == -1) {
				DEBUG(9,("svfs_open: mkdir %s errno=%d\n", unix_path, errno));
				return map_nt_error_from_unix(errno);
			}
			break;
		case NTCREATEX_DISP_OPEN_IF:
			if (mkdir(unix_path, 0755) == -1 && errno != EEXIST) {
				DEBUG(9,("svfs_open: mkdir %s errno=%d\n", unix_path, errno));
				return map_nt_error_from_unix(errno);
			}
			break;
		}
	}

do_open:
	fd = open(unix_path, flags, 0644);
	if (fd == -1) {
		return map_nt_error_from_unix(errno);
	}

	if (fstat(fd, &st) == -1) {
		DEBUG(9,("svfs_open: fstat errno=%d\n", errno));
		close(fd);
		return map_nt_error_from_unix(errno);
	}

	status = ntvfs_handle_new(ntvfs, req, &handle);
	NT_STATUS_NOT_OK_RETURN(status);

	f = talloc(handle, struct svfs_file);
	NT_STATUS_HAVE_NO_MEMORY(f);
	f->fd = fd;
	f->name = talloc_strdup(f, unix_path);
	NT_STATUS_HAVE_NO_MEMORY(f->name);

	DLIST_ADD(p->open_files, f);

	status = ntvfs_handle_set_backend_data(handle, ntvfs, f);
	NT_STATUS_NOT_OK_RETURN(status);

	ZERO_STRUCT(io->generic.out);
	
	unix_to_nt_time(&io->generic.out.create_time, st.st_ctime);
	unix_to_nt_time(&io->generic.out.access_time, st.st_atime);
	unix_to_nt_time(&io->generic.out.write_time,  st.st_mtime);
	unix_to_nt_time(&io->generic.out.change_time, st.st_mtime);
	io->generic.out.file.ntvfs = handle;
	io->generic.out.alloc_size = st.st_size;
	io->generic.out.size = st.st_size;
	io->generic.out.attrib = svfs_unix_to_dos_attrib(st.st_mode);
	io->generic.out.is_directory = S_ISDIR(st.st_mode) ? 1 : 0;

	return NT_STATUS_OK;
}
Example #20
0
 krb5_error_code kerberos_create_pac(TALLOC_CTX *mem_ctx,
				     struct auth_user_info_dc *user_info_dc,
				     krb5_context context,
				     const krb5_keyblock *krbtgt_keyblock,
				     const krb5_keyblock *service_keyblock,
				     krb5_principal client_principal,
				     time_t tgs_authtime,
				     DATA_BLOB *pac)
{
	NTSTATUS nt_status;
	krb5_error_code ret;
	struct PAC_DATA *pac_data = talloc(mem_ctx, struct PAC_DATA);
	struct netr_SamInfo3 *sam3;
	union PAC_INFO *u_LOGON_INFO;
	struct PAC_LOGON_INFO *LOGON_INFO;
	union PAC_INFO *u_LOGON_NAME;
	struct PAC_LOGON_NAME *LOGON_NAME;
	union PAC_INFO *u_KDC_CHECKSUM;
	union PAC_INFO *u_SRV_CHECKSUM;

	char *name;

	enum {
		PAC_BUF_LOGON_INFO = 0,
		PAC_BUF_LOGON_NAME = 1,
		PAC_BUF_SRV_CHECKSUM = 2,
		PAC_BUF_KDC_CHECKSUM = 3,
		PAC_BUF_NUM_BUFFERS = 4
	};

	if (!pac_data) {
		return ENOMEM;
	}

	pac_data->num_buffers = PAC_BUF_NUM_BUFFERS;
	pac_data->version = 0;

	pac_data->buffers = talloc_array(pac_data,
					 struct PAC_BUFFER,
					 pac_data->num_buffers);
	if (!pac_data->buffers) {
		talloc_free(pac_data);
		return ENOMEM;
	}

	/* LOGON_INFO */
	u_LOGON_INFO = talloc_zero(pac_data->buffers, union PAC_INFO);
	if (!u_LOGON_INFO) {
		talloc_free(pac_data);
		return ENOMEM;
	}
	pac_data->buffers[PAC_BUF_LOGON_INFO].type = PAC_TYPE_LOGON_INFO;
	pac_data->buffers[PAC_BUF_LOGON_INFO].info = u_LOGON_INFO;

	/* LOGON_NAME */
	u_LOGON_NAME = talloc_zero(pac_data->buffers, union PAC_INFO);
	if (!u_LOGON_NAME) {
		talloc_free(pac_data);
		return ENOMEM;
	}
	pac_data->buffers[PAC_BUF_LOGON_NAME].type = PAC_TYPE_LOGON_NAME;
	pac_data->buffers[PAC_BUF_LOGON_NAME].info = u_LOGON_NAME;
	LOGON_NAME = &u_LOGON_NAME->logon_name;

	/* SRV_CHECKSUM */
	u_SRV_CHECKSUM = talloc_zero(pac_data->buffers, union PAC_INFO);
	if (!u_SRV_CHECKSUM) {
		talloc_free(pac_data);
		return ENOMEM;
	}
	pac_data->buffers[PAC_BUF_SRV_CHECKSUM].type = PAC_TYPE_SRV_CHECKSUM;
	pac_data->buffers[PAC_BUF_SRV_CHECKSUM].info = u_SRV_CHECKSUM;

	/* KDC_CHECKSUM */
	u_KDC_CHECKSUM = talloc_zero(pac_data->buffers, union PAC_INFO);
	if (!u_KDC_CHECKSUM) {
		talloc_free(pac_data);
		return ENOMEM;
	}
	pac_data->buffers[PAC_BUF_KDC_CHECKSUM].type = PAC_TYPE_KDC_CHECKSUM;
	pac_data->buffers[PAC_BUF_KDC_CHECKSUM].info = u_KDC_CHECKSUM;

	/* now the real work begins... */

	LOGON_INFO = talloc_zero(u_LOGON_INFO, struct PAC_LOGON_INFO);
	if (!LOGON_INFO) {
		talloc_free(pac_data);
		return ENOMEM;
	}
	nt_status = auth_convert_user_info_dc_saminfo3(LOGON_INFO, user_info_dc, &sam3);
	if (!NT_STATUS_IS_OK(nt_status)) {
		DEBUG(1, ("Getting Samba info failed: %s\n", nt_errstr(nt_status)));
		talloc_free(pac_data);
		return EINVAL;
	}

	u_LOGON_INFO->logon_info.info		= LOGON_INFO;
	LOGON_INFO->info3 = *sam3;

	ret = krb5_unparse_name_flags(context, client_principal,
				      KRB5_PRINCIPAL_UNPARSE_NO_REALM |
				      KRB5_PRINCIPAL_UNPARSE_DISPLAY,
				      &name);
	if (ret) {
		return ret;
	}
	LOGON_NAME->account_name	= talloc_strdup(LOGON_NAME, name);
	free(name);
	/*
	  this logon_time field is absolutely critical. This is what
	  caused all our PAC troubles :-)
	*/
	unix_to_nt_time(&LOGON_NAME->logon_time, tgs_authtime);

	ret = kerberos_encode_pac(mem_ctx,
				  pac_data,
				  context,
				  krbtgt_keyblock,
				  service_keyblock,
				  pac);
	talloc_free(pac_data);
	return ret;
}
NTSTATUS serverinfo_to_SamInfo3(struct auth_serversupplied_info *server_info,
				uint8_t pipe_session_key[16],
				struct netr_SamInfo3 *sam3)
{
	struct samu *sampw;
	DOM_GID *gids = NULL;
	const DOM_SID *user_sid = NULL;
	const DOM_SID *group_sid = NULL;
	DOM_SID domain_sid;
	uint32 user_rid, group_rid;
	NTSTATUS status;

	int num_gids = 0;
	const char *my_name;

	struct netr_UserSessionKey user_session_key;
	struct netr_LMSessionKey lm_session_key;

	NTTIME last_logon, last_logoff, acct_expiry, last_password_change;
	NTTIME allow_password_change, force_password_change;
	struct samr_RidWithAttributeArray groups;
	int i;
	struct dom_sid2 *sid = NULL;

	ZERO_STRUCT(user_session_key);
	ZERO_STRUCT(lm_session_key);

	sampw = server_info->sam_account;

	user_sid = pdb_get_user_sid(sampw);
	group_sid = pdb_get_group_sid(sampw);

	if ((user_sid == NULL) || (group_sid == NULL)) {
		DEBUG(1, ("_netr_LogonSamLogon: User without group or user SID\n"));
		return NT_STATUS_UNSUCCESSFUL;
	}

	sid_copy(&domain_sid, user_sid);
	sid_split_rid(&domain_sid, &user_rid);

	sid = sid_dup_talloc(sam3, &domain_sid);
	if (!sid) {
		return NT_STATUS_NO_MEMORY;
	}

	if (!sid_peek_check_rid(&domain_sid, group_sid, &group_rid)) {
		DEBUG(1, ("_netr_LogonSamLogon: user %s\\%s has user sid "
			  "%s\n but group sid %s.\n"
			  "The conflicting domain portions are not "
			  "supported for NETLOGON calls\n",
			  pdb_get_domain(sampw),
			  pdb_get_username(sampw),
			  sid_string_dbg(user_sid),
			  sid_string_dbg(group_sid)));
		return NT_STATUS_UNSUCCESSFUL;
	}

	if(server_info->login_server) {
		my_name = server_info->login_server;
	} else {
		my_name = global_myname();
	}

	status = nt_token_to_group_list(sam3, &domain_sid,
					server_info->num_sids,
					server_info->sids,
					&num_gids, &gids);

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

	if (server_info->user_session_key.length) {
		memcpy(user_session_key.key,
		       server_info->user_session_key.data,
		       MIN(sizeof(user_session_key.key),
			   server_info->user_session_key.length));
		SamOEMhash(user_session_key.key, pipe_session_key, 16);
	}
	if (server_info->lm_session_key.length) {
		memcpy(lm_session_key.key,
		       server_info->lm_session_key.data,
		       MIN(sizeof(lm_session_key.key),
			   server_info->lm_session_key.length));
		SamOEMhash(lm_session_key.key, pipe_session_key, 8);
	}

	groups.count = num_gids;
	groups.rids = TALLOC_ARRAY(sam3, struct samr_RidWithAttribute, groups.count);
	if (!groups.rids) {
		return NT_STATUS_NO_MEMORY;
	}

	for (i=0; i < groups.count; i++) {
		groups.rids[i].rid = gids[i].g_rid;
		groups.rids[i].attributes = gids[i].attr;
	}

	unix_to_nt_time(&last_logon, pdb_get_logon_time(sampw));
	unix_to_nt_time(&last_logoff, get_time_t_max());
	unix_to_nt_time(&acct_expiry, get_time_t_max());
	unix_to_nt_time(&last_password_change, pdb_get_pass_last_set_time(sampw));
	unix_to_nt_time(&allow_password_change, pdb_get_pass_can_change_time(sampw));
	unix_to_nt_time(&force_password_change, pdb_get_pass_must_change_time(sampw));

	init_netr_SamInfo3(sam3,
			   last_logon,
			   last_logoff,
			   acct_expiry,
			   last_password_change,
			   allow_password_change,
			   force_password_change,
			   talloc_strdup(sam3, pdb_get_username(sampw)),
			   talloc_strdup(sam3, pdb_get_fullname(sampw)),
			   talloc_strdup(sam3, pdb_get_logon_script(sampw)),
			   talloc_strdup(sam3, pdb_get_profile_path(sampw)),
			   talloc_strdup(sam3, pdb_get_homedir(sampw)),
			   talloc_strdup(sam3, pdb_get_dir_drive(sampw)),
			   0, /* logon_count */
			   0, /* bad_password_count */
			   user_rid,
			   group_rid,
			   groups,
			   NETLOGON_EXTRA_SIDS,
			   user_session_key,
			   my_name,
			   talloc_strdup(sam3, pdb_get_domain(sampw)),
			   sid,
			   lm_session_key,
			   pdb_get_acct_ctrl(sampw),
			   0, /* sidcount */
			   NULL); /* struct netr_SidAttr *sids */
	ZERO_STRUCT(user_session_key);
	ZERO_STRUCT(lm_session_key);

	return NT_STATUS_OK;
}
Example #22
0
/* basic testing of all SMB2 setinfo calls 
   for each call we test that it succeeds, and where possible test 
   for consistency between the calls. 
*/
BOOL torture_smb2_setinfo(struct torture_context *torture)
{
	struct smb2_tree *tree;
	BOOL ret = True;
	TALLOC_CTX *mem_ctx = talloc_new(NULL);
	struct smb2_handle handle;
	char *fname;
	char *fname_new;
	union smb_fileinfo finfo2;
	union smb_setfileinfo sfinfo;
	struct security_ace ace;
	struct security_descriptor *sd;
	struct dom_sid *test_sid;
	NTSTATUS status, status2=NT_STATUS_OK;
	const char *call_name;
	time_t basetime = (time(NULL) - 86400) & ~1;
	int n = time(NULL) % 100;
	
	ZERO_STRUCT(handle);
	
	fname = talloc_asprintf(mem_ctx, BASEDIR "fnum_test_%d.txt", n);
	fname_new = talloc_asprintf(mem_ctx, BASEDIR "fnum_test_new_%d.txt", n);

	if (!torture_smb2_connection(mem_ctx, &tree)) {
		return False;
	}

#define RECREATE_FILE(fname) do { \
	smb2_util_close(tree, handle); \
	status = smb2_create_complex_file(tree, fname, &handle); \
	if (!NT_STATUS_IS_OK(status)) { \
		printf("(%s) ERROR: open of %s failed (%s)\n", \
		       __location__, fname, nt_errstr(status)); \
		ret = False; \
		goto done; \
	}} while (0)

#define RECREATE_BOTH do { \
		RECREATE_FILE(fname); \
	} while (0)

	RECREATE_BOTH;
	
#define CHECK_CALL(call, rightstatus) do { \
	call_name = #call; \
	sfinfo.generic.level = RAW_SFILEINFO_ ## call; \
	sfinfo.generic.in.file.handle = handle; \
	status = smb2_setinfo_file(tree, &sfinfo); \
	if (!NT_STATUS_EQUAL(status, rightstatus)) { \
		printf("(%s) %s - %s (should be %s)\n", __location__, #call, \
			nt_errstr(status), nt_errstr(rightstatus)); \
		ret = False; \
		goto done; \
	} \
	} while (0)

#define CHECK1(call) \
	do { if (NT_STATUS_IS_OK(status)) { \
		finfo2.generic.level = RAW_FILEINFO_ ## call; \
		finfo2.generic.in.file.handle = handle; \
		status2 = smb2_getinfo_file(tree, mem_ctx, &finfo2); \
		if (!NT_STATUS_IS_OK(status2)) { \
			printf("(%s) %s - %s\n", __location__, #call, nt_errstr(status2)); \
		ret = False; \
		goto done; \
		} \
	}} while (0)

#define CHECK_VALUE(call, stype, field, value) do { \
 	CHECK1(call); \
	if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(status2) && finfo2.stype.out.field != value) { \
		printf("(%s) %s - %s/%s should be 0x%x - 0x%x\n", __location__, \
		       call_name, #stype, #field, \
		       (uint_t)value, (uint_t)finfo2.stype.out.field); \
		torture_smb2_all_info(tree, handle); \
		ret = False; \
		goto done; \
	}} while (0)

#define CHECK_TIME(call, stype, field, value) do { \
 	CHECK1(call); \
	if (NT_STATUS_IS_OK(status) && NT_STATUS_IS_OK(status2) && nt_time_to_unix(finfo2.stype.out.field) != value) { \
		printf("(%s) %s - %s/%s should be 0x%x - 0x%x\n", __location__, \
		        call_name, #stype, #field, \
		        (uint_t)value, \
			(uint_t)nt_time_to_unix(finfo2.stype.out.field)); \
		printf("\t%s", timestring(mem_ctx, value)); \
		printf("\t%s\n", nt_time_string(mem_ctx, finfo2.stype.out.field)); \
		torture_smb2_all_info(tree, handle); \
		ret = False; \
		goto done; \
	}} while (0)

#define CHECK_STATUS(status, correct) do { \
	if (!NT_STATUS_EQUAL(status, correct)) { \
		printf("(%s) Incorrect status %s - should be %s\n", \
		       __location__, nt_errstr(status), nt_errstr(correct)); \
		ret = False; \
		goto done; \
	}} while (0)

	torture_smb2_all_info(tree, handle);
	
	printf("test basic_information level\n");
	basetime += 86400;
	unix_to_nt_time(&sfinfo.basic_info.in.create_time, basetime + 100);
	unix_to_nt_time(&sfinfo.basic_info.in.access_time, basetime + 200);
	unix_to_nt_time(&sfinfo.basic_info.in.write_time,  basetime + 300);
	unix_to_nt_time(&sfinfo.basic_info.in.change_time, basetime + 400);
	sfinfo.basic_info.in.attrib = FILE_ATTRIBUTE_READONLY;
	CHECK_CALL(BASIC_INFORMATION, NT_STATUS_OK);
	CHECK_TIME(SMB2_ALL_INFORMATION, all_info2, create_time, basetime + 100);
	CHECK_TIME(SMB2_ALL_INFORMATION, all_info2, access_time, basetime + 200);
	CHECK_TIME(SMB2_ALL_INFORMATION, all_info2, write_time,  basetime + 300);
	CHECK_TIME(SMB2_ALL_INFORMATION, all_info2, change_time, basetime + 400);
	CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, attrib,     FILE_ATTRIBUTE_READONLY);

	printf("a zero time means don't change\n");
	unix_to_nt_time(&sfinfo.basic_info.in.create_time, 0);
	unix_to_nt_time(&sfinfo.basic_info.in.access_time, 0);
	unix_to_nt_time(&sfinfo.basic_info.in.write_time,  0);
	unix_to_nt_time(&sfinfo.basic_info.in.change_time, 0);
	sfinfo.basic_info.in.attrib = FILE_ATTRIBUTE_NORMAL;
	CHECK_CALL(BASIC_INFORMATION, NT_STATUS_OK);
	CHECK_TIME(SMB2_ALL_INFORMATION, all_info2, create_time, basetime + 100);
	CHECK_TIME(SMB2_ALL_INFORMATION, all_info2, access_time, basetime + 200);
	CHECK_TIME(SMB2_ALL_INFORMATION, all_info2, write_time,  basetime + 300);
	CHECK_TIME(SMB2_ALL_INFORMATION, all_info2, change_time, basetime + 400);
	CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, attrib,     FILE_ATTRIBUTE_NORMAL);

	printf("change the attribute\n");
	sfinfo.basic_info.in.attrib = FILE_ATTRIBUTE_HIDDEN;
	CHECK_CALL(BASIC_INFORMATION, NT_STATUS_OK);
	CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, attrib, FILE_ATTRIBUTE_HIDDEN);

	printf("zero attrib means don't change\n");
	sfinfo.basic_info.in.attrib = 0;
	CHECK_CALL(BASIC_INFORMATION, NT_STATUS_OK);
	CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, attrib, FILE_ATTRIBUTE_HIDDEN);

	printf("restore attribute\n");
	sfinfo.basic_info.in.attrib = FILE_ATTRIBUTE_NORMAL;
	CHECK_CALL(BASIC_INFORMATION, NT_STATUS_OK);
	CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, attrib, FILE_ATTRIBUTE_NORMAL);

	printf("test disposition_information level\n");
	sfinfo.disposition_info.in.delete_on_close = 1;
	CHECK_CALL(DISPOSITION_INFORMATION, NT_STATUS_OK);
	CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, delete_pending, 1);
	CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, nlink, 0);

	sfinfo.disposition_info.in.delete_on_close = 0;
	CHECK_CALL(DISPOSITION_INFORMATION, NT_STATUS_OK);
	CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, delete_pending, 0);
	CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, nlink, 1);

	printf("test allocation_information level\n");
	sfinfo.allocation_info.in.alloc_size = 0;
	CHECK_CALL(ALLOCATION_INFORMATION, NT_STATUS_OK);
	CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, size, 0);
	CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, alloc_size, 0);

	sfinfo.allocation_info.in.alloc_size = 4096;
	CHECK_CALL(ALLOCATION_INFORMATION, NT_STATUS_OK);
	CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, alloc_size, 4096);
	CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, size, 0);

	printf("test end_of_file_info level\n");
	sfinfo.end_of_file_info.in.size = 37;
	CHECK_CALL(END_OF_FILE_INFORMATION, NT_STATUS_OK);
	CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, size, 37);

	sfinfo.end_of_file_info.in.size = 7;
	CHECK_CALL(END_OF_FILE_INFORMATION, NT_STATUS_OK);
	CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, size, 7);

	printf("test position_information level\n");
	sfinfo.position_information.in.position = 123456;
	CHECK_CALL(POSITION_INFORMATION, NT_STATUS_OK);
	CHECK_VALUE(POSITION_INFORMATION, position_information, position, 123456);
	CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, position, 123456);

	printf("test mode_information level\n");
	sfinfo.mode_information.in.mode = 2;
	CHECK_CALL(MODE_INFORMATION, NT_STATUS_OK);
	CHECK_VALUE(MODE_INFORMATION, mode_information, mode, 2);
	CHECK_VALUE(SMB2_ALL_INFORMATION, all_info2, mode, 2);

	sfinfo.mode_information.in.mode = 1;
	CHECK_CALL(MODE_INFORMATION, NT_STATUS_INVALID_PARAMETER);

	sfinfo.mode_information.in.mode = 0;
	CHECK_CALL(MODE_INFORMATION, NT_STATUS_OK);
	CHECK_VALUE(MODE_INFORMATION, mode_information, mode, 0);

	printf("test sec_desc level\n");
	ZERO_STRUCT(finfo2);
	finfo2.query_secdesc.in.secinfo_flags =
		SECINFO_OWNER |
		SECINFO_GROUP |
		SECINFO_DACL;
 	CHECK1(SEC_DESC);
	sd = finfo2.query_secdesc.out.sd;

	test_sid = dom_sid_parse_talloc(mem_ctx, "S-1-5-32-1234-5432");
	ZERO_STRUCT(ace);
	ace.type = SEC_ACE_TYPE_ACCESS_ALLOWED;
	ace.flags = 0;
	ace.access_mask = SEC_STD_ALL;
	ace.trustee = *test_sid;
	status = security_descriptor_dacl_add(sd, &ace);
	CHECK_STATUS(status, NT_STATUS_OK);

	printf("add a new ACE to the DACL\n");

	sfinfo.set_secdesc.in.secinfo_flags = finfo2.query_secdesc.in.secinfo_flags;
	sfinfo.set_secdesc.in.sd = sd;
	CHECK_CALL(SEC_DESC, NT_STATUS_OK);
 	CHECK1(SEC_DESC);

	if (!security_acl_equal(finfo2.query_secdesc.out.sd->dacl, sd->dacl)) {
		printf("%s: security descriptors don't match!\n", __location__);
		printf("got:\n");
		NDR_PRINT_DEBUG(security_descriptor, finfo2.query_secdesc.out.sd);
		printf("expected:\n");
		NDR_PRINT_DEBUG(security_descriptor, sd);
		ret = False;
	}

	printf("remove it again\n");

	status = security_descriptor_dacl_del(sd, test_sid);
	CHECK_STATUS(status, NT_STATUS_OK);

	sfinfo.set_secdesc.in.secinfo_flags = finfo2.query_secdesc.in.secinfo_flags;
	sfinfo.set_secdesc.in.sd = sd;
	CHECK_CALL(SEC_DESC, NT_STATUS_OK);
 	CHECK1(SEC_DESC);

	if (!security_acl_equal(finfo2.query_secdesc.out.sd->dacl, sd->dacl)) {
		printf("%s: security descriptors don't match!\n", __location__);
		printf("got:\n");
		NDR_PRINT_DEBUG(security_descriptor, finfo2.query_secdesc.out.sd);
		printf("expected:\n");
		NDR_PRINT_DEBUG(security_descriptor, sd);
		ret = False;
	}

done:
	status = smb2_util_close(tree, handle);
	if (NT_STATUS_IS_ERR(status)) {
		printf("Failed to delete %s - %s\n", fname, nt_errstr(status));
	}
	smb2_util_unlink(tree, fname);

	talloc_free(mem_ctx);
	return ret;
}
Example #23
0
/* continue a search */
static NTSTATUS svfs_search_next(struct ntvfs_module_context *ntvfs,
				 struct ntvfs_request *req, union smb_search_next *io, 
				 void *search_private, 
				 bool (*callback)(void *, const union smb_search_data *))
{
	struct svfs_dir *dir;
	int i;
	struct svfs_private *p = ntvfs->private_data;
	struct search_state *search;
	union smb_search_data file;
	unsigned int max_count;

	if (io->generic.level != RAW_SEARCH_TRANS2) {
		return NT_STATUS_NOT_SUPPORTED;
	}

	if (io->generic.data_level != RAW_SEARCH_DATA_BOTH_DIRECTORY_INFO) {
		return NT_STATUS_NOT_SUPPORTED;
	}

	for (search=p->search; search; search = search->next) {
		if (search->handle == io->t2fnext.in.handle) break;
	}
	
	if (!search) {
		/* we didn't find the search handle */
		return NT_STATUS_FOOBAR;
	}

	dir = search->dir;

	/* the client might be asking for something other than just continuing
	   with the search */
	if (!(io->t2fnext.in.flags & FLAG_TRANS2_FIND_CONTINUE) &&
	    (io->t2fnext.in.flags & FLAG_TRANS2_FIND_REQUIRE_RESUME) &&
	    io->t2fnext.in.last_name && *io->t2fnext.in.last_name) {
		/* look backwards first */
		for (i=search->current_index; i > 0; i--) {
			if (strcmp(io->t2fnext.in.last_name, dir->files[i-1].name) == 0) {
				search->current_index = i;
				goto found;
			}
		}

		/* then look forwards */
		for (i=search->current_index+1; i <= dir->count; i++) {
			if (strcmp(io->t2fnext.in.last_name, dir->files[i-1].name) == 0) {
				search->current_index = i;
				goto found;
			}
		}
	}

found:	
	max_count = search->current_index + io->t2fnext.in.max_count;

	if (max_count > dir->count) {
		max_count = dir->count;
	}

	for (i = search->current_index; i < max_count;i++) {
		ZERO_STRUCT(file);
		unix_to_nt_time(&file.both_directory_info.create_time, dir->files[i].st.st_ctime);
		unix_to_nt_time(&file.both_directory_info.access_time, dir->files[i].st.st_atime);
		unix_to_nt_time(&file.both_directory_info.write_time,  dir->files[i].st.st_mtime);
		unix_to_nt_time(&file.both_directory_info.change_time, dir->files[i].st.st_mtime);
		file.both_directory_info.name.s = dir->files[i].name;
		file.both_directory_info.short_name.s = dir->files[i].name;
		file.both_directory_info.size = dir->files[i].st.st_size;
		file.both_directory_info.attrib = svfs_unix_to_dos_attrib(dir->files[i].st.st_mode);

		if (!callback(search_private, &file)) {
			break;
		}
	}

	io->t2fnext.out.count = i - search->current_index;
	io->t2fnext.out.end_of_search = (i == dir->count) ? 1 : 0;

	search->current_index = i;

	/* work out if we are going to keep the search state */
	if ((io->t2fnext.in.flags & FLAG_TRANS2_FIND_CLOSE) ||
	    ((io->t2fnext.in.flags & FLAG_TRANS2_FIND_CLOSE_IF_END) && (i == dir->count))) {
		DLIST_REMOVE(p->search, search);
		talloc_free(search);
	}

	return NT_STATUS_OK;
}
Example #24
0
struct netr_SamInfo3 *wbcAuthUserInfo_to_netr_SamInfo3(TALLOC_CTX *mem_ctx,
					const struct wbcAuthUserInfo *info)
{
	struct netr_SamInfo3 *info3;
	struct dom_sid user_sid;
	struct dom_sid group_sid;
	struct dom_sid domain_sid;
	NTSTATUS status;
	bool ok;

	memcpy(&user_sid, &info->sids[0].sid, sizeof(user_sid));
	memcpy(&group_sid, &info->sids[1].sid, sizeof(group_sid));

	info3 = talloc_zero(mem_ctx, struct netr_SamInfo3);
	if (!info3) return NULL;

	unix_to_nt_time(&info3->base.logon_time, info->logon_time);
	unix_to_nt_time(&info3->base.logoff_time, info->logoff_time);
	unix_to_nt_time(&info3->base.kickoff_time, info->kickoff_time);
	unix_to_nt_time(&info3->base.last_password_change, info->pass_last_set_time);
	unix_to_nt_time(&info3->base.allow_password_change,
			info->pass_can_change_time);
	unix_to_nt_time(&info3->base.force_password_change,
			info->pass_must_change_time);

	if (info->account_name) {
		info3->base.account_name.string	=
				talloc_strdup(info3, info->account_name);
		RET_NOMEM(info3->base.account_name.string);
	}
	if (info->full_name) {
		info3->base.full_name.string =
				talloc_strdup(info3, info->full_name);
		RET_NOMEM(info3->base.full_name.string);
	}
	if (info->logon_script) {
		info3->base.logon_script.string =
				talloc_strdup(info3, info->logon_script);
		RET_NOMEM(info3->base.logon_script.string);
	}
	if (info->profile_path) {
		info3->base.profile_path.string	=
				talloc_strdup(info3, info->profile_path);
		RET_NOMEM(info3->base.profile_path.string);
	}
	if (info->home_directory) {
		info3->base.home_directory.string =
				talloc_strdup(info3, info->home_directory);
		RET_NOMEM(info3->base.home_directory.string);
	}
	if (info->home_drive) {
		info3->base.home_drive.string =
				talloc_strdup(info3, info->home_drive);
		RET_NOMEM(info3->base.home_drive.string);
	}

	info3->base.logon_count	= info->logon_count;
	info3->base.bad_password_count = info->bad_password_count;

	sid_copy(&domain_sid, &user_sid);
	sid_split_rid(&domain_sid, &info3->base.rid);

	ok = sid_peek_check_rid(&domain_sid, &group_sid,
				&info3->base.primary_gid);
	if (!ok) {
		DEBUG(1, ("The primary group sid domain does not"
			  "match user sid domain for user: %s\n",
			  info->account_name));
		TALLOC_FREE(info3);
		return NULL;
	}

	status = wbcsids_to_samr_RidWithAttributeArray(info3,
						       &info3->base.groups,
						       &domain_sid,
						       &info->sids[1],
						       info->num_sids - 1);
	if (!NT_STATUS_IS_OK(status)) {
		TALLOC_FREE(info3);
		return NULL;
	}

	status = wbcsids_to_netr_SidAttrArray(&domain_sid,
					      &info->sids[1],
					      info->num_sids - 1,
					      info3,
					      &info3->sids,
					      &info3->sidcount);
	if (!NT_STATUS_IS_OK(status)) {
		TALLOC_FREE(info3);
		return NULL;
	}

	info3->base.user_flags = info->user_flags;
	memcpy(info3->base.key.key, info->user_session_key, 16);

	if (info->logon_server) {
		info3->base.logon_server.string =
				talloc_strdup(info3, info->logon_server);
		RET_NOMEM(info3->base.logon_server.string);
	}
	if (info->domain_name) {
		info3->base.logon_domain.string =
				talloc_strdup(info3, info->domain_name);
		RET_NOMEM(info3->base.logon_domain.string);
	}

	info3->base.domain_sid = dom_sid_dup(info3, &domain_sid);
	RET_NOMEM(info3->base.domain_sid);

	memcpy(info3->base.LMSessKey.key, info->lm_session_key, 8);
	info3->base.acct_flags = info->acct_flags;

	return info3;
}