⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 password_hash.c

📁 samba最新软件
💻 C
📖 第 1 页 / 共 4 页
字号:
	pp->unknown1	= 2;	pp->data	= pb_hexstr;	/*	 * setup 'supplementalCredentials' value	 */	scb.sub.num_packages	= num_packages;	scb.sub.packages	= packages;	ndr_err = ndr_push_struct_blob(&io->g.supplemental, io->ac, 				       lp_iconv_convenience(ldb_get_opaque(io->ac->module->ldb, "loadparm")),				       &scb,				       (ndr_push_flags_fn_t)ndr_push_supplementalCredentialsBlob);	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {		NTSTATUS status = ndr_map_error2ntstatus(ndr_err);		ldb_asprintf_errstring(io->ac->module->ldb,				       "setup_supplemental_field: "				       "failed to push supplementalCredentialsBlob: %s",				       nt_errstr(status));		return LDB_ERR_OPERATIONS_ERROR;	}	return LDB_SUCCESS;}static int setup_last_set_field(struct setup_password_fields_io *io){	/* set it as now */	unix_to_nt_time(&io->g.last_set, time(NULL));	return LDB_SUCCESS;}static int setup_kvno_field(struct setup_password_fields_io *io){	/* increment by one */	io->g.kvno = io->o.kvno + 1;	return LDB_SUCCESS;}static int setup_password_fields(struct setup_password_fields_io *io){	bool ok;	int ret;	/*	 * refuse the change if someone want to change the cleartext	 * and supply his own hashes at the same time...	 */	if (io->n.cleartext && (io->n.nt_hash || io->n.lm_hash)) {		ldb_asprintf_errstring(io->ac->module->ldb,				       "setup_password_fields: "				       "it's only allowed to set the cleartext password or the password hashes");		return LDB_ERR_UNWILLING_TO_PERFORM;	}	if (io->n.cleartext && !io->n.nt_hash) {		struct samr_Password *hash;		hash = talloc(io->ac, struct samr_Password);		if (!hash) {			ldb_oom(io->ac->module->ldb);			return LDB_ERR_OPERATIONS_ERROR;		}		/* compute the new nt hash */		ok = E_md4hash(io->n.cleartext, hash->hash);		if (ok) {			io->n.nt_hash = hash;		} else {			ldb_asprintf_errstring(io->ac->module->ldb,					       "setup_password_fields: "					       "failed to generate nthash from cleartext password");			return LDB_ERR_OPERATIONS_ERROR;		}	}	if (io->n.cleartext && !io->n.lm_hash) {		struct samr_Password *hash;		hash = talloc(io->ac, struct samr_Password);		if (!hash) {			ldb_oom(io->ac->module->ldb);			return LDB_ERR_OPERATIONS_ERROR;		}		/* compute the new lm hash */		ok = E_deshash(io->n.cleartext, hash->hash);		if (ok) {			io->n.lm_hash = hash;		} else {			talloc_free(hash->hash);		}	}	ret = setup_nt_fields(io);	if (ret != 0) {		return ret;	}	ret = setup_lm_fields(io);	if (ret != 0) {		return ret;	}	ret = setup_supplemental_field(io);	if (ret != 0) {		return ret;	}	ret = setup_last_set_field(io);	if (ret != 0) {		return ret;	}	ret = setup_kvno_field(io);	if (ret != 0) {		return ret;	}	return LDB_SUCCESS;}static struct ldb_handle *ph_init_handle(struct ldb_request *req, struct ldb_module *module, enum ph_type type){	struct ph_context *ac;	struct ldb_handle *h;	h = talloc_zero(req, struct ldb_handle);	if (h == NULL) {		ldb_set_errstring(module->ldb, "Out of Memory");		return NULL;	}	h->module = module;	ac = talloc_zero(h, struct ph_context);	if (ac == NULL) {		ldb_set_errstring(module->ldb, "Out of Memory");		talloc_free(h);		return NULL;	}	h->private_data = (void *)ac;	h->state = LDB_ASYNC_INIT;	h->status = LDB_SUCCESS;	ac->type = type;	ac->module = module;	ac->orig_req = req;	return h;}static int get_domain_data_callback(struct ldb_context *ldb, void *context, struct ldb_reply *ares){	struct ph_context *ac;	ac = talloc_get_type(context, struct ph_context);	/* we are interested only in the single reply (base search) we receive here */	if (ares->type == LDB_REPLY_ENTRY) {		if (ac->dom_res != NULL) {			ldb_set_errstring(ldb, "Too many results");			talloc_free(ares);			return LDB_ERR_OPERATIONS_ERROR;		}		ac->dom_res = talloc_steal(ac, ares);	} else {		talloc_free(ares);	}	return LDB_SUCCESS;}static int build_domain_data_request(struct ph_context *ac){	/* attrs[] is returned from this function in	   ac->dom_req->op.search.attrs, so it must be static, as	   otherwise the compiler can put it on the stack */	static const char * const attrs[] = { "pwdProperties", "pwdHistoryLength", NULL };	char *filter;	ac->dom_req = talloc_zero(ac, struct ldb_request);	if (ac->dom_req == NULL) {		ldb_debug(ac->module->ldb, LDB_DEBUG_ERROR, "Out of Memory!\n");		return LDB_ERR_OPERATIONS_ERROR;	}	ac->dom_req->operation = LDB_SEARCH;	ac->dom_req->op.search.base = ldb_get_default_basedn(ac->module->ldb);	ac->dom_req->op.search.scope = LDB_SCOPE_SUBTREE;	filter = talloc_asprintf(ac->dom_req,				 "(&(objectSid=%s)(|(|(objectClass=domain)(objectClass=builtinDomain))(objectClass=samba4LocalDomain)))", 				 ldap_encode_ndr_dom_sid(ac->dom_req, ac->domain_sid));	if (filter == NULL) {		ldb_debug(ac->module->ldb, LDB_DEBUG_ERROR, "Out of Memory!\n");		talloc_free(ac->dom_req);		return LDB_ERR_OPERATIONS_ERROR;	}	ac->dom_req->op.search.tree = ldb_parse_tree(ac->dom_req, filter);	if (ac->dom_req->op.search.tree == NULL) {		ldb_set_errstring(ac->module->ldb, "Invalid search filter");		talloc_free(ac->dom_req);		return LDB_ERR_OPERATIONS_ERROR;	}	ac->dom_req->op.search.attrs = attrs;	ac->dom_req->controls = NULL;	ac->dom_req->context = ac;	ac->dom_req->callback = get_domain_data_callback;	ldb_set_timeout_from_prev_req(ac->module->ldb, ac->orig_req, ac->dom_req);	return LDB_SUCCESS;}static struct domain_data *get_domain_data(struct ldb_module *module, void *ctx, struct ldb_reply *res){	struct domain_data *data;	const char *tmp;	struct ph_context *ac;	char *p;	ac = talloc_get_type(ctx, struct ph_context);	data = talloc_zero(ac, struct domain_data);	if (data == NULL) {		return NULL;	}	if (res == NULL) {		ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Could not find this user's domain: %s!\n", dom_sid_string(data, ac->domain_sid));		talloc_free(data);		return NULL;	}	data->pwdProperties= samdb_result_uint(res->message, "pwdProperties", 0);	data->store_cleartext = data->pwdProperties & DOMAIN_PASSWORD_STORE_CLEARTEXT;	data->pwdHistoryLength = samdb_result_uint(res->message, "pwdHistoryLength", 0);	/* For a domain DN, this puts things in dotted notation */	/* For builtin domains, this will give details for the host,	 * but that doesn't really matter, as it's just used for salt	 * and kerberos principals, which don't exist here */	tmp = ldb_dn_canonical_string(ctx, res->message->dn);	if (!tmp) {		return NULL;	}		/* But it puts a trailing (or just before 'builtin') / on things, so kill that */	p = strchr(tmp, '/');	if (p) {		p[0] = '\0';	}	if (tmp != NULL) {		data->dns_domain = strlower_talloc(data, tmp);		if (data->dns_domain == NULL) {			ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Out of memory!\n");			return NULL;		}		data->realm = strupper_talloc(data, tmp);		if (data->realm == NULL) {			ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Out of memory!\n");			return NULL;		}		p = strchr(tmp, '.');		if (p) {			p[0] = '\0';		}		data->netbios_domain = strupper_talloc(data, tmp);		if (data->netbios_domain == NULL) {			ldb_debug(module->ldb, LDB_DEBUG_ERROR, "Out of memory!\n");			return NULL;		}	}	return data;}static int password_hash_add(struct ldb_module *module, struct ldb_request *req){	struct ldb_handle *h;	struct ph_context *ac;	struct ldb_message_element *sambaAttr;	struct ldb_message_element *ntAttr;	struct ldb_message_element *lmAttr;	int ret;	ldb_debug(module->ldb, LDB_DEBUG_TRACE, "password_hash_add\n");	if (ldb_dn_is_special(req->op.add.message->dn)) { /* do not manipulate our control entries */		return ldb_next_request(module, req);	}	/* If the caller is manipulating the local passwords directly, let them pass */	if (ldb_dn_compare_base(ldb_dn_new(req, module->ldb, LOCAL_BASE),				req->op.add.message->dn) == 0) {		return ldb_next_request(module, req);	}	/* nobody must touch this fields */	if (ldb_msg_find_element(req->op.add.message, "ntPwdHistory")) {		return LDB_ERR_UNWILLING_TO_PERFORM;	}	if (ldb_msg_find_element(req->op.add.message, "lmPwdHistory")) {		return LDB_ERR_UNWILLING_TO_PERFORM;	}	if (ldb_msg_find_element(req->op.add.message, "supplementalCredentials")) {		return LDB_ERR_UNWILLING_TO_PERFORM;	}	/* If no part of this ADD touches the sambaPassword, or the NT	 * or LM hashes, then we don't need to make any changes.  */	sambaAttr = ldb_msg_find_element(req->op.mod.message, "sambaPassword");	ntAttr = ldb_msg_find_element(req->op.mod.message, "unicodePwd");	lmAttr = ldb_msg_find_element(req->op.mod.message, "dBCSPwd");	if ((!sambaAttr) && (!ntAttr) && (!lmAttr)) {		return ldb_next_request(module, req);	}	/* if it is not an entry of type person its an error */	/* TODO: remove this when sambaPassword will be in schema */	if (!ldb_msg_check_string_attribute(req->op.add.message, "objectClass", "person")) {		ldb_set_errstring(module->ldb, "Cannot set a password on entry that does not have objectClass 'person'");		return LDB_ERR_OBJECT_CLASS_VIOLATION;	}	/* check sambaPassword is single valued here */	/* TODO: remove this when sambaPassword will be single valued in schema */	if (sambaAttr && sambaAttr->num_values > 1) {		ldb_set_errstring(module->ldb, "mupltiple values for sambaPassword not allowed!\n");		return LDB_ERR_CONSTRAINT_VIOLATION;	}	if (ntAttr && (ntAttr->num_values > 1)) {		ldb_set_errstring(module->ldb, "mupltiple values for unicodePwd not allowed!\n");		return LDB_ERR_CONSTRAINT_VIOLATION;	}	if (lmAttr && (lmAttr->num_values > 1)) {		ldb_set_errstring(module->ldb, "mupltiple values for dBCSPwd not allowed!\n");		return LDB_ERR_CONSTRAINT_VIOLATION;	}	if (sambaAttr && sambaAttr->num_values == 0) {		ldb_set_errstring(module->ldb, "sambaPassword must have a value!\n");		return LDB_ERR_CONSTRAINT_VIOLATION;	}	if (ntAttr && (ntAttr->num_values == 0)) {		ldb_set_errstring(module->ldb, "unicodePwd must have a value!\n");		return LDB_ERR_CONSTRAINT_VIOLATION;	}	if (lmAttr && (lmAttr->num_values == 0)) {		ldb_set_errstring(module->ldb, "dBCSPwd must have a value!\n");		return LDB_ERR_CONSTRAINT_VIOLATION;	}	h = ph_init_handle(req, module, PH_ADD);	if (!h) {		return LDB_ERR_OPERATIONS_ERROR;	}	ac = talloc_get_type(h->private_data, struct ph_context);	/* get user domain data */	ac->domain_sid = samdb_result_sid_prefix(ac, req->op.add.message, "objectSid");	if (ac->domain_sid == NULL) {		ldb_debug(module->ldb, LDB_DEBUG_ERROR, "can't handle entry with missing objectSid!\n");		return LDB_ERR_OPERATIONS_ERROR;	}	ret = build_domain_data_request(ac);	if (ret != LDB_SUCCESS) {		return ret;	}	ac->step = PH_ADD_SEARCH_DOM;	req->handle = h;	return ldb_next_request(module, ac->dom_req);}static int password_hash_add_do_add(struct ldb_handle *h) {	struct ph_context *ac;	struct domain_data *domain;	struct smb_krb5_context *smb_krb5_context;	struct ldb_message *msg;	struct setup_password_fields_io io;	int ret;	ac = talloc_get_type(h->private_data, struct ph_context);	domain = get_domain_data(ac->module, ac, ac->dom_res);	if (domain == NULL) {		return LDB_ERR_OPERATIONS_ERROR;	}	ac->down_req = talloc(ac, struct ldb_request);	if (ac->down_req == NULL) {		return LDB_ERR_OPERATIONS_ERROR;	}	*(ac->down_req) = *(ac->orig_req);	ac->down_req->op.add.message = msg = ldb_msg_copy_shallow(ac->down_req, ac->orig_req->op.add.message);	if (ac->down_req->op.add.message == NULL) {		return LDB_ERR_OPERATIONS_ERROR;	}	/* Some operations below require kerberos contexts */	if (smb_krb5_init_context(ac->down_req, 				  ldb_get_opaque(h->module->ldb, "EventContext"), 				  (struct loadparm_context *)ldb_get_opaque(h->module->ldb, "loadparm"), 				  &smb_krb5_context) != 0) {		return LDB_ERR_OPERATIONS_ERROR;	}	ZERO_STRUCT(io);	io.ac				= ac;	io.domain			= domain;	io.smb_krb5_context		= smb_krb5_context;	io.u.user_account_control	= samdb_result_uint(msg, "userAccountControl", 0);	io.u.sAMAccountName		= samdb_result_string(msg, "samAccountName", NULL);	io.u.user_principal_name	= samdb_result_string(msg, "userPrincipalName", NULL);	io.u.is_computer		= ldb_msg_check_string_attribute(msg, "objectClass", "computer");	io.n.cleartext			= samdb_result_string(msg, "sambaPassword", NULL);	io.n.nt_hash			= samdb_result_hash(io.ac, msg, "unicodePwd");	io.n.lm_hash			= samdb_result_hash(io.ac, msg, "dBCSPwd");	/* remove attributes */	if (io.n.cleartext) ldb_msg_remove_attr(msg, "sambaPassword");	if (io.n.nt_hash) ldb_msg_remove_attr(msg, "unicodePwd");	if (io.n.lm_hash) ldb_msg_remove_attr(msg, "dBCSPwd");	ldb_msg_remove_attr(msg, "pwdLastSet");	io.o.kvno = samdb_result_uint(msg, "msDs-KeyVersionNumber", 1) - 1;	ldb_msg_remove_attr(msg, "msDs-KeyVersionNumber");	ret = setup_password_fields(&io);	if (ret != LDB_SUCCESS) {		return ret;	}	if (io.g.nt_hash) {		ret = samdb_msg_add_hash(ac->module->ldb, ac, msg,					 "unicodePwd", io.g.nt_hash);		if (ret != LDB_SUCCESS) {			return ret;		}	}	if (io.g.lm_hash) {		ret = samdb_msg_add_hash(ac->module->ldb, ac, msg,					 "dBCSPwd", io.g.lm_hash);		if (ret != LDB_SUCCESS) {			return ret;		}	}	if (io.g.nt_history_len > 0) {		ret = samdb_msg_add_hashes(ac, msg,					   "ntPwdHistory",					   io.g.nt_history,					   io.g.nt_history_len);		if (ret != LDB_SUCCESS) {			return ret;		}	}	if (io.g.lm_history_len > 0) {		ret = samdb_msg_add_hashes(ac, msg,					   "lmPwdHistory",					   io.g.lm_history,					   io.g.lm_history_len);		if (ret != LDB_SUCCESS) {			return ret;		}	}	if (io.g.supplemental.length > 0) {		ret = ldb_msg_add_value(msg, "supplementalCredentials",					&io.g.supplemental, NULL);		if (ret != LDB_SUCCESS) {			return ret;		}	}	ret = samdb_msg_add_uint64(ac->module->ldb, ac, msg,				   "pwdLastSet",				   io.g.last_set);	if (ret != LDB_SUCCESS) {		return ret;	}	ret = samdb_msg_add_uint(ac->module->ldb, ac, msg,				 "msDs-KeyVersionNumber",				 io.g.kvno);	if (ret != LDB_SUCCESS) {		return ret;	}	h->state = LDB_ASYNC_INIT;	h->status = LDB_SUCCESS;	ac->step = PH_ADD_DO_ADD;	ldb_set_timeout_from_prev_req(ac->module->ldb, ac->orig_req, ac->down_req);	/* perform the operation */	return ldb_next_request(ac->module, ac->down_req);}static int password_hash_mod_search_self(struct ldb_handle *h);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -