summaryrefslogtreecommitdiff
path: root/source3/libads
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2003-02-24 02:55:00 +0000
committerAndrew Bartlett <abartlet@samba.org>2003-02-24 02:55:00 +0000
commitd1221c9b6c369113a531063737890b58d89bf6fe (patch)
treeefc7b8b8d33b675404dc7c5bc018db47a4136212 /source3/libads
parente075e1dfa9a88b5edadc9c989200a52f48182cef (diff)
downloadsamba-d1221c9b6c369113a531063737890b58d89bf6fe.tar.gz
samba-d1221c9b6c369113a531063737890b58d89bf6fe.tar.bz2
samba-d1221c9b6c369113a531063737890b58d89bf6fe.zip
Merge from HEAD client-side authentication changes:
- new kerberos code, allowing the account to change it's own password without special SD settings required - NTLMSSP client code, now seperated from cliconnect.c - NTLMv2 client code - SMB signing fixes Andrew Bartlett (This used to be commit 837680ca517982f2e5944730581a83012d4181ae)
Diffstat (limited to 'source3/libads')
-rw-r--r--source3/libads/krb5_setpw.c429
-rw-r--r--source3/libads/ldap.c51
-rw-r--r--source3/libads/sasl.c7
-rw-r--r--source3/libads/util.c10
4 files changed, 351 insertions, 146 deletions
diff --git a/source3/libads/krb5_setpw.c b/source3/libads/krb5_setpw.c
index 087b0e9a71..9d8fb8d24c 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,57 @@ 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 KRB5KDC_ERR_BADOPTION;
+ /* return KV5M_ALT_METHOD; MIT-only define */
+ 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 +370,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 +388,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 +407,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 +419,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 +430,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 +442,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 +453,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 +656,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 +696,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 67669fc078..bc90e90ea0 100644
--- a/source3/libads/ldap.c
+++ b/source3/libads/ldap.c
@@ -816,18 +816,18 @@ static ADS_STATUS ads_modlist_add(TALLOC_CTX *ctx, ADS_MODLIST *mods,
{
int curmod;
LDAPMod **modlist = (LDAPMod **) *mods;
- void **values;
+ struct berval **ber_values;
+ char **char_values;
if (!invals) {
- values = NULL;
mod_op = LDAP_MOD_DELETE;
} else {
if (mod_op & LDAP_MOD_BVALUES)
- values = (void **) ads_dup_values(ctx,
- (const struct berval **)invals);
+ ber_values = ads_dup_values(ctx,
+ (const struct berval **)invals);
else
- values = (void **) ads_push_strvals(ctx,
- (const char **) invals);
+ char_values = ads_push_strvals(ctx,
+ (const char **) invals);
}
/* find the first empty slot */
@@ -846,10 +846,14 @@ static ADS_STATUS ads_modlist_add(TALLOC_CTX *ctx, ADS_MODLIST *mods,
if (!(modlist[curmod] = talloc_zero(ctx, sizeof(LDAPMod))))
return ADS_ERROR(LDAP_NO_MEMORY);
modlist[curmod]->mod_type = talloc_strdup(ctx, name);
- if (mod_op & LDAP_MOD_BVALUES)
- modlist[curmod]->mod_bvalues = (struct berval **) values;
- else
- modlist[curmod]->mod_values = (char **) values;
+ if (mod_op & LDAP_MOD_BVALUES) {
+ modlist[curmod]->mod_bvalues = ber_values;
+ } else if (mod_op & LDAP_MOD_DELETE) {
+ modlist[curmod]->mod_values = NULL;
+ } else {
+ modlist[curmod]->mod_values = char_values;
+ }
+
modlist[curmod]->mod_op = mod_op;
return ADS_ERROR(LDAP_SUCCESS);
}
@@ -1500,16 +1504,24 @@ ADS_STATUS ads_set_machine_sd(ADS_STRUCT *ads, const char *hostname, char *dn)
#endif
if (!(mods = ads_init_mods(ctx))) return ADS_ERROR(LDAP_NO_MEMORY);
- bval.bv_len = sd_size;
- bval.bv_val = talloc(ctx, sd_size);
+ bval.bv_len = prs_offset(&ps_wire);
+ bval.bv_val = talloc(ctx, bval.bv_len);
if (!bval.bv_val) {
ret = ADS_ERROR(LDAP_NO_MEMORY);
goto ads_set_sd_error;
}
- prs_copy_all_data_out(bval.bv_val, &ps_wire);
- ads_mod_ber(ctx, &mods, attrs[0], &bval);
- ret = ads_gen_mod(ads, dn, mods);
+ prs_set_offset(&ps_wire, 0);
+
+ if (!prs_copy_data_out(bval.bv_val, &ps_wire, bval.bv_len)) {
+ ret = ADS_ERROR(LDAP_NO_MEMORY);
+ goto ads_set_sd_error;
+ }
+
+ ret = ads_mod_ber(ctx, &mods, attrs[0], &bval);
+ if (ADS_ERR_OK(ret)) {
+ ret = ads_gen_mod(ads, dn, mods);
+ }
ads_set_sd_error:
ads_msgfree(ads, res);
@@ -1554,7 +1566,7 @@ char *ads_pull_string(ADS_STRUCT *ads,
char **values;
char *ret = NULL;
char *ux_string;
- int rc;
+ size_t rc;
values = ldap_get_values(ads->ld, msg, field);
if (!values)
@@ -1563,7 +1575,7 @@ char *ads_pull_string(ADS_STRUCT *ads,
if (values[0]) {
rc = pull_utf8_talloc(mem_ctx, &ux_string,
values[0]);
- if (rc != -1)
+ if (rc != (size_t)-1)
ret = ux_string;
}
@@ -1725,8 +1737,11 @@ int ads_pull_sids(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx,
count = 0;
for (i=0; values[i]; i++) {
ret = sid_parse(values[i]->bv_val, values[i]->bv_len, &(*sids)[count]);
- if (ret)
+ if (ret) {
+ fstring sid;
+ DEBUG(10, ("pulling SID: %s\n", sid_to_string(sid, &(*sids)[count])));
count++;
+ }
}
ldap_value_free_len(values);
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);