Example #1
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);
		}
	}
}
Example #2
0
static int set_user_info(const char *username, const char *fullname,
			 const char *homedir, const char *acct_desc,
			 const char *drive, const char *script,
			 const char *profile, const char *account_control,
			 const char *user_sid, const char *user_domain,
			 const bool badpw, const bool hours,
			 const char *kickoff_time)
{
	bool updated_autolock = False, updated_badpw = False;
	struct samu *sam_pwent;
	uint8_t hours_array[MAX_HOURS_LEN];
	uint32_t hours_len;
	uint32_t acb_flags;
	uint32_t not_settable;
	uint32_t new_flags;
	struct dom_sid u_sid;
	bool ret;

	sam_pwent = samu_new(NULL);
	if (!sam_pwent) {
		return 1;
	}

	ret = pdb_getsampwnam(sam_pwent, username);
	if (!ret) {
		fprintf (stderr, "Username not found!\n");
		TALLOC_FREE(sam_pwent);
		return -1;
	}

	if (hours) {
		hours_len = pdb_get_hours_len(sam_pwent);
		memset(hours_array, 0xff, hours_len);

		pdb_set_hours(sam_pwent, hours_array, hours_len, PDB_CHANGED);
	}

	if (!pdb_update_autolock_flag(sam_pwent, &updated_autolock)) {
		DEBUG(2,("pdb_update_autolock_flag failed.\n"));
	}

	if (!pdb_update_bad_password_count(sam_pwent, &updated_badpw)) {
		DEBUG(2,("pdb_update_bad_password_count failed.\n"));
	}

	if (fullname)
		pdb_set_fullname(sam_pwent, fullname, PDB_CHANGED);
	if (acct_desc)
		pdb_set_acct_desc(sam_pwent, acct_desc, PDB_CHANGED);
	if (homedir)
		pdb_set_homedir(sam_pwent, homedir, PDB_CHANGED);
	if (drive)
		pdb_set_dir_drive(sam_pwent,drive, PDB_CHANGED);
	if (script)
		pdb_set_logon_script(sam_pwent, script, PDB_CHANGED);
	if (profile)
		pdb_set_profile_path (sam_pwent, profile, PDB_CHANGED);
	if (user_domain)
		pdb_set_domain(sam_pwent, user_domain, PDB_CHANGED);

	if (account_control) {
		not_settable = ~(ACB_DISABLED | ACB_HOMDIRREQ |
				 ACB_PWNOTREQ | ACB_PWNOEXP | ACB_AUTOLOCK);

		new_flags = pdb_decode_acct_ctrl(account_control);

		if (new_flags & not_settable) {
			fprintf(stderr, "Can only set [NDHLX] flags\n");
			TALLOC_FREE(sam_pwent);
			return -1;
		}

		acb_flags = pdb_get_acct_ctrl(sam_pwent);

		pdb_set_acct_ctrl(sam_pwent,
				  (acb_flags & not_settable) | new_flags,
				  PDB_CHANGED);
	}
	if (user_sid) {
		if (get_sid_from_cli_string(&u_sid, user_sid)) {
			fprintf(stderr, "Failed to parse SID\n");
			return -1;
		}
		pdb_set_user_sid(sam_pwent, &u_sid, PDB_CHANGED);
	}

	if (badpw) {
		pdb_set_bad_password_count(sam_pwent, 0, PDB_CHANGED);
		pdb_set_bad_password_time(sam_pwent, 0, PDB_CHANGED);
	}

	if (kickoff_time) {
		char *endptr;
		time_t value = get_time_t_max();

		if (strcmp(kickoff_time, "never") != 0) {
			uint32_t num = strtoul(kickoff_time, &endptr, 10);

			if ((endptr == kickoff_time) || (endptr[0] != '\0')) {
				fprintf(stderr, "Failed to parse kickoff time\n");
				return -1;
			}

			value = convert_uint32_t_to_time_t(num);
		}

		pdb_set_kickoff_time(sam_pwent, value, PDB_CHANGED);
	}

	if (NT_STATUS_IS_OK(pdb_update_sam_account(sam_pwent))) {
		print_user_info(username, True, False);
	} else {
		fprintf (stderr, "Unable to modify entry!\n");
		TALLOC_FREE(sam_pwent);
		return -1;
	}
	TALLOC_FREE(sam_pwent);
	return 0;
}
Example #3
0
static NTSTATUS check_sam_security(const struct auth_context *auth_context,
				   void *my_private_data, 
				   TALLOC_CTX *mem_ctx,
				   const auth_usersupplied_info *user_info, 
				   auth_serversupplied_info **server_info)
{
	struct samu *sampass=NULL;
	BOOL ret;
	NTSTATUS nt_status;
	NTSTATUS update_login_attempts_status;
	DATA_BLOB user_sess_key = data_blob(NULL, 0);
	DATA_BLOB lm_sess_key = data_blob(NULL, 0);
	BOOL updated_autolock = False, updated_badpw = False;

	if (!user_info || !auth_context) {
		return NT_STATUS_UNSUCCESSFUL;
	}

	/* Can't use the talloc version here, because the returned struct gets
	   kept on the server_info */

	if ( !(sampass = samu_new( NULL )) ) {
		return NT_STATUS_NO_MEMORY;
	}

	/* get the account information */

	become_root();
	ret = pdb_getsampwnam(sampass, user_info->internal_username);
	unbecome_root();

	if (ret == False) {
		DEBUG(3,("check_sam_security: Couldn't find user '%s' in "
			 "passdb.\n", user_info->internal_username));
		TALLOC_FREE(sampass);
		return NT_STATUS_NO_SUCH_USER;
	}

	/* see if autolock flag needs to be updated */
	if (pdb_get_acct_ctrl(sampass) & ACB_NORMAL)
		pdb_update_autolock_flag(sampass, &updated_autolock);
	/* Quit if the account was locked out. */
	if (pdb_get_acct_ctrl(sampass) & ACB_AUTOLOCK) {
		DEBUG(3,("check_sam_security: Account for user %s was locked out.\n", pdb_get_username(sampass)));
		return NT_STATUS_ACCOUNT_LOCKED_OUT;
	}

	nt_status = sam_password_ok(auth_context, mem_ctx, sampass, 
				    user_info, &user_sess_key, &lm_sess_key);

	/* Notify passdb backend of login success/failure. If not NT_STATUS_OK the backend doesn't like the login */
	update_login_attempts_status = pdb_update_login_attempts(sampass, NT_STATUS_IS_OK(nt_status));
	if (!NT_STATUS_IS_OK(update_login_attempts_status))
		nt_status = update_login_attempts_status;

	if (!NT_STATUS_IS_OK(nt_status)) {
		if (NT_STATUS_EQUAL(nt_status,NT_STATUS_WRONG_PASSWORD) && 
		    pdb_get_acct_ctrl(sampass) &ACB_NORMAL) {  
			pdb_increment_bad_password_count(sampass);
			updated_badpw = True;
		} else {
			pdb_update_bad_password_count(sampass, 
						      &updated_badpw);
		}
		if (updated_autolock || updated_badpw){
			become_root();
			if(!NT_STATUS_IS_OK(pdb_update_sam_account(sampass)))
				DEBUG(1, ("Failed to modify entry.\n"));
			unbecome_root();
		}
		data_blob_free(&user_sess_key);
		data_blob_free(&lm_sess_key);
		TALLOC_FREE(sampass);
		return nt_status;
	}

	if ((pdb_get_acct_ctrl(sampass) & ACB_NORMAL) && 
	    (pdb_get_bad_password_count(sampass) > 0)){
		pdb_set_bad_password_count(sampass, 0, PDB_CHANGED);
		pdb_set_bad_password_time(sampass, 0, PDB_CHANGED);
		updated_badpw = True;
	}

	if (updated_autolock || updated_badpw){
		become_root();
		if(!NT_STATUS_IS_OK(pdb_update_sam_account(sampass)))
			DEBUG(1, ("Failed to modify entry.\n"));
		unbecome_root();
 	}

	nt_status = sam_account_ok(mem_ctx, sampass, user_info);

	if (!NT_STATUS_IS_OK(nt_status)) {
		TALLOC_FREE(sampass);
		data_blob_free(&user_sess_key);
		data_blob_free(&lm_sess_key);
		return nt_status;
	}

	become_root();
	nt_status = make_server_info_sam(server_info, sampass);
	unbecome_root();

	if (!NT_STATUS_IS_OK(nt_status)) {
		DEBUG(0,("check_sam_security: make_server_info_sam() failed with '%s'\n", nt_errstr(nt_status)));
		TALLOC_FREE(sampass);
		data_blob_free(&user_sess_key);
		data_blob_free(&lm_sess_key);
		return nt_status;
	}

	(*server_info)->user_session_key =
		data_blob_talloc(*server_info, user_sess_key.data,
				 user_sess_key.length);
	data_blob_free(&user_sess_key);

	(*server_info)->lm_session_key =
		data_blob_talloc(*server_info, lm_sess_key.data,
				 lm_sess_key.length);
	data_blob_free(&lm_sess_key);

	(*server_info)->was_mapped |= user_info->was_mapped;

	return nt_status;
}
Example #4
0
NTSTATUS check_sam_security(const DATA_BLOB *challenge,
			    TALLOC_CTX *mem_ctx,
			    const struct auth_usersupplied_info *user_info,
			    struct auth_serversupplied_info **server_info)
{
	struct samu *sampass=NULL;
	bool ret;
	NTSTATUS nt_status;
	NTSTATUS update_login_attempts_status;
	DATA_BLOB user_sess_key = data_blob_null;
	DATA_BLOB lm_sess_key = data_blob_null;
	bool updated_badpw = False;
	const char *username;
	const uint8_t *nt_pw;
	const uint8_t *lm_pw;
	uint32_t acct_ctrl;

