summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/Makefile.in3
-rw-r--r--source3/libads/ads_struct.c182
-rw-r--r--source3/libads/kerberos.c5
-rw-r--r--source3/libads/ldap.c103
-rw-r--r--source3/smbd/negprot.c22
-rw-r--r--source3/smbd/sesssetup.c19
-rw-r--r--source3/utils/net_ads.c1
-rw-r--r--source3/utils/net_join.c13
8 files changed, 221 insertions, 127 deletions
diff --git a/source3/Makefile.in b/source3/Makefile.in
index ba94499de8..542dff65fc 100644
--- a/source3/Makefile.in
+++ b/source3/Makefile.in
@@ -131,7 +131,8 @@ UBIQX_OBJ = ubiqx/ubi_BinTree.o ubiqx/ubi_Cache.o ubiqx/ubi_SplayTree.o \
PARAM_OBJ = param/loadparm.o param/params.o dynconfig.o
-LIBADS_OBJ = libads/ldap.o libads/krb5_setpw.o libads/kerberos.o passdb/secrets.o
+LIBADS_OBJ = libads/ldap.o libads/krb5_setpw.o libads/kerberos.o \
+ libads/ads_struct.o passdb/secrets.o
LIBSMB_OBJ = libsmb/clientgen.o libsmb/cliconnect.o libsmb/clifile.o \
libsmb/clikrb5.o libsmb/clispnego.o libsmb/asn1.o \
diff --git a/source3/libads/ads_struct.c b/source3/libads/ads_struct.c
new file mode 100644
index 0000000000..be0374225b
--- /dev/null
+++ b/source3/libads/ads_struct.c
@@ -0,0 +1,182 @@
+/*
+ Unix SMB/Netbios implementation.
+ Version 3.0
+ ads (active directory) utility library
+ Copyright (C) Andrew Tridgell 2001
+ Copyright (C) Andrew Bartlett 2001
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "includes.h"
+
+static char *ads_build_dn(const char *realm)
+{
+ char *p, *r;
+ int numdots = 0;
+ char *ret;
+ int len;
+
+ r = strdup(realm);
+
+ if (!r || !*r) return r;
+
+ for (p=r; *p; p++) {
+ if (*p == '.') numdots++;
+ }
+
+ len = (numdots+1)*4 + strlen(r) + 1;
+
+ ret = malloc(len);
+ strlcpy(ret,"dc=", len);
+ p=strtok(r,".");
+ strlcat(ret, p, len);
+
+ while ((p=strtok(NULL,"."))) {
+ strlcat(ret,",dc=", len);
+ strlcat(ret, p, len);
+ }
+
+ free(r);
+
+ return ret;
+}
+
+#ifdef HAVE_KRB5
+
+/*
+ get the default relm from krb5.conf
+*/
+static char *get_default_realm(ADS_STRUCT *ads)
+{
+ BOOL ret;
+ krb5_context context;
+ char *realm;
+
+ ret = krb5_init_context(&context);
+ if (ret) {
+ DEBUG(1,("krb5_init_context failed (%s)\n", error_message(ret)));
+ return NULL;
+ }
+
+ ret = krb5_get_default_realm(context, &realm);
+ if (ret) {
+ DEBUG(1,("krb5_get_default_realm failed (%s)\n", error_message(ret)));
+ krb5_free_context(context);
+ return NULL;
+ } else {
+ DEBUG(5,("krb5_get_default_realm got (%s)\n", realm));
+ }
+ krb5_free_context(context);
+
+ return realm;
+}
+
+#else
+static char *get_default_realm(ADS_STRUCT *ads)
+{
+ /* We can't do this if we don't have krb5,
+ but save linking nightmares */
+ DEBUG(5,("get_default_realm: not compiled with krb5.\n"));
+ return NULL;
+}
+
+#endif
+
+#ifdef HAVE_LDAP
+/*
+ find the ldap server from DNS
+*/
+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;
+}
+
+#else
+
+static char *find_ldap_server(ADS_STRUCT *ads)
+{
+ /* Without LDAP this doesn't make much sense */
+ return NULL;
+}
+
+#endif
+
+
+/*
+ initialise a ADS_STRUCT, ready for some ads_ ops
+*/
+ADS_STRUCT *ads_init(const char *realm,
+ const char *ldap_server,
+ const char *bind_path)
+{
+ ADS_STRUCT *ads;
+
+ ads = (ADS_STRUCT *)smb_xmalloc(sizeof(*ads));
+ memset(ads, 0, sizeof(*ads));
+
+ ads->realm = realm? strdup(realm) : NULL;
+ ads->ldap_server = ldap_server? strdup(ldap_server) : NULL;
+ ads->bind_path = bind_path? strdup(bind_path) : NULL;
+ ads->ldap_port = LDAP_PORT;
+
+ if (!ads->realm) {
+ ads->realm = lp_realm();
+ if (!ads->realm[0]) {
+ ads->realm = get_default_realm(ads);
+ }
+ }
+ if (!ads->bind_path) {
+ ads->bind_path = ads_build_dn(ads->realm);
+ }
+ if (!ads->ldap_server) {
+ ads->ldap_server = lp_ads_server();
+ if (!ads->ldap_server[0]) {
+ 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 (False && (ads) && (*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);
+ SAFE_FREE(*ads);
+ }
+}
+
diff --git a/source3/libads/kerberos.c b/source3/libads/kerberos.c
index e4e946f0ce..a3aa8b1661 100644
--- a/source3/libads/kerberos.c
+++ b/source3/libads/kerberos.c
@@ -27,7 +27,7 @@
verify an incoming ticket and parse out the principal name and
authorization_data if available
*/
-NTSTATUS ads_verify_ticket(const DATA_BLOB *ticket,
+NTSTATUS ads_verify_ticket(ADS_STRUCT *ads, const DATA_BLOB *ticket,
char **principal, DATA_BLOB *auth_data)
{
krb5_context context;
@@ -66,9 +66,10 @@ NTSTATUS ads_verify_ticket(const DATA_BLOB *ticket,
return NT_STATUS_LOGON_FAILURE;
}
- ret = krb5_set_default_realm(context, lp_realm());
+ ret = krb5_set_default_realm(context, ads->realm);
if (ret) {
DEBUG(1,("krb5_set_default_realm failed (%s)\n", error_message(ret)));
+ ads_destroy(&ads);
return NT_STATUS_LOGON_FAILURE;
}
diff --git a/source3/libads/ldap.c b/source3/libads/ldap.c
index 49e803a49d..3e24273dc7 100644
--- a/source3/libads/ldap.c
+++ b/source3/libads/ldap.c
@@ -27,38 +27,6 @@
realm of the form AA.BB.CC
caller must free
*/
-static char *ads_build_dn(const char *realm)
-{
- char *p, *r;
- int numdots = 0;
- char *ret;
- int len;
-
- r = strdup(realm);
-
- if (!r || !*r) return r;
-
- for (p=r; *p; p++) {
- if (*p == '.') numdots++;
- }
-
- len = (numdots+1)*4 + strlen(r) + 1;
-
- ret = malloc(len);
- strlcpy(ret,"dc=", len);
- p=strtok(r,".");
- strlcat(ret, p, len);
-
- while ((p=strtok(NULL,"."))) {
- strlcat(ret,",dc=", len);
- strlcat(ret, p, len);
- }
-
- free(r);
-
- return ret;
-}
-
/*
return a string for an error from a ads routine
*/
@@ -68,75 +36,6 @@ char *ads_errstr(int rc)
}
/*
- find the ldap server from DNS
-*/
-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,
- const char *ldap_server,
- const char *bind_path)
-{
- ADS_STRUCT *ads;
-
- ads = (ADS_STRUCT *)malloc(sizeof(*ads));
- if (!ads) return NULL;
- memset(ads, 0, sizeof(*ads));
-
- ads->realm = realm? strdup(realm) : NULL;
- ads->ldap_server = ldap_server? strdup(ldap_server) : NULL;
- 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 = lp_ads_server();
- if (!ads->ldap_server[0]) {
- 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
@@ -474,7 +373,7 @@ BOOL ads_USN(ADS_STRUCT *ads, unsigned *usn)
void *res;
rc = ldap_search_s(ads->ld, ads->bind_path,
- LDAP_SCOPE_BASE, "(objectclass=*)", (char **)attrs, 0, (LDAPMessage *)&res);
+ LDAP_SCOPE_BASE, "(objectclass=*)", (char **)attrs, 0, (LDAPMessage **)&res);
if (rc || ads_count_replies(ads, res) != 1) return False;
return False;
}
diff --git a/source3/smbd/negprot.c b/source3/smbd/negprot.c
index 9a03e1ba96..78d4da3a75 100644
--- a/source3/smbd/negprot.c
+++ b/source3/smbd/negprot.c
@@ -184,15 +184,19 @@ static int negprot_spnego(char *p)
return 16;
}
#endif
-
- /* win2000 uses host$@REALM, which we will probably use eventually,
- but for now this works */
- asprintf(&principal, "HOST/%s@%s", guid, lp_realm());
- blob = spnego_gen_negTokenInit(guid,
- lp_security()==SEC_ADS ? OIDs_krb5 : OIDs_plain,
- principal);
- free(principal);
-
+ {
+ ADS_STRUCT *ads;
+ ads = ads_init(NULL, NULL, NULL);
+
+ /* win2000 uses host$@REALM, which we will probably use eventually,
+ but for now this works */
+ asprintf(&principal, "HOST/%s@%s", guid, ads->realm);
+ blob = spnego_gen_negTokenInit(guid,
+ lp_security()==SEC_ADS ? OIDs_krb5 : OIDs_plain,
+ principal);
+ free(principal);
+ ads_destroy(&ads);
+ }
memcpy(p, blob.data, blob.length);
len = blob.length;
data_blob_free(&blob);
diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c
index 863a509042..35155c0dec 100644
--- a/source3/smbd/sesssetup.c
+++ b/source3/smbd/sesssetup.c
@@ -74,23 +74,25 @@ static int reply_spnego_kerberos(connection_struct *conn,
DATA_BLOB *secblob)
{
DATA_BLOB ticket;
- char *realm, *client, *p;
+ char *client, *p;
const struct passwd *pw;
char *user;
int sess_vuid;
NTSTATUS ret;
DATA_BLOB auth_data;
auth_serversupplied_info *server_info = NULL;
-
- realm = lp_realm();
+ ADS_STRUCT *ads;
if (!spnego_parse_krb5_wrap(*secblob, &ticket)) {
return ERROR_NT(NT_STATUS_LOGON_FAILURE);
}
- ret = ads_verify_ticket(&ticket, &client, &auth_data);
+ ads = ads_init(NULL, NULL, NULL);
+
+ ret = ads_verify_ticket(ads, &ticket, &client, &auth_data);
if (!NT_STATUS_IS_OK(ret)) {
- DEBUG(1,("Failed to verify incoming ticket!\n"));
+ DEBUG(1,("Failed to verify incoming ticket!\n"));
+ ads_destroy(&ads);
return ERROR_NT(NT_STATUS_LOGON_FAILURE);
}
@@ -99,15 +101,18 @@ static int reply_spnego_kerberos(connection_struct *conn,
p = strchr_m(client, '@');
if (!p) {
DEBUG(3,("Doesn't look like a valid principal\n"));
+ ads_destroy(&ads);
return ERROR_NT(NT_STATUS_LOGON_FAILURE);
}
*p = 0;
- if (strcasecmp(p+1, realm) != 0) {
+ if (strcasecmp(p+1, ads->realm) != 0) {
DEBUG(3,("Ticket for incorrect realm %s\n", p+1));
+ ads_destroy(&ads);
return ERROR_NT(NT_STATUS_LOGON_FAILURE);
}
-
+ ads_destroy(&ads);
+
user = client;
/* the password is good - let them in */
diff --git a/source3/utils/net_ads.c b/source3/utils/net_ads.c
index 345fc5c3db..1bfd5c637a 100644
--- a/source3/utils/net_ads.c
+++ b/source3/utils/net_ads.c
@@ -74,6 +74,7 @@ static int net_ads_user(int argc, const char **argv)
}
ads_dump(ads, res);
+ ads_destroy(&ads);
return 0;
}
diff --git a/source3/utils/net_join.c b/source3/utils/net_join.c
index 883ff3ffa6..7456e54364 100644
--- a/source3/utils/net_join.c
+++ b/source3/utils/net_join.c
@@ -76,7 +76,6 @@ int net_join(int argc, const char **argv)
{
char *ldap_host;
char *hostname;
- char *realm;
ADS_STRUCT *ads;
int rc;
char *password;
@@ -85,10 +84,7 @@ int net_join(int argc, const char **argv)
hostname = strdup(global_myname);
strlower(hostname);
- realm = lp_realm();
- ldap_host = lp_ads_server();
if (!*ldap_host) ldap_host = NULL;
- if (!*realm) realm = NULL;
if (!secrets_init()) {
DEBUG(1,("Failed to initialise secrets database\n"));
@@ -97,33 +93,38 @@ int net_join(int argc, const char **argv)
password = generate_random_password(15);
- ads = ads_init(realm, ldap_host, NULL);
+ ads = ads_init(NULL, NULL, NULL);
rc = ads_connect(ads);
if (rc) {
d_printf("ads_connect: %s\n", ads_errstr(rc));
+ ads_destory(&ads);
return -1;
}
rc = ads_join_realm(ads, hostname);
if (rc) {
d_printf("ads_join_realm: %s\n", ads_errstr(rc));
+ ads_destory(&ads);
return -1;
}
status = ads_set_machine_password(ads, hostname, password);
if (!NT_STATUS_IS_OK(status)) {
d_printf("ads_set_machine_password: %s\n", get_nt_error_msg(status));
+ ads_destory(&ads);
return -1;
}
if (!secrets_store_machine_password(password)) {
DEBUG(1,("Failed to save machine password\n"));
+ ads_destory(&ads);
return -1;
}
- d_printf("Joined %s to realm %s\n", hostname, realm);
+ d_printf("Joined %s to realm %s\n", hostname, ads->realm);
+ ads_destory(&ads);
return 0;
}