summaryrefslogtreecommitdiff
path: root/source3/libads
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2003-02-15 00:29:21 +0000
committerAndrew Bartlett <abartlet@samba.org>2003-02-15 00:29:21 +0000
commite4202a9fe70785a0a5b47c90df696a880294d310 (patch)
tree452600615827b27c95820d184ee495e476f57618 /source3/libads
parent3b2693f1ae3b1e06d3015843d2933177fcb97a87 (diff)
downloadsamba-e4202a9fe70785a0a5b47c90df696a880294d310.tar.gz
samba-e4202a9fe70785a0a5b47c90df696a880294d310.tar.bz2
samba-e4202a9fe70785a0a5b47c90df696a880294d310.zip
Antti Andreimann <Antti.Andreimann@mail.ee> has done some changes to enable
users w/o full administrative access on computer accounts to join a computer into AD domain. The patch and detailed changelog is available at: http://www.itcollege.ee/~aandreim/samba This is a list of changes in general: 1. When creating machine account do not fail if SD cannot be changed. setting SD is not mandatory and join will work perfectly without it. 2. Implement KPASSWD CHANGEPW protocol for changing trust password so machine account does not need to have reset password right for itself. 3. Command line utilities no longer interfere with user's existing kerberos ticket cache. 4. Command line utilities can do kerberos authentication even if username is specified (-U). Initial TGT will be requested in this case. I've modified the patch to share the kinit code, rather than copying it, and updated it to current CVS. The other change included in the original patch (local realms) has been left out for now. Andrew Bartlett (This used to be commit ce52f1c2ed4d3ddafe8ae6258c90b90fa434fe43)
Diffstat (limited to 'source3/libads')
-rw-r--r--source3/libads/krb5_setpw.c428
-rw-r--r--source3/libads/ldap.c24
-rw-r--r--source3/libads/sasl.c7
-rw-r--r--source3/libads/util.c10
4 files changed, 337 insertions, 132 deletions
diff --git a/source3/libads/krb5_setpw.c b/source3/libads/krb5_setpw.c
index 087b0e9a71..c3ec754e39 100644
--- a/source3/libads/krb5_setpw.c
+++ b/source3/libads/krb5_setpw.c
@@ -24,13 +24,23 @@
#ifdef HAVE_KRB5
#define DEFAULT_KPASSWD_PORT 464
-#define KRB5_KPASSWD_VERS_CHANGEPW 1
-#define KRB5_KPASSWD_VERS_SETPW 0xff80
-#define KRB5_KPASSWD_ACCESSDENIED 5
-#define KRB5_KPASSWD_BAD_VERSION 6
-
-/* This implements the Kerb password change protocol as specifed in
- * kerb-chg-password-02.txt
+#define KRB5_KPASSWD_VERS_CHANGEPW 1
+#define KRB5_KPASSWD_VERS_SETPW 2
+#define KRB5_KPASSWD_VERS_SETPW_MS 0xff80
+#define KRB5_KPASSWD_ACCESSDENIED 5
+#define KRB5_KPASSWD_BAD_VERSION 6
+#define KRB5_KPASSWD_INITIAL_FLAG_NEEDED 7
+
+/* Those are defined by kerberos-set-passwd-02.txt and are probably
+ * not supported by M$ implementation */
+#define KRB5_KPASSWD_POLICY_REJECT 8
+#define KRB5_KPASSWD_BAD_PRINCIPAL 9
+#define KRB5_KPASSWD_ETYPE_NOSUPP 10
+
+/* This implements kerberos password change protocol as specified in
+ * kerb-chg-password-02.txt and kerberos-set-passwd-02.txt
+ * as well as microsoft version of the protocol
+ * as specified in kerberos-set-passwd-00.txt
*/
static DATA_BLOB encode_krb5_setpw(const char *principal, const char *password)
{
@@ -101,7 +111,8 @@ static DATA_BLOB encode_krb5_setpw(const char *principal, const char *password)
return ret;
}
-static krb5_error_code build_setpw_request(krb5_context context,
+static krb5_error_code build_kpasswd_request(uint16 pversion,
+ krb5_context context,
krb5_auth_context auth_context,
krb5_data *ap_req,
const char *princ,
@@ -123,7 +134,14 @@ static krb5_error_code build_setpw_request(krb5_context context,
return ret;
}
- setpw = encode_krb5_setpw(princ, passwd);
+ /* handle protocol differences in chpw and setpw */
+ if (pversion == KRB5_KPASSWD_VERS_CHANGEPW)
+ setpw = data_blob(passwd, strlen(passwd));
+ else if (pversion == KRB5_KPASSWD_VERS_SETPW ||
+ pversion == KRB5_KPASSWD_VERS_SETPW_MS)
+ setpw = encode_krb5_setpw(princ, passwd);
+ else
+ return EINVAL;
encoded_setpw.data = setpw.data;
encoded_setpw.length = setpw.length;
@@ -144,7 +162,7 @@ static krb5_error_code build_setpw_request(krb5_context context,
/* see the RFC for details */
p = ((char *)packet->data) + 2;
- RSSVAL(p, 0, 0xff80);
+ RSSVAL(p, 0, pversion);
p += 2;
RSSVAL(p, 0, ap_req->length);
p += 2;
@@ -160,6 +178,49 @@ static krb5_error_code build_setpw_request(krb5_context context,
return 0;
}
+static krb5_error_code krb5_setpw_result_code_string(krb5_context context,
+ int result_code,
+ char **code_string)
+{
+ switch (result_code) {
+ case KRB5_KPASSWD_MALFORMED:
+ *code_string = "Malformed request error";
+ break;
+ case KRB5_KPASSWD_HARDERROR:
+ *code_string = "Server error";
+ break;
+ case KRB5_KPASSWD_AUTHERROR:
+ *code_string = "Authentication error";
+ break;
+ case KRB5_KPASSWD_SOFTERROR:
+ *code_string = "Password change rejected";
+ break;
+ case KRB5_KPASSWD_ACCESSDENIED:
+ *code_string = "Client does not have proper authorization";
+ break;
+ case KRB5_KPASSWD_BAD_VERSION:
+ *code_string = "Protocol version not supported";
+ break;
+ case KRB5_KPASSWD_INITIAL_FLAG_NEEDED:
+ *code_string = "Authorization ticket must have initial flag set";
+ break;
+ case KRB5_KPASSWD_POLICY_REJECT:
+ *code_string = "Password rejected due to policy requirements";
+ break;
+ case KRB5_KPASSWD_BAD_PRINCIPAL:
+ *code_string = "Target principal does not exist";
+ break;
+ case KRB5_KPASSWD_ETYPE_NOSUPP:
+ *code_string = "Unsupported encryption type";
+ break;
+ default:
+ *code_string = "Password change failed";
+ break;
+ }
+
+ return(0);
+}
+
static krb5_error_code parse_setpw_reply(krb5_context context,
krb5_auth_context auth_context,
krb5_data *packet)
@@ -194,8 +255,11 @@ static krb5_error_code parse_setpw_reply(krb5_context context,
p += 2;
vnum = RSVAL(p, 0); p += 2;
-
- if (vnum != KRB5_KPASSWD_VERS_SETPW && vnum != KRB5_KPASSWD_VERS_CHANGEPW) {
+
+ /* FIXME: According to standard there is only one type of reply */
+ if (vnum != KRB5_KPASSWD_VERS_SETPW &&
+ vnum != KRB5_KPASSWD_VERS_SETPW_MS &&
+ vnum != KRB5_KPASSWD_VERS_CHANGEPW) {
DEBUG(1,("Bad vnum (%d) from kpasswd server\n", vnum));
return KRB5KDC_ERR_BAD_PVNO;
}
@@ -247,96 +311,56 @@ static krb5_error_code parse_setpw_reply(krb5_context context,
free(clearresult.data);
if ((res_code < KRB5_KPASSWD_SUCCESS) ||
- (res_code >= KRB5_KPASSWD_ACCESSDENIED)) {
+ (res_code > KRB5_KPASSWD_ETYPE_NOSUPP)) {
return KRB5KRB_AP_ERR_MODIFIED;
}
-
- return 0;
+
+ if(res_code == KRB5_KPASSWD_SUCCESS)
+ return 0;
+ else {
+ char *errstr;
+ krb5_setpw_result_code_string(context, res_code, &errstr);
+ DEBUG(1, ("Error changing password: %s\n", errstr));
+
+ switch(res_code) {
+ case KRB5_KPASSWD_ACCESSDENIED:
+ return KRB5KDC_ERR_BADOPTION;
+ break;
+ case KRB5_KPASSWD_INITIAL_FLAG_NEEDED:
+ return KV5M_ALT_METHOD;
+ break;
+ case KRB5_KPASSWD_ETYPE_NOSUPP:
+ return KRB5KDC_ERR_ETYPE_NOSUPP;
+ break;
+ case KRB5_KPASSWD_BAD_PRINCIPAL:
+ return KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
+ break;
+ case KRB5_KPASSWD_POLICY_REJECT:
+ return KRB5KDC_ERR_POLICY;
+ break;
+ default:
+ return KRB5KRB_ERR_GENERIC;
+ break;
+ }
+ }
}
-ADS_STATUS krb5_set_password(const char *kdc_host, const char *princ, const char *newpw,
- int time_offset)
+static ADS_STATUS do_krb5_kpasswd_request(krb5_context context,
+ const char *kdc_host,
+ uint16 pversion,
+ krb5_creds *credsp,
+ const char *princ,
+ const char *newpw)
{
- krb5_context context;
krb5_auth_context auth_context = NULL;
- krb5_principal principal;
- char *princ_name;
- char *realm;
- krb5_creds creds, *credsp;
- krb5_ccache ccache;
krb5_data ap_req, chpw_req, chpw_rep;
int ret, sock, addr_len;
struct sockaddr remote_addr, local_addr;
krb5_address local_kaddr, remote_kaddr;
- ret = krb5_init_context(&context);
- if (ret) {
- DEBUG(1,("Failed to init krb5 context (%s)\n", error_message(ret)));
- return ADS_ERROR_KRB5(ret);
- }
-
- if (time_offset != 0) {
- krb5_set_real_time(context, time(NULL) + time_offset, 0);
- }
-
- ret = krb5_cc_default(context, &ccache);
- if (ret) {
- krb5_free_context(context);
- DEBUG(1,("Failed to get default creds (%s)\n", error_message(ret)));
- return ADS_ERROR_KRB5(ret);
- }
-
- ZERO_STRUCT(creds);
-
- realm = strchr(princ, '@');
- realm++;
-
- asprintf(&princ_name, "kadmin/changepw@%s", realm);
- ret = krb5_parse_name(context, princ_name, &creds.server);
- if (ret) {
- krb5_free_context(context);
- DEBUG(1,("Failed to parse kadmin/changepw (%s)\n", error_message(ret)));
- return ADS_ERROR_KRB5(ret);
- }
- free(princ_name);
-
- /* parse the principal we got as a function argument */
- ret = krb5_parse_name(context, princ, &principal);
- if (ret) {
- krb5_free_context(context);
- DEBUG(1,("Failed to parse %s (%s)\n", princ_name, error_message(ret)));
- return ADS_ERROR_KRB5(ret);
- }
-
- krb5_princ_set_realm(context, creds.server,
- krb5_princ_realm(context, principal));
-
- ret = krb5_cc_get_principal(context, ccache, &creds.client);
- if (ret) {
- krb5_free_principal(context, principal);
- krb5_free_context(context);
- DEBUG(1,("Failed to get principal from ccache (%s)\n",
- error_message(ret)));
- return ADS_ERROR_KRB5(ret);
- }
-
- ret = krb5_get_credentials(context, 0, ccache, &creds, &credsp);
- if (ret) {
- krb5_free_principal(context, creds.client);
- krb5_free_principal(context, principal);
- krb5_free_context(context);
- DEBUG(1,("krb5_get_credentials failed (%s)\n", error_message(ret)));
- return ADS_ERROR_KRB5(ret);
- }
-
- /* we might have to call krb5_free_creds(...) from now on ... */
ret = krb5_mk_req_extended(context, &auth_context, AP_OPTS_USE_SUBKEY,
NULL, credsp, &ap_req);
if (ret) {
- krb5_free_creds(context, credsp);
- krb5_free_principal(context, creds.client);
- krb5_free_principal(context, principal);
- krb5_free_context(context);
DEBUG(1,("krb5_mk_req_extended failed (%s)\n", error_message(ret)));
return ADS_ERROR_KRB5(ret);
}
@@ -345,10 +369,7 @@ ADS_STATUS krb5_set_password(const char *kdc_host, const char *princ, const char
if (sock == -1) {
int rc = errno;
free(ap_req.data);
- krb5_free_creds(context, credsp);
- krb5_free_principal(context, creds.client);
- krb5_free_principal(context, principal);
- krb5_free_context(context);
+ krb5_auth_con_free(context, auth_context);
DEBUG(1,("failed to open kpasswd socket to %s (%s)\n",
kdc_host, strerror(errno)));
return ADS_ERROR_SYSTEM(rc);
@@ -366,23 +387,17 @@ ADS_STATUS krb5_set_password(const char *kdc_host, const char *princ, const char
if (ret) {
close(sock);
free(ap_req.data);
- krb5_free_creds(context, credsp);
- krb5_free_principal(context, creds.client);
- krb5_free_principal(context, principal);
- krb5_free_context(context);
+ krb5_auth_con_free(context, auth_context);
DEBUG(1,("krb5_auth_con_setaddrs failed (%s)\n", error_message(ret)));
return ADS_ERROR_KRB5(ret);
}
- ret = build_setpw_request(context, auth_context, &ap_req,
+ ret = build_kpasswd_request(pversion, context, auth_context, &ap_req,
princ, newpw, &chpw_req);
if (ret) {
close(sock);
free(ap_req.data);
- krb5_free_creds(context, credsp);
- krb5_free_principal(context, creds.client);
- krb5_free_principal(context, principal);
- krb5_free_context(context);
+ krb5_auth_con_free(context, auth_context);
DEBUG(1,("build_setpw_request failed (%s)\n", error_message(ret)));
return ADS_ERROR_KRB5(ret);
}
@@ -391,10 +406,7 @@ ADS_STATUS krb5_set_password(const char *kdc_host, const char *princ, const char
close(sock);
free(chpw_req.data);
free(ap_req.data);
- krb5_free_creds(context, credsp);
- krb5_free_principal(context, creds.client);
- krb5_free_principal(context, principal);
- krb5_free_context(context);
+ krb5_auth_con_free(context, auth_context);
DEBUG(1,("send of chpw failed (%s)\n", strerror(errno)));
return ADS_ERROR_SYSTEM(errno);
}
@@ -406,10 +418,7 @@ ADS_STATUS krb5_set_password(const char *kdc_host, const char *princ, const char
if (!chpw_rep.data) {
close(sock);
free(ap_req.data);
- krb5_free_creds(context, credsp);
- krb5_free_principal(context, creds.client);
- krb5_free_principal(context, principal);
- krb5_free_context(context);
+ krb5_auth_con_free(context, auth_context);
DEBUG(1,("send of chpw failed (%s)\n", strerror(errno)));
errno = ENOMEM;
return ADS_ERROR_SYSTEM(errno);
@@ -420,10 +429,7 @@ ADS_STATUS krb5_set_password(const char *kdc_host, const char *princ, const char
close(sock);
free(chpw_rep.data);
free(ap_req.data);
- krb5_free_creds(context, credsp);
- krb5_free_principal(context, creds.client);
- krb5_free_principal(context, principal);
- krb5_free_context(context);
+ krb5_auth_con_free(context, auth_context);
DEBUG(1,("recv of chpw reply failed (%s)\n", strerror(errno)));
return ADS_ERROR_SYSTEM(errno);
}
@@ -435,10 +441,7 @@ ADS_STATUS krb5_set_password(const char *kdc_host, const char *princ, const char
if (ret) {
free(chpw_rep.data);
free(ap_req.data);
- krb5_free_creds(context, credsp);
- krb5_free_principal(context, creds.client);
- krb5_free_principal(context, principal);
- krb5_free_context(context);
+ krb5_auth_con_free(context, auth_context);
DEBUG(1,("krb5_auth_con_setaddrs on reply failed (%s)\n",
error_message(ret)));
return ADS_ERROR_KRB5(ret);
@@ -449,22 +452,194 @@ ADS_STATUS krb5_set_password(const char *kdc_host, const char *princ, const char
if (ret) {
free(ap_req.data);
- krb5_free_creds(context, credsp);
- krb5_free_principal(context, creds.client);
- krb5_free_principal(context, principal);
- krb5_free_context(context);
+ krb5_auth_con_free(context, auth_context);
DEBUG(1,("parse_setpw_reply failed (%s)\n",
error_message(ret)));
return ADS_ERROR_KRB5(ret);
}
free(ap_req.data);
+ krb5_auth_con_free(context, auth_context);
+
+ return ADS_SUCCESS;
+}
+
+ADS_STATUS krb5_set_password(const char *kdc_host, const char *princ, const char *newpw,
+ int time_offset)
+{
+
+ ADS_STATUS aret;
+ krb5_error_code ret;
+ krb5_context context;
+ krb5_principal principal;
+ char *princ_name;
+ char *realm;
+ krb5_creds creds, *credsp;
+ krb5_ccache ccache;
+
+ ret = krb5_init_context(&context);
+ if (ret) {
+ DEBUG(1,("Failed to init krb5 context (%s)\n", error_message(ret)));
+ return ADS_ERROR_KRB5(ret);
+ }
+
+ if (time_offset != 0) {
+ krb5_set_real_time(context, time(NULL) + time_offset, 0);
+ }
+
+ ret = krb5_cc_default(context, &ccache);
+ if (ret) {
+ krb5_free_context(context);
+ DEBUG(1,("Failed to get default creds (%s)\n", error_message(ret)));
+ return ADS_ERROR_KRB5(ret);
+ }
+
+ ZERO_STRUCT(creds);
+
+ realm = strchr(princ, '@');
+ realm++;
+
+ asprintf(&princ_name, "kadmin/changepw@%s", realm);
+ ret = krb5_parse_name(context, princ_name, &creds.server);
+ if (ret) {
+ krb5_free_context(context);
+ DEBUG(1,("Failed to parse kadmin/changepw (%s)\n", error_message(ret)));
+ return ADS_ERROR_KRB5(ret);
+ }
+ free(princ_name);
+
+ /* parse the principal we got as a function argument */
+ ret = krb5_parse_name(context, princ, &principal);
+ if (ret) {
+ krb5_free_context(context);
+ DEBUG(1,("Failed to parse %s (%s)\n", princ_name, error_message(ret)));
+ return ADS_ERROR_KRB5(ret);
+ }
+
+ krb5_princ_set_realm(context, creds.server,
+ krb5_princ_realm(context, principal));
+
+ ret = krb5_cc_get_principal(context, ccache, &creds.client);
+ if (ret) {
+ krb5_free_principal(context, principal);
+ krb5_free_context(context);
+ DEBUG(1,("Failed to get principal from ccache (%s)\n",
+ error_message(ret)));
+ return ADS_ERROR_KRB5(ret);
+ }
+
+ ret = krb5_get_credentials(context, 0, ccache, &creds, &credsp);
+ if (ret) {
+ krb5_free_principal(context, creds.client);
+ krb5_free_principal(context, principal);
+ krb5_free_context(context);
+ DEBUG(1,("krb5_get_credentials failed (%s)\n", error_message(ret)));
+ return ADS_ERROR_KRB5(ret);
+ }
+
+ /* we might have to call krb5_free_creds(...) from now on ... */
+
+ aret = do_krb5_kpasswd_request(context, kdc_host,
+ KRB5_KPASSWD_VERS_SETPW_MS,
+ credsp, princ, newpw);
+
krb5_free_creds(context, credsp);
krb5_free_principal(context, creds.client);
+ krb5_free_principal(context, creds.server);
krb5_free_principal(context, principal);
krb5_free_context(context);
- return ADS_SUCCESS;
+ return aret;
+}
+
+/*
+ we use a prompter to avoid a crash bug in the kerberos libs when
+ dealing with empty passwords
+ this prompter is just a string copy ...
+*/
+static krb5_error_code
+kerb_prompter(krb5_context ctx, void *data,
+ const char *name,
+ const char *banner,
+ int num_prompts,
+ krb5_prompt prompts[])
+{
+ if (num_prompts == 0) return 0;
+
+ memset(prompts[0].reply->data, 0, prompts[0].reply->length);
+ if (prompts[0].reply->length > 0) {
+ if (data) {
+ strncpy(prompts[0].reply->data, data, prompts[0].reply->length-1);
+ prompts[0].reply->length = strlen(prompts[0].reply->data);
+ } else {
+ prompts[0].reply->length = 0;
+ }
+ }
+ return 0;
+}
+
+ADS_STATUS krb5_chg_password(const char *kdc_host,
+ const char *principal,
+ const char *oldpw,
+ const char *newpw,
+ int time_offset)
+{
+ ADS_STATUS aret;
+ krb5_error_code ret;
+ krb5_context context;
+ krb5_principal princ;
+ krb5_get_init_creds_opt opts;
+ krb5_creds creds;
+ char *chpw_princ = NULL, *password;
+
+ ret = krb5_init_context(&context);
+ if (ret) {
+ DEBUG(1,("Failed to init krb5 context (%s)\n", error_message(ret)));
+ return ADS_ERROR_KRB5(ret);
+ }
+
+ if ((ret = krb5_parse_name(context, principal,
+ &princ))) {
+ krb5_free_context(context);
+ DEBUG(1,("Failed to parse %s (%s)\n", principal, error_message(ret)));
+ return ADS_ERROR_KRB5(ret);
+ }
+
+ krb5_get_init_creds_opt_init(&opts);
+ krb5_get_init_creds_opt_set_tkt_life(&opts, 5*60);
+ krb5_get_init_creds_opt_set_renew_life(&opts, 0);
+ krb5_get_init_creds_opt_set_forwardable(&opts, 0);
+ krb5_get_init_creds_opt_set_proxiable(&opts, 0);
+
+ /* We have to obtain an INITIAL changepw ticket for changing password */
+ asprintf(&chpw_princ, "kadmin/changepw@%s",
+ (char *) krb5_princ_realm(context, princ));
+ password = strdup(oldpw);
+ ret = krb5_get_init_creds_password(context, &creds, princ, password,
+ kerb_prompter, NULL,
+ 0, chpw_princ, &opts);
+ SAFE_FREE(chpw_princ);
+ SAFE_FREE(password);
+
+ if (ret) {
+ if (ret == KRB5KRB_AP_ERR_BAD_INTEGRITY)
+ DEBUG(1,("Password incorrect while getting initial ticket"));
+ else
+ DEBUG(1,("krb5_get_init_creds_password failed (%s)\n", error_message(ret)));
+
+ krb5_free_principal(context, princ);
+ krb5_free_context(context);
+ return ADS_ERROR_KRB5(ret);
+ }
+
+ aret = do_krb5_kpasswd_request(context, kdc_host,
+ KRB5_KPASSWD_VERS_CHANGEPW,
+ &creds, principal, newpw);
+
+ krb5_free_principal(context, princ);
+ krb5_free_context(context);
+
+ return aret;
}
@@ -480,7 +655,12 @@ ADS_STATUS kerberos_set_password(const char *kpasswd_server,
return ADS_ERROR_KRB5(ret);
}
- return krb5_set_password(kpasswd_server, target_principal, new_password, time_offset);
+ if (!strcmp(auth_principal, target_principal))
+ return krb5_chg_password(kpasswd_server, target_principal,
+ auth_password, new_password, time_offset);
+ else
+ return krb5_set_password(kpasswd_server, target_principal,
+ new_password, time_offset);
}
@@ -515,4 +695,6 @@ ADS_STATUS ads_set_machine_password(ADS_STRUCT *ads,
return status;
}
+
+
#endif
diff --git a/source3/libads/ldap.c b/source3/libads/ldap.c
index 47a94f0a08..c92e481078 100644
--- a/source3/libads/ldap.c
+++ b/source3/libads/ldap.c
@@ -1022,7 +1022,7 @@ char *ads_ou_string(const char *org_unit)
static ADS_STATUS ads_add_machine_acct(ADS_STRUCT *ads, const char *hostname,
const char *org_unit)
{
- ADS_STATUS ret;
+ ADS_STATUS ret, status;
char *host_spn, *host_upn, *new_dn, *samAccountName, *controlstr;
char *ou_str;
TALLOC_CTX *ctx;
@@ -1089,9 +1089,21 @@ static ADS_STATUS ads_add_machine_acct(ADS_STRUCT *ads, const char *hostname,
ads_mod_str(ctx, &mods, "operatingSystem", "Samba");
ads_mod_str(ctx, &mods, "operatingSystemVersion", VERSION);
- ads_gen_add(ads, new_dn, mods);
- ret = ads_set_machine_sd(ads, hostname, new_dn);
+ ret = ads_gen_add(ads, new_dn, mods);
+ if (!ADS_ERR_OK(ret))
+ goto done;
+
+ /* Do not fail if we can't set security descriptor
+ * it shouldn't be mandatory and probably we just
+ * don't have enough rights to do it.
+ */
+ status = ads_set_machine_sd(ads, hostname, new_dn);
+
+ if (!ADS_ERR_OK(status)) {
+ DEBUG(0, ("Warning: ads_set_machine_sd: %s\n",
+ ads_errstr(status)));
+ }
done:
talloc_destroy(ctx);
return ret;
@@ -1406,7 +1418,7 @@ ADS_STATUS ads_leave_realm(ADS_STRUCT *ads, const char *hostname)
**/
ADS_STATUS ads_set_machine_sd(ADS_STRUCT *ads, const char *hostname, char *dn)
{
- const char *attrs[] = {"ntSecurityDescriptor", "objectSid", 0};
+ const char *attrs[] = {"nTSecurityDescriptor", "objectSid", 0};
char *exp = 0;
size_t sd_size = 0;
struct berval bval = {0, NULL};
@@ -1423,6 +1435,10 @@ ADS_STATUS ads_set_machine_sd(ADS_STRUCT *ads, const char *hostname, char *dn)
SEC_DESC *psd = 0;
TALLOC_CTX *ctx = 0;
+ /* Avoid segmentation fault in prs_mem_free if
+ * we have to bail out before prs_init */
+ ps_wire.is_dynamic = False;
+
if (!ads) return ADS_ERROR(LDAP_SERVER_DOWN);
ret = ADS_ERROR(LDAP_SUCCESS);
diff --git a/source3/libads/sasl.c b/source3/libads/sasl.c
index 7aa77bf2a2..29d4533a54 100644
--- a/source3/libads/sasl.c
+++ b/source3/libads/sasl.c
@@ -241,7 +241,12 @@ static ADS_STATUS ads_sasl_gssapi_bind(ADS_STRUCT *ads)
ADS_STATUS status;
krb5_principal principal;
krb5_context ctx;
- krb5_enctype enc_types[] = {ENCTYPE_DES_CBC_MD5, ENCTYPE_NULL};
+ krb5_enctype enc_types[] = {
+#ifdef ENCTYPE_ARCFOUR_HMAC
+ ENCTYPE_ARCFOUR_HMAC,
+#endif
+ ENCTYPE_DES_CBC_MD5,
+ ENCTYPE_NULL};
gss_OID_desc nt_principal =
{10, "\052\206\110\206\367\022\001\002\002\002"};
diff --git a/source3/libads/util.c b/source3/libads/util.c
index 021f2d93e4..335cabc952 100644
--- a/source3/libads/util.c
+++ b/source3/libads/util.c
@@ -29,7 +29,7 @@ ADS_STATUS ads_change_trust_account_password(ADS_STRUCT *ads, char *host_princip
char *new_password;
char *service_principal;
ADS_STATUS ret;
-
+
if ((password = secrets_fetch_machine_password()) == NULL) {
DEBUG(1,("Failed to retrieve password for principal %s\n", host_principal));
return ADS_ERROR_SYSTEM(ENOENT);
@@ -38,15 +38,17 @@ ADS_STATUS ads_change_trust_account_password(ADS_STRUCT *ads, char *host_princip
tmp_password = generate_random_str(DEFAULT_TRUST_ACCOUNT_PASSWORD_LENGTH);
new_password = strdup(tmp_password);
asprintf(&service_principal, "HOST/%s", host_principal);
-
- ret = kerberos_set_password(ads->auth.kdc_server, host_principal, password,
- service_principal, new_password, ads->auth.time_offset);
+
+ ret = kerberos_set_password(ads->auth.kdc_server, service_principal, password, service_principal, new_password, ads->auth.time_offset);
+
+ if (!ADS_ERR_OK(ret)) goto failed;
if (!secrets_store_machine_password(new_password)) {
DEBUG(1,("Failed to save machine password\n"));
return ADS_ERROR_SYSTEM(EACCES);
}
+failed:
SAFE_FREE(service_principal);
SAFE_FREE(new_password);