示例#1
0
NTSTATUS libnet_SamDump(struct libnet_context *ctx, TALLOC_CTX *mem_ctx, 
			struct libnet_SamDump *r)
{
	NTSTATUS nt_status;
	struct libnet_SamSync r2;
	struct samdump_state *samdump_state = talloc(mem_ctx, struct samdump_state);

	struct samdump_trusted_domain *t;
	struct samdump_secret *s;

	if (!samdump_state) {
		return NT_STATUS_NO_MEMORY;
	}

	samdump_state->secrets         = NULL;
	samdump_state->trusted_domains = NULL;

	r2.out.error_string            = NULL;
	r2.in.binding_string           = r->in.binding_string;
	r2.in.init_fn                  = NULL;
	r2.in.delta_fn                 = libnet_samdump_fn;
	r2.in.fn_ctx                   = samdump_state;
	r2.in.machine_account          = r->in.machine_account;
	nt_status                      = libnet_SamSync_netlogon(ctx, samdump_state, &r2);
	r->out.error_string            = r2.out.error_string;
	talloc_steal(mem_ctx, r->out.error_string);

	if (!NT_STATUS_IS_OK(nt_status)) {
		talloc_free(samdump_state);
		return nt_status;
	}

	printf("Trusted domains, sids and secrets:\n");
	for (t=samdump_state->trusted_domains; t; t=t->next) {
		char *secret_name = talloc_asprintf(mem_ctx, "G$$%s", t->name);
		for (s=samdump_state->secrets; s; s=s->next) {
			size_t converted_size = 0;
			char *secret_string;
			if (strcasecmp_m(s->name, secret_name) != 0) {
				continue;
			}
			if (!convert_string_talloc_handle(mem_ctx, lpcfg_iconv_handle(ctx->lp_ctx), CH_UTF16, CH_UNIX,
						  s->secret.data, s->secret.length, 
						  (void **)&secret_string, &converted_size)) {
				r->out.error_string = talloc_asprintf(mem_ctx, 
								      "Could not convert secret for domain %s to a string",
								      t->name);
				talloc_free(samdump_state);
				return NT_STATUS_INVALID_PARAMETER;
			}
			printf("%s\t%s\t%s\n", 
			       t->name, dom_sid_string(mem_ctx, t->sid), 
			       secret_string);
		}
	}
	talloc_free(samdump_state);
	return nt_status;
}
示例#2
0
/*
  samr_OemChangePasswordUser2
*/
NTSTATUS dcesrv_samr_OemChangePasswordUser2(struct dcesrv_call_state *dce_call,
					    TALLOC_CTX *mem_ctx,
					    struct samr_OemChangePasswordUser2 *r)
{
	NTSTATUS status;
	DATA_BLOB new_password, new_unicode_password;
	char *new_pass;
	struct samr_CryptPassword *pwbuf = r->in.password;
	struct ldb_context *sam_ctx;
	struct ldb_dn *user_dn;
	int ret;
	struct ldb_message **res;
	const char * const attrs[] = { "objectSid", "dBCSPwd", NULL };
	struct samr_Password *lm_pwd;
	DATA_BLOB lm_pwd_blob;
	uint8_t new_lm_hash[16];
	struct samr_Password lm_verifier;
	size_t unicode_pw_len;
	size_t converted_size = 0;

	if (pwbuf == NULL) {
		return NT_STATUS_INVALID_PARAMETER;
	}

	if (r->in.hash == NULL) {
		return NT_STATUS_INVALID_PARAMETER;
	}

	/* this call can only work with lanman auth */
	if (!lpcfg_lanman_auth(dce_call->conn->dce_ctx->lp_ctx)) {
		return NT_STATUS_WRONG_PASSWORD;
	}

	/* Connect to a SAMDB with system privileges for fetching the old pw
	 * hashes. */
	sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
				dce_call->conn->dce_ctx->lp_ctx,
				system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
	if (sam_ctx == NULL) {
		return NT_STATUS_INVALID_SYSTEM_SERVICE;
	}

	/* we need the users dn and the domain dn (derived from the
	   user SID). We also need the current lm password hash in
	   order to decrypt the incoming password */
	ret = gendb_search(sam_ctx,
			   mem_ctx, NULL, &res, attrs,
			   "(&(sAMAccountName=%s)(objectclass=user))",
			   r->in.account->string);
	if (ret != 1) {
		/* Don't give the game away:  (don't allow anonymous users to prove the existance of usernames) */
		return NT_STATUS_WRONG_PASSWORD;
	}

