summaryrefslogtreecommitdiff
path: root/source3/libads/ldap.c
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2001-11-24 14:16:41 +0000
committerAndrew Tridgell <tridge@samba.org>2001-11-24 14:16:41 +0000
commitad2974cd05b4d08c8b92f505bf95aa8e8533235f (patch)
tree68ed4b1c3c99a13154fb768ba9f4bfcc1a3e7ce9 /source3/libads/ldap.c
parent0ebb29e032f2cdbfdb55184c0b97fd1f71b84609 (diff)
downloadsamba-ad2974cd05b4d08c8b92f505bf95aa8e8533235f.tar.gz
samba-ad2974cd05b4d08c8b92f505bf95aa8e8533235f.tar.bz2
samba-ad2974cd05b4d08c8b92f505bf95aa8e8533235f.zip
added "net join" command
this completes the first stage of the smbd ADS support (This used to be commit 058a5aee901e6609969ef7e1d482a720a84a4a12)
Diffstat (limited to 'source3/libads/ldap.c')
-rw-r--r--source3/libads/ldap.c103
1 files changed, 91 insertions, 12 deletions
diff --git a/source3/libads/ldap.c b/source3/libads/ldap.c
index 2853dbbaa3..568e220c0b 100644
--- a/source3/libads/ldap.c
+++ b/source3/libads/ldap.c
@@ -44,7 +44,7 @@ static char *ads_build_dn(const char *realm)
len = (numdots+1)*4 + strlen(r) + 1;
-ret = malloc(len);
+ ret = malloc(len);
strlcpy(ret,"dc=", len);
p=strtok(r,".");
strlcat(ret, p, len);
@@ -68,6 +68,25 @@ char *ads_errstr(int rc)
}
/*
+ find the ldap server from DNS
+ this won't work till we add a DNS packet parser. Talk about a
+ lousy resolv interface!
+*/
+static char *find_ldap_server(ADS_STRUCT *ads)
+{
+ char *list = NULL;
+
+ if (ldap_domain2hostlist(ads->realm, &list) == LDAP_SUCCESS) {
+ char *p;
+ p = strchr(list, ':');
+ if (p) *p = 0;
+ return list;
+ }
+
+ return NULL;
+}
+
+/*
initialise a ADS_STRUCT, ready for some ads_ ops
*/
ADS_STRUCT *ads_init(const char *realm,
@@ -76,7 +95,8 @@ ADS_STRUCT *ads_init(const char *realm,
{
ADS_STRUCT *ads;
- ads = (ADS_STRUCT *)xmalloc(sizeof(*ads));
+ ads = (ADS_STRUCT *)malloc(sizeof(*ads));
+ if (!ads) return NULL;
memset(ads, 0, sizeof(*ads));
ads->realm = realm? strdup(realm) : NULL;
@@ -84,17 +104,42 @@ ADS_STRUCT *ads_init(const char *realm,
ads->bind_path = bind_path? strdup(bind_path) : NULL;
ads->ldap_port = LDAP_PORT;
+ if (!ads->realm) {
+ ads->realm = lp_realm();
+ }
if (!ads->bind_path) {
ads->bind_path = ads_build_dn(ads->realm);
}
+ if (!ads->ldap_server) {
+ ads->ldap_server = find_ldap_server(ads);
+ }
+ if (!ads->kdc_server) {
+ /* assume its the same as LDAP */
+ ads->kdc_server = ads->ldap_server? strdup(ads->ldap_server) : NULL;
+ }
return ads;
}
+/*
+ free the memory used by the ADS structure initialized with 'ads_init(...)'
+*/
+void ads_destroy(ADS_STRUCT *ads)
+{
+ if (ads->ld) ldap_unbind(ads->ld);
+ SAFE_FREE(ads->realm);
+ SAFE_FREE(ads->ldap_server);
+ SAFE_FREE(ads->kdc_server);
+ SAFE_FREE(ads->bind_path);
+ ZERO_STRUCTP(ads);
+ free(ads);
+}
/*
this is a minimal interact function, just enough for SASL to talk
GSSAPI/kerberos to W2K
+ Error handling is a bit of a problem. I can't see how to get Cyrus-sasl
+ to give sensible errors
*/
static int sasl_interact(LDAP *ld,unsigned flags,void *defaults,void *in)
{
@@ -102,7 +147,7 @@ static int sasl_interact(LDAP *ld,unsigned flags,void *defaults,void *in)
while (interact->id != SASL_CB_LIST_END) {
interact->result = strdup("");
- interact->len = 0;
+ interact->len = strlen(interact->result);
interact++;
}
@@ -123,7 +168,8 @@ int ads_connect(ADS_STRUCT *ads)
}
ldap_set_option(ads->ld, LDAP_OPT_PROTOCOL_VERSION, &version);
- rc = ldap_sasl_interactive_bind_s(ads->ld, NULL, NULL, NULL, NULL, 0,
+ rc = ldap_sasl_interactive_bind_s(ads->ld, NULL, NULL, NULL, NULL,
+ LDAP_SASL_QUIET,
sasl_interact, NULL);
return rc;
@@ -290,12 +336,11 @@ int ads_join_realm(ADS_STRUCT *ads, const char *hostname)
{
int rc;
LDAPMessage *res;
- char *principal;
rc = ads_find_machine_acct(ads, (void **)&res, hostname);
if (rc == LDAP_SUCCESS && ads_count_replies(ads, res) == 1) {
DEBUG(0, ("Host account for %s already exists\n", hostname));
- goto set_password;
+ return LDAP_SUCCESS;
}
rc = ads_add_machine_acct(ads, hostname);
@@ -311,14 +356,48 @@ int ads_join_realm(ADS_STRUCT *ads, const char *hostname)
return -1;
}
-set_password:
- asprintf(&principal, "HOST/%s@%s", hostname, ads->realm);
-#if 0
- krb5_set_principal_password(principal, ads->ldap_server, hostname, ads->realm);
-#endif
- free(principal);
+ return LDAP_SUCCESS;
+}
+/*
+ delete a machine from the realm
+*/
+int ads_leave_realm(ADS_STRUCT *ads, const char *hostname)
+{
+ int rc;
+ void *res;
+ char *hostnameDN;
+
+ rc = ads_find_machine_acct(ads, &res, hostname);
+ if (rc != LDAP_SUCCESS || ads_count_replies(ads, res) != 1) {
+ DEBUG(0, ("Host account for %s does not exist.\n", hostname));
+ return -1;
+ }
+
+ hostnameDN = ldap_get_dn(ads->ld, (LDAPMessage *)res);
+ rc = ldap_delete_s(ads->ld, hostnameDN);
+ ldap_memfree(hostnameDN);
+ if (rc != LDAP_SUCCESS) {
+ DEBUG(0, ("ldap_delete_s: %s\n", ads_errstr(rc)));
+ return rc;
+ }
+
+ rc = ads_find_machine_acct(ads, &res, hostname);
+ if (rc == LDAP_SUCCESS && ads_count_replies(ads, res) == 1 ) {
+ DEBUG(0, ("Failed to remove host account.\n"));
+ /*hmmm, we need NTSTATUS */
+ return -1;
+ }
+
return LDAP_SUCCESS;
}
+
+NTSTATUS ads_set_machine_password(ADS_STRUCT *ads,
+ const char *hostname,
+ const char *password)
+{
+ return krb5_set_password(ads->kdc_server, hostname, ads->realm, password);
+}
+
#endif