	/* the returned struct gets kept on the server_info, by means
	   of a steal further down */

	sampass = samu_new(mem_ctx);
	if (sampass == NULL) {
		return NT_STATUS_NO_MEMORY;
	}

	/* get the account information */

	become_root();
	ret = pdb_getsampwnam(sampass, user_info->mapped.account_name);
	unbecome_root();

	if (ret == False) {
		DEBUG(3,("check_sam_security: Couldn't find user '%s' in "
			 "passdb.\n", user_info->mapped.account_name));
		TALLOC_FREE(sampass);
		return NT_STATUS_NO_SUCH_USER;
	}

	acct_ctrl = pdb_get_acct_ctrl(sampass);
	username = pdb_get_username(sampass);
	nt_pw = pdb_get_nt_passwd(sampass);
	lm_pw = pdb_get_lanman_passwd(sampass);

	/* Quit if the account was locked out. */
	if (acct_ctrl & ACB_AUTOLOCK) {
		DEBUG(3,("check_sam_security: Account for user %s was locked out.\n", username));
		TALLOC_FREE(sampass);
		return NT_STATUS_ACCOUNT_LOCKED_OUT;
	}

	nt_status = sam_password_ok(mem_ctx,
				    username, acct_ctrl,
				    challenge, lm_pw, nt_pw,
				    user_info, &user_sess_key, &lm_sess_key);

