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
,
60 if (!NT_STATUS_IS_OK(status
)) {
61 return ADS_ERROR_NT(status
);
64 status
= NT_STATUS_REQUEST_NOT_ACCEPTED
;
65 secrets_failed_password_change("localhost",
67 NT_STATUS_NOT_COMMITTED
,
69 return ADS_ERROR_NT(status
);
72 cleartext_blob
= &info
->password
->cleartext_blob
;
73 ok
= convert_string_talloc(talloc_tos(), CH_UTF16MUNGED
, CH_UNIX
,
75 cleartext_blob
->length
,
76 (void **)&pw_blob
.data
,
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
,
93 cleartext_blob
->length
,
94 (void **)&new_pw_blob
.data
,
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",
106 NT_STATUS_NOT_COMMITTED
,
108 return ADS_ERROR_NT(status
);
110 talloc_keep_secret(new_pw_blob
.data
);
111 new_password
= (const char *)new_pw_blob
.data
;
113 ret
= kerberos_set_password(host_principal
,
118 if (!ADS_ERR_OK(ret
)) {
119 status
= ads_ntstatus(ret
);
120 DBG_ERR("kerberos_set_password(%s, %s) "
121 "failed for new_password of %s - %s\n",
122 ads
->auth
.kdc_server
, host_principal
,
123 domain
, nt_errstr(status
));
124 secrets_failed_password_change(ads
->auth
.kdc_server
,
125 NT_STATUS_NOT_COMMITTED
,
131 status
= secrets_finish_password_change(ads
->auth
.kdc_server
, now
, info
);
132 if (!NT_STATUS_IS_OK(status
)) {
133 DEBUG(1,("Failed to save machine password\n"));
134 return ADS_ERROR_NT(status
);
142 * @brief Parses windows style SPN service/host:port/servicename
143 * serviceclass - A string that identifies the general class of service
145 * host - A netbios name or fully-qualified DNS name
146 * port - An optional TCP or UDP port number
147 * servicename - An optional distinguished name, GUID, DNS name or
148 * DNS name of an SRV or MX record. (not needed for host
151 * @param[in] ctx - Talloc context.
152 * @param[in] srvprinc - The service principal
154 * @return - struct spn_struct containing the fields parsed or NULL
155 * if srvprinc could not be parsed.
157 struct spn_struct
*parse_spn(TALLOC_CTX
*ctx
, const char *srvprinc
)
159 struct spn_struct
* result
= NULL
;
161 char *port_str
= NULL
;
162 char *host_str
= NULL
;
164 result
= talloc_zero(ctx
, struct spn_struct
);
165 if (result
== NULL
) {
166 DBG_ERR("Out of memory\n");
170 result
->serviceclass
= talloc_strdup(result
, srvprinc
);
171 if (result
->serviceclass
== NULL
) {
172 DBG_ERR("Out of memory\n");
177 tmp
= strchr_m(result
->serviceclass
, '/');
180 DBG_ERR("Failed to parse spn %s, no host definition\n",
185 /* terminate service principal */
190 tmp
= strchr_m(host_str
, ':');
199 tmp
= strchr_m(tmp
, '/');
203 result
->servicename
= tmp
;
206 if (strlen(host_str
) == 0) {
208 DBG_ERR("Failed to parse spn %s, illegal host definition\n",
212 result
->host
= host_str
;
214 if (result
->servicename
!= NULL
&& (strlen(result
->servicename
) == 0)) {
215 DBG_ERR("Failed to parse spn %s, empty servicename "
216 "definition\n", srvprinc
);
219 if (port_str
!= NULL
) {
220 if (strlen(port_str
) == 0) {
221 DBG_ERR("Failed to parse spn %s, empty port "
222 "definition\n", srvprinc
);
225 result
->port
= (int32_t)strtol(port_str
, NULL
, 10);
226 if (result
->port
<= 0
227 || result
->port
> 65535
228 || errno
== ERANGE
) {
229 DBG_ERR("Failed to parse spn %s, port number "
230 "conversion failed\n", srvprinc
);