Ejemplo n.º 1
0
/****************************************************************************
 Interpret a long filename structure.
****************************************************************************/
static bool interpret_long_filename(enum smb_search_data_level level,
				    const union smb_search_data *info,
				    struct clilist_file_info *finfo)
{
	struct clilist_file_info finfo2;

	if (!finfo) finfo = &finfo2;
	ZERO_STRUCTP(finfo);

	switch (level) {
	case RAW_SEARCH_DATA_STANDARD:
		finfo->size = info->standard.size;
		finfo->mtime = info->standard.write_time;
		finfo->attrib = info->standard.attrib;
		finfo->name = info->standard.name.s;
		finfo->short_name = info->standard.name.s;
		break;

	case RAW_SEARCH_DATA_BOTH_DIRECTORY_INFO:
		finfo->size = info->both_directory_info.size;
		finfo->mtime = nt_time_to_unix(info->both_directory_info.write_time);
		finfo->attrib = info->both_directory_info.attrib;
		finfo->short_name = info->both_directory_info.short_name.s;
		finfo->name = info->both_directory_info.name.s;
		break;

	default:
		DEBUG(0,("Unhandled level %d in interpret_long_filename\n", (int)level));
		return false;
	}

	return true;
}
Ejemplo n.º 2
0
void print_registry_key(const char *keyname, NTTIME *modtime)
{
	d_printf("Keyname   = %s\n", keyname);
	d_printf("Modtime   = %s\n",
		 modtime
		 ? http_timestring(nt_time_to_unix(*modtime))
		 : "None");
	d_printf("\n");
}
Ejemplo n.º 3
0
void print_registry_key(const char *keyname, NTTIME *modtime)
{
	d_printf(_("Keyname   = %s\n"), keyname);
	d_printf(_("Modtime   = %s\n"),
		 modtime
		 ? http_timestring(talloc_tos(), nt_time_to_unix(*modtime))
		 : _("None"));
	d_printf("\n");
}
Ejemplo n.º 4
0
time_t cli_state_server_time(struct cli_state *cli)
{
	NTTIME nt;
	time_t t;

	nt = smbXcli_conn_server_system_time(cli->conn);
	t = nt_time_to_unix(nt);

	return t;
}
Ejemplo n.º 5
0
static PyObject *py_nttime2unix(PyObject *self, PyObject *args)
{
	time_t t;
	NTTIME nt;
	if (!PyArg_ParseTuple(args, "K", &nt))
		return NULL;

	t = nt_time_to_unix(nt);

	return PyInt_FromLong((uint64_t)t);
}
Ejemplo n.º 6
0
static WERROR cmd_info(struct regshell_context *ctx, int argc, char **argv)
{
	struct security_descriptor *sec_desc = NULL;
	time_t last_mod;
	WERROR error;
	const char *classname = NULL;
	NTTIME last_change;
	uint32_t max_subkeynamelen;
	uint32_t max_valnamelen;
	uint32_t max_valbufsize;
	uint32_t num_subkeys;
	uint32_t num_values;

	error = reg_key_get_info(ctx, ctx->current, &classname, &num_subkeys, &num_values,
				 &last_change, &max_subkeynamelen, &max_valnamelen, &max_valbufsize);
	if (!W_ERROR_IS_OK(error)) {
		printf("Error getting key info: %s\n", win_errstr(error));
		return error;
	}


	printf("Name: %s\n", strchr(ctx->path, '\\')?strrchr(ctx->path, '\\')+1:
		   ctx->path);
	printf("Full path: %s\n", ctx->path);
	if (classname != NULL)
		printf("Key Class: %s\n", classname);
	last_mod = nt_time_to_unix(last_change);
	printf("Time Last Modified: %s", ctime(&last_mod));
	printf("Number of subkeys: %d\n", num_subkeys);
	printf("Number of values: %d\n", num_values);

	if (max_valnamelen > 0)
		printf("Maximum value name length: %d\n", max_valnamelen);

	if (max_valbufsize > 0)
		printf("Maximum value data length: %d\n", max_valbufsize);

	if (max_subkeynamelen > 0)
		printf("Maximum sub key name length: %d\n", max_subkeynamelen);

	error = reg_get_sec_desc(ctx, ctx->current, &sec_desc);
	if (!W_ERROR_IS_OK(error)) {
		printf("Error getting security descriptor: %s\n", win_errstr(error));
		return WERR_OK;
	}
	ndr_print_debug((ndr_print_fn_t)ndr_print_security_descriptor,
			"Security", sec_desc);
	talloc_free(sec_desc);

	return WERR_OK;
}
Ejemplo n.º 7
0
static WERROR dsdb_syntax_NTTIME_UTC_drsuapi_to_ldb(struct ldb_context *ldb, 
						    const struct dsdb_schema *schema,
						    const struct dsdb_attribute *attr,
						    const struct drsuapi_DsReplicaAttribute *in,
						    TALLOC_CTX *mem_ctx,
						    struct ldb_message_element *out)
{
	uint32_t i;

	out->flags	= 0;
	out->name	= talloc_strdup(mem_ctx, attr->lDAPDisplayName);
	W_ERROR_HAVE_NO_MEMORY(out->name);

	out->num_values	= in->value_ctr.num_values;
	out->values	= talloc_array(mem_ctx, struct ldb_val, out->num_values);
	W_ERROR_HAVE_NO_MEMORY(out->values);

	for (i=0; i < out->num_values; i++) {
		NTTIME v;
		time_t t;
		char *str;

		if (in->value_ctr.values[i].blob == NULL) {
			return WERR_FOOBAR;
		}

		if (in->value_ctr.values[i].blob->length != 8) {
			return WERR_FOOBAR;
		}

		v = BVAL(in->value_ctr.values[i].blob->data, 0);
		v *= 10000000;
		t = nt_time_to_unix(v);

		/* 
		 * NOTE: On a w2k3 server you can set a GeneralizedTime string
		 *       via LDAP, but you get back an UTCTime string,
		 *       but via DRSUAPI you get back the NTTIME_1sec value
		 *       that represents the GeneralizedTime value!
		 *
		 *       So if we store the UTCTime string in our ldb
		 *       we'll loose information!
		 */
		str = ldb_timestring_utc(out->values, t); 
		W_ERROR_HAVE_NO_MEMORY(str);
		out->values[i] = data_blob_string_const(str);
	}

	return WERR_OK;
}
Ejemplo n.º 8
0
static WERROR dsdb_syntax_NTTIME_drsuapi_to_ldb(struct ldb_context *ldb, 
						const struct dsdb_schema *schema,
						const struct dsdb_attribute *attr,
						const struct drsuapi_DsReplicaAttribute *in,
						TALLOC_CTX *mem_ctx,
						struct ldb_message_element *out)
{
	uint32_t i;

	out->flags	= 0;
	out->name	= talloc_strdup(mem_ctx, attr->lDAPDisplayName);
	W_ERROR_HAVE_NO_MEMORY(out->name);

	out->num_values	= in->value_ctr.num_values;
	out->values	= talloc_array(mem_ctx, struct ldb_val, out->num_values);
	W_ERROR_HAVE_NO_MEMORY(out->values);

	for (i=0; i < out->num_values; i++) {
		NTTIME v;
		time_t t;
		char *str;

		if (in->value_ctr.values[i].blob == NULL) {
			return WERR_FOOBAR;
		}

		if (in->value_ctr.values[i].blob->length != 8) {
			return WERR_FOOBAR;
		}

		v = BVAL(in->value_ctr.values[i].blob->data, 0);
		v *= 10000000;
		t = nt_time_to_unix(v);

		str = ldb_timestring(out->values, t); 
		W_ERROR_HAVE_NO_MEMORY(str);

		out->values[i] = data_blob_string_const(str);
	}

	return WERR_OK;
}
Ejemplo n.º 9
0
static NTSTATUS vampire_samdump_handle_user(TALLOC_CTX *mem_ctx,
					    struct netr_DELTA_ENUM *delta) 
{
	uint32_t rid = delta->delta_id_union.rid;
	struct netr_DELTA_USER *user = delta->delta_union.user;
	const char *username = user->account_name.string;
	char *hex_lm_password;
	char *hex_nt_password;

	hex_lm_password = smbpasswd_sethexpwd(mem_ctx, 
					      user->lm_password_present ? &user->lmpassword : NULL, 
					      user->acct_flags);
	hex_nt_password = smbpasswd_sethexpwd(mem_ctx, 
					      user->nt_password_present ? &user->ntpassword : NULL, 
					      user->acct_flags);

	printf("%s:%d:%s:%s:%s:LCT-%08X\n", username,
	       rid, hex_lm_password, hex_nt_password,
	       smbpasswd_encode_acb_info(mem_ctx, user->acct_flags),
	       (unsigned int)nt_time_to_unix(user->last_password_change));

	return NT_STATUS_OK;
}
Ejemplo n.º 10
0
/*
  support the old Samba3 TXT form of the info3
 */
static NTSTATUS wb_samba3_append_info3_as_txt(TALLOC_CTX *mem_ctx,
					      struct wbsrv_samba3_call *s3call,
					      DATA_BLOB info3b)
{
	struct netr_SamInfo3 *info3;
	char *ex;
	uint32_t i;
	enum ndr_err_code ndr_err;

	info3 = talloc(mem_ctx, struct netr_SamInfo3);
	NT_STATUS_HAVE_NO_MEMORY(info3);

	/* The Samba3 protocol has a redundent 4 bytes at the start */
	info3b.data += 4;
	info3b.length -= 4;

	ndr_err = ndr_pull_struct_blob(&info3b,
				       mem_ctx,
				       lp_iconv_convenience(s3call->wbconn->lp_ctx), 
				       info3,
				       (ndr_pull_flags_fn_t)ndr_pull_netr_SamInfo3);
	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
		return ndr_map_error2ntstatus(ndr_err);
	}

	s3call->response.data.auth.info3.logon_time =
		nt_time_to_unix(info3->base.last_logon);
	s3call->response.data.auth.info3.logoff_time =
		nt_time_to_unix(info3->base.last_logoff);
	s3call->response.data.auth.info3.kickoff_time =
		nt_time_to_unix(info3->base.acct_expiry);
	s3call->response.data.auth.info3.pass_last_set_time =
		nt_time_to_unix(info3->base.last_password_change);
	s3call->response.data.auth.info3.pass_can_change_time =
		nt_time_to_unix(info3->base.allow_password_change);
	s3call->response.data.auth.info3.pass_must_change_time =
		nt_time_to_unix(info3->base.force_password_change);

	s3call->response.data.auth.info3.logon_count = info3->base.logon_count;
	s3call->response.data.auth.info3.bad_pw_count = info3->base.bad_password_count;

	s3call->response.data.auth.info3.user_rid = info3->base.rid;
	s3call->response.data.auth.info3.group_rid = info3->base.primary_gid;
	fstrcpy(s3call->response.data.auth.info3.dom_sid, dom_sid_string(mem_ctx, info3->base.domain_sid));

	s3call->response.data.auth.info3.num_groups = info3->base.groups.count;
	s3call->response.data.auth.info3.user_flgs = info3->base.user_flags;

	s3call->response.data.auth.info3.acct_flags = info3->base.acct_flags;
	s3call->response.data.auth.info3.num_other_sids = info3->sidcount;

	fstrcpy(s3call->response.data.auth.info3.user_name,
		info3->base.account_name.string);
	fstrcpy(s3call->response.data.auth.info3.full_name,
		info3->base.full_name.string);
	fstrcpy(s3call->response.data.auth.info3.logon_script,
		info3->base.logon_script.string);
	fstrcpy(s3call->response.data.auth.info3.profile_path,
		info3->base.profile_path.string);
	fstrcpy(s3call->response.data.auth.info3.home_dir,
		info3->base.home_directory.string);
	fstrcpy(s3call->response.data.auth.info3.dir_drive,
		info3->base.home_drive.string);

	fstrcpy(s3call->response.data.auth.info3.logon_srv,
		info3->base.logon_server.string);
	fstrcpy(s3call->response.data.auth.info3.logon_dom,
		info3->base.domain.string);

	ex = talloc_strdup(mem_ctx, "");
	NT_STATUS_HAVE_NO_MEMORY(ex);

	for (i=0; i < info3->base.groups.count; i++) {
		ex = talloc_asprintf_append_buffer(ex, "0x%08X:0x%08X\n",
						   info3->base.groups.rids[i].rid,
						   info3->base.groups.rids[i].attributes);
		NT_STATUS_HAVE_NO_MEMORY(ex);
	}

	for (i=0; i < info3->sidcount; i++) {
		char *sid;

		sid = dom_sid_string(mem_ctx, info3->sids[i].sid);
		NT_STATUS_HAVE_NO_MEMORY(sid);

		ex = talloc_asprintf_append_buffer(ex, "%s:0x%08X\n",
						   sid,
						   info3->sids[i].attributes);
		NT_STATUS_HAVE_NO_MEMORY(ex);

		talloc_free(sid);
	}

	s3call->response.extra_data.data = ex;
	s3call->response.length += talloc_get_size(ex);

	return NT_STATUS_OK;
}
Ejemplo n.º 11
0
/* basic testing of all RAW_CLOSE_* calls 
*/
BOOL torture_raw_close(struct torture_context *torture)
{
	struct smbcli_state *cli;
	BOOL ret = True;
	TALLOC_CTX *mem_ctx;
	union smb_close io;
	union smb_flush io_flush;
	int fnum;
	const char *fname = "\\torture_close.txt";
	time_t basetime = (time(NULL) + 3*86400) & ~1;
	union smb_fileinfo finfo, finfo2;
	NTSTATUS status;

	if (!torture_open_connection(&cli, 0)) {
		return False;
	}

	mem_ctx = talloc_init("torture_raw_close");

#define REOPEN do { \
	fnum = create_complex_file(cli, mem_ctx, fname); \
	if (fnum == -1) { \
		printf("(%d) Failed to create %s\n", __LINE__, fname); \
		ret = False; \
		goto done; \
	}} while (0)

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

	REOPEN;

	io.close.level = RAW_CLOSE_CLOSE;
	io.close.in.file.fnum = fnum;
	io.close.in.write_time = basetime;
	status = smb_raw_close(cli->tree, &io);
	CHECK_STATUS(status, NT_STATUS_OK);

	status = smb_raw_close(cli->tree, &io);
	CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
	
	printf("testing close.in.write_time\n");

	/* the file should have the write time set */
	finfo.generic.level = RAW_FILEINFO_ALL_INFO;
	finfo.generic.in.file.path = fname;
	status = smb_raw_pathinfo(cli->tree, mem_ctx, &finfo);
	CHECK_STATUS(status, NT_STATUS_OK);

	if (basetime != nt_time_to_unix(finfo.all_info.out.write_time)) {
		printf("Incorrect write time on file - %s - %s\n",
		       timestring(mem_ctx, basetime), 
		       nt_time_string(mem_ctx, finfo.all_info.out.write_time));
		dump_all_info(mem_ctx, &finfo);
		ret = False;
	}

	printf("testing other times\n");

	/* none of the other times should be set to that time */
	if (nt_time_equal(&finfo.all_info.out.write_time, 
			  &finfo.all_info.out.access_time) ||
	    nt_time_equal(&finfo.all_info.out.write_time, 
			  &finfo.all_info.out.create_time) ||
	    nt_time_equal(&finfo.all_info.out.write_time, 
			  &finfo.all_info.out.change_time)) {
		printf("Incorrect times after close - only write time should be set\n");
		dump_all_info(mem_ctx, &finfo);
		ret = False;
	}
	    

	smbcli_unlink(cli->tree, fname);
	REOPEN;

	finfo2.generic.level = RAW_FILEINFO_ALL_INFO;
	finfo2.generic.in.file.path = fname;
	status = smb_raw_pathinfo(cli->tree, mem_ctx, &finfo2);
	CHECK_STATUS(status, NT_STATUS_OK);

	io.close.level = RAW_CLOSE_CLOSE;
	io.close.in.file.fnum = fnum;
	io.close.in.write_time = 0;
	status = smb_raw_close(cli->tree, &io);
	CHECK_STATUS(status, NT_STATUS_OK);

	/* the file should have the write time set equal to access time */
	finfo.generic.level = RAW_FILEINFO_ALL_INFO;
	finfo.generic.in.file.path = fname;
	status = smb_raw_pathinfo(cli->tree, mem_ctx, &finfo);
	CHECK_STATUS(status, NT_STATUS_OK);

	if (!nt_time_equal(&finfo.all_info.out.write_time, 
			   &finfo2.all_info.out.write_time)) {
		printf("Incorrect write time on file - 0 time should be ignored\n");
		dump_all_info(mem_ctx, &finfo);
		ret = False;
	}

	printf("testing splclose\n");

	/* check splclose on a file */
	REOPEN;
	io.splclose.level = RAW_CLOSE_SPLCLOSE;
	io.splclose.in.file.fnum = fnum;
	status = smb_raw_close(cli->tree, &io);
	CHECK_STATUS(status, NT_STATUS_DOS(ERRSRV, ERRerror));

	printf("testing flush\n");
	smbcli_close(cli->tree, fnum);

	io_flush.flush.level		= RAW_FLUSH_FLUSH;
	io_flush.flush.in.file.fnum	= fnum;
	status = smb_raw_flush(cli->tree, &io_flush);
	CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);

	io_flush.flush_all.level	= RAW_FLUSH_ALL;
	status = smb_raw_flush(cli->tree, &io_flush);
	CHECK_STATUS(status, NT_STATUS_OK);

	REOPEN;

	io_flush.flush.level		= RAW_FLUSH_FLUSH;
	io_flush.flush.in.file.fnum	= fnum;
	status = smb_raw_flush(cli->tree, &io_flush);
	CHECK_STATUS(status, NT_STATUS_OK);

	printf("Testing SMBexit\n");
	smb_raw_exit(cli->session);

	io_flush.flush.level		= RAW_FLUSH_FLUSH;
	io_flush.flush.in.file.fnum	= fnum;
	status = smb_raw_flush(cli->tree, &io_flush);
	CHECK_STATUS(status, NT_STATUS_INVALID_HANDLE);
	

