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 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
,
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
);
138 * @brief Parses windows style SPN service/host:port/servicename
139 * serviceclass - A string that identifies the general class of service
141 * host - A netbios name or fully-qualified DNS name
142 * port - An optional TCP or UDP port number
143 * servicename - An optional distinguished name, GUID, DNS name or
144 * DNS name of an SRV or MX record. (not needed for host
147 * @param[in] ctx - Talloc context.
148 * @param[in] srvprinc - The service principal
150 * @return - struct spn_struct containing the fields parsed or NULL
151 * if srvprinc could not be parsed.
153 struct spn_struct
*parse_spn(TALLOC_CTX
*ctx
, const char *srvprinc
)
155 struct spn_struct
* result
= NULL
;
157 char *port_str
= NULL
;
158 char *host_str
= NULL
;
160 result
= talloc_zero(ctx
, struct spn_struct
);
161 if (result
== NULL
) {
162 DBG_ERR("Out of memory\n");
166 result
->serviceclass
= talloc_strdup(result
, srvprinc
);
167 if (result
->serviceclass
== NULL
) {
168 DBG_ERR("Out of memory\n");
173 tmp
= strchr_m(result
->serviceclass
, '/');
176 DBG_ERR("Failed to parse spn %s, no host definition\n",
181 /* terminate service principal */
186 tmp
= strchr_m(host_str
, ':');
195 tmp
= strchr_m(tmp
, '/');
199 result
->servicename
= tmp
;
202 if (strlen(host_str
) == 0) {
204 DBG_ERR("Failed to parse spn %s, illegal host definition\n",
208 result
->host
= host_str
;
210 if (result
->servicename
!= NULL
&& (strlen(result
->servicename
) == 0)) {
211 DBG_ERR("Failed to parse spn %s, empty servicename "
212 "definition\n", srvprinc
);
215 if (port_str
!= NULL
) {
216 if (strlen(port_str
) == 0) {
217 DBG_ERR("Failed to parse spn %s, empty port "
218 "definition\n", srvprinc
);
221 result
->port
= (int32_t)strtol(port_str
, NULL
, 10);
222 if (result
->port
<= 0
223 || result
->port
> 65535
224 || errno
== ERANGE
) {
225 DBG_ERR("Failed to parse spn %s, port number "
226 "convertion failed\n", srvprinc
);