Пример #1
0
static NTSTATUS password_policy(struct winbindd_domain *domain,
				TALLOC_CTX *mem_ctx,
				SAM_UNK_INFO_1 *policy)
{
	uint32 min_pass_len,pass_hist,password_properties;
	time_t u_expire, u_min_age;
	NTTIME nt_expire, nt_min_age;
	uint32 account_policy_temp;

	if ((policy = TALLOC_ZERO_P(mem_ctx, SAM_UNK_INFO_1)) == NULL) {
		return NT_STATUS_NO_MEMORY;
	}

	if (!pdb_get_account_policy(AP_MIN_PASSWORD_LEN, &account_policy_temp)) {
		return NT_STATUS_ACCESS_DENIED;
	}
	min_pass_len = account_policy_temp;

	if (!pdb_get_account_policy(AP_PASSWORD_HISTORY, &account_policy_temp)) {
		return NT_STATUS_ACCESS_DENIED;
	}
	pass_hist = account_policy_temp;

	if (!pdb_get_account_policy(AP_USER_MUST_LOGON_TO_CHG_PASS, &account_policy_temp)) {
		return NT_STATUS_ACCESS_DENIED;
	}
	password_properties = account_policy_temp;
	
	if (!pdb_get_account_policy(AP_MAX_PASSWORD_AGE, &account_policy_temp)) {
		return NT_STATUS_ACCESS_DENIED;
	}
	u_expire = account_policy_temp;

	if (!pdb_get_account_policy(AP_MIN_PASSWORD_AGE, &account_policy_temp)) {
		return NT_STATUS_ACCESS_DENIED;
	}
	u_min_age = account_policy_temp;

	unix_to_nt_time_abs(&nt_expire, u_expire);
	unix_to_nt_time_abs(&nt_min_age, u_min_age);

	init_unk_info1(policy, (uint16)min_pass_len, (uint16)pass_hist, 
	               password_properties, nt_expire, nt_min_age);

	return NT_STATUS_OK;
}
Пример #2
0
time_t pdb_get_pass_must_change_time(const struct samu *sampass)
{
	uint32 expire;

	if (sampass->pass_last_set_time == 0)
		return (time_t) 0;

	if (sampass->acct_ctrl & ACB_PWNOEXP)
		return get_time_t_max();

	if (!pdb_get_account_policy(PDB_POLICY_MAX_PASSWORD_AGE, &expire)
	    || expire == (uint32)-1 || expire == 0) 
		return get_time_t_max();

	return sampass->pass_last_set_time + expire;
}
Пример #3
0
time_t pdb_get_pass_can_change_time(const struct samu *sampass)
{
	uint32 allow;

	/* if the last set time is zero, it means the user cannot 
	   change their password, and this time must be zero.   jmcd 
	*/
	if (sampass->pass_last_set_time == 0)
		return (time_t) 0;

	/* if the time is max, and the field has been changed,
	   we're trying to update this real value from the sampass
	   to indicate that the user cannot change their password.  jmcd
	*/
	if (sampass->pass_can_change_time == get_time_t_max() &&
	    pdb_get_init_flags(sampass, PDB_CANCHANGETIME) == PDB_CHANGED)
		return sampass->pass_can_change_time;

	if (!pdb_get_account_policy(PDB_POLICY_MIN_PASSWORD_AGE, &allow))
		allow = 0;

	/* in normal cases, just calculate it from policy */
	return sampass->pass_last_set_time + allow;
}
Пример #4
0
int main(int argc, const char **argv)
{
	static int list_users = False;
	static int verbose = False;
	static int spstyle = False;
	static int machine = False;
	static int add_user = False;
	static int delete_user = False;
	static int modify_user = False;
	uint32_t   setparms, checkparms;
	int opt;
	static char *full_name = NULL;
	static char *acct_desc = NULL;
	static const char *user_name = NULL;
	static char *home_dir = NULL;
	static char *home_drive = NULL;
	static const char *backend = NULL;
	static char *backend_in = NULL;
	static char *backend_out = NULL;
	static int transfer_groups = False;
	static int transfer_account_policies = False;
	static int reset_account_policies = False;
	static int  force_initialised_password = False;
	static char *logon_script = NULL;
	static char *profile_path = NULL;
	static char *user_domain = NULL;
	static char *account_control = NULL;
	static char *account_policy = NULL;
	static char *user_sid = NULL;
	static char *machine_sid = NULL;
	static long int account_policy_value = 0;
	bool account_policy_value_set = False;
	static int badpw_reset = False;
	static int hours_reset = False;
	static char *pwd_time_format = NULL;
	static int pw_from_stdin = False;
	struct pdb_methods *bin, *bout;
	static char *kickoff_time = NULL;
	TALLOC_CTX *frame = talloc_stackframe();
	NTSTATUS status;
	poptContext pc;
	struct poptOption long_options[] = {
		POPT_AUTOHELP
		{"list",	'L', POPT_ARG_NONE, &list_users, 0, "list all users", NULL},
		{"verbose",	'v', POPT_ARG_NONE, &verbose, 0, "be verbose", NULL },
		{"smbpasswd-style",	'w',POPT_ARG_NONE, &spstyle, 0, "give output in smbpasswd style", NULL},
		{"user",	'u', POPT_ARG_STRING, &user_name, 0, "use username", "USER" },
		{"account-desc",	'N', POPT_ARG_STRING, &acct_desc, 0, "set account description", NULL},
		{"fullname",	'f', POPT_ARG_STRING, &full_name, 0, "set full name", NULL},
		{"homedir",	'h', POPT_ARG_STRING, &home_dir, 0, "set home directory", NULL},
		{"drive",	'D', POPT_ARG_STRING, &home_drive, 0, "set home drive", NULL},
		{"script",	'S', POPT_ARG_STRING, &logon_script, 0, "set logon script", NULL},
		{"profile",	'p', POPT_ARG_STRING, &profile_path, 0, "set profile path", NULL},
		{"domain",	'I', POPT_ARG_STRING, &user_domain, 0, "set a users' domain", NULL},
		{"user SID",	'U', POPT_ARG_STRING, &user_sid, 0, "set user SID or RID", NULL},
		{"machine SID",	'M', POPT_ARG_STRING, &machine_sid, 0, "set machine SID or RID", NULL},
		{"create",	'a', POPT_ARG_NONE, &add_user, 0, "create user", NULL},
		{"modify",	'r', POPT_ARG_NONE, &modify_user, 0, "modify user", NULL},
		{"machine",	'm', POPT_ARG_NONE, &machine, 0, "account is a machine account", NULL},
		{"delete",	'x', POPT_ARG_NONE, &delete_user, 0, "delete user", NULL},
		{"backend",	'b', POPT_ARG_STRING, &backend, 0, "use different passdb backend as default backend", NULL},
		{"import",	'i', POPT_ARG_STRING, &backend_in, 0, "import user accounts from this backend", NULL},
		{"export",	'e', POPT_ARG_STRING, &backend_out, 0, "export user accounts to this backend", NULL},
		{"group",	'g', POPT_ARG_NONE, &transfer_groups, 0, "use -i and -e for groups", NULL},
		{"policies",	'y', POPT_ARG_NONE, &transfer_account_policies, 0, "use -i and -e to move account policies between backends", NULL},
		{"policies-reset",	0, POPT_ARG_NONE, &reset_account_policies, 0, "restore default policies", NULL},
		{"account-policy",	'P', POPT_ARG_STRING, &account_policy, 0,"value of an account policy (like maximum password age)",NULL},
		{"value",       'C', POPT_ARG_LONG, &account_policy_value, 'C',"set the account policy to this value", NULL},
		{"account-control",	'c', POPT_ARG_STRING, &account_control, 0, "Values of account control", NULL},
		{"force-initialized-passwords", 0, POPT_ARG_NONE, &force_initialised_password, 0, "Force initialization of corrupt password strings in a passdb backend", NULL},
		{"bad-password-count-reset", 'z', POPT_ARG_NONE, &badpw_reset, 0, "reset bad password count", NULL},
		{"logon-hours-reset", 'Z', POPT_ARG_NONE, &hours_reset, 0, "reset logon hours", NULL},
		{"time-format", 0, POPT_ARG_STRING, &pwd_time_format, 0, "The time format for time parameters", NULL },
		{"password-from-stdin", 't', POPT_ARG_NONE, &pw_from_stdin, 0, "get password from standard in", NULL},
		{"kickoff-time", 'K', POPT_ARG_STRING, &kickoff_time, 0, "set the kickoff time", NULL},
		POPT_COMMON_SAMBA
		POPT_TABLEEND
	};

	bin = bout = NULL;

	smb_init_locale();

	setup_logging("pdbedit", DEBUG_STDOUT);

	pc = poptGetContext(NULL, argc, argv, long_options,
			    POPT_CONTEXT_KEEP_FIRST);

	while((opt = poptGetNextOpt(pc)) != -1) {
		switch (opt) {
		case 'C':
			account_policy_value_set = True;
			break;
		}
	}

	poptGetArg(pc); /* Drop argv[0], the program name */

	if (user_name == NULL)
		user_name = poptGetArg(pc);

	if (!lp_load_global(get_dyn_CONFIGFILE())) {
		fprintf(stderr, "Can't load %s - run testparm to debug it\n", get_dyn_CONFIGFILE());
		exit(1);
	}

	if (!init_names())
		exit(1);

	setparms =	(backend ? BIT_BACKEND : 0) +
			(verbose ? BIT_VERBOSE : 0) +
			(spstyle ? BIT_SPSTYLE : 0) +
			(full_name ? BIT_FULLNAME : 0) +
			(home_dir ? BIT_HOMEDIR : 0) +
			(home_drive ? BIT_HDIRDRIVE : 0) +
			(logon_script ? BIT_LOGSCRIPT : 0) +
			(profile_path ? BIT_PROFILE : 0) +
			(user_domain ? BIT_USERDOMAIN : 0) +
			(machine ? BIT_MACHINE : 0) +
			(user_name ? BIT_USER : 0) +
			(list_users ? BIT_LIST : 0) +
			(force_initialised_password ? BIT_FIX_INIT : 0) +
			(user_sid ? BIT_USERSIDS : 0) +
			(machine_sid ? BIT_USERSIDS : 0) +
			(modify_user ? BIT_MODIFY : 0) +
			(add_user ? BIT_CREATE : 0) +
			(delete_user ? BIT_DELETE : 0) +
			(account_control ? BIT_ACCTCTRL : 0) +
			(account_policy ? BIT_ACCPOLICY : 0) +
			(account_policy_value_set ? BIT_ACCPOLVAL : 0) +
			(backend_in ? BIT_IMPORT : 0) +
			(backend_out ? BIT_EXPORT : 0) +
			(badpw_reset ? BIT_BADPWRESET : 0) +
			(hours_reset ? BIT_LOGONHOURS : 0) +
			(kickoff_time ? BIT_KICKOFFTIME : 0) +
			(acct_desc ? BIT_DESCRIPTION : 0);

	if (setparms & BIT_BACKEND) {
		/* HACK: set the global passdb backend by overwriting globals.
		 * This way we can use regular pdb functions for default
		 * operations that do not involve passdb migrations */
		lp_set_cmdline("passdb backend", backend);
	} else {
		backend = lp_passdb_backend();
	}

	if (!initialize_password_db(False, NULL)) {
		fprintf(stderr, "Can't initialize passdb backend.\n");
		exit(1);
	}

	/* the lowest bit options are always accepted */
	checkparms = setparms & ~MASK_ALWAYS_GOOD;

	if (checkparms & BIT_FIX_INIT) {
		return fix_users_list();
	}

	/* account policy operations */
	if ((checkparms & BIT_ACCPOLICY) && !(checkparms & ~(BIT_ACCPOLICY + BIT_ACCPOLVAL))) {
		uint32_t value;
		enum pdb_policy_type field = account_policy_name_to_typenum(account_policy);
		if (field == 0) {
			const char **names;
			int count;
			int i;
			account_policy_names_list(talloc_tos(), &names, &count);
			fprintf(stderr, "No account policy by that name!\n");
			if (count !=0) {
				fprintf(stderr, "Account policy names are:\n");
				for (i = 0; i < count ; i++) {
                        		d_fprintf(stderr, "%s\n", names[i]);
				}
			}
			TALLOC_FREE(names);
			exit(1);
		}
		if (!pdb_get_account_policy(field, &value)) {
			fprintf(stderr, "valid account policy, but unable to fetch value!\n");
			if (!account_policy_value_set)
				exit(1);
		}
		printf("account policy \"%s\" description: %s\n", account_policy, account_policy_get_desc(field));
		if (account_policy_value_set) {
			printf("account policy \"%s\" value was: %u\n", account_policy, value);
			if (!pdb_set_account_policy(field, account_policy_value)) {
				fprintf(stderr, "valid account policy, but unable to set value!\n");
				exit(1);
			}
			printf("account policy \"%s\" value is now: %lu\n", account_policy, account_policy_value);
			exit(0);
		} else {
			printf("account policy \"%s\" value is: %u\n", account_policy, value);
			exit(0);
		}
	}

	if (reset_account_policies) {
		if (reinit_account_policies()) {
			exit(1);
		}

		exit(0);
	}

	/* import and export operations */

	if (((checkparms & BIT_IMPORT) ||
	     (checkparms & BIT_EXPORT)) &&
	    !(checkparms & ~(BIT_IMPORT +BIT_EXPORT +BIT_USER))) {

		if (backend_in) {
			status = make_pdb_method_name(&bin, backend_in);
		} else {
			status = make_pdb_method_name(&bin, backend);
		}

		if (!NT_STATUS_IS_OK(status)) {
			fprintf(stderr, "Unable to initialize %s.\n",
				backend_in ? backend_in : backend);
			return 1;
		}

		if (backend_out) {
			status = make_pdb_method_name(&bout, backend_out);
		} else {
			status = make_pdb_method_name(&bout, backend);
		}

		if (!NT_STATUS_IS_OK(status)) {
			fprintf(stderr, "Unable to initialize %s.\n",
				backend_out ? backend_out : backend);
			return 1;
		}

		if (transfer_account_policies) {

			if (!(checkparms & BIT_USER)) {
				return export_account_policies(bin, bout);
			}

		} else 	if (transfer_groups) {

			if (!(checkparms & BIT_USER)) {
				return export_groups(bin, bout);
			}

		} else {
			return export_database(bin, bout,
				(checkparms & BIT_USER) ? user_name : NULL);
		}
	}

	/* if BIT_USER is defined but nothing else then threat it as -l -u for compatibility */
	/* fake up BIT_LIST if only BIT_USER is defined */
	if ((checkparms & BIT_USER) && !(checkparms & ~BIT_USER)) {
		checkparms += BIT_LIST;
	}

	/* modify flag is optional to maintain backwards compatibility */
	/* fake up BIT_MODIFY if BIT_USER  and at least one of MASK_USER_GOOD is defined */
	if (!((checkparms & ~MASK_USER_GOOD) & ~BIT_USER) && (checkparms & MASK_USER_GOOD)) {
		checkparms += BIT_MODIFY;
	}

	/* list users operations */
	if (checkparms & BIT_LIST) {
		if (!(checkparms & ~BIT_LIST)) {
			return print_users_list(verbose, spstyle);
		}
		if (!(checkparms & ~(BIT_USER + BIT_LIST))) {
			return print_user_info(user_name, verbose, spstyle);
		}
	}

	/* mask out users options */
	checkparms &= ~MASK_USER_GOOD;

	/* if bad password count is reset, we must be modifying */
	if (checkparms & BIT_BADPWRESET) {
		checkparms |= BIT_MODIFY;
		checkparms &= ~BIT_BADPWRESET;
	}

	/* if logon hours is reset, must modify */
	if (checkparms & BIT_LOGONHOURS) {
		checkparms |= BIT_MODIFY;
		checkparms &= ~BIT_LOGONHOURS;
	}

	/* account operation */
	if ((checkparms & BIT_CREATE) || (checkparms & BIT_MODIFY) || (checkparms & BIT_DELETE)) {
		/* check use of -u option */
		if (!(checkparms & BIT_USER)) {
			fprintf (stderr, "Username not specified! (use -u option)\n");
			return -1;
		}

		/* account creation operations */
		if (!(checkparms & ~(BIT_CREATE + BIT_USER + BIT_MACHINE))) {
		       	if (checkparms & BIT_MACHINE) {
				return new_machine(user_name, machine_sid);
			} else {
				return new_user(user_name, full_name,
						home_dir, home_drive,
						logon_script, profile_path,
						user_sid, pw_from_stdin);
			}
		}

		/* account deletion operations */
		if (!(checkparms & ~(BIT_DELETE + BIT_USER + BIT_MACHINE))) {
		       	if (checkparms & BIT_MACHINE) {
				return delete_machine_entry(user_name);
			} else {
				return delete_user_entry(user_name);
			}
		}

		/* account modification operations */
		if (!(checkparms & ~(BIT_MODIFY + BIT_USER + BIT_MACHINE))) {
			if (checkparms & BIT_MACHINE) {
				return set_machine_info(user_name,
							account_control,
							machine_sid);
			} else {
				return set_user_info(user_name, full_name,
						     home_dir, acct_desc,
						     home_drive, logon_script,
						     profile_path, account_control,
						     user_sid, user_domain,
						     badpw_reset, hours_reset,
						     kickoff_time);
			}
		}
	}

	if (setparms >= 0x20) {
		fprintf (stderr, "Incompatible or insufficient options on command line!\n");
	}
	poptPrintHelp(pc, stderr, 0);

	TALLOC_FREE(frame);
	return 1;
}
Пример #5
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);
		}
	}
}
Пример #6
0
/**
 * Check whether the given password is one of the last two
 * password history entries. If so, the bad pwcount should
 * not be incremented even thought the actual password check
 * failed.
 */