done:
	smbcli_close(cli->tree, fnum);
	smbcli_unlink(cli->tree, fname);
	torture_close_connection(cli);
	talloc_free(mem_ctx);
	return ret;
}
Ejemplo n.º 12
0
static NTSTATUS fetch_account_info_to_ldif(TALLOC_CTX *mem_ctx,
					   struct netr_DELTA_USER *r,
					   GROUPMAP *groupmap,
					   ACCOUNTMAP *accountmap,
					   FILE *add_fd,
					   const char *sid,
					   const char *suffix,
					   int alloced)
{
	fstring username, logonscript, homedrive, homepath = "", homedir = "";
	fstring hex_nt_passwd, hex_lm_passwd;
	fstring description, profilepath, fullname, sambaSID;
	char *flags, *user_rdn;
	const char *ou;
	const char* nopasswd = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
	uint32_t rid = 0, group_rid = 0, gidNumber = 0;
	time_t unix_time;
	int i, ret;

	/* Get the username */
	fstrcpy(username, r->account_name.string);

	/* Get the rid */
	rid = r->rid;

	/* Map the rid and username for group member info later */
	accountmap->rid = rid;
	accountmap->cn = talloc_strdup(mem_ctx, username);
	NT_STATUS_HAVE_NO_MEMORY(accountmap->cn);

	/* Get the home directory */
	if (r->acct_flags & ACB_NORMAL) {
		fstrcpy(homedir, r->home_directory.string);
		if (!*homedir) {
			snprintf(homedir, sizeof(homedir), "/home/%s", username);
		} else {
			snprintf(homedir, sizeof(homedir), "/nobodyshomedir");
		}
		ou = lp_ldap_user_suffix(talloc_tos());
	} else {
		ou = lp_ldap_machine_suffix(talloc_tos());
		snprintf(homedir, sizeof(homedir), "/machinehomedir");
	}

        /* Get the logon script */
	fstrcpy(logonscript, r->logon_script.string);

        /* Get the home drive */
	fstrcpy(homedrive, r->home_drive.string);

        /* Get the home path */
	fstrcpy(homepath, r->home_directory.string);

	/* Get the description */
	fstrcpy(description, r->description.string);

	/* Get the display name */
	fstrcpy(fullname, r->full_name.string);

	/* Get the profile path */
	fstrcpy(profilepath, r->profile_path.string);

	/* Get lm and nt password data */
	if (!all_zero(r->lmpassword.hash, 16)) {
		pdb_sethexpwd(hex_lm_passwd, r->lmpassword.hash, r->acct_flags);
	} else {
		pdb_sethexpwd(hex_lm_passwd, NULL, 0);
	}
	if (!all_zero(r->ntpassword.hash, 16)) {
		pdb_sethexpwd(hex_nt_passwd, r->ntpassword.hash, r->acct_flags);
	} else {
		pdb_sethexpwd(hex_nt_passwd, NULL, 0);
	}
	unix_time = nt_time_to_unix(r->last_password_change);

	/* Increment the uid for the new user */
	ldif_uid++;

	/* Set up group id and sambaSID for the user */
	group_rid = r->primary_gid;
	for (i=0; i<alloced; i++) {
		if (groupmap[i].rid == group_rid) break;
	}
	if (i == alloced){
		DEBUG(1, ("Could not find rid %d in groupmap array\n",
			  group_rid));
		return NT_STATUS_UNSUCCESSFUL;
	}
	gidNumber = groupmap[i].gidNumber;
	ret = snprintf(sambaSID, sizeof(sambaSID), "%s", groupmap[i].sambaSID);
	if (ret < 0 || ret == sizeof(sambaSID)) {
		return NT_STATUS_UNSUCCESSFUL;
	}

	/* Set up sambaAcctFlags */
	flags = pdb_encode_acct_ctrl(r->acct_flags,
				     NEW_PW_FORMAT_SPACE_PADDED_LEN);

	/* Add the user to the temporary add ldif file */
	/* this isn't quite right...we can't assume there's just OU=. jmcd */
	user_rdn = sstring_sub(ou, '=', ',');
	fprintf(add_fd, "# %s, %s, %s\n", username, user_rdn, suffix);
	fprintf_attr(add_fd, "dn", "uid=%s,ou=%s,%s", username, user_rdn,
		     suffix);
	SAFE_FREE(user_rdn);
	fprintf(add_fd, "ObjectClass: top\n");
	fprintf(add_fd, "objectClass: inetOrgPerson\n");
	fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_POSIXACCOUNT);
	fprintf(add_fd, "objectClass: shadowAccount\n");
	fprintf(add_fd, "objectClass: %s\n", LDAP_OBJ_SAMBASAMACCOUNT);
	fprintf_attr(add_fd, "cn", "%s", username);
	fprintf_attr(add_fd, "sn", "%s", username);
	fprintf_attr(add_fd, "uid", "%s", username);
	fprintf(add_fd, "uidNumber: %d\n", ldif_uid);
	fprintf(add_fd, "gidNumber: %d\n", gidNumber);
	fprintf_attr(add_fd, "homeDirectory", "%s", homedir);
	if (*homepath)
		fprintf_attr(add_fd, "sambaHomePath", "%s", homepath);
        if (*homedrive)
                fprintf_attr(add_fd, "sambaHomeDrive", "%s", homedrive);
        if (*logonscript)
                fprintf_attr(add_fd, "sambaLogonScript", "%s", logonscript);
	fprintf(add_fd, "loginShell: %s\n",
		((r->acct_flags & ACB_NORMAL) ?
		 "/bin/bash" : "/bin/false"));
	fprintf(add_fd, "gecos: System User\n");
	if (*description)
		fprintf_attr(add_fd, "description", "%s", description);
	fprintf(add_fd, "sambaSID: %s-%d\n", sid, rid);
	fprintf(add_fd, "sambaPrimaryGroupSID: %s\n", sambaSID);
	if(*fullname)
		fprintf_attr(add_fd, "displayName", "%s", fullname);
	if(*profilepath)
		fprintf_attr(add_fd, "sambaProfilePath", "%s", profilepath);
	if (strcmp(nopasswd, hex_lm_passwd) != 0)
		fprintf(add_fd, "sambaLMPassword: %s\n", hex_lm_passwd);
	if (strcmp(nopasswd, hex_nt_passwd) != 0)
		fprintf(add_fd, "sambaNTPassword: %s\n", hex_nt_passwd);
	fprintf(add_fd, "sambaPwdLastSet: %d\n", (int)unix_time);
	fprintf(add_fd, "sambaAcctFlags: %s\n", flags);
	fprintf(add_fd, "\n");
	fflush(add_fd);

	/* Return */
	return NT_STATUS_OK;
}
Ejemplo n.º 13
0
/****************************************************************************
 display sam_user_info_21 structure
 ****************************************************************************/
static void display_sam_user_info_21(SAM_USER_INFO_21 *usr)
{
	fstring temp;

	unistr2_to_unix(temp, &usr->uni_user_name, sizeof(temp)-1);
	printf("\tUser Name   :\t%s\n", temp);
	
	unistr2_to_unix(temp, &usr->uni_full_name, sizeof(temp)-1);
	printf("\tFull Name   :\t%s\n", temp);
	
	unistr2_to_unix(temp, &usr->uni_home_dir, sizeof(temp)-1);
	printf("\tHome Drive  :\t%s\n", temp);
	
	unistr2_to_unix(temp, &usr->uni_dir_drive, sizeof(temp)-1);
	printf("\tDir Drive   :\t%s\n", temp);
	
	unistr2_to_unix(temp, &usr->uni_profile_path, sizeof(temp)-1);
	printf("\tProfile Path:\t%s\n", temp);
	
	unistr2_to_unix(temp, &usr->uni_logon_script, sizeof(temp)-1);
	printf("\tLogon Script:\t%s\n", temp);
	
	unistr2_to_unix(temp, &usr->uni_acct_desc, sizeof(temp)-1);
	printf("\tDescription :\t%s\n", temp);
	
	unistr2_to_unix(temp, &usr->uni_workstations, sizeof(temp)-1);
	printf("\tWorkstations:\t%s\n", temp);
	
	unistr2_to_unix(temp, &usr->uni_unknown_str, sizeof(temp)-1);
	printf("\tUnknown Str :\t%s\n", temp);
	
	unistr2_to_unix(temp, &usr->uni_munged_dial, sizeof(temp)-1);
	printf("\tRemote Dial :\t%s\n", temp);
	
	printf("\tLogon Time               :\t%s\n", 
	       http_timestring(nt_time_to_unix(&usr->logon_time)));
	printf("\tLogoff Time              :\t%s\n", 
	       http_timestring(nt_time_to_unix(&usr->logoff_time)));
	printf("\tKickoff Time             :\t%s\n", 
	       http_timestring(nt_time_to_unix(&usr->kickoff_time)));
	printf("\tPassword last set Time   :\t%s\n", 
	       http_timestring(nt_time_to_unix(&usr->pass_last_set_time)));
	printf("\tPassword can change Time :\t%s\n", 
	       http_timestring(nt_time_to_unix(&usr->pass_can_change_time)));
	printf("\tPassword must change Time:\t%s\n", 
	       http_timestring(nt_time_to_unix(&usr->pass_must_change_time)));
	
	printf("\tunknown_2[0..31]...\n"); /* user passwords? */
	
	printf("\tuser_rid :\t%x\n"  , usr->user_rid ); /* User ID */
	printf("\tgroup_rid:\t%x\n"  , usr->group_rid); /* Group ID */
	printf("\tacb_info :\t%04x\n", usr->acb_info ); /* Account Control Info */
	
	printf("\tunknown_3:\t%08x\n", usr->unknown_3); /* 0x00ff ffff */
	printf("\tlogon_divs:\t%d\n", usr->logon_divs); /* 0x0000 00a8 which is 168 which is num hrs in a week */
	printf("\tunknown_5:\t%08x\n", usr->unknown_5); /* 0x0002 0000 */
	
	printf("\tpadding1[0..7]...\n");
	
	if (usr->ptr_logon_hrs) {
		printf("\tlogon_hrs[0..%d]...\n", usr->logon_hrs.len);
	}
}
Ejemplo n.º 14
0
static WERROR dsdb_convert_object_ex(struct ldb_context *ldb,
				     const struct dsdb_schema *schema,
				     const struct drsuapi_DsReplicaObjectListItemEx *in,
				     const DATA_BLOB *gensec_skey,
				     TALLOC_CTX *mem_ctx,
				     struct dsdb_extended_replicated_object *out)
{
	NTSTATUS nt_status;
	WERROR status;
	uint32_t i;
	struct ldb_message *msg;
	struct replPropertyMetaDataBlob *md;
	struct ldb_val guid_value;
	NTTIME whenChanged = 0;
	time_t whenChanged_t;
	const char *whenChanged_s;
	const char *rdn_name = NULL;
	const struct ldb_val *rdn_value = NULL;
	const struct dsdb_attribute *rdn_attr = NULL;
	uint32_t rdn_attid;
	struct drsuapi_DsReplicaAttribute *name_a = NULL;
	struct drsuapi_DsReplicaMetaData *name_d = NULL;
	struct replPropertyMetaData1 *rdn_m = NULL;
	struct dom_sid *sid = NULL;
	uint32_t rid = 0;
	int ret;