	user_dn = res[0]->dn;

	status = samdb_result_passwords(mem_ctx, dce_call->conn->dce_ctx->lp_ctx,
					res[0], &lm_pwd, NULL);
	if (!NT_STATUS_IS_OK(status) || !lm_pwd) {
		return NT_STATUS_WRONG_PASSWORD;
	}

	/* decrypt the password we have been given */
	lm_pwd_blob = data_blob(lm_pwd->hash, sizeof(lm_pwd->hash));
	arcfour_crypt_blob(pwbuf->data, 516, &lm_pwd_blob);
	data_blob_free(&lm_pwd_blob);

	if (!extract_pw_from_buffer(mem_ctx, pwbuf->data, &new_password)) {
		DEBUG(3,("samr: failed to decode password buffer\n"));
		return NT_STATUS_WRONG_PASSWORD;
	}

	if (!convert_string_talloc_handle(mem_ctx, lpcfg_iconv_handle(dce_call->conn->dce_ctx->lp_ctx),
				  CH_DOS, CH_UNIX,
				  (const char *)new_password.data,
				  new_password.length,
				  (void **)&new_pass, &converted_size)) {
		DEBUG(3,("samr: failed to convert incoming password buffer to unix charset\n"));
		return NT_STATUS_WRONG_PASSWORD;
	}

	if (!convert_string_talloc_handle(mem_ctx, lpcfg_iconv_handle(dce_call->conn->dce_ctx->lp_ctx),
					       CH_DOS, CH_UTF16,
					       (const char *)new_password.data,
					       new_password.length,
					       (void **)&new_unicode_password.data, &unicode_pw_len)) {
		DEBUG(3,("samr: failed to convert incoming password buffer to UTF16 charset\n"));
		return NT_STATUS_WRONG_PASSWORD;
	}
	new_unicode_password.length = unicode_pw_len;

	E_deshash(new_pass, new_lm_hash);
	E_old_pw_hash(new_lm_hash, lm_pwd->hash, lm_verifier.hash);
	if (memcmp(lm_verifier.hash, r->in.hash->hash, 16) != 0) {
		return NT_STATUS_WRONG_PASSWORD;
	}