	/* Notify passdb backend of login success/failure. If not
	   NT_STATUS_OK the backend doesn't like the login */

	update_login_attempts_status = pdb_update_login_attempts(sampass, NT_STATUS_IS_OK(nt_status));

	if (!NT_STATUS_IS_OK(nt_status)) {
		bool increment_bad_pw_count = false;

		if (NT_STATUS_EQUAL(nt_status,NT_STATUS_WRONG_PASSWORD) &&
		    (acct_ctrl & ACB_NORMAL) &&
		    NT_STATUS_IS_OK(update_login_attempts_status))
		{
			increment_bad_pw_count =
				need_to_increment_bad_pw_count(
					challenge, sampass, user_info);
		}

		if (increment_bad_pw_count) {
			pdb_increment_bad_password_count(sampass);
			updated_badpw = True;
		} else {
			pdb_update_bad_password_count(sampass,
						      &updated_badpw);
		}
		if (updated_badpw){
			NTSTATUS status;

			become_root();
			status = pdb_update_sam_account(sampass);
			unbecome_root();

			if (!NT_STATUS_IS_OK(status)) {
				DEBUG(1, ("Failed to modify entry: %s\n",
					  nt_errstr(status)));
			}
		}
		goto done;
	}

	/*
	 * We must only reset the bad password count if the login was
	 * successful, including checking account policies
	 */
	nt_status = sam_account_ok(mem_ctx, sampass, user_info);
	if (!NT_STATUS_IS_OK(nt_status)) {
		goto done;
	}

	if ((acct_ctrl & ACB_NORMAL) &&
	    (pdb_get_bad_password_count(sampass) > 0)){
		NTSTATUS status;

		pdb_set_bad_password_count(sampass, 0, PDB_CHANGED);
		pdb_set_bad_password_time(sampass, 0, PDB_CHANGED);

		become_root();
		status = pdb_update_sam_account(sampass);
		unbecome_root();

		if (!NT_STATUS_IS_OK(status)) {
			DEBUG(1, ("Failed to modify entry: %s\n",
				  nt_errstr(status)));
		}
	}

	become_root();
	nt_status = make_server_info_sam(mem_ctx, sampass, server_info);
	unbecome_root();

	TALLOC_FREE(sampass);

	if (!NT_STATUS_IS_OK(nt_status)) {
		DEBUG(0,("check_sam_security: make_server_info_sam() failed with '%s'\n", nt_errstr(nt_status)));
		goto done;
	}