	if (!in->object.identifier) {
		return WERR_FOOBAR;
	}

	if (!in->object.identifier->dn || !in->object.identifier->dn[0]) {
		return WERR_FOOBAR;
	}

	if (in->object.attribute_ctr.num_attributes != 0 && !in->meta_data_ctr) {
		return WERR_FOOBAR;
	}

	if (in->object.attribute_ctr.num_attributes != in->meta_data_ctr->count) {
		return WERR_FOOBAR;
	}

	sid = &in->object.identifier->sid;
	if (sid->num_auths > 0) {
		rid = sid->sub_auths[sid->num_auths - 1];
	}

	msg = ldb_msg_new(mem_ctx);
	W_ERROR_HAVE_NO_MEMORY(msg);

	msg->dn			= ldb_dn_new(msg, ldb, in->object.identifier->dn);
	W_ERROR_HAVE_NO_MEMORY(msg->dn);

	rdn_name	= ldb_dn_get_rdn_name(msg->dn);
	rdn_attr	= dsdb_attribute_by_lDAPDisplayName(schema, rdn_name);
	if (!rdn_attr) {
		return WERR_FOOBAR;
	}
	rdn_attid	= rdn_attr->attributeID_id;
	rdn_value	= ldb_dn_get_rdn_val(msg->dn);

	msg->num_elements	= in->object.attribute_ctr.num_attributes;
	msg->elements		= talloc_array(msg, struct ldb_message_element,
					       msg->num_elements);
	W_ERROR_HAVE_NO_MEMORY(msg->elements);

	md = talloc(mem_ctx, struct replPropertyMetaDataBlob);
	W_ERROR_HAVE_NO_MEMORY(md);

	md->version		= 1;
	md->reserved		= 0;
	md->ctr.ctr1.count	= in->meta_data_ctr->count;
	md->ctr.ctr1.reserved	= 0;
	md->ctr.ctr1.array	= talloc_array(mem_ctx,
					       struct replPropertyMetaData1,
					       md->ctr.ctr1.count + 1); /* +1 because of the RDN attribute */
	W_ERROR_HAVE_NO_MEMORY(md->ctr.ctr1.array);

	for (i=0; i < in->meta_data_ctr->count; i++) {
		struct drsuapi_DsReplicaAttribute *a;
		struct drsuapi_DsReplicaMetaData *d;
		struct replPropertyMetaData1 *m;
		struct ldb_message_element *e;
		int j;

		a = &in->object.attribute_ctr.attributes[i];
		d = &in->meta_data_ctr->meta_data[i];
		m = &md->ctr.ctr1.array[i];
		e = &msg->elements[i];

		for (j=0; j<a->value_ctr.num_values; j++) {
			status = drsuapi_decrypt_attribute(a->value_ctr.values[j].blob, gensec_skey, rid, a);
			W_ERROR_NOT_OK_RETURN(status);
		}

		status = dsdb_attribute_drsuapi_to_ldb(ldb, schema, a, msg->elements, e);
		if (!NT_STATUS_IS_OK(status) && a->value_ctr.num_values == 0) {
			/* w2k8-r2 occasionally sends bogus empty
			   attributes with rubbish attribute IDs. The
			   only think we can do is discard these */
			DEBUG(0,(__location__ ": Discarding bogus empty DsReplicaAttribute with attid 0x%x\n",
				 a->attid));
			ZERO_STRUCTP(e);
			continue;
		}
		W_ERROR_NOT_OK_RETURN(status);

		m->attid			= a->attid;
		m->version			= d->version;
		m->originating_change_time	= d->originating_change_time;
		m->originating_invocation_id	= d->originating_invocation_id;
		m->originating_usn		= d->originating_usn;
		m->local_usn			= 0;

		if (d->originating_change_time > whenChanged) {
			whenChanged = d->originating_change_time;
		}

		if (a->attid == DRSUAPI_ATTRIBUTE_name) {
			name_a = a;
			name_d = d;
			rdn_m = &md->ctr.ctr1.array[md->ctr.ctr1.count];
		}
	}

	/* delete any empty elements */
	for (i=0; i < msg->num_elements; i++) {
		if (msg->elements[i].name == NULL) {
			ldb_msg_remove_element(msg, &msg->elements[i]);
			i--;
		}
	}

	if (rdn_m) {
		struct ldb_message_element *el;
		el = ldb_msg_find_element(msg, rdn_attr->lDAPDisplayName);
		if (!el) {
			ret = ldb_msg_add_value(msg, rdn_attr->lDAPDisplayName, rdn_value, NULL);
			if (ret != LDB_SUCCESS) {
				return WERR_FOOBAR;
			}
		} else {
			if (el->num_values != 1) {
				DEBUG(0,(__location__ ": Unexpected num_values=%u\n",
					 el->num_values));
				return WERR_FOOBAR;				
			}
			if (!ldb_val_equal_exact(&el->values[0], rdn_value)) {
				DEBUG(0,(__location__ ": RDN value changed? '%*.*s' '%*.*s'\n",
					 (int)el->values[0].length, (int)el->values[0].length, el->values[0].data,
					 (int)rdn_value->length, (int)rdn_value->length, rdn_value->data));
				return WERR_FOOBAR;				
			}
		}

		rdn_m->attid				= rdn_attid;
		rdn_m->version				= name_d->version;
		rdn_m->originating_change_time		= name_d->originating_change_time;
		rdn_m->originating_invocation_id	= name_d->originating_invocation_id;
		rdn_m->originating_usn			= name_d->originating_usn;
		rdn_m->local_usn			= 0;
		md->ctr.ctr1.count++;

	}

	whenChanged_t = nt_time_to_unix(whenChanged);
	whenChanged_s = ldb_timestring(msg, whenChanged_t);
	W_ERROR_HAVE_NO_MEMORY(whenChanged_s);

	nt_status = GUID_to_ndr_blob(&in->object.identifier->guid, msg, &guid_value);
	if (!NT_STATUS_IS_OK(nt_status)) {
		return ntstatus_to_werror(nt_status);
	}

	out->msg		= msg;
	out->guid_value		= guid_value;
	out->when_changed	= whenChanged_s;
	out->meta_data		= md;
	return WERR_OK;
}
Ejemplo n.º 15
0
static int traverse_tcon_fn(struct smbXsrv_tcon_global0 *global,
			    void *connections_forall_state)
{
	NTSTATUS status;
	struct connections_forall_state *state =
		(struct connections_forall_state*)connections_forall_state;

	struct connections_key key;
	struct connections_data data;

	uint32_t sess_id = global->session_global_id;
	struct connections_forall_session sess = {
		.uid = -1,
		.gid = -1,
	};

	TDB_DATA val = tdb_null;

	/*
	 * Note: that share_name is defined as array without a pointer.
	 * that's why it's always a valid pointer here.
	 */
	if (strlen(global->share_name) == 0) {
		/*
		 * when a smbXsrv_tcon is created it's created
		 * with emtpy share_name first in order to allocate
		 * an id, before filling in the details.
		 */
		return 0;
	}

	status = dbwrap_fetch(state->session_by_pid, state,
			      make_tdb_data((void*)&sess_id, sizeof(sess_id)),
			      &val);
	if (NT_STATUS_IS_OK(status)) {
		memcpy((uint8_t *)&sess, val.dptr, val.dsize);
	}

	ZERO_STRUCT(key);
	ZERO_STRUCT(data);

	key.pid = data.pid = global->server_id;
	key.cnum = data.cnum = global->tcon_global_id;
	fstrcpy(key.name, global->share_name);
	fstrcpy(data.servicename, global->share_name);
	data.uid = sess.uid;
	data.gid = sess.gid;
	fstrcpy(data.addr, sess.addr);
	fstrcpy(data.machine, sess.machine);
	data.start = nt_time_to_unix(global->creation_time);
	data.encryption_flags = global->encryption_flags;
	data.cipher = sess.cipher;
	data.dialect = sess.dialect;
	data.signing_flags = global->signing_flags;

	state->count++;

	return state->fn(&key, &data, state->private_data);
}

int connections_forall_read(int (*fn)(const struct connections_key *key,
				      const struct connections_data *data,
				      void *private_data),
			    void *private_data)
{
	TALLOC_CTX *frame = talloc_stackframe();
	struct connections_forall_state *state =
		talloc_zero(talloc_tos(), struct connections_forall_state);
	NTSTATUS status;
	int ret = -1;

	state->session_by_pid = db_open_rbt(state);
	state->fn = fn;
	state->private_data = private_data;
	status = smbXsrv_session_global_traverse(collect_sessions_fn, state);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(0, ("Failed to traverse sessions: %s\n",
			  nt_errstr(status)));
		goto done;
	}

	status = smbXsrv_tcon_global_traverse(traverse_tcon_fn, state);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(0, ("Failed to traverse tree connects: %s\n",
			  nt_errstr(status)));
		goto done;
	}
	ret = state->count;
done:
	talloc_free(frame);
	return ret;
}
Ejemplo n.º 16
0
/*
  fill in a single search result for a given info level
*/
static NTSTATUS fill_search_info(struct pvfs_state *pvfs,
				 enum smb_search_data_level level,
				 const char *unix_path,
				 const char *fname, 
				 struct pvfs_search_state *search,
				 off_t dir_offset,
				 union smb_search_data *file)
{
	struct pvfs_filename *name;
	NTSTATUS status;
	const char *shortname;
	uint32_t dir_index = (uint32_t)dir_offset; /* truncated - see the code 
						      in pvfs_list_seek_ofs() for 
						      how we cope with this */

	status = pvfs_resolve_partial(pvfs, file, unix_path, fname, 0, &name);
	if (!NT_STATUS_IS_OK(status)) {
		return status;
	}

	status = pvfs_match_attrib(pvfs, name, search->search_attrib, search->must_attrib);
	if (!NT_STATUS_IS_OK(status)) {
		return status;
	}

