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/>.
23 #include "librpc/gen_ndr/ndr_secrets.h"
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
;
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
;
38 struct timeval tv
= timeval_current();
39 NTTIME now
= timeval_to_nttime(&tv
);
40 int role
= lp_server_role();
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"));
55 status
= secrets_prepare_password_change(domain
,
66 if (!NT_STATUS_IS_OK(status
)) {
67 return ADS_ERROR_NT(status
);
70 status
= NT_STATUS_REQUEST_NOT_ACCEPTED
;
71 secrets_failed_password_change("localhost",
73 NT_STATUS_NOT_COMMITTED
,
75 return ADS_ERROR_NT(status
);
78 cleartext_blob
= &info
->password
->cleartext_blob
;
79 ok
= convert_string_talloc(talloc_tos(), CH_UTF16MUNGED
, CH_UNIX
,
81 cleartext_blob
->length
,
82 (void **)&pw_blob
.data
,
85 status
= NT_STATUS_UNMAPPABLE_CHARACTER
;
86 if (errno
== ENOMEM
) {
87 status
= NT_STATUS_NO_MEMORY
;
89 DBG_ERR("convert_string_talloc(CH_UTF16MUNGED, CH_UNIX) "
90 "failed for password of %s - %s\n",
91 domain
, nt_errstr(status
));
92 return ADS_ERROR_NT(status
);
94 password
= (const char *)pw_blob
.data
;
96 cleartext_blob
= &info
->next_change
->password
->cleartext_blob
;
97 ok
= convert_string_talloc(talloc_tos(), CH_UTF16MUNGED
, CH_UNIX
,
99 cleartext_blob
->length
,
100 (void **)&new_pw_blob
.data
,
101 &new_pw_blob
.length
);
103 status
= NT_STATUS_UNMAPPABLE_CHARACTER
;
104 if (errno
== ENOMEM
) {
105 status
= NT_STATUS_NO_MEMORY
;
107 DBG_ERR("convert_string_talloc(CH_UTF16MUNGED, CH_UNIX) "
108 "failed for new_password of %s - %s\n",
109 domain
, nt_errstr(status
));
110 secrets_failed_password_change("localhost",
112 NT_STATUS_NOT_COMMITTED
,
114 return ADS_ERROR_NT(status
);
116 talloc_keep_secret(new_pw_blob
.data
);
117 new_password
= (const char *)new_pw_blob
.data
;
119 ret
= kerberos_set_password(host_principal
,
124 if (!ADS_ERR_OK(ret
)) {
125 status
= ads_ntstatus(ret
);
126 DBG_ERR("kerberos_set_password(%s, %s) "
127 "failed for new_password of %s - %s\n",
128 ads
->auth
.kdc_server
, host_principal
,
129 domain
, nt_errstr(status
));
130 secrets_failed_password_change(ads
->auth
.kdc_server
,
131 NT_STATUS_NOT_COMMITTED
,
137 status
= secrets_finish_password_change(ads
->auth
.kdc_server
,
145 if (!NT_STATUS_IS_OK(status
)) {
146 DEBUG(1,("Failed to save machine password\n"));
147 return ADS_ERROR_NT(status
);
155 * @brief Parses windows style SPN service/host:port/servicename
156 * serviceclass - A string that identifies the general class of service
158 * host - A netbios name or fully-qualified DNS name
159 * port - An optional TCP or UDP port number
160 * servicename - An optional distinguished name, GUID, DNS name or
161 * DNS name of an SRV or MX record. (not needed for host
164 * @param[in] ctx - Talloc context.
165 * @param[in] srvprinc - The service principal
167 * @return - struct spn_struct containing the fields parsed or NULL
168 * if srvprinc could not be parsed.
170 struct spn_struct
*parse_spn(TALLOC_CTX
*ctx
, const char *srvprinc
)
172 struct spn_struct
* result
= NULL
;
174 char *port_str
= NULL
;
175 char *host_str
= NULL
;
177 result
= talloc_zero(ctx
, struct spn_struct
);
178 if (result
== NULL
) {
179 DBG_ERR("Out of memory\n");
183 result
->serviceclass
= talloc_strdup(result
, srvprinc
);
184 if (result
->serviceclass
== NULL
) {
185 DBG_ERR("Out of memory\n");
190 tmp
= strchr_m(result
->serviceclass
, '/');
193 DBG_ERR("Failed to parse spn %s, no host definition\n",
198 /* terminate service principal */
203 tmp
= strchr_m(host_str
, ':');
212 tmp
= strchr_m(tmp
, '/');
216 result
->servicename
= tmp
;
219 if (strlen(host_str
) == 0) {
221 DBG_ERR("Failed to parse spn %s, illegal host definition\n",
225 result
->host
= host_str
;
227 if (result
->servicename
!= NULL
&& (strlen(result
->servicename
) == 0)) {
228 DBG_ERR("Failed to parse spn %s, empty servicename "
229 "definition\n", srvprinc
);
232 if (port_str
!= NULL
) {
233 if (strlen(port_str
) == 0) {
234 DBG_ERR("Failed to parse spn %s, empty port "
235 "definition\n", srvprinc
);
238 result
->port
= (int32_t)strtol(port_str
, NULL
, 10);
239 if (result
->port
<= 0
240 || result
->port
> 65535
241 || errno
== ERANGE
) {
242 DBG_ERR("Failed to parse spn %s, port number "
243 "conversion failed\n", srvprinc
);