Make better use of the ads_init() function to get the kerberos relam etc.
authorAndrew Bartlett <abartlet@samba.org>
Thu, 29 Nov 2001 06:21:56 +0000 (06:21 +0000)
committerAndrew Bartlett <abartlet@samba.org>
Thu, 29 Nov 2001 06:21:56 +0000 (06:21 +0000)
This allows us to use automagically obtained values in future, and the value
from krb5.conf now.

Also fix mem leaks etc.

Andrew Bartlett

source/Makefile.in
source/libads/ads_struct.c [new file with mode: 0644]
source/libads/kerberos.c
source/libads/ldap.c
source/smbd/negprot.c
source/smbd/sesssetup.c
source/utils/net_ads.c
source/utils/net_join.c

index ba94499de8b95b12a91fd7b24b363fc5a576143e..542dff65fcd32733219e882b28e790ce67da823f 100644 (file)
@@ -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/source/libads/ads_struct.c b/source/libads/ads_struct.c
new file mode 100644 (file)
index 0000000..be03742
--- /dev/null
@@ -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);
+       }
+}
+
index e4e946f0ce4f7759a31947d17e96ac3a0abd9c28..a3aa8b16617841ad9fcaf66bda724fbb8728008a 100644 (file)
@@ -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;
        }
 
index 49e803a49d6e4a6792050f33516a673e3f116fd2..3e24273dc751294ff5e158c34e72d65df0d7c935 100644 (file)
    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
 */
@@ -67,75 +35,6 @@ char *ads_errstr(int rc)
        return ldap_err2string(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
@@ -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;
 }
index 9a03e1ba96141fe7ad00c985ab049cd49dded24e..78d4da3a757037c3cbbeb24a729df9d45681e018 100644 (file)
@@ -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);
index 863a50904231c544d747cf6d4291a9a000ed9461..35155c0decc4afa48420ac0ca3b62f908c74e89f 100644 (file)
@@ -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 */
index 345fc5c3db332f3d9783a3e33d743f3669b14f2a..1bfd5c637a8d18287a9d0ccf9a8759967c24368f 100644 (file)
@@ -74,6 +74,7 @@ static int net_ads_user(int argc, const char **argv)
        }
 
        ads_dump(ads, res);
+       ads_destroy(&ads);
        return 0;
 }
 
index 883ff3ffa6f6390f0e9e1689a0b399c5d790cd3d..7456e54364cac4e8942704d8313b31cf7f0a1d1a 100644 (file)
@@ -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;
 }