	switch (level) {
	case RAW_SEARCH_DATA_SEARCH:
		shortname = pvfs_short_name(pvfs, name, name);
		file->search.attrib           = name->dos.attrib;
		file->search.write_time       = nt_time_to_unix(name->dos.write_time);
		file->search.size             = name->st.st_size;
		file->search.name             = shortname;
		file->search.id.reserved      = search->handle >> 8;
		memset(file->search.id.name, ' ', sizeof(file->search.id.name));
		memcpy(file->search.id.name, shortname, 
		       MIN(strlen(shortname)+1, sizeof(file->search.id.name)));
		file->search.id.handle        = search->handle & 0xFF;
		file->search.id.server_cookie = dir_index;
		file->search.id.client_cookie = 0;
		return NT_STATUS_OK;

	case RAW_SEARCH_DATA_STANDARD:
		file->standard.resume_key   = dir_index;
		file->standard.create_time  = nt_time_to_unix(name->dos.create_time);
		file->standard.access_time  = nt_time_to_unix(name->dos.access_time);
		file->standard.write_time   = nt_time_to_unix(name->dos.write_time);
		file->standard.size         = name->st.st_size;
		file->standard.alloc_size   = name->dos.alloc_size;
		file->standard.attrib       = name->dos.attrib;
		file->standard.name.s       = fname;
		return NT_STATUS_OK;

	case RAW_SEARCH_DATA_EA_SIZE:
		file->ea_size.resume_key   = dir_index;
		file->ea_size.create_time  = nt_time_to_unix(name->dos.create_time);
		file->ea_size.access_time  = nt_time_to_unix(name->dos.access_time);
		file->ea_size.write_time   = nt_time_to_unix(name->dos.write_time);
		file->ea_size.size         = name->st.st_size;
		file->ea_size.alloc_size   = name->dos.alloc_size;
		file->ea_size.attrib       = name->dos.attrib;
		file->ea_size.ea_size      = name->dos.ea_size;
		file->ea_size.name.s       = fname;
		return NT_STATUS_OK;

	case RAW_SEARCH_DATA_EA_LIST:
		file->ea_list.resume_key   = dir_index;
		file->ea_list.create_time  = nt_time_to_unix(name->dos.create_time);
		file->ea_list.access_time  = nt_time_to_unix(name->dos.access_time);
		file->ea_list.write_time   = nt_time_to_unix(name->dos.write_time);
		file->ea_list.size         = name->st.st_size;
		file->ea_list.alloc_size   = name->dos.alloc_size;
		file->ea_list.attrib       = name->dos.attrib;
		file->ea_list.name.s       = fname;
		return pvfs_query_ea_list(pvfs, file, name, -1, 
					  search->num_ea_names,
					  search->ea_names,
					  &file->ea_list.eas);

	case RAW_SEARCH_DATA_DIRECTORY_INFO:
		file->directory_info.file_index   = dir_index;
		file->directory_info.create_time  = name->dos.create_time;
		file->directory_info.access_time  = name->dos.access_time;
		file->directory_info.write_time   = name->dos.write_time;
		file->directory_info.change_time  = name->dos.change_time;
		file->directory_info.size         = name->st.st_size;
		file->directory_info.alloc_size   = name->dos.alloc_size;
		file->directory_info.attrib       = name->dos.attrib;
		file->directory_info.name.s       = fname;
		return NT_STATUS_OK;

	case RAW_SEARCH_DATA_FULL_DIRECTORY_INFO:
		file->full_directory_info.file_index   = dir_index;
		file->full_directory_info.create_time  = name->dos.create_time;
		file->full_directory_info.access_time  = name->dos.access_time;
		file->full_directory_info.write_time   = name->dos.write_time;
		file->full_directory_info.change_time  = name->dos.change_time;
		file->full_directory_info.size         = name->st.st_size;
		file->full_directory_info.alloc_size   = name->dos.alloc_size;
		file->full_directory_info.attrib       = name->dos.attrib;
		file->full_directory_info.ea_size      = name->dos.ea_size;
		file->full_directory_info.name.s       = fname;
		return NT_STATUS_OK;

	case RAW_SEARCH_DATA_NAME_INFO:
		file->name_info.file_index   = dir_index;
		file->name_info.name.s       = fname;
		return NT_STATUS_OK;

	case RAW_SEARCH_DATA_BOTH_DIRECTORY_INFO:
		file->both_directory_info.file_index   = dir_index;
		file->both_directory_info.create_time  = name->dos.create_time;
		file->both_directory_info.access_time  = name->dos.access_time;
		file->both_directory_info.write_time   = name->dos.write_time;
		file->both_directory_info.change_time  = name->dos.change_time;
		file->both_directory_info.size         = name->st.st_size;
		file->both_directory_info.alloc_size   = name->dos.alloc_size;
		file->both_directory_info.attrib       = name->dos.attrib;
		file->both_directory_info.ea_size      = name->dos.ea_size;
		file->both_directory_info.short_name.s = pvfs_short_name(pvfs, file, name);
		file->both_directory_info.name.s       = fname;
		return NT_STATUS_OK;

	case RAW_SEARCH_DATA_ID_FULL_DIRECTORY_INFO:
		file->id_full_directory_info.file_index   = dir_index;
		file->id_full_directory_info.create_time  = name->dos.create_time;
		file->id_full_directory_info.access_time  = name->dos.access_time;
		file->id_full_directory_info.write_time   = name->dos.write_time;
		file->id_full_directory_info.change_time  = name->dos.change_time;
		file->id_full_directory_info.size         = name->st.st_size;
		file->id_full_directory_info.alloc_size   = name->dos.alloc_size;
		file->id_full_directory_info.attrib       = name->dos.attrib;
		file->id_full_directory_info.ea_size      = name->dos.ea_size;
		file->id_full_directory_info.file_id      = name->dos.file_id;
		file->id_full_directory_info.name.s       = fname;
		return NT_STATUS_OK;

	case RAW_SEARCH_DATA_ID_BOTH_DIRECTORY_INFO:
		file->id_both_directory_info.file_index   = dir_index;
		file->id_both_directory_info.create_time  = name->dos.create_time;
		file->id_both_directory_info.access_time  = name->dos.access_time;
		file->id_both_directory_info.write_time   = name->dos.write_time;
		file->id_both_directory_info.change_time  = name->dos.change_time;
		file->id_both_directory_info.size         = name->st.st_size;
		file->id_both_directory_info.alloc_size   = name->dos.alloc_size;
		file->id_both_directory_info.attrib       = name->dos.attrib;
		file->id_both_directory_info.ea_size      = name->dos.ea_size;
		file->id_both_directory_info.file_id      = name->dos.file_id;
		file->id_both_directory_info.short_name.s = pvfs_short_name(pvfs, file, name);
		file->id_both_directory_info.name.s       = fname;
		return NT_STATUS_OK;

	case RAW_SEARCH_DATA_GENERIC:
		break;
	}

	return NT_STATUS_INVALID_LEVEL;
}
Ejemplo n.º 17
0
/*
  compare a dos time (2 second resolution) to a nt time
*/
static int dos_nt_time_cmp(time_t t, NTTIME nt)
{
	time_t t2 = nt_time_to_unix(nt);
	if (abs(t2 - t) <= 2) return 0;
	return t2 > t ? 1 : -1;
}
Ejemplo n.º 18
0
void copy_id21_to_sam_passwd(const char *log_prefix,
			     struct samu *to,
			     struct samr_UserInfo21 *from)
{
	time_t unix_time, stored_time;
	const char *old_string, *new_string;
	const char *l;

	if (from == NULL || to == NULL) {
		return;
	}

	if (log_prefix) {
		l = log_prefix;
	} else {
		l = "INFO_21";
	}

	if (from->fields_present & SAMR_FIELD_LAST_LOGON) {
		unix_time = nt_time_to_unix(from->last_logon);
		stored_time = pdb_get_logon_time(to);
		DEBUG(10,("%s SAMR_FIELD_LAST_LOGON: %lu -> %lu\n", l,
			(long unsigned int)stored_time,
			(long unsigned int)unix_time));
		if (stored_time != unix_time) {
			pdb_set_logon_time(to, unix_time, PDB_CHANGED);
		}
	}

	if (from->fields_present & SAMR_FIELD_LAST_LOGOFF) {
		unix_time = nt_time_to_unix(from->last_logoff);
		stored_time = pdb_get_logoff_time(to);
		DEBUG(10,("%s SAMR_FIELD_LAST_LOGOFF: %lu -> %lu\n", l,
			(long unsigned int)stored_time,
			(long unsigned int)unix_time));
		if (stored_time != unix_time) {
			pdb_set_logoff_time(to, unix_time, PDB_CHANGED);
		}
	}

	if (from->fields_present & SAMR_FIELD_ACCT_EXPIRY) {
		unix_time = nt_time_to_unix(from->acct_expiry);
		stored_time = pdb_get_kickoff_time(to);
		DEBUG(10,("%s SAMR_FIELD_ACCT_EXPIRY: %lu -> %lu\n", l,
			(long unsigned int)stored_time,
			(long unsigned int)unix_time));
		if (stored_time != unix_time) {
			pdb_set_kickoff_time(to, unix_time , PDB_CHANGED);
		}
	}

	if (from->fields_present & SAMR_FIELD_LAST_PWD_CHANGE) {
		unix_time = nt_time_to_unix(from->last_password_change);
		stored_time = pdb_get_pass_last_set_time(to);
		DEBUG(10,("%s SAMR_FIELD_LAST_PWD_CHANGE: %lu -> %lu\n", l,
			(long unsigned int)stored_time,
			(long unsigned int)unix_time));
		if (stored_time != unix_time) {
			pdb_set_pass_last_set_time(to, unix_time, PDB_CHANGED);
		}
	}

	if ((from->fields_present & SAMR_FIELD_ACCOUNT_NAME) &&
	    (from->account_name.string)) {
		old_string = pdb_get_username(to);
		new_string = from->account_name.string;
		DEBUG(10,("%s SAMR_FIELD_ACCOUNT_NAME: %s -> %s\n", l,
			old_string, new_string));
		if (STRING_CHANGED) {
			pdb_set_username(to, new_string, PDB_CHANGED);
		}
	}

	if ((from->fields_present & SAMR_FIELD_FULL_NAME) &&
	    (from->full_name.string)) {
		old_string = pdb_get_fullname(to);
		new_string = from->full_name.string;
		DEBUG(10,("%s SAMR_FIELD_FULL_NAME: %s -> %s\n", l,
			old_string, new_string));
		if (STRING_CHANGED) {
			pdb_set_fullname(to, new_string, PDB_CHANGED);
		}
	}

	if ((from->fields_present & SAMR_FIELD_HOME_DIRECTORY) &&
	    (from->home_directory.string)) {
		old_string = pdb_get_homedir(to);
		new_string = from->home_directory.string;
		DEBUG(10,("%s SAMR_FIELD_HOME_DIRECTORY: %s -> %s\n", l,
			old_string, new_string));
		if (STRING_CHANGED) {
			pdb_set_homedir(to, new_string, PDB_CHANGED);
		}
	}

	if ((from->fields_present & SAMR_FIELD_HOME_DRIVE) &&
	    (from->home_drive.string)) {
		old_string = pdb_get_dir_drive(to);
		new_string = from->home_drive.string;
		DEBUG(10,("%s SAMR_FIELD_HOME_DRIVE: %s -> %s\n", l,
			old_string, new_string));
		if (STRING_CHANGED) {
			pdb_set_dir_drive(to, new_string, PDB_CHANGED);
		}
	}

	if ((from->fields_present & SAMR_FIELD_LOGON_SCRIPT) &&
	    (from->logon_script.string)) {
		old_string = pdb_get_logon_script(to);
		new_string = from->logon_script.string;
		DEBUG(10,("%s SAMR_FIELD_LOGON_SCRIPT: %s -> %s\n", l,
			old_string, new_string));
		if (STRING_CHANGED) {
			pdb_set_logon_script(to  , new_string, PDB_CHANGED);
		}
	}

	if ((from->fields_present & SAMR_FIELD_PROFILE_PATH) &&
	    (from->profile_path.string)) {
		old_string = pdb_get_profile_path(to);
		new_string = from->profile_path.string;
		DEBUG(10,("%s SAMR_FIELD_PROFILE_PATH: %s -> %s\n", l,
			old_string, new_string));
		if (STRING_CHANGED) {
			pdb_set_profile_path(to  , new_string, PDB_CHANGED);
		}
	}

	if ((from->fields_present & SAMR_FIELD_DESCRIPTION) &&
	    (from->description.string)) {
		old_string = pdb_get_acct_desc(to);
		new_string = from->description.string;
		DEBUG(10,("%s SAMR_FIELD_DESCRIPTION: %s -> %s\n", l,
			old_string, new_string));
		if (STRING_CHANGED) {
			pdb_set_acct_desc(to, new_string, PDB_CHANGED);
		}
	}

	if ((from->fields_present & SAMR_FIELD_WORKSTATIONS) &&
	    (from->workstations.string)) {
		old_string = pdb_get_workstations(to);
		new_string = from->workstations.string;
		DEBUG(10,("%s SAMR_FIELD_WORKSTATIONS: %s -> %s\n", l,
			old_string, new_string));
		if (STRING_CHANGED) {
			pdb_set_workstations(to  , new_string, PDB_CHANGED);
		}
	}

	if ((from->fields_present & SAMR_FIELD_COMMENT) &&
	    (from->comment.string)) {
		old_string = pdb_get_comment(to);
		new_string = from->comment.string;
		DEBUG(10,("%s SAMR_FIELD_COMMENT: %s -> %s\n", l,
			old_string, new_string));
		if (STRING_CHANGED) {
			pdb_set_comment(to, new_string, PDB_CHANGED);
		}
	}

	if ((from->fields_present & SAMR_FIELD_PARAMETERS) &&
	    (from->parameters.array)) {
		char *newstr;
		DATA_BLOB mung;
		old_string = pdb_get_munged_dial(to);

		mung = data_blob_const(from->parameters.array,
				       from->parameters.length);
		newstr = (mung.length == 0) ?
			NULL : base64_encode_data_blob(talloc_tos(), mung);
		DEBUG(10,("%s SAMR_FIELD_PARAMETERS: %s -> %s\n", l,
			old_string, newstr));
		if (STRING_CHANGED_NC(old_string,newstr)) {
			pdb_set_munged_dial(to, newstr, PDB_CHANGED);
		}

		TALLOC_FREE(newstr);
	}

	if (from->fields_present & SAMR_FIELD_RID) {
		if (from->rid == 0) {
			DEBUG(10,("%s: Asked to set User RID to 0 !? Skipping change!\n", l));
		} else if (from->rid != pdb_get_user_rid(to)) {
			DEBUG(10,("%s SAMR_FIELD_RID: %u -> %u NOT UPDATED!\n", l,
				pdb_get_user_rid(to), from->rid));
		}
	}

	if (from->fields_present & SAMR_FIELD_PRIMARY_GID) {
		if (from->primary_gid == 0) {
			DEBUG(10,("%s: Asked to set Group RID to 0 !? Skipping change!\n", l));
		} else if (from->primary_gid != pdb_get_group_rid(to)) {
			DEBUG(10,("%s SAMR_FIELD_PRIMARY_GID: %u -> %u\n", l,
				pdb_get_group_rid(to), from->primary_gid));
			pdb_set_group_sid_from_rid(to,
				from->primary_gid, PDB_CHANGED);
		}
	}

