summaryrefslogtreecommitdiff
path: root/source3/libads
diff options
context:
space:
mode:
Diffstat (limited to 'source3/libads')
-rw-r--r--source3/libads/kerberos.c8
-rw-r--r--source3/libads/krb5_setpw.c14
-rw-r--r--source3/libads/ldap.c66
-rw-r--r--source3/libads/sasl.c7
-rw-r--r--source3/libads/util.c2
5 files changed, 75 insertions, 22 deletions
diff --git a/source3/libads/kerberos.c b/source3/libads/kerberos.c
index 9a486237c9..a80837cf4d 100644
--- a/source3/libads/kerberos.c
+++ b/source3/libads/kerberos.c
@@ -50,7 +50,7 @@ kerb_prompter(krb5_context ctx, void *data,
simulate a kinit, putting the tgt in the default cache location
remus@snapserver.com
*/
-int kerberos_kinit_password(const char *principal, const char *password)
+int kerberos_kinit_password(const char *principal, const char *password, int time_offset)
{
krb5_context ctx;
krb5_error_code code = 0;
@@ -60,6 +60,10 @@ int kerberos_kinit_password(const char *principal, const char *password)
if ((code = krb5_init_context(&ctx)))
return code;
+
+ if (time_offset != 0) {
+ krb5_set_real_time(ctx, time(NULL) + time_offset, 0);
+ }
if ((code = krb5_cc_default(ctx, &cc))) {
krb5_free_context(ctx);
@@ -111,7 +115,7 @@ int ads_kinit_password(ADS_STRUCT *ads)
int ret;
asprintf(&s, "%s@%s", ads->auth.user_name, ads->auth.realm);
- ret = kerberos_kinit_password(s, ads->auth.password);
+ ret = kerberos_kinit_password(s, ads->auth.password, ads->auth.time_offset);
if (ret) {
DEBUG(0,("kerberos_kinit_password %s failed: %s\n",
diff --git a/source3/libads/krb5_setpw.c b/source3/libads/krb5_setpw.c
index ec79a8658f..a49b6cbe3b 100644
--- a/source3/libads/krb5_setpw.c
+++ b/source3/libads/krb5_setpw.c
@@ -248,7 +248,8 @@ static krb5_error_code parse_setpw_reply(krb5_context context,
return 0;
}
-ADS_STATUS krb5_set_password(const char *kdc_host, const char *princ, const char *newpw)
+ADS_STATUS krb5_set_password(const char *kdc_host, const char *princ, const char *newpw,
+ int time_offset)
{
krb5_context context;
krb5_auth_context auth_context = NULL;
@@ -268,6 +269,10 @@ ADS_STATUS krb5_set_password(const char *kdc_host, const char *princ, const char
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);
@@ -452,16 +457,17 @@ ADS_STATUS krb5_set_password(const char *kdc_host, const char *princ, const char
ADS_STATUS kerberos_set_password(const char *kpasswd_server,
const char *auth_principal, const char *auth_password,
- const char *target_principal, const char *new_password)
+ const char *target_principal, const char *new_password,
+ int time_offset)
{
int ret;
- if ((ret = kerberos_kinit_password(auth_principal, auth_password))) {
+ if ((ret = kerberos_kinit_password(auth_principal, auth_password, time_offset))) {
DEBUG(1,("Failed kinit for principal %s (%s)\n", auth_principal, error_message(ret)));
return ADS_ERROR_KRB5(ret);
}
- return krb5_set_password(kpasswd_server, target_principal, new_password);
+ return krb5_set_password(kpasswd_server, target_principal, new_password, time_offset);
}
diff --git a/source3/libads/ldap.c b/source3/libads/ldap.c
index 2f70d3a285..385a9bd93f 100644
--- a/source3/libads/ldap.c
+++ b/source3/libads/ldap.c
@@ -63,6 +63,7 @@ static BOOL ads_try_connect(ADS_STRUCT *ads, const char *server, unsigned port)
ads->ldap_port = port;
ads->ldap_ip = *interpret_addr2(srv);
free(srv);
+
return True;
}
@@ -204,7 +205,6 @@ static BOOL ads_try_netbios(ADS_STRUCT *ads)
ADS_STATUS ads_connect(ADS_STRUCT *ads)
{
int version = LDAP_VERSION3;
- int code;
ADS_STATUS status;
ads->last_attempt = time(NULL);
@@ -274,7 +274,7 @@ got_connection:
}
#endif
- if (ads->auth.no_bind) {
+ if (ads->auth.flags & ADS_AUTH_NO_BIND) {
return ADS_SUCCESS;
}
@@ -1416,7 +1416,7 @@ ADS_STATUS ads_set_machine_password(ADS_STRUCT *ads,
*/
asprintf(&principal, "%s$@%s", host, ads->auth.realm);
- status = krb5_set_password(ads->auth.kdc_server, principal, password);
+ status = krb5_set_password(ads->auth.kdc_server, principal, password, ads->auth.time_offset);
free(host);
free(principal);
@@ -1622,6 +1622,26 @@ ADS_STATUS ads_USN(ADS_STRUCT *ads, uint32 *usn)
return ADS_SUCCESS;
}
+/* parse a ADS timestring - typical string is
+ '20020917091222.0Z0' which means 09:12.22 17th September
+ 2002, timezone 0 */
+static time_t ads_parse_time(const char *str)
+{
+ struct tm tm;
+
+ ZERO_STRUCT(tm);
+
+ if (sscanf(str, "%4d%2d%2d%2d%2d%2d",
+ &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
+ &tm.tm_hour, &tm.tm_min, &tm.tm_sec) != 6) {
+ return 0;
+ }
+ tm.tm_year -= 1900;
+ tm.tm_mon -= 1;
+
+ return timegm(&tm);
+}
+
/**
* Find the servers name and realm - this can be done before authentication
@@ -1632,22 +1652,36 @@ ADS_STATUS ads_USN(ADS_STRUCT *ads, uint32 *usn)
**/
ADS_STATUS ads_server_info(ADS_STRUCT *ads)
{
- const char *attrs[] = {"ldapServiceName", NULL};
+ const char *attrs[] = {"ldapServiceName", "currentTime", NULL};
ADS_STATUS status;
void *res;
- char **values;
+ char *value;
char *p;
+ char *timestr;
+ TALLOC_CTX *ctx;
+
+ if (!(ctx = talloc_init())) {
+ return ADS_ERROR(LDAP_NO_MEMORY);
+ }
status = ads_do_search(ads, "", LDAP_SCOPE_BASE, "(objectclass=*)", attrs, &res);
if (!ADS_ERR_OK(status)) return status;
- values = ldap_get_values(ads->ld, res, "ldapServiceName");
- if (!values || !values[0]) return ADS_ERROR(LDAP_NO_RESULTS_RETURNED);
+ value = ads_pull_string(ads, ctx, res, "ldapServiceName");
+ if (!value) {
+ return ADS_ERROR(LDAP_NO_RESULTS_RETURNED);
+ }
+
+ timestr = ads_pull_string(ads, ctx, res, "currentTime");
+ if (!timestr) {
+ return ADS_ERROR(LDAP_NO_RESULTS_RETURNED);
+ }
- p = strchr(values[0], ':');
+ ldap_msgfree(res);
+
+ p = strchr(value, ':');
if (!p) {
- ldap_value_free(values);
- ldap_msgfree(res);
+ talloc_destroy(ctx);
DEBUG(1, ("ads_server_info: returned ldap server name did not contain a ':' so was deemed invalid\n"));
return ADS_ERROR(LDAP_DECODING_ERROR);
}
@@ -1657,8 +1691,7 @@ ADS_STATUS ads_server_info(ADS_STRUCT *ads)
ads->config.ldap_server_name = strdup(p+1);
p = strchr(ads->config.ldap_server_name, '$');
if (!p || p[1] != '@') {
- ldap_value_free(values);
- ldap_msgfree(res);
+ talloc_destroy(ctx);
SAFE_FREE(ads->config.ldap_server_name);
DEBUG(1, ("ads_server_info: returned ldap server name did not contain '$@' so was deemed invalid\n"));
return ADS_ERROR(LDAP_DECODING_ERROR);
@@ -1675,6 +1708,15 @@ ADS_STATUS ads_server_info(ADS_STRUCT *ads)
DEBUG(3,("got ldap server name %s@%s\n",
ads->config.ldap_server_name, ads->config.realm));
+ ads->config.current_time = ads_parse_time(timestr);
+
+ if (ads->config.current_time != 0) {
+ ads->auth.time_offset = ads->config.current_time - time(NULL);
+ DEBUG(4,("time offset is %d seconds\n", ads->auth.time_offset));
+ }
+
+ talloc_destroy(ctx);
+
return ADS_SUCCESS;
}
diff --git a/source3/libads/sasl.c b/source3/libads/sasl.c
index 12a5722319..c110c1d2cd 100644
--- a/source3/libads/sasl.c
+++ b/source3/libads/sasl.c
@@ -122,7 +122,7 @@ static ADS_STATUS ads_sasl_spnego_krb5_bind(ADS_STRUCT *ads, const char *princip
struct berval cred, *scred;
int rc;
- blob = spnego_gen_negTokenTarg(principal);
+ blob = spnego_gen_negTokenTarg(principal, ads->auth.time_offset);
if (!blob.data) {
return ADS_ERROR(LDAP_OPERATIONS_ERROR);
@@ -144,7 +144,7 @@ static ADS_STATUS ads_sasl_spnego_krb5_bind(ADS_STRUCT *ads, const char *princip
*/
static ADS_STATUS ads_sasl_spnego_bind(ADS_STRUCT *ads)
{
- struct berval *scred;
+ struct berval *scred=NULL;
int rc, i;
ADS_STATUS status;
DATA_BLOB blob;
@@ -185,7 +185,8 @@ static ADS_STATUS ads_sasl_spnego_bind(ADS_STRUCT *ads)
}
DEBUG(3,("got principal=%s\n", principal));
- if (got_kerberos_mechanism && ads_kinit_password(ads) == 0) {
+ if (!(ads->auth.flags & ADS_AUTH_DISABLE_KERBEROS) &&
+ got_kerberos_mechanism && ads_kinit_password(ads) == 0) {
return ads_sasl_spnego_krb5_bind(ads, principal);
}
diff --git a/source3/libads/util.c b/source3/libads/util.c
index b10b130a31..021f2d93e4 100644
--- a/source3/libads/util.c
+++ b/source3/libads/util.c
@@ -40,7 +40,7 @@ ADS_STATUS ads_change_trust_account_password(ADS_STRUCT *ads, char *host_princip
asprintf(&service_principal, "HOST/%s", host_principal);
ret = kerberos_set_password(ads->auth.kdc_server, host_principal, password,
- service_principal, new_password);
+ service_principal, new_password, ads->auth.time_offset);
if (!secrets_store_machine_password(new_password)) {
DEBUG(1,("Failed to save machine password\n"));