s3:libads: make use of secrets_*_password_change() in ads_change_trust_account_password()
[Samba.git] / source3 / libads / util.c
blob14dbf86b21a935b9ca324d337a35de2dac25021f
1 /*
2 Unix SMB/CIFS implementation.
3 krb5 set password implementation
4 Copyright (C) Remus Koos 2001 (remuskoos@yahoo.com)
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include "includes.h"
21 #include "ads.h"
22 #include "secrets.h"
23 #include "librpc/gen_ndr/ndr_secrets.h"
25 #ifdef HAVE_KRB5
26 ADS_STATUS ads_change_trust_account_password(ADS_STRUCT *ads, char *host_principal)
28 const char *password = NULL;
29 const char *new_password = NULL;
30 ADS_STATUS ret;
31 const char *domain = lp_workgroup();
32 struct secrets_domain_info1 *info = NULL;
33 struct secrets_domain_info1_change *prev = NULL;
34 const DATA_BLOB *cleartext_blob = NULL;
35 DATA_BLOB pw_blob = data_blob_null;
36 DATA_BLOB new_pw_blob = data_blob_null;
37 NTSTATUS status;
38 struct timeval tv = timeval_current();
39 NTTIME now = timeval_to_nttime(&tv);
40 int role = lp_server_role();
41 bool ok;
43 if (role != ROLE_DOMAIN_MEMBER) {
44 DBG_ERR("Machine account password change only supported on a DOMAIN_MEMBER.\n");
45 return ADS_ERROR_NT(NT_STATUS_INVALID_SERVER_STATE);
48 new_password = trust_pw_new_value(talloc_tos(), SEC_CHAN_WKSTA, SEC_ADS);
49 if (new_password == NULL) {
50 ret = ADS_ERROR_SYSTEM(errno);
51 DEBUG(1,("Failed to generate machine password\n"));
52 return ret;
55 status = secrets_prepare_password_change(domain,
56 ads->auth.kdc_server,
57 new_password,
58 talloc_tos(),
59 &info, &prev);
60 if (!NT_STATUS_IS_OK(status)) {
61 return ADS_ERROR_NT(status);
63 if (prev != NULL) {
64 status = NT_STATUS_REQUEST_NOT_ACCEPTED;
65 secrets_failed_password_change("localhost",
66 status,
67 NT_STATUS_NOT_COMMITTED,
68 info);
69 return ADS_ERROR_NT(status);
72 cleartext_blob = &info->password->cleartext_blob;
73 ok = convert_string_talloc(talloc_tos(), CH_UTF16MUNGED, CH_UNIX,
74 cleartext_blob->data,
75 cleartext_blob->length,
76 (void **)&pw_blob.data,
77 &pw_blob.length);
78 if (!ok) {
79 status = NT_STATUS_UNMAPPABLE_CHARACTER;
80 if (errno == ENOMEM) {
81 status = NT_STATUS_NO_MEMORY;
83 DBG_ERR("convert_string_talloc(CH_UTF16MUNGED, CH_UNIX) "
84 "failed for password of %s - %s\n",
85 domain, nt_errstr(status));
86 return ADS_ERROR_NT(status);
88 password = (const char *)pw_blob.data;
90 cleartext_blob = &info->next_change->password->cleartext_blob;
91 ok = convert_string_talloc(talloc_tos(), CH_UTF16MUNGED, CH_UNIX,
92 cleartext_blob->data,
93 cleartext_blob->length,
94 (void **)&new_pw_blob.data,
95 &new_pw_blob.length);
96 if (!ok) {
97 status = NT_STATUS_UNMAPPABLE_CHARACTER;
98 if (errno == ENOMEM) {
99 status = NT_STATUS_NO_MEMORY;
101 DBG_ERR("convert_string_talloc(CH_UTF16MUNGED, CH_UNIX) "
102 "failed for new_password of %s - %s\n",
103 domain, nt_errstr(status));
104 secrets_failed_password_change("localhost",
105 status,
106 NT_STATUS_NOT_COMMITTED,
107 info);
108 return ADS_ERROR_NT(status);
110 new_password = (const char *)new_pw_blob.data;
112 ret = kerberos_set_password(ads->auth.kdc_server, host_principal, password, host_principal, new_password, ads->auth.time_offset);
114 if (!ADS_ERR_OK(ret)) {
115 status = ads_ntstatus(ret);
116 DBG_ERR("kerberos_set_password(%s, %s) "
117 "failed for new_password of %s - %s\n",
118 ads->auth.kdc_server, host_principal,
119 domain, nt_errstr(status));
120 secrets_failed_password_change(ads->auth.kdc_server,
121 NT_STATUS_NOT_COMMITTED,
122 status,
123 info);
124 return ret;
127 status = secrets_finish_password_change(ads->auth.kdc_server, now, info);
128 if (!NT_STATUS_IS_OK(status)) {
129 DEBUG(1,("Failed to save machine password\n"));
130 return ADS_ERROR_NT(status);
133 return ADS_SUCCESS;
135 #endif