	if (from->fields_present & SAMR_FIELD_ACCT_FLAGS) {
		DEBUG(10,("%s SAMR_FIELD_ACCT_FLAGS: %08X -> %08X\n", l,
			pdb_get_acct_ctrl(to), from->acct_flags));
		if (from->acct_flags != pdb_get_acct_ctrl(to)) {

			/* You cannot autolock an unlocked account via
			 * setuserinfo calls, so make sure to remove the
			 * ACB_AUTOLOCK bit here - gd */

			if ((from->acct_flags & ACB_AUTOLOCK) &&
			    !(pdb_get_acct_ctrl(to) & ACB_AUTOLOCK)) {
				from->acct_flags &= ~ACB_AUTOLOCK;
			}

			if (!(from->acct_flags & ACB_AUTOLOCK) &&
			     (pdb_get_acct_ctrl(to) & ACB_AUTOLOCK)) {
				/* We're unlocking a previously locked user. Reset bad password counts.
				   Patch from Jianliang Lu. <*****@*****.**> */
				pdb_set_bad_password_count(to, 0, PDB_CHANGED);
				pdb_set_bad_password_time(to, 0, PDB_CHANGED);
			}
			pdb_set_acct_ctrl(to, from->acct_flags, PDB_CHANGED);
		}
	}

	if (from->fields_present & SAMR_FIELD_LOGON_HOURS) {
		char oldstr[44]; /* hours strings are 42 bytes. */
		char newstr[44];
		DEBUG(15,("%s SAMR_FIELD_LOGON_HOURS (units_per_week): %08X -> %08X\n", l,
			pdb_get_logon_divs(to), from->logon_hours.units_per_week));
		if (from->logon_hours.units_per_week != pdb_get_logon_divs(to)) {
			pdb_set_logon_divs(to,
				from->logon_hours.units_per_week, PDB_CHANGED);
		}

		DEBUG(15,("%s SAMR_FIELD_LOGON_HOURS (units_per_week/8): %08X -> %08X\n", l,
			pdb_get_hours_len(to),
			from->logon_hours.units_per_week/8));
		if (from->logon_hours.units_per_week/8 != pdb_get_hours_len(to)) {
			pdb_set_hours_len(to,
				from->logon_hours.units_per_week/8, PDB_CHANGED);
		}

		DEBUG(15,("%s SAMR_FIELD_LOGON_HOURS (bits): %s -> %s\n", l,
			pdb_get_hours(to), from->logon_hours.bits));
		pdb_sethexhours(oldstr, pdb_get_hours(to));
		pdb_sethexhours(newstr, from->logon_hours.bits);
		if (!strequal(oldstr, newstr)) {
			pdb_set_hours(to, from->logon_hours.bits,
				      from->logon_hours.units_per_week/8,
				      PDB_CHANGED);
		}
	}

	if (from->fields_present & SAMR_FIELD_BAD_PWD_COUNT) {
		DEBUG(10,("%s SAMR_FIELD_BAD_PWD_COUNT: %08X -> %08X\n", l,
			pdb_get_bad_password_count(to), from->bad_password_count));
		if (from->bad_password_count != pdb_get_bad_password_count(to)) {
			pdb_set_bad_password_count(to,
				from->bad_password_count, PDB_CHANGED);
		}
	}

	if (from->fields_present & SAMR_FIELD_NUM_LOGONS) {
		DEBUG(10,("%s SAMR_FIELD_NUM_LOGONS: %08X -> %08X\n", l,
			pdb_get_logon_count(to), from->logon_count));
		if (from->logon_count != pdb_get_logon_count(to)) {
			pdb_set_logon_count(to, from->logon_count, PDB_CHANGED);
		}
	}

	/* If the must change flag is set, the last set time goes to zero.
	   the must change and can change fields also do, but they are
	   calculated from policy, not set from the wire */

	if (from->fields_present & SAMR_FIELD_EXPIRED_FLAG) {
		DEBUG(10,("%s SAMR_FIELD_EXPIRED_FLAG: %02X\n", l,
			from->password_expired));
		if (from->password_expired != 0) {
			/* Only allow the set_time to zero (which means
			   "User Must Change Password on Next Login"
			   if the user object allows password change. */
			if (pdb_get_pass_can_change(to)) {
				pdb_set_pass_last_set_time(to, 0, PDB_CHANGED);
			} else {
				DEBUG(10,("%s Disallowing set of 'User Must "
					"Change Password on Next Login' as "
					"user object disallows this.\n", l));
			}
		} else {
			/* A subtlety here: some windows commands will
			   clear the expired flag even though it's not
			   set, and we don't want to reset the time
			   in these caess.  "net user /dom <user> /active:y"
			   for example, to clear an autolocked acct.
			   We must check to see if it's expired first. jmcd */

			uint32_t pwd_max_age = 0;
			time_t now = time(NULL);

			pdb_get_account_policy(PDB_POLICY_MAX_PASSWORD_AGE, &pwd_max_age);

			if (pwd_max_age == (uint32_t)-1 || pwd_max_age == 0) {
				pwd_max_age = get_time_t_max();
			}

			stored_time = pdb_get_pass_last_set_time(to);

			/* we will only *set* a pwdlastset date when
			   a) the last pwdlastset time was 0 (user was forced to
			      change password).
			   b) the users password has not expired. gd. */

			if ((stored_time == 0) ||
			    ((now - stored_time) > pwd_max_age)) {
				pdb_set_pass_last_set_time(to, now, PDB_CHANGED);
			}
		}
	}

	if (from->fields_present & SAMR_FIELD_COUNTRY_CODE) {
		DEBUG(10,("%s SAMR_FIELD_COUNTRY_CODE: %08X -> %08X\n", l,
			pdb_get_country_code(to), from->country_code));
		if (from->country_code != pdb_get_country_code(to)) {
			pdb_set_country_code(to,
				from->country_code, PDB_CHANGED);
		}
	}

	if (from->fields_present & SAMR_FIELD_CODE_PAGE) {
		DEBUG(10,("%s SAMR_FIELD_CODE_PAGE: %08X -> %08X\n", l,
			pdb_get_code_page(to), from->code_page));
		if (from->code_page != pdb_get_code_page(to)) {
			pdb_set_code_page(to,
				from->code_page, PDB_CHANGED);
		}
	}
}
Ejemplo n.º 19
0
WERROR dsdb_convert_object_ex(struct ldb_context *ldb,
			      const struct dsdb_schema *schema,
			      const struct dsdb_schema_prefixmap *pfm_remote,
			      const struct drsuapi_DsReplicaObjectListItemEx *in,
			      const DATA_BLOB *gensec_skey,
			      const uint32_t *ignore_attids,
			      uint32_t dsdb_repl_flags,
			      TALLOC_CTX *mem_ctx,
			      struct dsdb_extended_replicated_object *out)
{
	NTSTATUS nt_status;
	WERROR status = WERR_OK;
	uint32_t i;
	struct ldb_message *msg;
	struct replPropertyMetaDataBlob *md;
	int instanceType;
	struct ldb_message_element *instanceType_e = NULL;
	struct ldb_val guid_value;
	struct ldb_val parent_guid_value;
	NTTIME whenChanged = 0;
	time_t whenChanged_t;
	const char *whenChanged_s;
	struct drsuapi_DsReplicaAttribute *name_a = NULL;
	struct drsuapi_DsReplicaMetaData *name_d = NULL;
	struct replPropertyMetaData1 *rdn_m = NULL;
	struct dom_sid *sid = NULL;
	uint32_t rid = 0;
	uint32_t attr_count;
	int ret;

	if (!in->object.identifier) {
		return WERR_FOOBAR;
	}

	if (!in->object.identifier->dn || !in->object.identifier->dn[0]) {
		return WERR_FOOBAR;
	}

	if (in->object.attribute_ctr.num_attributes != 0 && !in->meta_data_ctr) {
		return WERR_FOOBAR;
	}

	if (in->object.attribute_ctr.num_attributes != in->meta_data_ctr->count) {
		return WERR_FOOBAR;
	}

	sid = &in->object.identifier->sid;
	if (sid->num_auths > 0) {
		rid = sid->sub_auths[sid->num_auths - 1];
	}

	msg = ldb_msg_new(mem_ctx);
	W_ERROR_HAVE_NO_MEMORY(msg);

	msg->dn			= ldb_dn_new(msg, ldb, in->object.identifier->dn);
	W_ERROR_HAVE_NO_MEMORY(msg->dn);

	msg->num_elements	= in->object.attribute_ctr.num_attributes;
	msg->elements		= talloc_array(msg, struct ldb_message_element,
					       msg->num_elements + 1); /* +1 because of the RDN attribute */
	W_ERROR_HAVE_NO_MEMORY(msg->elements);

	md = talloc(mem_ctx, struct replPropertyMetaDataBlob);
	W_ERROR_HAVE_NO_MEMORY(md);

	md->version		= 1;
	md->reserved		= 0;
	md->ctr.ctr1.count	= in->meta_data_ctr->count;
	md->ctr.ctr1.reserved	= 0;
	md->ctr.ctr1.array	= talloc_array(mem_ctx,
					       struct replPropertyMetaData1,
					       md->ctr.ctr1.count + 1); /* +1 because of the RDN attribute */
	W_ERROR_HAVE_NO_MEMORY(md->ctr.ctr1.array);

	for (i=0, attr_count=0; i < in->meta_data_ctr->count; i++, attr_count++) {
		struct drsuapi_DsReplicaAttribute *a;
		struct drsuapi_DsReplicaMetaData *d;
		struct replPropertyMetaData1 *m;
		struct ldb_message_element *e;
		uint32_t j;

		a = &in->object.attribute_ctr.attributes[i];
		d = &in->meta_data_ctr->meta_data[i];
		m = &md->ctr.ctr1.array[attr_count];
		e = &msg->elements[attr_count];

		if (dsdb_attid_in_list(ignore_attids, a->attid)) {
			attr_count--;
			continue;
		}

		if (GUID_all_zero(&d->originating_invocation_id)) {
			status = WERR_DS_SRC_GUID_MISMATCH;
			DEBUG(0, ("Refusing replication of object containing invalid zero invocationID on attribute %d of %s: %s\n",
				  a->attid,
				  ldb_dn_get_linearized(msg->dn),
				  win_errstr(status)));
			return status;
		}

		if (a->attid == DRSUAPI_ATTID_instanceType) {
			if (instanceType_e != NULL) {
				return WERR_FOOBAR;
			}
			instanceType_e = e;
		}

		for (j=0; j<a->value_ctr.num_values; j++) {
			status = drsuapi_decrypt_attribute(a->value_ctr.values[j].blob,
							   gensec_skey, rid,
							   dsdb_repl_flags, a);
			if (!W_ERROR_IS_OK(status)) {
				break;
			}
		}
		if (W_ERROR_EQUAL(status, WERR_TOO_MANY_SECRETS)) {
			WERROR get_name_status = dsdb_attribute_drsuapi_to_ldb(ldb, schema, pfm_remote,
									       a, msg->elements, e);
			if (W_ERROR_IS_OK(get_name_status)) {
				DEBUG(0, ("Unxpectedly got secret value %s on %s from DRS server\n",
					  e->name, ldb_dn_get_linearized(msg->dn)));
			} else {
				DEBUG(0, ("Unxpectedly got secret value on %s from DRS server",
					  ldb_dn_get_linearized(msg->dn)));
			}
		} else if (!W_ERROR_IS_OK(status)) {
			return status;
		}

		status = dsdb_attribute_drsuapi_to_ldb(ldb, schema, pfm_remote,
						       a, msg->elements, e);
		W_ERROR_NOT_OK_RETURN(status);

		m->attid			= a->attid;
		m->version			= d->version;
		m->originating_change_time	= d->originating_change_time;
		m->originating_invocation_id	= d->originating_invocation_id;
		m->originating_usn		= d->originating_usn;
		m->local_usn			= 0;

		if (d->originating_change_time > whenChanged) {
			whenChanged = d->originating_change_time;
		}

		if (a->attid == DRSUAPI_ATTID_name) {
			name_a = a;
			name_d = d;
		}
	}

	msg->num_elements = attr_count;
	md->ctr.ctr1.count = attr_count;
	if (name_a) {
		rdn_m = &md->ctr.ctr1.array[md->ctr.ctr1.count];
	}

	if (rdn_m) {
		struct ldb_message_element *el;
		const char *rdn_name = NULL;
		const struct ldb_val *rdn_value = NULL;
		const struct dsdb_attribute *rdn_attr = NULL;
		uint32_t rdn_attid;

		/*
		 * We only need the schema calls for the RDN in this
		 * codepath, and by doing this we avoid needing to
		 * have the dsdb_attribute_by_lDAPDisplayName accessor
		 * working during the schema load.
		 */
		rdn_name	= ldb_dn_get_rdn_name(msg->dn);
		rdn_attr	= dsdb_attribute_by_lDAPDisplayName(schema, rdn_name);
		if (!rdn_attr) {
			return WERR_FOOBAR;
		}
		rdn_attid	= rdn_attr->attributeID_id;
		rdn_value	= ldb_dn_get_rdn_val(msg->dn);

		el = ldb_msg_find_element(msg, rdn_attr->lDAPDisplayName);
		if (!el) {
			ret = ldb_msg_add_value(msg, rdn_attr->lDAPDisplayName, rdn_value, NULL);
			if (ret != LDB_SUCCESS) {
				return WERR_FOOBAR;
			}
		} else {
			if (el->num_values != 1) {
				DEBUG(0,(__location__ ": Unexpected num_values=%u\n",
					 el->num_values));
				return WERR_FOOBAR;				
			}
			if (!ldb_val_equal_exact(&el->values[0], rdn_value)) {
				DEBUG(0,(__location__ ": RDN value changed? '%*.*s' '%*.*s'\n",
					 (int)el->values[0].length, (int)el->values[0].length, el->values[0].data,
					 (int)rdn_value->length, (int)rdn_value->length, rdn_value->data));
				return WERR_FOOBAR;				
			}
		}

		rdn_m->attid				= rdn_attid;
		rdn_m->version				= name_d->version;
		rdn_m->originating_change_time		= name_d->originating_change_time;
		rdn_m->originating_invocation_id	= name_d->originating_invocation_id;
		rdn_m->originating_usn			= name_d->originating_usn;
		rdn_m->local_usn			= 0;
		md->ctr.ctr1.count++;

	}