static bool need_to_increment_bad_pw_count(
	const DATA_BLOB *challenge,
	struct samu* sampass,
	const struct auth_usersupplied_info *user_info)
{
	uint8_t i;
	const uint8_t *pwhistory;
	uint32_t pwhistory_len;
	uint32_t policy_pwhistory_len;
	uint32_t acct_ctrl;
	const char *username;
	TALLOC_CTX *mem_ctx = talloc_stackframe();
	bool result = true;

	pdb_get_account_policy(PDB_POLICY_PASSWORD_HISTORY,
			       &policy_pwhistory_len);
	if (policy_pwhistory_len == 0) {
		goto done;
	}

	pwhistory = pdb_get_pw_history(sampass, &pwhistory_len);
	if (!pwhistory || pwhistory_len == 0) {
		goto done;
	}

	acct_ctrl = pdb_get_acct_ctrl(sampass);
	username = pdb_get_username(sampass);

	for (i=1; i < MIN(MIN(3, policy_pwhistory_len), pwhistory_len); i++) {
		static const uint8_t zero16[SALTED_MD5_HASH_LEN];
		const uint8_t *salt;
		const uint8_t *nt_pw;
		NTSTATUS status;
		DATA_BLOB user_sess_key = data_blob_null;
		DATA_BLOB lm_sess_key = data_blob_null;

		salt = &pwhistory[i*PW_HISTORY_ENTRY_LEN];
		nt_pw = salt + PW_HISTORY_SALT_LEN;

		if (memcmp(zero16, nt_pw, NT_HASH_LEN) == 0) {
			/* skip zero password hash */
			continue;
		}

		if (memcmp(zero16, salt, PW_HISTORY_SALT_LEN) != 0) {
			/* skip nonzero salt (old format entry) */
			continue;
		}

		status = sam_password_ok(mem_ctx,
					 username, acct_ctrl,
					 challenge,
					 NULL, nt_pw,
					 user_info, &user_sess_key, &lm_sess_key);
		if (NT_STATUS_IS_OK(status)) {
			result = false;
			break;
		}
	}

done:
	TALLOC_FREE(mem_ctx);
	return result;
}
Пример #7
0
int main(int argc, char **argv)
{
	TALLOC_CTX *ctx;
	struct samu *out = NULL;
	struct samu *in = NULL;
	NTSTATUS rv;
	int i;
	struct timeval tv;
	BOOL error = False;
	struct passwd *pwd;
	uint8 *buf;
	uint32 expire, min_age, history;
	struct pdb_methods *pdb;
	poptContext pc;
	static const char *backend = NULL;
	static const char *unix_user = "******";
	struct poptOption long_options[] = {
		{"username", 'u', POPT_ARG_STRING, &unix_user, 0, "Unix user to use for testing", "USERNAME" },
		{"backend", 'b', POPT_ARG_STRING, &backend, 0, "Backend to use if not default", "BACKEND[:SETTINGS]" },
		POPT_AUTOHELP
		POPT_COMMON_SAMBA
		POPT_TABLEEND
	};

	load_case_tables();

	pc = poptGetContext("vfstest", argc, (const char **) argv,
			    long_options, 0);

	poptSetOtherOptionHelp(pc, "backend[:settings] username");
	
	while(poptGetNextOpt(pc) != -1);

	poptFreeContext(pc);

	/* Load configuration */
	lp_load(dyn_CONFIGFILE, False, False, True, True);
	setup_logging("pdbtest", True);

	if (backend == NULL) {
		backend = lp_passdb_backend();
	}

	rv = make_pdb_method_name(&pdb, backend);
	if (NT_STATUS_IS_ERR(rv)) {
		fprintf(stderr, "Error initializing '%s': %s\n", backend, get_friendly_nt_error_msg(rv));
		exit(1);
	}
	
	ctx = talloc_init("PDBTEST");
	
	if (!(out = samu_new(ctx))) {
		fprintf(stderr, "Can't create samu structure.\n");
		exit(1);
	}
	
	if ((pwd = getpwnam_alloc(ctx, unix_user)) == NULL) {
		fprintf(stderr, "Error getting user information for %s\n", unix_user);
		exit(1);
	}
	
	samu_set_unix(out, pwd);

	pdb_set_profile_path(out, "\\\\torture\\profile", PDB_SET);
	pdb_set_homedir(out, "\\\\torture\\home", PDB_SET);
	pdb_set_logon_script(out, "torture_script.cmd", PDB_SET);

	pdb_get_account_policy(AP_PASSWORD_HISTORY, &history);
	if (history * PW_HISTORY_ENTRY_LEN < NT_HASH_LEN) {
		buf = (uint8 *)TALLOC(ctx, NT_HASH_LEN);
	} else {
		buf = (uint8 *)TALLOC(ctx, history * PW_HISTORY_ENTRY_LEN);
	}

	/* Generate some random hashes */
	GetTimeOfDay(&tv);
	srand(tv.tv_usec);
	for (i = 0; i < NT_HASH_LEN; i++) {
		buf[i] = (uint8) rand();
	}
	pdb_set_nt_passwd(out, buf, PDB_SET);
	for (i = 0; i < LM_HASH_LEN; i++) {
		buf[i] = (uint8) rand();
	}
	pdb_set_lanman_passwd(out, buf, PDB_SET);
	for (i = 0; i < history * PW_HISTORY_ENTRY_LEN; i++) {
		buf[i] = (uint8) rand();
	}
	pdb_set_pw_history(out, buf, history, PDB_SET);

	pdb_get_account_policy(AP_MAX_PASSWORD_AGE, &expire);
	pdb_get_account_policy(AP_MIN_PASSWORD_AGE, &min_age);
	pdb_set_pass_last_set_time(out, time(NULL), PDB_SET);
	
	if (expire == 0 || expire == (uint32)-1) {
		pdb_set_pass_must_change_time(out, get_time_t_max(), PDB_SET);
	} else {
		pdb_set_pass_must_change_time(out, time(NULL)+expire, PDB_SET);
	}

	if (min_age == (uint32)-1) {
		pdb_set_pass_can_change_time(out, 0, PDB_SET);
	} else {
		pdb_set_pass_can_change_time(out, time(NULL)+min_age, PDB_SET);
	}
	
	/* Create account */
	if (!NT_STATUS_IS_OK(rv = pdb->add_sam_account(pdb, out))) {
		fprintf(stderr, "Error in add_sam_account: %s\n", 
				get_friendly_nt_error_msg(rv));
		exit(1);
	}

	if (!(in = samu_new(ctx))) {
		fprintf(stderr, "Can't create samu structure.\n");
		exit(1);
	}
	
	/* Get account information through getsampwnam() */
	if (NT_STATUS_IS_ERR(pdb->getsampwnam(pdb, in, out->username))) {
		fprintf(stderr, "Error getting sampw of added user %s.\n",
				out->username);
		if (!NT_STATUS_IS_OK(rv = pdb->delete_sam_account(pdb, out))) {
			fprintf(stderr, "Error in delete_sam_account %s\n", 
					get_friendly_nt_error_msg(rv));
		}
		TALLOC_FREE(ctx);
	}
	
	/* Verify integrity */
	if (samu_correct(out, in)) {
		printf("User info written correctly\n");
	} else {
		printf("User info NOT written correctly\n");
		error = True;
	}
	
	/* Delete account */
	if (!NT_STATUS_IS_OK(rv = pdb->delete_sam_account(pdb, out))) {
		fprintf(stderr, "Error in delete_sam_account %s\n", 
					get_friendly_nt_error_msg(rv));
	}

	pdb->setsampwent(pdb, False, 0);
	while (NT_STATUS_IS_OK(pdb->getsampwent(pdb, out))) {
		if (pdb_get_username(out) == NULL) {
			fprintf(stderr, "Got bad username through getsampwent()\n");
			error = True;
			break;
		}
		if (NT_STATUS_IS_ERR(pdb->getsampwnam(pdb, in, pdb_get_username(out)))) {
			fprintf(stderr, "Error getting samu through getsampwnam() of an account we got through getsampwent!\n");
			error = True;
			continue;
		}
		if (!samu_correct(out, in)) {
			printf("Record gotten through getsampwnam() differs from same record through getsampwent()\n");
		}
	}
	pdb->endsampwent(pdb);
	
	TALLOC_FREE(ctx);

	if (error) {
		return 1;
	}
	return 0;
}
Пример #8
0
bool pdb_set_plaintext_passwd(struct samu *sampass, const char *plaintext)
{
	uchar new_lanman_p16[LM_HASH_LEN];
	uchar new_nt_p16[NT_HASH_LEN];
	uchar *pwhistory;
	uint32 pwHistLen;
	uint32 current_history_len;

	if (!plaintext)
		return False;

	/* Calculate the MD4 hash (NT compatible) of the password */
	E_md4hash(plaintext, new_nt_p16);

	if (!pdb_set_nt_passwd (sampass, new_nt_p16, PDB_CHANGED)) 
		return False;

	if (!E_deshash(plaintext, new_lanman_p16)) {
		/* E_deshash returns false for 'long' passwords (> 14
		   DOS chars).  This allows us to match Win2k, which
		   does not store a LM hash for these passwords (which
		   would reduce the effective password length to 14 */

		if (!pdb_set_lanman_passwd (sampass, NULL, PDB_CHANGED)) 
			return False;
	} else {
		if (!pdb_set_lanman_passwd (sampass, new_lanman_p16, PDB_CHANGED)) 
			return False;
	}

	if (!pdb_set_plaintext_pw_only (sampass, plaintext, PDB_CHANGED)) 
		return False;

	if (!pdb_set_pass_last_set_time (sampass, time(NULL), PDB_CHANGED))
		return False;

	if ((pdb_get_acct_ctrl(sampass) & ACB_NORMAL) == 0) {
		/*
		 * No password history for non-user accounts
		 */
		return true;
	}

	pdb_get_account_policy(PDB_POLICY_PASSWORD_HISTORY, &pwHistLen);

	if (pwHistLen == 0) {
		/* Set the history length to zero. */
		pdb_set_pw_history(sampass, NULL, 0, PDB_CHANGED);
		return true;
	}

	/*
	 * We need to make sure we don't have a race condition here -
	 * the account policy history length can change between when
	 * the pw_history was first loaded into the struct samu struct
	 * and now.... JRA.
	 */
	pwhistory = (uchar *)pdb_get_pw_history(sampass, &current_history_len);

	if ((current_history_len != 0) && (pwhistory == NULL)) {
		DEBUG(1, ("pdb_set_plaintext_passwd: pwhistory == NULL!\n"));
		return false;
	}

	if (current_history_len < pwHistLen) {
		/*
		 * Ensure we have space for the needed history. This
		 * also takes care of an account which did not have
		 * any history at all so far, i.e. pwhistory==NULL
		 */
		uchar *new_history = talloc_zero_array(
			sampass, uchar,
			pwHistLen*PW_HISTORY_ENTRY_LEN);

		if (!new_history) {
			return False;
		}

		memcpy(new_history, pwhistory,
		       current_history_len*PW_HISTORY_ENTRY_LEN);

		pwhistory = new_history;
	}

	/*
	 * Make room for the new password in the history list.
	 */
	if (pwHistLen > 1) {
		memmove(&pwhistory[PW_HISTORY_ENTRY_LEN], pwhistory,
			(pwHistLen-1)*PW_HISTORY_ENTRY_LEN );
	}

	/*
	 * Fill the salt area with 0-s: this indicates that
	 * a plain nt hash is stored in the has area.
	 * The old format was to store a 16 byte salt and
	 * then an md5hash of the nt_hash concatenated with
	 * the salt.
	 */
	memset(pwhistory, 0, PW_HISTORY_SALT_LEN);

	/*
	 * Store the plain nt hash in the second 16 bytes.
	 * The old format was to store the md5 hash of
	 * the salt+newpw.
	 */
	memcpy(&pwhistory[PW_HISTORY_SALT_LEN], new_nt_p16, SALTED_MD5_HASH_LEN);

	pdb_set_pw_history(sampass, pwhistory, pwHistLen, PDB_CHANGED);

	return True;
}
Пример #9
0
bool pdb_set_plaintext_passwd(struct samu *sampass, const char *plaintext)
{
	uchar new_lanman_p16[LM_HASH_LEN];
	uchar new_nt_p16[NT_HASH_LEN];

	if (!plaintext)
		return False;

	/* Calculate the MD4 hash (NT compatible) of the password */
	E_md4hash(plaintext, new_nt_p16);

	if (!pdb_set_nt_passwd (sampass, new_nt_p16, PDB_CHANGED)) 
		return False;

	if (!E_deshash(plaintext, new_lanman_p16)) {
		/* E_deshash returns false for 'long' passwords (> 14
		   DOS chars).  This allows us to match Win2k, which
		   does not store a LM hash for these passwords (which
		   would reduce the effective password length to 14 */

		if (!pdb_set_lanman_passwd (sampass, NULL, PDB_CHANGED)) 
			return False;
	} else {
		if (!pdb_set_lanman_passwd (sampass, new_lanman_p16, PDB_CHANGED)) 
			return False;
	}

	if (!pdb_set_plaintext_pw_only (sampass, plaintext, PDB_CHANGED)) 
		return False;

	if (!pdb_set_pass_last_set_time (sampass, time(NULL), PDB_CHANGED))
		return False;

	/* Store the password history. */
	if (pdb_get_acct_ctrl(sampass) & ACB_NORMAL) {
		uchar *pwhistory;
		uint32 pwHistLen;
		pdb_get_account_policy(AP_PASSWORD_HISTORY, &pwHistLen);
		if (pwHistLen != 0){
			uint32 current_history_len;
			/* We need to make sure we don't have a race condition here - the
			   account policy history length can change between when the pw_history
			   was first loaded into the struct samu struct and now.... JRA. */
			pwhistory = (uchar *)pdb_get_pw_history(sampass, &current_history_len);

			if (current_history_len != pwHistLen) {
				/* After closing and reopening struct samu the history
					values will sync up. We can't do this here. */

				/* current_history_len > pwHistLen is not a problem - we
					have more history than we need. */

				if (current_history_len < pwHistLen) {
					/* Ensure we have space for the needed history. */
					uchar *new_history = (uchar *)TALLOC(sampass,
								pwHistLen*PW_HISTORY_ENTRY_LEN);
					if (!new_history) {
						return False;
					}

					/* And copy it into the new buffer. */
					if (current_history_len) {
						memcpy(new_history, pwhistory,
							current_history_len*PW_HISTORY_ENTRY_LEN);
					}
					/* Clearing out any extra space. */
					memset(&new_history[current_history_len*PW_HISTORY_ENTRY_LEN],
						'\0', (pwHistLen-current_history_len)*PW_HISTORY_ENTRY_LEN);
					/* Finally replace it. */
					pwhistory = new_history;
				}
			}
			if (pwhistory && pwHistLen){
				/* Make room for the new password in the history list. */
				if (pwHistLen > 1) {
					memmove(&pwhistory[PW_HISTORY_ENTRY_LEN],
						pwhistory, (pwHistLen -1)*PW_HISTORY_ENTRY_LEN );
				}
				/* Create the new salt as the first part of the history entry. */
				generate_random_buffer(pwhistory, PW_HISTORY_SALT_LEN);

				/* Generate the md5 hash of the salt+new password as the second
					part of the history entry. */

				E_md5hash(pwhistory, new_nt_p16, &pwhistory[PW_HISTORY_SALT_LEN]);
				pdb_set_pw_history(sampass, pwhistory, pwHistLen, PDB_CHANGED);
			} else {
				DEBUG (10,("pdb_get_set.c: pdb_set_plaintext_passwd: pwhistory was NULL!\n"));
			}
		} else {
			/* Set the history length to zero. */
			pdb_set_pw_history(sampass, NULL, 0, PDB_CHANGED);
		}
	}

	return True;
}