	/* Connect to a SAMDB with user privileges for the password change */
	sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
				dce_call->conn->dce_ctx->lp_ctx,
				dce_call->conn->auth_state.session_info, 0);
	if (sam_ctx == NULL) {
		return NT_STATUS_INVALID_SYSTEM_SERVICE;
	}

	/* Start transaction */
	ret = ldb_transaction_start(sam_ctx);
	if (ret != LDB_SUCCESS) {
		DEBUG(1, ("Failed to start transaction: %s\n", ldb_errstring(sam_ctx)));
		return NT_STATUS_TRANSACTION_ABORTED;
	}

	/* Performs the password modification. We pass the old hashes read out
	 * from the database since they were already checked against the user-
	 * provided ones. */
	status = samdb_set_password(sam_ctx, mem_ctx,
				    user_dn, NULL,
				    &new_unicode_password,
				    NULL, NULL,
				    lm_pwd, NULL, /* this is a user password change */
				    NULL,
				    NULL);
	if (!NT_STATUS_IS_OK(status)) {
		ldb_transaction_cancel(sam_ctx);
		return status;
	}

	/* And this confirms it in a transaction commit */
	ret = ldb_transaction_commit(sam_ctx);
	if (ret != LDB_SUCCESS) {
		DEBUG(1,("Failed to commit transaction to change password on %s: %s\n",
			 ldb_dn_get_linearized(user_dn),
			 ldb_errstring(sam_ctx)));
		return NT_STATUS_TRANSACTION_ABORTED;
	}

	return NT_STATUS_OK;
}
示例#3
0
static krb5_error_code kpasswd_set_password(struct kdc_server *kdc,
					    TALLOC_CTX *mem_ctx,
					    struct auth_session_info *session_info,
					    DATA_BLOB *decoded_data,
					    DATA_BLOB *kpasswd_reply,
					    const char **error_string)
{
	krb5_context context = kdc->smb_krb5_context->krb5_context;
	krb5_data k_dec_data;
	krb5_data *k_clear_data;
	krb5_principal target_principal;
	krb5_error_code code;
	DATA_BLOB password;
	char *target_realm = NULL;
	char *target_name = NULL;
	char *target_principal_string = NULL;
	bool is_service_principal = false;
	bool ok;
	size_t num_components;
	enum samPwdChangeReason reject_reason = SAM_PWD_CHANGE_NO_ERROR;
	struct samr_DomInfo1 *dominfo = NULL;
	NTSTATUS status;

	k_dec_data.length = decoded_data->length;
	k_dec_data.data   = (char *)decoded_data->data;

	code = decode_krb5_setpw_req(&k_dec_data,
				     &k_clear_data,
				     &target_principal);
	if (code != 0) {
		DBG_WARNING("decode_krb5_setpw_req failed: %s\n",
			    error_message(code));
		ok = kpasswd_make_error_reply(mem_ctx,
					      KRB5_KPASSWD_MALFORMED,
					      "Failed to decode packet",
					      kpasswd_reply);
		if (!ok) {
			*error_string = "Failed to create reply";
			return KRB5_KPASSWD_HARDERROR;
		}
		return 0;
	}

	ok = convert_string_talloc_handle(mem_ctx,
					  lpcfg_iconv_handle(kdc->task->lp_ctx),
					  CH_UTF8,
					  CH_UTF16,
					  (const char *)k_clear_data->data,
					  k_clear_data->length,
					  (void **)&password.data,
					  &password.length);
	krb5_free_data(context, k_clear_data);
	if (!ok) {
		DBG_WARNING("String conversion failed\n");
		*error_string = "String conversion failed";
		return KRB5_KPASSWD_HARDERROR;
	}

	target_realm = smb_krb5_principal_get_realm(context, target_principal);
	code = krb5_unparse_name_flags(context,
				       target_principal,
				       KRB5_PRINCIPAL_UNPARSE_NO_REALM,
				       &target_name);
	if (code != 0) {
		DBG_WARNING("Failed to parse principal\n");
		*error_string = "String conversion failed";
		return KRB5_KPASSWD_HARDERROR;
	}

	if ((target_name != NULL && target_realm == NULL) ||
	    (target_name == NULL && target_realm != NULL)) {
		krb5_free_principal(context, target_principal);
		SAFE_FREE(target_realm);
		SAFE_FREE(target_name);

		ok = kpasswd_make_error_reply(mem_ctx,
					      KRB5_KPASSWD_MALFORMED,
					      "Realm and principal must be "
					      "both present, or neither "
					      "present",
					      kpasswd_reply);
		if (!ok) {
			*error_string = "Failed to create reply";
			return KRB5_KPASSWD_HARDERROR;
		}
		return 0;
	}

	if (target_name != NULL && target_realm != NULL) {
		SAFE_FREE(target_realm);
		SAFE_FREE(target_name);
	} else {
		krb5_free_principal(context, target_principal);
		SAFE_FREE(target_realm);
		SAFE_FREE(target_name);

		return kpasswd_change_password(kdc,
					       mem_ctx,
					       session_info,
					       &password,
					       kpasswd_reply,
					       error_string);
	}

	num_components = krb5_princ_size(context, target_principal);
	if (num_components >= 2) {
		is_service_principal = true;
		code = krb5_unparse_name_flags(context,
					       target_principal,
					       KRB5_PRINCIPAL_UNPARSE_SHORT,
					       &target_principal_string);
	} else {
		code = krb5_unparse_name(context,
					 target_principal,
					 &target_principal_string);
	}
	krb5_free_principal(context, target_principal);
	if (code != 0) {
		ok = kpasswd_make_error_reply(mem_ctx,
					      KRB5_KPASSWD_MALFORMED,
					      "Failed to parse principal",
					      kpasswd_reply);
		if (!ok) {
			*error_string = "Failed to create reply";
			return KRB5_KPASSWD_HARDERROR;
		}
	}

	status = kpasswd_samdb_set_password(mem_ctx,
					    kdc->task->event_ctx,
					    kdc->task->lp_ctx,
					    session_info,
					    is_service_principal,
					    target_principal_string,
					    &password,
					    &reject_reason,
					    &dominfo);
	if (!NT_STATUS_IS_OK(status)) {
		DBG_ERR("kpasswd_samdb_set_password failed - %s\n",
			nt_errstr(status));
	}

	ok = kpasswd_make_pwchange_reply(mem_ctx,
					 status,
					 reject_reason,
					 dominfo,
					 kpasswd_reply);
	if (!ok) {
		*error_string = "Failed to create reply";
		return KRB5_KPASSWD_HARDERROR;
	}

	return 0;
}
示例#4
0
/*
  samr_ChangePasswordUser3
*/
NTSTATUS dcesrv_samr_ChangePasswordUser3(struct dcesrv_call_state *dce_call,
					 TALLOC_CTX *mem_ctx,
					 struct samr_ChangePasswordUser3 *r)
{
	NTSTATUS status;
	DATA_BLOB new_password;
	struct ldb_context *sam_ctx = NULL;
	struct ldb_dn *user_dn;
	int ret;
	struct ldb_message **res;
	const char * const attrs[] = { "unicodePwd", "dBCSPwd", NULL };
	struct samr_Password *nt_pwd, *lm_pwd;
	DATA_BLOB nt_pwd_blob;
	struct samr_DomInfo1 *dominfo = NULL;
	struct userPwdChangeFailureInformation *reject = NULL;
	enum samPwdChangeReason reason = SAM_PWD_CHANGE_NO_ERROR;
	uint8_t new_nt_hash[16], new_lm_hash[16];
	struct samr_Password nt_verifier, lm_verifier;