	if (instanceType_e == NULL) {
		return WERR_FOOBAR;
	}

	instanceType = ldb_msg_find_attr_as_int(msg, "instanceType", 0);
	if (dsdb_repl_flags & DSDB_REPL_FLAG_PARTIAL_REPLICA) {
		/* the instanceType type for partial_replica
		   replication is sent via DRS with TYPE_WRITE set, but
		   must be used on the client with TYPE_WRITE removed
		*/
		if (instanceType & INSTANCE_TYPE_WRITE) {
			/*
			 * Make sure we do not change the order
			 * of msg->elements!
			 *
			 * That's why we use
			 * instanceType_e->num_values = 0
			 * instead of
			 * ldb_msg_remove_attr(msg, "instanceType");
			 */
			struct ldb_message_element *e;

			e = ldb_msg_find_element(msg, "instanceType");
			if (e != instanceType_e) {
				DEBUG(0,("instanceType_e[%p] changed to e[%p]\n",
					 instanceType_e, e));
				return WERR_FOOBAR;
			}

			instanceType_e->num_values = 0;

			instanceType &= ~INSTANCE_TYPE_WRITE;
			if (ldb_msg_add_fmt(msg, "instanceType", "%d", instanceType) != LDB_SUCCESS) {
				return WERR_INTERNAL_ERROR;
			}
		}
	} else {
		if (!(instanceType & INSTANCE_TYPE_WRITE)) {
			DEBUG(0, ("Refusing to replicate %s from a read-only repilca into a read-write replica!\n",
				  ldb_dn_get_linearized(msg->dn)));
			return WERR_DS_DRA_SOURCE_IS_PARTIAL_REPLICA;
		}
	}

	whenChanged_t = nt_time_to_unix(whenChanged);
	whenChanged_s = ldb_timestring(msg, whenChanged_t);
	W_ERROR_HAVE_NO_MEMORY(whenChanged_s);

	nt_status = GUID_to_ndr_blob(&in->object.identifier->guid, msg, &guid_value);
	if (!NT_STATUS_IS_OK(nt_status)) {
		return ntstatus_to_werror(nt_status);
	}

	if (in->parent_object_guid) {
		nt_status = GUID_to_ndr_blob(in->parent_object_guid, msg, &parent_guid_value);
		if (!NT_STATUS_IS_OK(nt_status)) {
			return ntstatus_to_werror(nt_status);
		}
	} else {
		parent_guid_value = data_blob_null;
	}

	out->msg		= msg;
	out->guid_value		= guid_value;
	out->parent_guid_value	= parent_guid_value;
	out->when_changed	= whenChanged_s;
	out->meta_data		= md;
	return WERR_OK;
}
Ejemplo n.º 20
0
/*
 Send a negprot command.
*/
NTSTATUS smb_raw_negotiate_recv(struct smbcli_request *req)
{
	struct smbcli_transport *transport = req->transport;
	int protocol;

	if (!smbcli_request_receive(req) ||
	    smbcli_request_is_error(req)) {
		return smbcli_request_destroy(req);
	}

	SMBCLI_CHECK_MIN_WCT(req, 1);

	protocol = SVALS(req->in.vwv, VWV(0));

	if (protocol >= ARRAY_SIZE(prots) || protocol < 0) {
		req->status = NT_STATUS_UNSUCCESSFUL;
		return smbcli_request_destroy(req);
	}

	transport->negotiate.protocol = prots[protocol].prot;

	if (transport->negotiate.protocol >= PROTOCOL_NT1) {
		NTTIME ntt;

		/* NT protocol */
		SMBCLI_CHECK_WCT(req, 17);
		transport->negotiate.sec_mode = CVAL(req->in.vwv,VWV(1));
		transport->negotiate.max_mux  = SVAL(req->in.vwv,VWV(1)+1);
		transport->negotiate.max_xmit = IVAL(req->in.vwv,VWV(3)+1);
		transport->negotiate.sesskey  = IVAL(req->in.vwv,VWV(7)+1);
		transport->negotiate.capabilities = IVAL(req->in.vwv,VWV(9)+1);

		/* this time arrives in real GMT */
		ntt = smbcli_pull_nttime(req->in.vwv, VWV(11)+1);
		transport->negotiate.server_time = nt_time_to_unix(ntt);		
		transport->negotiate.server_zone = SVALS(req->in.vwv,VWV(15)+1) * 60;
		transport->negotiate.key_len = CVAL(req->in.vwv,VWV(16)+1);

		if (transport->negotiate.capabilities & CAP_EXTENDED_SECURITY) {
			if (req->in.data_size < 16) {
				goto failed;
			}
			transport->negotiate.server_guid = smbcli_req_pull_blob(&req->in.bufinfo, transport, req->in.data, 16);
			transport->negotiate.secblob = smbcli_req_pull_blob(&req->in.bufinfo, transport, req->in.data + 16, req->in.data_size - 16);
		} else {
			if (req->in.data_size < (transport->negotiate.key_len)) {
				goto failed;
			}
			transport->negotiate.secblob = smbcli_req_pull_blob(&req->in.bufinfo, transport, req->in.data, transport->negotiate.key_len);
			smbcli_req_pull_string(&req->in.bufinfo, transport, &transport->negotiate.server_domain,
					    req->in.data+transport->negotiate.key_len,
					    req->in.data_size-transport->negotiate.key_len, STR_UNICODE|STR_NOALIGN);
			/* here comes the server name */
		}

		if (transport->negotiate.capabilities & CAP_RAW_MODE) {
			transport->negotiate.readbraw_supported = true;
			transport->negotiate.writebraw_supported = true;
		}

		if (transport->negotiate.capabilities & CAP_LOCK_AND_READ)
			transport->negotiate.lockread_supported = true;
	} else if (transport->negotiate.protocol >= PROTOCOL_LANMAN1) {
		SMBCLI_CHECK_WCT(req, 13);
		transport->negotiate.sec_mode = SVAL(req->in.vwv,VWV(1));
		transport->negotiate.max_xmit = SVAL(req->in.vwv,VWV(2));
		transport->negotiate.sesskey =  IVAL(req->in.vwv,VWV(6));
		transport->negotiate.server_zone = SVALS(req->in.vwv,VWV(10)) * 60;
		
		/* this time is converted to GMT by raw_pull_dos_date */
		transport->negotiate.server_time = raw_pull_dos_date(transport,
								     req->in.vwv+VWV(8));
		if ((SVAL(req->in.vwv,VWV(5)) & 0x1)) {
			transport->negotiate.readbraw_supported = 1;
		}
		if ((SVAL(req->in.vwv,VWV(5)) & 0x2)) {
			transport->negotiate.writebraw_supported = 1;
		}
		transport->negotiate.secblob = smbcli_req_pull_blob(&req->in.bufinfo, transport, 
								 req->in.data, req->in.data_size);
	} else {
		/* the old core protocol */
		transport->negotiate.sec_mode = 0;
		transport->negotiate.server_time = time(NULL);
		transport->negotiate.max_xmit = transport->options.max_xmit;
		transport->negotiate.server_zone = get_time_zone(transport->negotiate.server_time);
	}

	/* a way to force ascii SMB */
	if (!transport->options.unicode) {
		transport->negotiate.capabilities &= ~CAP_UNICODE;
	}

	if (!transport->options.ntstatus_support) {
		transport->negotiate.capabilities &= ~CAP_STATUS32;
	}

	if (!transport->options.use_level2_oplocks) {
		transport->negotiate.capabilities &= ~CAP_LEVEL_II_OPLOCKS;
	}

failed:
	return smbcli_request_destroy(req);
}
Ejemplo n.º 21
0
void copy_id21_to_sam_passwd(const char *log_prefix,
			     struct samu *to,
			     struct samr_UserInfo21 *from)
{
	time_t unix_time, stored_time;
	const char *old_string, *new_string;
	const char *l;

	if (from == NULL || to == NULL) {
		return;
	}

	if (log_prefix) {
		l = log_prefix;
	} else {
		l = "INFO_21";
	}

	if (from->fields_present & SAMR_FIELD_LAST_LOGON) {
		unix_time = nt_time_to_unix(from->last_logon);
		stored_time = pdb_get_logon_time(to);
		DEBUG(10,("%s SAMR_FIELD_LAST_LOGON: %lu -> %lu\n", l,
			(long unsigned int)stored_time,
			(long unsigned int)unix_time));
		if (stored_time != unix_time) {
			pdb_set_logon_time(to, unix_time, PDB_CHANGED);
		}
	}

	if (from->fields_present & SAMR_FIELD_LAST_LOGOFF) {
		unix_time = nt_time_to_unix(from->last_logoff);
		stored_time = pdb_get_logoff_time(to);
		DEBUG(10,("%s SAMR_FIELD_LAST_LOGOFF: %lu -> %lu\n", l,
			(long unsigned int)stored_time,
			(long unsigned int)unix_time));
		if (stored_time != unix_time) {
			pdb_set_logoff_time(to, unix_time, PDB_CHANGED);
		}
	}

	if (from->fields_present & SAMR_FIELD_ACCT_EXPIRY) {
		unix_time = nt_time_to_unix(from->acct_expiry);
		stored_time = pdb_get_kickoff_time(to);
		DEBUG(10,("%s SAMR_FIELD_ACCT_EXPIRY: %lu -> %lu\n", l,
			(long unsigned int)stored_time,
			(long unsigned int)unix_time));
		if (stored_time != unix_time) {
			pdb_set_kickoff_time(to, unix_time , PDB_CHANGED);
		}
	}

	if (from->fields_present & SAMR_FIELD_LAST_PWD_CHANGE) {
		unix_time = nt_time_to_unix(from->last_password_change);
		stored_time = pdb_get_pass_last_set_time(to);
		DEBUG(10,("%s SAMR_FIELD_LAST_PWD_CHANGE: %lu -> %lu\n", l,
			(long unsigned int)stored_time,
			(long unsigned int)unix_time));
		if (stored_time != unix_time) {
			pdb_set_pass_last_set_time(to, unix_time, PDB_CHANGED);
		}
	}

	if ((from->fields_present & SAMR_FIELD_ACCOUNT_NAME) &&
	    (from->account_name.string)) {
		old_string = pdb_get_username(to);
		new_string = from->account_name.string;
		DEBUG(10,("%s SAMR_FIELD_ACCOUNT_NAME: %s -> %s\n", l,
			old_string, new_string));
		if (STRING_CHANGED) {
			pdb_set_username(to, new_string, PDB_CHANGED);
		}
	}

	if ((from->fields_present & SAMR_FIELD_FULL_NAME) &&
	    (from->full_name.string)) {
		old_string = pdb_get_fullname(to);
		new_string = from->full_name.string;
		DEBUG(10,("%s SAMR_FIELD_FULL_NAME: %s -> %s\n", l,
			old_string, new_string));
		if (STRING_CHANGED) {
			pdb_set_fullname(to, new_string, PDB_CHANGED);
		}
	}

	if ((from->fields_present & SAMR_FIELD_HOME_DIRECTORY) &&
	    (from->home_directory.string)) {
		old_string = pdb_get_homedir(to);
		new_string = from->home_directory.string;
		DEBUG(10,("%s SAMR_FIELD_HOME_DIRECTORY: %s -> %s\n", l,
			old_string, new_string));
		if (STRING_CHANGED) {
			pdb_set_homedir(to, new_string, PDB_CHANGED);
		}
	}

	if ((from->fields_present & SAMR_FIELD_HOME_DRIVE) &&
	    (from->home_drive.string)) {
		old_string = pdb_get_dir_drive(to);
		new_string = from->home_drive.string;
		DEBUG(10,("%s SAMR_FIELD_HOME_DRIVE: %s -> %s\n", l,
			old_string, new_string));
		if (STRING_CHANGED) {
			pdb_set_dir_drive(to, new_string, PDB_CHANGED);
		}
	}

	if ((from->fields_present & SAMR_FIELD_LOGON_SCRIPT) &&
	    (from->logon_script.string)) {
		old_string = pdb_get_logon_script(to);
		new_string = from->logon_script.string;
		DEBUG(10,("%s SAMR_FIELD_LOGON_SCRIPT: %s -> %s\n", l,
			old_string, new_string));
		if (STRING_CHANGED) {
			pdb_set_logon_script(to  , new_string, PDB_CHANGED);
		}
	}

	if ((from->fields_present & SAMR_FIELD_PROFILE_PATH) &&
	    (from->profile_path.string)) {
		old_string = pdb_get_profile_path(to);
		new_string = from->profile_path.string;
		DEBUG(10,("%s SAMR_FIELD_PROFILE_PATH: %s -> %s\n", l,
			old_string, new_string));
		if (STRING_CHANGED) {
			pdb_set_profile_path(to  , new_string, PDB_CHANGED);
		}
	}

