summaryrefslogtreecommitdiff
path: root/source3/libads
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2002-09-17 12:12:50 +0000
committerAndrew Tridgell <tridge@samba.org>2002-09-17 12:12:50 +0000
commitb33681fc0b8ef7b9fa91c154f7c3117afafa349e (patch)
treea83b6dc52ddcd4fdc873882b5a127a33044e55c5 /source3/libads
parent3fefef7a7238e63716a8003aa27a08627a61b927 (diff)
downloadsamba-b33681fc0b8ef7b9fa91c154f7c3117afafa349e.tar.gz
samba-b33681fc0b8ef7b9fa91c154f7c3117afafa349e.tar.bz2
samba-b33681fc0b8ef7b9fa91c154f7c3117afafa349e.zip
Add clock skew handling to our kerberos code. This allows us to cope with
the DC being out of sync with the local machine. (This used to be commit 0d28d769472ea3b98ae4c8757093dfd4499f6dd1)
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"));