diff options
-rw-r--r-- | source3/Makefile.in | 3 | ||||
-rw-r--r-- | source3/libads/ads_struct.c | 182 | ||||
-rw-r--r-- | source3/libads/kerberos.c | 5 | ||||
-rw-r--r-- | source3/libads/ldap.c | 103 | ||||
-rw-r--r-- | source3/smbd/negprot.c | 22 | ||||
-rw-r--r-- | source3/smbd/sesssetup.c | 19 | ||||
-rw-r--r-- | source3/utils/net_ads.c | 1 | ||||
-rw-r--r-- | source3/utils/net_join.c | 13 |
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; } |