	*r->out.dominfo = NULL;
	*r->out.reject = NULL;

	if (r->in.nt_password == NULL ||
	    r->in.nt_verifier == NULL) {
		return NT_STATUS_INVALID_PARAMETER;
	}

	/* Connect to a SAMDB with system privileges for fetching the old pw
	 * hashes. */
	sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
				dce_call->conn->dce_ctx->lp_ctx,
				system_session(dce_call->conn->dce_ctx->lp_ctx), 0);
	if (sam_ctx == NULL) {
		return NT_STATUS_INVALID_SYSTEM_SERVICE;
	}

	/* we need the users dn and the domain dn (derived from the
	   user SID). We also need the current lm and nt password hashes
	   in order to decrypt the incoming passwords */
	ret = gendb_search(sam_ctx,
			   mem_ctx, NULL, &res, attrs,
			   "(&(sAMAccountName=%s)(objectclass=user))",
			   r->in.account->string);
	if (ret != 1) {
		/* Don't give the game away:  (don't allow anonymous users to prove the existance of usernames) */
		status = NT_STATUS_WRONG_PASSWORD;
		goto failed;
	}

	user_dn = res[0]->dn;

	status = samdb_result_passwords(mem_ctx, dce_call->conn->dce_ctx->lp_ctx,
					res[0], &lm_pwd, &nt_pwd);
	if (!NT_STATUS_IS_OK(status) ) {
		goto failed;
	}

	if (!nt_pwd) {
		status = NT_STATUS_WRONG_PASSWORD;
		goto failed;
	}

	/* decrypt the password we have been given */
	nt_pwd_blob = data_blob(nt_pwd->hash, sizeof(nt_pwd->hash));
	arcfour_crypt_blob(r->in.nt_password->data, 516, &nt_pwd_blob);
	data_blob_free(&nt_pwd_blob);

	if (!extract_pw_from_buffer(mem_ctx, r->in.nt_password->data, &new_password)) {
		DEBUG(3,("samr: failed to decode password buffer\n"));
		status =  NT_STATUS_WRONG_PASSWORD;
		goto failed;
	}

	if (r->in.nt_verifier == NULL) {
		status = NT_STATUS_WRONG_PASSWORD;
		goto failed;
	}

	/* check NT verifier */
	mdfour(new_nt_hash, new_password.data, new_password.length);

	E_old_pw_hash(new_nt_hash, nt_pwd->hash, nt_verifier.hash);
	if (memcmp(nt_verifier.hash, r->in.nt_verifier->hash, 16) != 0) {
		status = NT_STATUS_WRONG_PASSWORD;
		goto failed;
	}

	/* check LM verifier (really not needed as we just checked the
	 * much stronger NT hash, but the RPC-SAMR test checks for
	 * this) */
	if (lm_pwd && r->in.lm_verifier != NULL) {
		char *new_pass;
		size_t converted_size = 0;

		if (!convert_string_talloc_handle(mem_ctx, lpcfg_iconv_handle(dce_call->conn->dce_ctx->lp_ctx),
					  CH_UTF16, CH_UNIX,
					  (const char *)new_password.data,
					  new_password.length,
					  (void **)&new_pass, &converted_size)) {
			E_deshash(new_pass, new_lm_hash);
			E_old_pw_hash(new_nt_hash, lm_pwd->hash, lm_verifier.hash);
			if (memcmp(lm_verifier.hash, r->in.lm_verifier->hash, 16) != 0) {
				status = NT_STATUS_WRONG_PASSWORD;
				goto failed;
			}
		}
	}

	/* Connect to a SAMDB with user privileges for the password change */
	sam_ctx = samdb_connect(mem_ctx, dce_call->event_ctx,
				dce_call->conn->dce_ctx->lp_ctx,
				dce_call->conn->auth_state.session_info, 0);
	if (sam_ctx == NULL) {
		return NT_STATUS_INVALID_SYSTEM_SERVICE;
	}

	ret = ldb_transaction_start(sam_ctx);
	if (ret != LDB_SUCCESS) {
		DEBUG(1, ("Failed to start transaction: %s\n", ldb_errstring(sam_ctx)));
		return NT_STATUS_TRANSACTION_ABORTED;
	}

	/* Performs the password modification. We pass the old hashes read out
	 * from the database since they were already checked against the user-
	 * provided ones. */
	status = samdb_set_password(sam_ctx, mem_ctx,
				    user_dn, NULL,
				    &new_password,
				    NULL, NULL,
				    lm_pwd, nt_pwd, /* this is a user password change */
				    &reason,
				    &dominfo);

	if (!NT_STATUS_IS_OK(status)) {
		ldb_transaction_cancel(sam_ctx);
		goto failed;
	}

	/* And this confirms it in a transaction commit */
	ret = ldb_transaction_commit(sam_ctx);
	if (ret != LDB_SUCCESS) {
		DEBUG(1,("Failed to commit transaction to change password on %s: %s\n",
			 ldb_dn_get_linearized(user_dn),
			 ldb_errstring(sam_ctx)));
		status = NT_STATUS_TRANSACTION_ABORTED;
		goto failed;
	}

	return NT_STATUS_OK;