	if ((from->fields_present & SAMR_FIELD_DESCRIPTION) &&
	    (from->description.string)) {
		old_string = pdb_get_acct_desc(to);
		new_string = from->description.string;
		DEBUG(10,("%s SAMR_FIELD_DESCRIPTION: %s -> %s\n", l,
			old_string, new_string));
		if (STRING_CHANGED) {
			pdb_set_acct_desc(to, new_string, PDB_CHANGED);
		}
	}

	if ((from->fields_present & SAMR_FIELD_WORKSTATIONS) &&
	    (from->workstations.string)) {
		old_string = pdb_get_workstations(to);
		new_string = from->workstations.string;
		DEBUG(10,("%s SAMR_FIELD_WORKSTATIONS: %s -> %s\n", l,
			old_string, new_string));
		if (STRING_CHANGED) {
			pdb_set_workstations(to  , new_string, PDB_CHANGED);
		}
	}

	if ((from->fields_present & SAMR_FIELD_COMMENT) &&
	    (from->comment.string)) {
		old_string = pdb_get_comment(to);
		new_string = from->comment.string;
		DEBUG(10,("%s SAMR_FIELD_COMMENT: %s -> %s\n", l,
			old_string, new_string));
		if (STRING_CHANGED) {
			pdb_set_comment(to, new_string, PDB_CHANGED);
		}
	}

	if ((from->fields_present & SAMR_FIELD_PARAMETERS) &&
	    (from->parameters.array)) {
		char *newstr;
		DATA_BLOB mung;
		old_string = pdb_get_munged_dial(to);

		mung = data_blob_const(from->parameters.array,
				       from->parameters.length);
		newstr = (mung.length == 0) ?
			NULL : base64_encode_data_blob(talloc_tos(), mung);
		DEBUG(10,("%s SAMR_FIELD_PARAMETERS: %s -> %s\n", l,
			old_string, newstr));
		if (STRING_CHANGED_NC(old_string,newstr)) {
			pdb_set_munged_dial(to, newstr, PDB_CHANGED);
		}

		TALLOC_FREE(newstr);
	}

	if (from->fields_present & SAMR_FIELD_RID) {
		if (from->rid == 0) {
			DEBUG(10,("%s: Asked to set User RID to 0 !? Skipping change!\n", l));
		} else if (from->rid != pdb_get_user_rid(to)) {
			DEBUG(10,("%s SAMR_FIELD_RID: %u -> %u NOT UPDATED!\n", l,
				pdb_get_user_rid(to), from->rid));
		}
	}

	if (from->fields_present & SAMR_FIELD_PRIMARY_GID) {
		if (from->primary_gid == 0) {
			DEBUG(10,("%s: Asked to set Group RID to 0 !? Skipping change!\n", l));
		} else if (from->primary_gid != pdb_get_group_rid(to)) {
			DEBUG(10,("%s SAMR_FIELD_PRIMARY_GID: %u -> %u\n", l,
				pdb_get_group_rid(to), from->primary_gid));
			pdb_set_group_sid_from_rid(to,
				from->primary_gid, PDB_CHANGED);
		}
	}

	if (from->fields_present & SAMR_FIELD_ACCT_FLAGS) {
		DEBUG(10,("%s SAMR_FIELD_ACCT_FLAGS: %08X -> %08X\n", l,
			pdb_get_acct_ctrl(to), from->acct_flags));
		if (from->acct_flags != pdb_get_acct_ctrl(to)) {

			/* You cannot autolock an unlocked account via
			 * setuserinfo calls, so make sure to remove the
			 * ACB_AUTOLOCK bit here - gd */

			if ((from->acct_flags & ACB_AUTOLOCK) &&
			    !(pdb_get_acct_ctrl(to) & ACB_AUTOLOCK)) {
				from->acct_flags &= ~ACB_AUTOLOCK;
			}

			if (!(from->acct_flags & ACB_AUTOLOCK) &&
			     (pdb_get_acct_ctrl(to) & ACB_AUTOLOCK)) {
				/* We're unlocking a previously locked user. Reset bad password counts.
				   Patch from Jianliang Lu. <*****@*****.**> */
				pdb_set_bad_password_count(to, 0, PDB_CHANGED);
				pdb_set_bad_password_time(to, 0, PDB_CHANGED);
			}
			pdb_set_acct_ctrl(to, from->acct_flags, PDB_CHANGED);
		}
	}

