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(ads
->auth
.kdc_server
, host_principal
, password
, host_principal
, new_password
, 0);
115 if (!ADS_ERR_OK(ret
)) {
116 status
= ads_ntstatus(ret
);
117 DBG_ERR("kerberos_set_password(%s, %s) "
118 "failed for new_password of %s - %s\n",
119 ads
->auth
.kdc_server
, host_principal
,
120 domain
, nt_errstr(status
));
121 secrets_failed_password_change(ads
->auth
.kdc_server
,
122 NT_STATUS_NOT_COMMITTED
,
128 status
= secrets_finish_password_change(ads
->auth
.kdc_server
, now
, info
);
129 if (!NT_STATUS_IS_OK(status
)) {
130 DEBUG(1,("Failed to save machine password\n"));
131 return ADS_ERROR_NT(status
);
139 * @brief Parses windows style SPN service/host:port/servicename
140 * serviceclass - A string that identifies the general class of service
142 * host - A netbios name or fully-qualified DNS name
143 * port - An optional TCP or UDP port number
144 * servicename - An optional distinguished name, GUID, DNS name or
145 * DNS name of an SRV or MX record. (not needed for host
148 * @param[in] ctx - Talloc context.
149 * @param[in] srvprinc - The service principal
151 * @return - struct spn_struct containing the fields parsed or NULL
152 * if srvprinc could not be parsed.
154 struct spn_struct
*parse_spn(TALLOC_CTX
*ctx
, const char *srvprinc
)
156 struct spn_struct
* result
= NULL
;
158 char *port_str
= NULL
;
159 char *host_str
= NULL
;
161 result
= talloc_zero(ctx
, struct spn_struct
);
162 if (result
== NULL
) {
163 DBG_ERR("Out of memory\n");
167 result
->serviceclass
= talloc_strdup(result
, srvprinc
);
168 if (result
->serviceclass
== NULL
) {
169 DBG_ERR("Out of memory\n");
174 tmp
= strchr_m(result
->serviceclass
, '/');
177 DBG_ERR("Failed to parse spn %s, no host definition\n",
182 /* terminate service principal */
187 tmp
= strchr_m(host_str
, ':');
196 tmp
= strchr_m(tmp
, '/');
200 result
->servicename
= tmp
;
203 if (strlen(host_str
) == 0) {
205 DBG_ERR("Failed to parse spn %s, illegal host definition\n",
209 result
->host
= host_str
;
211 if (result
->servicename
!= NULL
&& (strlen(result
->servicename
) == 0)) {
212 DBG_ERR("Failed to parse spn %s, empty servicename "
213 "definition\n", srvprinc
);
216 if (port_str
!= NULL
) {
217 if (strlen(port_str
) == 0) {
218 DBG_ERR("Failed to parse spn %s, empty port "
219 "definition\n", srvprinc
);
222 result
->port
= (int32_t)strtol(port_str
, NULL
, 10);
223 if (result
->port
<= 0
224 || result
->port
> 65535
225 || errno
== ERANGE
) {
226 DBG_ERR("Failed to parse spn %s, port number "
227 "conversion failed\n", srvprinc
);