failed:
	reject = talloc_zero(mem_ctx, struct userPwdChangeFailureInformation);
	if (reject != NULL) {
		reject->extendedFailureReason = reason;

		*r->out.reject = reject;
	}

	*r->out.dominfo = dominfo;

	return status;
}
示例#5
0
krb5_error_code kpasswd_handle_request(struct kdc_server *kdc,
				       TALLOC_CTX *mem_ctx,
				       struct gensec_security *gensec_security,
				       uint16_t verno,
				       DATA_BLOB *decoded_data,
				       DATA_BLOB *kpasswd_reply,
				       const char **error_string)
{
	struct auth_session_info *session_info;
	NTSTATUS status;

	status = gensec_session_info(gensec_security,
				     mem_ctx,
				     &session_info);
	if (!NT_STATUS_IS_OK(status)) {
		*error_string = talloc_asprintf(mem_ctx,
						"gensec_session_info failed - "
						"%s",
						nt_errstr(status));
		return KRB5_KPASSWD_HARDERROR;
	}

	switch(verno) {
	case 1: {
		DATA_BLOB password;
		bool ok;

		ok = convert_string_talloc_handle(mem_ctx,
						  lpcfg_iconv_handle(kdc->task->lp_ctx),
						  CH_UTF8,
						  CH_UTF16,
						  (const char *)decoded_data->data,
						  decoded_data->length,
						  (void **)&password.data,
						  &password.length);
		if (!ok) {
			*error_string = "String conversion failed!";
			DBG_WARNING("%s\n", *error_string);
			return KRB5_KPASSWD_HARDERROR;
		}

		return kpasswd_change_password(kdc,
					       mem_ctx,
					       session_info,
					       &password,
					       kpasswd_reply,
					       error_string);
	}
	case RFC3244_VERSION: {
		return kpasswd_set_password(kdc,
					    mem_ctx,
					    session_info,
					    decoded_data,
					    kpasswd_reply,
					    error_string);
	}
	default:
		return KRB5_KPASSWD_BAD_VERSION;
	}

	return 0;
}