	if (from->fields_present & SAMR_FIELD_LOGON_HOURS) {
		char oldstr[44]; /* hours strings are 42 bytes. */
		char newstr[44];
		DEBUG(15,("%s SAMR_FIELD_LOGON_HOURS (units_per_week): %08X -> %08X\n", l,
			pdb_get_logon_divs(to), from->logon_hours.units_per_week));
		if (from->logon_hours.units_per_week != pdb_get_logon_divs(to)) {
			pdb_set_logon_divs(to,
				from->logon_hours.units_per_week, PDB_CHANGED);
		}

		DEBUG(15,("%s SAMR_FIELD_LOGON_HOURS (units_per_week/8): %08X -> %08X\n", l,
			pdb_get_hours_len(to),
			from->logon_hours.units_per_week/8));
		if (from->logon_hours.units_per_week/8 != pdb_get_hours_len(to)) {
			pdb_set_hours_len(to,
				from->logon_hours.units_per_week/8, PDB_CHANGED);
		}

		DEBUG(15,("%s SAMR_FIELD_LOGON_HOURS (bits): %s -> %s\n", l,
			pdb_get_hours(to), from->logon
Ejemplo n.º 22
0
/*
  approximately map a struct pvfs_filename to a generic fileinfo struct
*/
static NTSTATUS pvfs_map_fileinfo(struct pvfs_state *pvfs, 
				  struct ntvfs_request *req,
				  struct pvfs_filename *name, union smb_fileinfo *info, 
				  int fd)
{
	switch (info->generic.level) {
	case RAW_FILEINFO_GETATTR:
		info->getattr.out.attrib     = name->dos.attrib;
		info->getattr.out.size       = name->st.st_size;
		info->getattr.out.write_time = nt_time_to_unix(name->dos.write_time);
		return NT_STATUS_OK;

	case RAW_FILEINFO_GETATTRE:
	case RAW_FILEINFO_STANDARD:
		info->standard.out.create_time = nt_time_to_unix(name->dos.create_time);
		info->standard.out.access_time = nt_time_to_unix(name->dos.access_time);
		info->standard.out.write_time  = nt_time_to_unix(name->dos.write_time);
		info->standard.out.size        = name->st.st_size;
		info->standard.out.alloc_size  = name->dos.alloc_size;
		info->standard.out.attrib      = name->dos.attrib;
		return NT_STATUS_OK;

	case RAW_FILEINFO_EA_SIZE:
		info->ea_size.out.create_time = nt_time_to_unix(name->dos.create_time);
		info->ea_size.out.access_time = nt_time_to_unix(name->dos.access_time);
		info->ea_size.out.write_time  = nt_time_to_unix(name->dos.write_time);
		info->ea_size.out.size        = name->st.st_size;
		info->ea_size.out.alloc_size  = name->dos.alloc_size;
		info->ea_size.out.attrib      = name->dos.attrib;
		info->ea_size.out.ea_size     = name->dos.ea_size;
		return NT_STATUS_OK;

	case RAW_FILEINFO_EA_LIST:
		return pvfs_query_ea_list(pvfs, req, name, fd, 
					  info->ea_list.in.num_names,
					  info->ea_list.in.ea_names, 
					  &info->ea_list.out);

	case RAW_FILEINFO_ALL_EAS:
		return pvfs_query_all_eas(pvfs, req, name, fd, &info->all_eas.out);

	case RAW_FILEINFO_SMB2_ALL_EAS: {
		NTSTATUS status = pvfs_query_all_eas(pvfs, req, name, fd, &info->all_eas.out);
		if (NT_STATUS_IS_OK(status) &&
		    info->all_eas.out.num_eas == 0) {
			return NT_STATUS_NO_EAS_ON_FILE;
		}
		return status;
	}

	case RAW_FILEINFO_IS_NAME_VALID:
		return NT_STATUS_OK;

	case RAW_FILEINFO_BASIC_INFO:
	case RAW_FILEINFO_BASIC_INFORMATION:
		info->basic_info.out.create_time = name->dos.create_time;
		info->basic_info.out.access_time = name->dos.access_time;
		info->basic_info.out.write_time  = name->dos.write_time;
		info->basic_info.out.change_time = name->dos.change_time;
		info->basic_info.out.attrib      = name->dos.attrib;
		return NT_STATUS_OK;

	case RAW_FILEINFO_STANDARD_INFO:
	case RAW_FILEINFO_STANDARD_INFORMATION:
		info->standard_info.out.alloc_size     = name->dos.alloc_size;
		info->standard_info.out.size           = name->st.st_size;
		info->standard_info.out.nlink          = name->dos.nlink;
		info->standard_info.out.delete_pending = 0; /* only for qfileinfo */
		info->standard_info.out.directory   = 
			(name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY)? 1 : 0;
		return NT_STATUS_OK;

	case RAW_FILEINFO_EA_INFO:
	case RAW_FILEINFO_EA_INFORMATION:
		info->ea_info.out.ea_size = name->dos.ea_size;
		return NT_STATUS_OK;

	case RAW_FILEINFO_NAME_INFO:
	case RAW_FILEINFO_NAME_INFORMATION:
		if (req->ctx->protocol == PROTOCOL_SMB2) {
			/* strange that SMB2 doesn't have this */
			return NT_STATUS_NOT_SUPPORTED;
		}
		info->name_info.out.fname.s = name->original_name;
		return NT_STATUS_OK;

	case RAW_FILEINFO_ALL_INFO:
	case RAW_FILEINFO_ALL_INFORMATION:
		info->all_info.out.create_time    = name->dos.create_time;
		info->all_info.out.access_time    = name->dos.access_time;
		info->all_info.out.write_time     = name->dos.write_time;
		info->all_info.out.change_time    = name->dos.change_time;
		info->all_info.out.attrib         = name->dos.attrib;
		info->all_info.out.alloc_size     = name->dos.alloc_size;
		info->all_info.out.size           = name->st.st_size;
		info->all_info.out.nlink          = name->dos.nlink;
		info->all_info.out.delete_pending = 0; /* only set by qfileinfo */
		info->all_info.out.directory      = 
			(name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY)? 1 : 0;
		info->all_info.out.ea_size        = name->dos.ea_size;
		info->all_info.out.fname.s        = name->original_name;
		return NT_STATUS_OK;

	case RAW_FILEINFO_ALT_NAME_INFO:
	case RAW_FILEINFO_ALT_NAME_INFORMATION:
		info->name_info.out.fname.s = pvfs_short_name(pvfs, name, name);
		return NT_STATUS_OK;

	case RAW_FILEINFO_STREAM_INFO:
	case RAW_FILEINFO_STREAM_INFORMATION:
		return pvfs_stream_information(pvfs, req, name, fd, &info->stream_info.out);

	case RAW_FILEINFO_COMPRESSION_INFO:
	case RAW_FILEINFO_COMPRESSION_INFORMATION:
		info->compression_info.out.compressed_size = name->st.st_size;
		info->compression_info.out.format          = 0;
		info->compression_info.out.unit_shift      = 0;
		info->compression_info.out.chunk_shift     = 0;
		info->compression_info.out.cluster_shift   = 0;
		return NT_STATUS_OK;

	case RAW_FILEINFO_INTERNAL_INFORMATION:
		info->internal_information.out.file_id = name->dos.file_id;
		return NT_STATUS_OK;

	case RAW_FILEINFO_ACCESS_INFORMATION:
		info->access_information.out.access_flags = 0; /* only set by qfileinfo */
		return NT_STATUS_OK;

	case RAW_FILEINFO_POSITION_INFORMATION:
		info->position_information.out.position = 0; /* only set by qfileinfo */
		return NT_STATUS_OK;

	case RAW_FILEINFO_MODE_INFORMATION:
		info->mode_information.out.mode = 0; /* only set by qfileinfo */
		return NT_STATUS_OK;

	case RAW_FILEINFO_ALIGNMENT_INFORMATION:
		info->alignment_information.out.alignment_requirement = 0;
		return NT_STATUS_OK;

	case RAW_FILEINFO_NETWORK_OPEN_INFORMATION:
		info->network_open_information.out.create_time = name->dos.create_time;
		info->network_open_information.out.access_time = name->dos.access_time;
		info->network_open_information.out.write_time  = name->dos.write_time;
		info->network_open_information.out.change_time = name->dos.change_time;
		info->network_open_information.out.alloc_size  = name->dos.alloc_size;
		info->network_open_information.out.size        = name->st.st_size;
		info->network_open_information.out.attrib      = name->dos.attrib;
		return NT_STATUS_OK;

	case RAW_FILEINFO_ATTRIBUTE_TAG_INFORMATION:
		info->attribute_tag_information.out.attrib      = name->dos.attrib;
		info->attribute_tag_information.out.reparse_tag = 0;
		return NT_STATUS_OK;

	case RAW_FILEINFO_SEC_DESC:
		return pvfs_acl_query(pvfs, req, name, fd, info);

	case RAW_FILEINFO_SMB2_ALL_INFORMATION:
		info->all_info2.out.create_time    = name->dos.create_time;
		info->all_info2.out.access_time    = name->dos.access_time;
		info->all_info2.out.write_time     = name->dos.write_time;
		info->all_info2.out.change_time    = name->dos.change_time;
		info->all_info2.out.attrib         = name->dos.attrib;
		info->all_info2.out.unknown1       = 0;
		info->all_info2.out.alloc_size     = name->dos.alloc_size;
		info->all_info2.out.size           = name->st.st_size;
		info->all_info2.out.nlink          = name->dos.nlink;
		info->all_info2.out.delete_pending = 0; /* only set by qfileinfo */
		info->all_info2.out.directory      = 
			(name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY)? 1 : 0;
		info->all_info2.out.file_id        = name->dos.file_id;
		info->all_info2.out.ea_size        = name->dos.ea_size;
		info->all_info2.out.access_mask    = 0; /* only set by qfileinfo */
		info->all_info2.out.position       = 0; /* only set by qfileinfo */
		info->all_info2.out.mode           = 0; /* only set by qfileinfo */
		info->all_info2.out.alignment_requirement = 0;
		/* windows wants the full path on disk for this
		   result, but I really don't want to expose that on
		   the wire, so I'll give the path with a share
		   prefix, which is a good approximation */
		info->all_info2.out.fname.s = talloc_asprintf(req, "\\%s\\%s",
							      pvfs->share_name, 
							      name->original_name);
		NT_STATUS_HAVE_NO_MEMORY(info->all_info2.out.fname.s);
		return NT_STATUS_OK;

	case RAW_FILEINFO_GENERIC:
	case RAW_FILEINFO_UNIX_BASIC:
	case RAW_FILEINFO_UNIX_INFO2:
	case RAW_FILEINFO_UNIX_LINK:
		return NT_STATUS_INVALID_LEVEL;
	}

	return NT_STATUS_INVALID_LEVEL;
}
Ejemplo n.º 23
0
void copy_id21_to_sam_passwd(SAM_ACCOUNT *to, SAM_USER_INFO_21 *from)
{
	time_t unix_time, stored_time;
	const char *old_string, *new_string;
	DATA_BLOB mung;

	if (from == NULL || to == NULL) 
		return;

	if (from->fields_present & ACCT_LAST_LOGON) {
		unix_time=nt_time_to_unix(&from->logon_time);
		stored_time = pdb_get_logon_time(to);
		DEBUG(10,("INFO_21 LOGON_TIME: %lu -> %lu\n",(long unsigned int)stored_time, (long unsigned int)unix_time));
		if (stored_time != unix_time) 
			pdb_set_logon_time(to, unix_time, PDB_CHANGED);
	}

	if (from->fields_present & ACCT_LAST_LOGOFF) {
		unix_time=nt_time_to_unix(&from->logoff_time);
		stored_time = pdb_get_logoff_time(to);
		DEBUG(10,("INFO_21 LOGOFF_TIME: %lu -> %lu\n",(long unsigned int)stored_time, (long unsigned int)unix_time));
		if (stored_time != unix_time) 
			pdb_set_logoff_time(to, unix_time, PDB_CHANGED);
	}

	if (from->fields_present & ACCT_EXPIRY) {
		unix_time=nt_time_to_unix(&from->kickoff_time);
		stored_time = pdb_get_kickoff_time(to);
		DEBUG(10,("INFO_21 KICKOFF_TIME: %lu -> %lu\n",(long unsigned int)stored_time, (long unsigned int)unix_time));
		if (stored_time != unix_time) 
			pdb_set_kickoff_time(to, unix_time , PDB_CHANGED);
	}	

	if (from->fields_present & ACCT_ALLOW_PWD_CHANGE) {
		unix_time=nt_time_to_unix(&from->pass_can_change_time);
		stored_time = pdb_get_pass_can_change_time(to);
		DEBUG(10,("INFO_21 PASS_CAN_CH: %lu -> %lu\n",(long unsigned int)stored_time, (long unsigned int)unix_time));
		if (stored_time != unix_time) 
			pdb_set_pass_can_change_time(to, unix_time, PDB_CHANGED);
	}

	if (from->fields_present & ACCT_LAST_PWD_CHANGE) {
		unix_time=nt_time_to_unix(&from->pass_last_set_time);
		stored_time = pdb_get_pass_last_set_time(to);
		DEBUG(10,("INFO_21 PASS_LAST_SET: %lu -> %lu\n",(long unsigned int)stored_time, (long unsigned int)unix_time));
		if (stored_time != unix_time) 
			pdb_set_pass_last_set_time(to, unix_time, PDB_CHANGED);
	}

	if (from->fields_present & ACCT_FORCE_PWD_CHANGE) {
		unix_time=nt_time_to_unix(&from->pass_must_change_time);
		stored_time=pdb_get_pass_must_change_time(to);
		DEBUG(10,("INFO_21 PASS_MUST_CH: %lu -> %lu\n",(long unsigned int)stored_time, (long unsigned int)unix_time));
		if (stored_time != unix_time) 
			pdb_set_pass_must_change_time(to, unix_time, PDB_CHANGED);
	}

	if ((from->fields_present & ACCT_USERNAME) &&
	    (from->hdr_user_name.buffer)) {
		old_string = pdb_get_username(to);
		new_string = unistr2_static(&from->uni_user_name);
		DEBUG(10,("INFO_21 UNI_USER_NAME: %s -> %s\n", old_string, new_string));
		if (STRING_CHANGED)
		    pdb_set_username(to      , new_string, PDB_CHANGED);
	}

	if ((from->fields_present & ACCT_FULL_NAME) &&
	    (from->hdr_full_name.buffer)) {
		old_string = pdb_get_fullname(to);
		new_string = unistr2_static(&from->uni_full_name);
		DEBUG(10,("INFO_21 UNI_FULL_NAME: %s -> %s\n",old_string, new_string));
		if (STRING_CHANGED)
			pdb_set_fullname(to      , new_string, PDB_CHANGED);
	}
	
	if ((from->fields_present & ACCT_HOME_DIR) &&
	    (from->hdr_home_dir.buffer)) {
		old_string = pdb_get_homedir(to);
		new_string = unistr2_static(&from->uni_home_dir);
		DEBUG(10,("INFO_21 UNI_HOME_DIR: %s -> %s\n",old_string,new_string));
		if (STRING_CHANGED)
			pdb_set_homedir(to       , new_string, PDB_CHANGED);
	}

	if ((from->fields_present & ACCT_HOME_DRIVE) &&
	    (from->hdr_dir_drive.buffer)) {
		old_string = pdb_get_dir_drive(to);
		new_string = unistr2_static(&from->uni_dir_drive);
		DEBUG(10,("INFO_21 UNI_DIR_DRIVE: %s -> %s\n",old_string,new_string));
		if (STRING_CHANGED)
			pdb_set_dir_drive(to     , new_string, PDB_CHANGED);
	}

	if ((from->fields_present & ACCT_LOGON_SCRIPT) &&
	    (from->hdr_logon_script.buffer)) {
		old_string = pdb_get_logon_script(to);
		new_string = unistr2_static(&from->uni_logon_script);
		DEBUG(10,("INFO_21 UNI_LOGON_SCRIPT: %s -> %s\n",old_string,new_string));
		if (STRING_CHANGED)
			pdb_set_logon_script(to  , new_string, PDB_CHANGED);
	}

	if ((from->fields_present & ACCT_PROFILE) &&
	    (from->hdr_profile_path.buffer)) {
		old_string = pdb_get_profile_path(to);
		new_string = unistr2_static(&from->uni_profile_path);
		DEBUG(10,("INFO_21 UNI_PROFILE_PATH: %s -> %s\n",old_string, new_string));
		if (STRING_CHANGED)
			pdb_set_profile_path(to  , new_string, PDB_CHANGED);
	}
	
	if ((from->fields_present & ACCT_DESCRIPTION) &&
	    (from->hdr_acct_desc.buffer)) {
		old_string = pdb_get_acct_desc(to);
		new_string = unistr2_static(&from->uni_acct_desc);
		DEBUG(10,("INFO_21 UNI_ACCT_DESC: %s -> %s\n",old_string,new_string));
		if (STRING_CHANGED)
			pdb_set_acct_desc(to     , new_string, PDB_CHANGED);
	}
	
	if ((from->fields_present & ACCT_WORKSTATIONS) &&
	    (from->hdr_workstations.buffer)) {
		old_string = pdb_get_workstations(to);
		new_string = unistr2_static(&from->uni_workstations);
		DEBUG(10,("INFO_21 UNI_WORKSTATIONS: %s -> %s\n",old_string, new_string));
		if (STRING_CHANGED)
			pdb_set_workstations(to  , new_string, PDB_CHANGED);
	}

	/* is this right? */
	if ((from->fields_present & ACCT_ADMIN_DESC) &&
	    (from->hdr_unknown_str.buffer)) {
		old_string = pdb_get_unknown_str(to);
		new_string = unistr2_static(&from->uni_unknown_str);
		DEBUG(10,("INFO_21 UNI_UNKNOWN_STR: %s -> %s\n",old_string, new_string));
		if (STRING_CHANGED)
			pdb_set_unknown_str(to   , new_string, PDB_CHANGED);
	}
	
	if ((from->fields_present & ACCT_CALLBACK) &&
	    (from->hdr_munged_dial.buffer)) {
		char *newstr;
		old_string = pdb_get_munged_dial(to);
		mung.length = from->hdr_munged_dial.uni_str_len;
		mung.data = (uint8 *) from->uni_munged_dial.buffer;
		newstr = (mung.length == 0) ?
			NULL : base64_encode_data_blob(mung);
		DEBUG(10,("INFO_21 UNI_MUNGED_DIAL: %s -> %s\n",old_string, newstr));
		if (STRING_CHANGED_NC(old_string,newstr))
			pdb_set_munged_dial(to   , newstr, PDB_CHANGED);

		SAFE_FREE(newstr);
	}
	
	if (from->fields_present & ACCT_RID) {
		if (from->user_rid == 0) {
			DEBUG(10, ("INFO_21: Asked to set User RID to 0 !? Skipping change!\n"));
		} else if (from->user_rid != pdb_get_user_rid(to)) {
			DEBUG(10,("INFO_21 USER_RID: %u -> %u NOT UPDATED!\n",pdb_get_user_rid(to),from->user_rid));
		}
	}
	
	if (from->fields_present & ACCT_PRIMARY_GID) {
		if (from->group_rid == 0) {
			DEBUG(10, ("INFO_21: Asked to set Group RID to 0 !? Skipping change!\n"));
		} else if (from->group_rid != pdb_get_group_rid(to)) {
			DEBUG(10,("INFO_21 GROUP_RID: %u -> %u\n",pdb_get_group_rid(to),from->group_rid));
			pdb_set_group_sid_from_rid(to, from->group_rid, PDB_CHANGED);
		}
	}
	
	if (from->fields_present & ACCT_FLAGS) {
		DEBUG(10,("INFO_21 ACCT_CTRL: %08X -> %08X\n",pdb_get_acct_ctrl(to),from->acb_info));
		if (from->acb_info != pdb_get_acct_ctrl(to)) {
			if (!(from->acb_info & ACB_AUTOLOCK) && (pdb_get_acct_ctrl(to) & ACB_AUTOLOCK)) {
				/* We're unlocking a previously locked user. Reset bad password counts.
				   Patch from Jianliang Lu. <*****@*****.**> */
				pdb_set_bad_password_count(to, 0, PDB_CHANGED);
				pdb_set_bad_password_time(to, 0, PDB_CHANGED);
			}
			pdb_set_acct_ctrl(to, from->acb_info, PDB_CHANGED);
		}
	}

	if (from->fields_present & ACCT_LOGON_HOURS) {
		DEBUG(15,("INFO_21 LOGON_DIVS: %08X -> %08X\n",pdb_get_logon_divs(to),from->logon_divs));
		if (from->logon_divs != pdb_get_logon_divs(to)) {
			pdb_set_logon_divs(to, from->logon_divs, PDB_CHANGED);
		}

		DEBUG(15,("INFO_21 LOGON_HRS.LEN: %08X -> %08X\n",pdb_get_hours_len(to),from->logon_hrs.len));
		if (from->logon_hrs.len != pdb_get_hours_len(to)) {
			pdb_set_hours_len(to, from->logon_hrs.len, PDB_CHANGED);
		}

		DEBUG(15,("INFO_21 LOGON_HRS.HOURS: %s -> %s\n",pdb_get_hours(to),from->logon_hrs.hours));
		/* Fix me: only update if it changes --metze */
		pdb_set_hours(to, from->logon_hrs.hours, PDB_CHANGED);

		/* This is max logon hours */
		DEBUG(10,("INFO_21 UNKNOWN_6: %08X -> %08X\n",pdb_get_unknown_6(to),from->unknown_6));
		if (from->unknown_6 != pdb_get_unknown_6(to)) {
			pdb_set_unknown_6(to, from->unknown_6, PDB_CHANGED);
		}
	}

	if (from->fields_present & ACCT_BAD_PWD_COUNT) {
		DEBUG(10,("INFO_21 BAD_PASSWORD_COUNT: %08X -> %08X\n",pdb_get_bad_password_count(to),from->bad_password_count));
		if (from->bad_password_count != pdb_get_bad_password_count(to)) {
			pdb_set_bad_password_count(to, from->bad_password_count, PDB_CHANGED);
		}
	}

	if (from->fields_present & ACCT_NUM_LOGONS) {
		DEBUG(10,("INFO_21 LOGON_COUNT: %08X -> %08X\n",pdb_get_logon_count(to),from->logon_count));
		if (from->logon_count != pdb_get_logon_count(to)) {
			pdb_set_logon_count(to, from->logon_count, PDB_CHANGED);
		}
	}

	DEBUG(10,("INFO_21 PASS_MUST_CHANGE_AT_NEXT_LOGON: %02X\n",from->passmustchange));
	if (from->passmustchange==PASS_MUST_CHANGE_AT_NEXT_LOGON) {
		pdb_set_pass_must_change_time(to,0, PDB_CHANGED);		
	}

	DEBUG(10,("INFO_21 PADDING_2: %02X\n",from->padding2));

	DEBUG(10,("INFO_21 PADDING_4: %08X\n",from->padding4));
}