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

📄 kpasswdd.c

📁 samba最新软件
💻 C
📖 第 1 页 / 共 2 页
字号:
/*    Unix SMB/CIFS implementation.   kpasswd Server implementation   Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005   Copyright (C) Andrew Tridgell	2005   This program is free software; you can redistribute it and/or modify   it under the terms of the GNU General Public License as published by   the Free Software Foundation; either version 3 of the License, or   (at your option) any later version.      This program is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the   GNU General Public License for more details.      You should have received a copy of the GNU General Public License   along with this program.  If not, see <http://www.gnu.org/licenses/>.*/#include "includes.h"#include "smbd/service_task.h"#include "lib/events/events.h"#include "lib/socket/socket.h"#include "kdc/kdc.h"#include "system/network.h"#include "lib/util/dlinklist.h"#include "lib/ldb/include/ldb.h"#include "heimdal/lib/krb5/krb5_locl.h"#include "heimdal/lib/krb5/krb5-private.h"#include "auth/gensec/gensec.h"#include "auth/credentials/credentials.h"#include "auth/credentials/credentials_krb5.h"#include "auth/auth.h"#include "dsdb/samdb/samdb.h"#include "rpc_server/dcerpc_server.h"#include "rpc_server/samr/proto.h"#include "libcli/security/security.h"#include "param/param.h"/* hold information about one kdc socket */struct kpasswd_socket {	struct socket_context *sock;	struct kdc_server *kdc;	struct fd_event *fde;	/* a queue of outgoing replies that have been deferred */	struct kdc_reply *send_queue;};/* Return true if there is a valid error packet formed in the error_blob */static bool kpasswdd_make_error_reply(struct kdc_server *kdc, 				     TALLOC_CTX *mem_ctx, 				     uint16_t result_code, 				     const char *error_string, 				     DATA_BLOB *error_blob) {	char *error_string_utf8;	ssize_t len;		DEBUG(result_code ? 3 : 10, ("kpasswdd: %s\n", error_string));	len = push_utf8_talloc(mem_ctx, lp_iconv_convenience(kdc->task->lp_ctx), &error_string_utf8, error_string);	if (len == -1) {		return false;	}	*error_blob = data_blob_talloc(mem_ctx, NULL, 2 + len + 1);	if (!error_blob->data) {		return false;	}	RSSVAL(error_blob->data, 0, result_code);	memcpy(error_blob->data + 2, error_string_utf8, len + 1);	return true;}/* Return true if there is a valid error packet formed in the error_blob */static bool kpasswdd_make_unauth_error_reply(struct kdc_server *kdc, 					    TALLOC_CTX *mem_ctx, 					    uint16_t result_code, 					    const char *error_string, 					    DATA_BLOB *error_blob) {	bool ret;	int kret;	DATA_BLOB error_bytes;	krb5_data k5_error_bytes, k5_error_blob;	ret = kpasswdd_make_error_reply(kdc, mem_ctx, result_code, error_string, 				       &error_bytes);	if (!ret) {		return false;	}	k5_error_bytes.data = error_bytes.data;	k5_error_bytes.length = error_bytes.length;	kret = krb5_mk_error(kdc->smb_krb5_context->krb5_context,			     result_code, NULL, &k5_error_bytes, 			     NULL, NULL, NULL, NULL, &k5_error_blob);	if (kret) {		return false;	}	*error_blob = data_blob_talloc(mem_ctx, k5_error_blob.data, k5_error_blob.length);	krb5_data_free(&k5_error_blob);	if (!error_blob->data) {		return false;	}	return true;}static bool kpasswd_make_pwchange_reply(struct kdc_server *kdc, 					TALLOC_CTX *mem_ctx, 					NTSTATUS status, 					enum samr_RejectReason reject_reason,					struct samr_DomInfo1 *dominfo,					DATA_BLOB *error_blob) {	if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {		return kpasswdd_make_error_reply(kdc, mem_ctx, 						KRB5_KPASSWD_ACCESSDENIED,						"No such user when changing password",						error_blob);	}	if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {		return kpasswdd_make_error_reply(kdc, mem_ctx, 						KRB5_KPASSWD_ACCESSDENIED,						"Not permitted to change password",						error_blob);	}	if (dominfo && NT_STATUS_EQUAL(status, NT_STATUS_PASSWORD_RESTRICTION)) {		const char *reject_string;		switch (reject_reason) {		case SAMR_REJECT_TOO_SHORT:			reject_string = talloc_asprintf(mem_ctx, "Password too short, password must be at least %d characters long",							dominfo->min_password_length);			break;		case SAMR_REJECT_COMPLEXITY:			reject_string = "Password does not meet complexity requirements";			break;		case SAMR_REJECT_IN_HISTORY:			reject_string = "Password is already in password history";			break;		case SAMR_REJECT_OTHER:		default:			reject_string = talloc_asprintf(mem_ctx, "Password must be at least %d characters long, and cannot match any of your %d previous passwords",							dominfo->min_password_length, dominfo->password_history_length);			break;		}		return kpasswdd_make_error_reply(kdc, mem_ctx, 						KRB5_KPASSWD_SOFTERROR,						reject_string,						error_blob);	}	if (!NT_STATUS_IS_OK(status)) {		return kpasswdd_make_error_reply(kdc, mem_ctx, 						 KRB5_KPASSWD_HARDERROR,						 talloc_asprintf(mem_ctx, "failed to set password: %s", nt_errstr(status)),						 error_blob);			}	return kpasswdd_make_error_reply(kdc, mem_ctx, KRB5_KPASSWD_SUCCESS,					"Password changed",					error_blob);}/*    A user password change      Return true if there is a valid error packet (or sucess) formed in   the error_blob*/static bool kpasswdd_change_password(struct kdc_server *kdc,				     TALLOC_CTX *mem_ctx, 				     struct auth_session_info *session_info,				     const char *password,				     DATA_BLOB *reply){	NTSTATUS status;	enum samr_RejectReason reject_reason;	struct samr_DomInfo1 *dominfo;	struct ldb_context *samdb;	samdb = samdb_connect(mem_ctx, kdc->task->event_ctx, kdc->task->lp_ctx, system_session(mem_ctx, kdc->task->lp_ctx));	if (!samdb) {		return kpasswdd_make_error_reply(kdc, mem_ctx, 						KRB5_KPASSWD_HARDERROR,						"Failed to open samdb",						reply);	}		DEBUG(3, ("Changing password of %s\\%s (%s)\n", 		  session_info->server_info->domain_name,		  session_info->server_info->account_name,		  dom_sid_string(mem_ctx, session_info->security_token->user_sid)));	/* User password change */	status = samdb_set_password_sid(samdb, mem_ctx, 					session_info->security_token->user_sid,					password, NULL, NULL, 					true, /* this is a user password change */					&reject_reason,					&dominfo);	return kpasswd_make_pwchange_reply(kdc, mem_ctx, 					   status, 					   reject_reason,					   dominfo, 					   reply);}static bool kpasswd_process_request(struct kdc_server *kdc,				    TALLOC_CTX *mem_ctx, 				    struct gensec_security *gensec_security,				    uint16_t version,				    DATA_BLOB *input, 				    DATA_BLOB *reply){	struct auth_session_info *session_info;	if (!NT_STATUS_IS_OK(gensec_session_info(gensec_security, 						 &session_info))) {		return kpasswdd_make_error_reply(kdc, mem_ctx, 						KRB5_KPASSWD_HARDERROR,						"gensec_session_info failed!",						reply);	}	switch (version) {	case KRB5_KPASSWD_VERS_CHANGEPW:	{		char *password = talloc_strndup(mem_ctx, (const char *)input->data, input->length);		if (!password) {			return false;		}		return kpasswdd_change_password(kdc, mem_ctx, session_info, 						password, reply);		break;	}	case KRB5_KPASSWD_VERS_SETPW:	{		NTSTATUS status;		enum samr_RejectReason reject_reason = SAMR_REJECT_OTHER;		struct samr_DomInfo1 *dominfo = NULL;		struct ldb_context *samdb;		struct ldb_message *msg;		krb5_context context = kdc->smb_krb5_context->krb5_context;		ChangePasswdDataMS chpw;		char *password;		krb5_principal principal;		char *set_password_on_princ;		struct ldb_dn *set_password_on_dn;		size_t len;		int ret;		msg = ldb_msg_new(mem_ctx);		if (!msg) {			return false;		}		ret = decode_ChangePasswdDataMS(input->data, input->length,						&chpw, &len);		if (ret) {			return kpasswdd_make_error_reply(kdc, mem_ctx, 							KRB5_KPASSWD_MALFORMED,							"failed to decode password change structure",							reply);		}				password = talloc_strndup(mem_ctx, 					  (const char *)chpw.newpasswd.data, 					  chpw.newpasswd.length);		if (!password) {			free_ChangePasswdDataMS(&chpw);			return false;		}		if ((chpw.targname && !chpw.targrealm) 		    || (!chpw.targname && chpw.targrealm)) {			return kpasswdd_make_error_reply(kdc, mem_ctx, 							KRB5_KPASSWD_MALFORMED,							"Realm and principal must be both present, or neither present",							reply);		}		if (chpw.targname && chpw.targrealm) {			if (_krb5_principalname2krb5_principal(kdc->smb_krb5_context->krb5_context,							       &principal, *chpw.targname, 							       *chpw.targrealm) != 0) {				free_ChangePasswdDataMS(&chpw);				return kpasswdd_make_error_reply(kdc, mem_ctx, 								KRB5_KPASSWD_MALFORMED,								"failed to extract principal to set",								reply);							}		} else {			free_ChangePasswdDataMS(&chpw);			return kpasswdd_change_password(kdc, mem_ctx, session_info, 							password, reply);		}		free_ChangePasswdDataMS(&chpw);		if (krb5_unparse_name(context, principal, &set_password_on_princ) != 0) {

⌨️ 快捷键说明

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