	(*server_info)->session_key =
		data_blob_talloc(*server_info, user_sess_key.data,
				 user_sess_key.length);
	data_blob_free(&user_sess_key);

	(*server_info)->lm_session_key =
		data_blob_talloc(*server_info, lm_sess_key.data,
				 lm_sess_key.length);
	data_blob_free(&lm_sess_key);

	(*server_info)->nss_token |= user_info->was_mapped;

done:
	TALLOC_FREE(sampass);
	data_blob_free(&user_sess_key);
	data_blob_free(&lm_sess_key);
	return nt_status;
}
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
Example #6
0
static int set_user_info (struct pdb_methods *in, const char *username, 
			  const char *fullname, const char *homedir, 
			  const char *acct_desc, 
			  const char *drive, const char *script, 
			  const char *profile, const char *account_control,
			  const char *user_sid, const char *user_domain,
			  const BOOL badpw, const BOOL hours)
{
	BOOL updated_autolock = False, updated_badpw = False;
	struct samu *sam_pwent=NULL;
	BOOL ret;
	
	if ( (sam_pwent = samu_new( NULL )) == NULL ) {
		return 1;
	}
	
	ret = NT_STATUS_IS_OK(in->getsampwnam (in, sam_pwent, username));
	if (ret==False) {
		fprintf (stderr, "Username not found!\n");
		TALLOC_FREE(sam_pwent);
		return -1;
	}

	if (hours) {
		uint8 hours_array[MAX_HOURS_LEN];
		uint32 hours_len;
		
		hours_len = pdb_get_hours_len(sam_pwent);
		memset(hours_array, 0xff, hours_len);
		
		pdb_set_hours(sam_pwent, hours_array, PDB_CHANGED);
	}

	if (!pdb_update_autolock_flag(sam_pwent, &updated_autolock)) {
		DEBUG(2,("pdb_update_autolock_flag failed.\n"));
	}

	if (!pdb_update_bad_password_count(sam_pwent, &updated_badpw)) {
		DEBUG(2,("pdb_update_bad_password_count failed.\n"));
	}

	if (fullname)
		pdb_set_fullname(sam_pwent, fullname, PDB_CHANGED);
	if (acct_desc)
		pdb_set_acct_desc(sam_pwent, acct_desc, PDB_CHANGED);
	if (homedir)
		pdb_set_homedir(sam_pwent, homedir, PDB_CHANGED);
	if (drive)
		pdb_set_dir_drive(sam_pwent,drive, PDB_CHANGED);
	if (script)
		pdb_set_logon_script(sam_pwent, script, PDB_CHANGED);
	if (profile)
		pdb_set_profile_path (sam_pwent, profile, PDB_CHANGED);
	if (user_domain)
		pdb_set_domain(sam_pwent, user_domain, PDB_CHANGED);

	if (account_control) {
		uint32 not_settable = ~(ACB_DISABLED|ACB_HOMDIRREQ|ACB_PWNOTREQ|
					ACB_PWNOEXP|ACB_AUTOLOCK);

		uint32 newflag = pdb_decode_acct_ctrl(account_control);

		if (newflag & not_settable) {
			fprintf(stderr, "Can only set [NDHLX] flags\n");
			TALLOC_FREE(sam_pwent);
			return -1;
		}

		pdb_set_acct_ctrl(sam_pwent,
				  (pdb_get_acct_ctrl(sam_pwent) & not_settable) | newflag,
				  PDB_CHANGED);
	}
	if (user_sid) {
		DOM_SID u_sid;
		if (!string_to_sid(&u_sid, user_sid)) {
			/* not a complete sid, may be a RID, try building a SID */
			int u_rid;
			
			if (sscanf(user_sid, "%d", &u_rid) != 1) {
				fprintf(stderr, "Error passed string is not a complete user SID or RID!\n");
				return -1;
			}
			sid_copy(&u_sid, get_global_sam_sid());
			sid_append_rid(&u_sid, u_rid);
		}
		pdb_set_user_sid (sam_pwent, &u_sid, PDB_CHANGED);
	}

	if (badpw) {
		pdb_set_bad_password_count(sam_pwent, 0, PDB_CHANGED);
		pdb_set_bad_password_time(sam_pwent, 0, PDB_CHANGED);
	}

	if (NT_STATUS_IS_OK(in->update_sam_account (in, sam_pwent)))
		print_user_info (in, username, True, False);
	else {
		fprintf (stderr, "Unable to modify entry!\n");
		TALLOC_FREE(sam_pwent);
		return -1;
	}
	TALLOC_FREE(sam_pwent);
	return 0;
}
Example #7
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));
}