summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/Makefile.in2
-rw-r--r--source3/include/ads.h7
-rw-r--r--source3/include/sam.h12
-rw-r--r--source3/libads/ads_ldap.c2
-rw-r--r--source3/libads/ads_struct.c1
-rw-r--r--source3/libads/ldap.c43
-rw-r--r--source3/libads/ldap_utils.c3
-rw-r--r--source3/sam/api.c12
-rw-r--r--source3/sam/interface.c25
-rwxr-xr-xsource3/sam/sam_ads.c1080
-rw-r--r--source3/torture/cmd_sam.c6
11 files changed, 1161 insertions, 32 deletions
diff --git a/source3/Makefile.in b/source3/Makefile.in
index 32c2e3f70f..598062ec05 100644
--- a/source3/Makefile.in
+++ b/source3/Makefile.in
@@ -221,7 +221,7 @@ PASSDB_OBJ = $(PASSDB_GET_SET_OBJ) passdb/passdb.o passdb/pdb_interface.o \
passdb/pdb_unix.o passdb/util_sam_sid.o \
passdb/pdb_compat.o passdb/pdb_nisplus.o
-SAM_STATIC_MODULES = sam/sam_plugin.o
+SAM_STATIC_MODULES = sam/sam_plugin.o sam/sam_skel.o sam/sam_ads.o
SAM_OBJ = sam/account.o sam/get_set_account.o sam/get_set_group.o \
sam/get_set_domain.o sam/interface.o sam/api.o $(SAM_STATIC_MODULES)
diff --git a/source3/include/ads.h b/source3/include/ads.h
index 0181ae535e..88a90229b1 100644
--- a/source3/include/ads.h
+++ b/source3/include/ads.h
@@ -15,6 +15,7 @@ typedef struct {
char *realm;
char *workgroup;
char *ldap_server;
+ char *ldap_uri;
int foreign; /* set to 1 if connecting to a foreign realm */
} server;
@@ -255,5 +256,7 @@ typedef void **ADS_MODLIST;
/* ads auth control flags */
-#define ADS_AUTH_DISABLE_KERBEROS 1
-#define ADS_AUTH_NO_BIND 2
+#define ADS_AUTH_DISABLE_KERBEROS 0x01
+#define ADS_AUTH_NO_BIND 0x02
+#define ADS_AUTH_ANON_BIND 0x04
+#define ADS_AUTH_SIMPLE_BIND 0x08
diff --git a/source3/include/sam.h b/source3/include/sam.h
index 2157a37065..8fbda7e857 100644
--- a/source3/include/sam.h
+++ b/source3/include/sam.h
@@ -167,8 +167,8 @@ typedef struct sam_context
NTSTATUS (*sam_get_sec_desc) (const struct sam_context *, const NT_USER_TOKEN *access_token, const DOM_SID *sid, SEC_DESC **sd);
NTSTATUS (*sam_set_sec_desc) (const struct sam_context *, const NT_USER_TOKEN *access_token, const DOM_SID *sid, const SEC_DESC *sd);
- NTSTATUS (*sam_lookup_sid) (const struct sam_context *, const NT_USER_TOKEN *access_token, const DOM_SID *sid, char **name, uint32 *type);
- NTSTATUS (*sam_lookup_name) (const struct sam_context *, const NT_USER_TOKEN *access_token, const char *domain, const char *name, DOM_SID **sid, uint32 *type);
+ NTSTATUS (*sam_lookup_sid) (const struct sam_context *, const NT_USER_TOKEN *access_token, TALLOC_CTX *ctx, const DOM_SID *sid, char **name, uint32 *type);
+ NTSTATUS (*sam_lookup_name) (const struct sam_context *, const NT_USER_TOKEN *access_token, const char *domain, const char *name, DOM_SID *sid, uint32 *type);
/* Domain API */
@@ -183,7 +183,7 @@ typedef struct sam_context
/* Account API */
- NTSTATUS (*sam_create_account) (const struct sam_context *context, const NT_USER_TOKEN *access_token, uint32 access_desired, const DOM_SID *domainsid, const char *account_name, uint16 acct_ctrl, SAM_ACCOUNT_HANDLE **account);
+ NTSTATUS (*sam_create_account) (const struct sam_context *context, const NT_USER_TOKEN *access_token, uint32 access_desired, TALLOC_CTX *mem_ctx, const DOM_SID *domainsid, const char *account_name, uint16 acct_ctrl, SAM_ACCOUNT_HANDLE **account);
NTSTATUS (*sam_add_account) (const struct sam_context *, const DOM_SID *domainsid, const SAM_ACCOUNT_HANDLE *account);
NTSTATUS (*sam_update_account) (const struct sam_context *, const SAM_ACCOUNT_HANDLE *account);
NTSTATUS (*sam_delete_account) (const struct sam_context *, const SAM_ACCOUNT_HANDLE *account);
@@ -225,8 +225,8 @@ typedef struct sam_methods
NTSTATUS (*sam_get_sec_desc) (const struct sam_methods *, const NT_USER_TOKEN *access_token, const DOM_SID *sid, SEC_DESC **sd);
NTSTATUS (*sam_set_sec_desc) (const struct sam_methods *, const NT_USER_TOKEN *access_token, const DOM_SID *sid, const SEC_DESC *sd);
- NTSTATUS (*sam_lookup_sid) (const struct sam_methods *, const NT_USER_TOKEN *access_token, const DOM_SID *sid, char **name, uint32 *type);
- NTSTATUS (*sam_lookup_name) (const struct sam_methods *, const NT_USER_TOKEN *access_token, const char *name, DOM_SID **sid, uint32 *type);
+ NTSTATUS (*sam_lookup_sid) (const struct sam_methods *, const NT_USER_TOKEN *access_token, TALLOC_CTX *mem_ctx, const DOM_SID *sid, char **name, uint32 *type);
+ NTSTATUS (*sam_lookup_name) (const struct sam_methods *, const NT_USER_TOKEN *access_token, const char *name, DOM_SID *sid, uint32 *type);
/* Domain API */
@@ -235,7 +235,7 @@ typedef struct sam_methods
/* Account API */
- NTSTATUS (*sam_create_account) (const struct sam_methods *, const NT_USER_TOKEN *access_token, uint32 access_desired, const char *account_name, uint16 acct_ctrl, SAM_ACCOUNT_HANDLE **account);
+ NTSTATUS (*sam_create_account) (const struct sam_methods *, const NT_USER_TOKEN *access_token, uint32 access_desired, TALLOC_CTX *mem_ctx, const char *account_name, uint16 acct_ctrl, SAM_ACCOUNT_HANDLE **account);
NTSTATUS (*sam_add_account) (const struct sam_methods *, const SAM_ACCOUNT_HANDLE *account);
NTSTATUS (*sam_update_account) (const struct sam_methods *, const SAM_ACCOUNT_HANDLE *account);
NTSTATUS (*sam_delete_account) (const struct sam_methods *, const SAM_ACCOUNT_HANDLE *account);
diff --git a/source3/libads/ads_ldap.c b/source3/libads/ads_ldap.c
index 8c39a89762..05b016539e 100644
--- a/source3/libads/ads_ldap.c
+++ b/source3/libads/ads_ldap.c
@@ -83,7 +83,7 @@ done:
/* convert a sid to a user or group name */
NTSTATUS ads_sid_to_name(ADS_STRUCT *ads,
TALLOC_CTX *mem_ctx,
- DOM_SID *sid,
+ const DOM_SID *sid,
char **name,
enum SID_NAME_USE *type)
{
diff --git a/source3/libads/ads_struct.c b/source3/libads/ads_struct.c
index b68c822ce3..3cdd015bf4 100644
--- a/source3/libads/ads_struct.c
+++ b/source3/libads/ads_struct.c
@@ -122,6 +122,7 @@ void ads_destroy(ADS_STRUCT **ads)
SAFE_FREE((*ads)->server.realm);
SAFE_FREE((*ads)->server.workgroup);
SAFE_FREE((*ads)->server.ldap_server);
+ SAFE_FREE((*ads)->server.ldap_uri);
SAFE_FREE((*ads)->auth.realm);
SAFE_FREE((*ads)->auth.password);
diff --git a/source3/libads/ldap.c b/source3/libads/ldap.c
index e09ffeb3f6..1004ea229c 100644
--- a/source3/libads/ldap.c
+++ b/source3/libads/ldap.c
@@ -67,6 +67,29 @@ static BOOL ads_try_connect(ADS_STRUCT *ads, const char *server, unsigned port)
return True;
}
+/*
+ try a connection to a given ldap server, based on URL, returning True if successful
+ */
+static BOOL ads_try_connect_uri(ADS_STRUCT *ads)
+{
+#if defined(LDAP_API_FEATURE_X_OPENLDAP) && (LDAP_API_VERSION > 2000)
+ DEBUG(5,("ads_try_connect: trying ldap server at URI '%s'\n",
+ ads->server.ldap_uri));
+
+
+ if (ldap_initialize((LDAP**)&(ads->ld), ads->server.ldap_uri) == LDAP_SUCCESS) {
+ return True;
+ }
+ DEBUG(0, ("ldap_initialize: %s\n", strerror(errno)));
+
+#else
+
+ DEBUG(1, ("no URL support in LDAP libs!\n"));
+#endif
+
+ return False;
+}
+
/* used by the IP comparison function */
struct ldap_ip {
struct in_addr ip;
@@ -210,6 +233,13 @@ ADS_STATUS ads_connect(ADS_STRUCT *ads)
ads->last_attempt = time(NULL);
ads->ld = NULL;
+ /* try with a URL based server */
+
+ if (ads->server.ldap_uri &&
+ ads_try_connect_uri(ads)) {
+ goto got_connection;
+ }
+
/* try with a user specified server */
if (ads->server.ldap_server &&
ads_try_connect(ads, ads->server.ldap_server, LDAP_PORT)) {
@@ -278,6 +308,14 @@ got_connection:
return ADS_SUCCESS;
}
+ if (ads->auth.flags & ADS_AUTH_ANON_BIND) {
+ return ADS_ERROR(ldap_simple_bind_s( ads->ld, NULL, NULL));
+ }
+
+ if (ads->auth.flags & ADS_AUTH_SIMPLE_BIND) {
+ return ADS_ERROR(ldap_simple_bind_s( ads->ld, ads->auth.user_name, ads->auth.password));
+ }
+
return ads_sasl_bind(ads);
}
@@ -1771,8 +1809,9 @@ ADS_STATUS ads_server_info(ADS_STRUCT *ads)
ads->config.realm = strdup(p+2);
ads->config.bind_path = ads_build_dn(ads->config.realm);
- DEBUG(3,("got ldap server name %s@%s\n",
- ads->config.ldap_server_name, ads->config.realm));
+ DEBUG(3,("got ldap server name %s@%s, using bind path: %s\n",
+ ads->config.ldap_server_name, ads->config.realm,
+ ads->config.bind_path));
ads->config.current_time = ads_parse_time(timestr);
diff --git a/source3/libads/ldap_utils.c b/source3/libads/ldap_utils.c
index 9e4b8a1de9..907f7c8aff 100644
--- a/source3/libads/ldap_utils.c
+++ b/source3/libads/ldap_utils.c
@@ -42,6 +42,9 @@ ADS_STATUS ads_do_search_retry(ADS_STRUCT *ads, const char *bind_path, int scope
bp = strdup(bind_path);
+ if (!bp)
+ return ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
+
while (count--) {
status = ads_do_search_all(ads, bp, scope, exp, attrs, res);
if (ADS_ERR_OK(status)) {
diff --git a/source3/sam/api.c b/source3/sam/api.c
index fb2f015e95..349c18787c 100644
--- a/source3/sam/api.c
+++ b/source3/sam/api.c
@@ -50,7 +50,7 @@ NTSTATUS sam_set_sec_desc(const NT_USER_TOKEN *access_token, const DOM_SID *sid,
return sam_context->sam_set_sec_desc(sam_context, access_token, sid, sd);
}
-NTSTATUS sam_lookup_sid(const NT_USER_TOKEN *access_token, const DOM_SID *sid, char **name, uint32 *type)
+NTSTATUS sam_lookup_sid(const NT_USER_TOKEN *access_token, TALLOC_CTX *mem_ctx, const DOM_SID *sid, char **name, uint32 *type)
{
SAM_CONTEXT *sam_context = sam_get_static_context(False);
@@ -58,10 +58,10 @@ NTSTATUS sam_lookup_sid(const NT_USER_TOKEN *access_token, const DOM_SID *sid, c
return NT_STATUS_UNSUCCESSFUL;
}
- return sam_context->sam_lookup_sid(sam_context, access_token, sid, name, type);
+ return sam_context->sam_lookup_sid(sam_context, access_token, mem_ctx, sid, name, type);
}
-NTSTATUS sam_lookup_name(const NT_USER_TOKEN *access_token, const char *domain, const char *name, DOM_SID **sid, uint32 *type)
+NTSTATUS sam_lookup_name(const NT_USER_TOKEN *access_token, const char *domain, const char *name, DOM_SID *sid, uint32 *type)
{
SAM_CONTEXT *sam_context = sam_get_static_context(False);
@@ -69,7 +69,7 @@ NTSTATUS sam_lookup_name(const NT_USER_TOKEN *access_token, const char *domain,
return NT_STATUS_UNSUCCESSFUL;
}
- return sam_context->sam_lookup_name(sam_context, access_token, domain, name, sid, type);
+ return sam_context->sam_lookup_name(sam_context, access_token,domain, name, sid, type);
}
/* Domain API */
@@ -120,7 +120,7 @@ NTSTATUS sam_get_domain_by_sid(const NT_USER_TOKEN *access_token, const uint32 a
/* Account API */
-NTSTATUS sam_create_account(const NT_USER_TOKEN *access_token, const uint32 access_desired, const DOM_SID *domainsid, const char *account_name, uint16 acct_ctrl, SAM_ACCOUNT_HANDLE **account)
+NTSTATUS sam_create_account(const NT_USER_TOKEN *access_token, const uint32 access_desired, TALLOC_CTX *mem_ctx, const DOM_SID *domainsid, const char *account_name, uint16 acct_ctrl, SAM_ACCOUNT_HANDLE **account)
{
SAM_CONTEXT *sam_context = sam_get_static_context(False);
@@ -128,7 +128,7 @@ NTSTATUS sam_create_account(const NT_USER_TOKEN *access_token, const uint32 acce
return NT_STATUS_UNSUCCESSFUL;
}
- return sam_context->sam_create_account(sam_context, access_token, access_desired, domainsid, account_name, acct_ctrl, account);
+ return sam_context->sam_create_account(sam_context, access_token, access_desired, mem_ctx, domainsid, account_name, acct_ctrl, account);
}
NTSTATUS sam_add_account(const DOM_SID *domainsid, const SAM_ACCOUNT_HANDLE *account)
diff --git a/source3/sam/interface.c b/source3/sam/interface.c
index 0943a0e8f1..5d12cfc999 100644
--- a/source3/sam/interface.c
+++ b/source3/sam/interface.c
@@ -32,6 +32,8 @@ extern DOM_SID global_sid_Builtin;
const struct sam_init_function_entry builtin_sam_init_functions[] = {
{ "plugin", sam_init_plugin },
+ { "ads", sam_init_ads },
+ { "skel", sam_init_skel },
{ NULL, NULL}
};
@@ -79,7 +81,7 @@ NTSTATUS sam_get_methods_by_name(const SAM_CONTEXT *context, SAM_METHODS **sam_m
tmp_methods = context->methods;
while (tmp_methods) {
- if (!strcmp(domainname, tmp_methods->domain_name))
+ if (strequal(domainname, tmp_methods->domain_name))
{
(*sam_method) = tmp_methods;
return NT_STATUS_OK;
@@ -143,7 +145,7 @@ NTSTATUS context_sam_set_sec_desc(const SAM_CONTEXT *context, const NT_USER_TOKE
}
-NTSTATUS context_sam_lookup_name(const SAM_CONTEXT *context, const NT_USER_TOKEN *access_token, const char *domain, const char *name, DOM_SID **sid, uint32 *type)
+NTSTATUS context_sam_lookup_name(const SAM_CONTEXT *context, const NT_USER_TOKEN *access_token, const char *domain, const char *name, DOM_SID *sid, uint32 *type)
{
SAM_METHODS *tmp_methods;
NTSTATUS nt_status;
@@ -169,7 +171,7 @@ NTSTATUS context_sam_lookup_name(const SAM_CONTEXT *context, const NT_USER_TOKEN
return NT_STATUS_OK;
}
-NTSTATUS context_sam_lookup_sid(const SAM_CONTEXT *context, const NT_USER_TOKEN *access_token, const DOM_SID *sid, char **name, uint32 *type)
+NTSTATUS context_sam_lookup_sid(const SAM_CONTEXT *context, const NT_USER_TOKEN *access_token, TALLOC_CTX *mem_ctx, const DOM_SID *sid, char **name, uint32 *type)
{
SAM_METHODS *tmp_methods;
uint32 rid;
@@ -194,7 +196,7 @@ NTSTATUS context_sam_lookup_sid(const SAM_CONTEXT *context, const NT_USER_TOKEN
return NT_STATUS_NOT_IMPLEMENTED;
}
- if (!NT_STATUS_IS_OK(nt_status = tmp_methods->sam_lookup_sid(tmp_methods, access_token, sid, name, type))) {
+ if (!NT_STATUS_IS_OK(nt_status = tmp_methods->sam_lookup_sid(tmp_methods, access_token, mem_ctx, sid, name, type))) {
DEBUG(4,("sam_lookup_name for %s in backend %s failed\n",
sid_string_static(sid), tmp_methods->backendname));
return nt_status;
@@ -354,7 +356,7 @@ NTSTATUS context_sam_get_domain_by_sid(const SAM_CONTEXT *context, const NT_USER
return NT_STATUS_OK;
}
-NTSTATUS context_sam_create_account(const SAM_CONTEXT *context, const NT_USER_TOKEN *access_token, uint32 access_desired, const DOM_SID *domainsid, const char *account_name, uint16 acct_ctrl, SAM_ACCOUNT_HANDLE **account)
+NTSTATUS context_sam_create_account(const SAM_CONTEXT *context, const NT_USER_TOKEN *access_token, uint32 access_desired, TALLOC_CTX *mem_ctx, const DOM_SID *domainsid, const char *account_name, uint16 acct_ctrl, SAM_ACCOUNT_HANDLE **account)
{
SAM_METHODS *tmp_methods;
NTSTATUS nt_status;
@@ -371,7 +373,7 @@ NTSTATUS context_sam_create_account(const SAM_CONTEXT *context, const NT_USER_TO
return NT_STATUS_NOT_IMPLEMENTED;
}
- if (!NT_STATUS_IS_OK(nt_status = tmp_methods->sam_create_account(tmp_methods, access_token, access_desired, account_name, acct_ctrl, account))) {
+ if (!NT_STATUS_IS_OK(nt_status = tmp_methods->sam_create_account(tmp_methods, access_token, access_desired, mem_ctx, account_name, acct_ctrl, account))) {
DEBUG(4,("sam_create_account in backend %s failed\n",
tmp_methods->backendname));
return nt_status;
@@ -924,21 +926,21 @@ static NTSTATUS make_backend_entry(SAM_BACKEND_ENTRY *backend_entry, char *sam_b
if ((tmp = strchr(tmp_string, '|')) != NULL) {
DEBUGADD(20,("a domain name has been specified\n"));
*tmp = 0;
- backend_entry->domain_name = tmp + 1;
+ backend_entry->domain_name = smb_xstrdup(tmp + 1);
tmp_string = tmp + 1;
}
if ((tmp = strchr(tmp_string, ':')) != NULL) {
DEBUG(20,("options for the backend have been specified\n"));
*tmp = 0;
- backend_entry->module_params = tmp + 1;
+ backend_entry->module_params = smb_xstrdup(tmp + 1);
tmp_string = tmp + 1;
}
if (backend_entry->domain_name == NULL) {
DEBUG(10,("make_backend_entry: no domain was specified for sam module %s. Useing default domain %s\n",
backend_entry->module_name, lp_workgroup()));
- backend_entry->domain_name = lp_workgroup();
+ backend_entry->domain_name = smb_xstrdup(lp_workgroup());
}
if ((backend_entry->domain_sid = (DOM_SID *)malloc(sizeof(DOM_SID))) == NULL) {
@@ -1109,11 +1111,12 @@ NTSTATUS make_sam_context_list(SAM_CONTEXT **context, char **sam_backends_param)
DEBUG(6,("There are %d domains listed with there backends\n", nBackends));
- if ((backends = (SAM_BACKEND_ENTRY *)malloc(sizeof(SAM_BACKEND_ENTRY)*nBackends)) == NULL) {
+ if ((backends = (SAM_BACKEND_ENTRY *)malloc(sizeof(*backends)*nBackends)) == NULL) {
DEBUG(0,("make_sam_context_list: failed to allocate backends\n"));
return NT_STATUS_NO_MEMORY;
}
- ZERO_STRUCTP(backends);
+
+ memset(backends, '\0', sizeof(*backends)*nBackends);
for (i = 0; i < nBackends; i++) {
DEBUG(8,("processing %s\n",sam_backends_param[i]));
diff --git a/source3/sam/sam_ads.c b/source3/sam/sam_ads.c
new file mode 100755
index 0000000000..7f2a901d81
--- /dev/null
+++ b/source3/sam/sam_ads.c
@@ -0,0 +1,1080 @@
+/*
+ Unix SMB/CIFS implementation.
+ Active Directory SAM backend, for simulate a W2K DC in mixed mode.
+
+ Copyright (C) Stefan (metze) Metzmacher 2002
+ Copyright (C) Andrew Bartlett 2002
+
+ 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"
+
+
+#ifdef HAVE_LDAP
+
+static int sam_ads_debug_level = DBGC_SAM;
+
+#undef DBGC_CLASS
+#define DBGC_CLASS sam_ads_debug_level
+
+#define ADS_STATUS_OK ADS_ERROR(0)
+#define ADS_STATUS_UNSUCCESSFUL ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL)
+#define ADS_STATUS_NOT_IMPLEMENTED ADS_ERROR_NT(NT_STATUS_NOT_IMPLEMENTED)
+
+
+#define ADS_SUBTREE_BUILTIN "CN=Builtin,"
+#define ADS_SUBTREE_COMPUTERS "CN=Computers,"
+#define ADS_SUBTREE_DC "CN=Domain Controllers,"
+#define ADS_SUBTREE_USERS "CN=Users,"
+#define ADS_ROOT_TREE ""
+/* Here are private module structs and functions */
+
+struct sam_ads_privates {
+ ADS_STRUCT *ads_struct;
+ TALLOC_CTX *mem_ctx;
+ BOOL bind_plaintext;
+ char *ads_bind_dn;
+ char *ads_bind_pw;
+ char *ldap_uri;
+ /* did we need something more? */
+};
+
+
+/* get only these LDAP attributes, witch we really need for an account */
+const char *account_attrs[] = { "objectSid",
+ "objectGUID",
+ "sAMAccountType",
+ "sAMAcountName",
+ "userPrincipalName",
+ "accountExpires",
+ "badPasswordTime",
+ "badPwdCount",
+ "lastLogoff",
+ "lastLogon",
+ "userWorkstations",
+ "dBCSPwd",
+ "unicodePwd",
+ "pwdLastSet",
+ "userAccountControl",
+ "profilePath",
+ "homeDrive",
+ "scriptPath",
+ "homeDirectory",
+ "cn",
+ "primaryGroupID",/* 513 */
+ "nsNPAllowDialIn",/* TRUE */
+ "userParameters",/* Dial Back number ...*/
+ "codePage",/* 0 */
+ "countryCode",/* 0 */
+ "adminCount",/* 1 or 0 */
+ "logonCount",/* 0 */
+ "managedObjects",
+ "memberOf",/* dn */
+ "instanceType",/* 4 */
+ "name", /* sync with cn */
+ "description",
+ /* "nTSecurityDescriptor", */
+ NULL};
+
+/* get only these LDAP attributes, witch we really need for a group */
+const char *group_attrs[] = {"objectSid",
+ /* "objectGUID", */
+ "sAMAccountType",
+ "sAMAcountName",
+ "groupType",
+ /* "member", */
+ "description",
+ "name", /* sync with cn */
+ /* "nTSecurityDescriptor", */
+ NULL};
+
+
+/***************************************************
+ return our ads connection. We keep the connection
+ open to make things faster
+****************************************************/
+static ADS_STATUS sam_ads_cached_connection(struct sam_ads_privates *private)
+{
+ ADS_STRUCT *ads_struct;
+ ADS_STATUS ads_status;
+
+ if (!private->ads_struct) {
+ private->ads_struct = ads_init_simple();
+ ads_struct = private->ads_struct;
+ ads_struct->server.ldap_uri = smb_xstrdup(private->ldap_uri);
+ if ((!private->ads_bind_dn) || (!*private->ads_bind_dn)) {
+ ads_struct->auth.flags |= ADS_AUTH_ANON_BIND;
+ } else {
+ ads_struct->auth.user_name
+ = smb_xstrdup(private->ads_bind_dn);
+ if (private->ads_bind_pw) {
+ ads_struct->auth.password
+ = smb_xstrdup(private->ads_bind_pw);
+ }
+ }
+ if (private->bind_plaintext) {
+ ads_struct->auth.flags |= ADS_AUTH_SIMPLE_BIND;
+ }
+ } else {
+ ads_struct = private->ads_struct;
+ }
+
+ if (ads_struct->ld != NULL) {
+ /* connection has been opened. ping server. */
+ struct sockaddr_un addr;
+ socklen_t len;
+ int sd;
+ if (ldap_get_option(ads_struct->ld, LDAP_OPT_DESC, &sd) == 0 &&
+ getpeername(sd, (struct sockaddr *) &addr, &len) < 0) {
+ /* the other end has died. reopen. */
+ ldap_unbind_ext(ads_struct->ld, NULL, NULL);
+ ads_struct->ld = NULL;
+ }
+ }
+
+ if (ads_struct->ld != NULL) {
+ DEBUG(5,("sam_ads_cached_connection: allready connected to the LDAP server\n"));
+ return ADS_SUCCESS;
+ }
+
+ ads_status = ads_connect(ads_struct);
+
+ ads_status = ads_server_info(ads_struct);
+ if (!ADS_ERR_OK(ads_status)) {
+ DEBUG(0,("Can't set server info: %s\n",ads_errstr(ads_status)));
+ /* return ads_status; */ /*for now we only warn! */
+ }
+
+ DEBUG(2, ("sam_ads_cached_connection: succesful connection to the LDAP server\n"));
+ return ADS_SUCCESS;
+}
+
+static ADS_STATUS sam_ads_do_search(struct sam_ads_privates *private, const char *bind_path, int scope, const char *exp, const char **attrs, void **res)
+{
+ ADS_STATUS ads_status = ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL);
+
+ ads_status = sam_ads_cached_connection(private);
+ if (!ADS_ERR_OK(ads_status))
+ return ads_status;
+
+ return ads_do_search_retry(private->ads_struct, bind_path, scope, exp, attrs, res);
+}
+
+/***********************************************
+Initialize SAM_ACCOUNT_HANDLE from an ADS query
+************************************************/
+/* not ready :-( */
+static ADS_STATUS ads_entry2sam_account_handle(ADS_STRUCT *ads_struct, SAM_ACCOUNT_HANDLE *account ,const void *entry)
+{
+ ADS_STATUS ads_status = ADS_STATUS_NOT_IMPLEMENTED;
+ DEBUG(0,("sam_ads: %s was called!\n",__FUNCTION__));
+ SAM_ASSERT(ads_struct && account && entry);
+
+
+
+ return ads_status;
+}
+
+
+/***********************************************
+Initialize SAM_GROUP_ENUM from an ads entry
+************************************************/
+/* not ready :-( */
+static ADS_STATUS ads_entry2sam_group_enum(ADS_STRUCT *ads_struct, TALLOC_CTX *mem_ctx, SAM_GROUP_ENUM **group_enum,const void *entry)
+{
+ ADS_STATUS ads_status = ADS_STATUS_UNSUCCESSFUL;
+ SAM_GROUP_ENUM __group_enum;
+ SAM_GROUP_ENUM *_group_enum = &__group_enum;
+
+ SAM_ASSERT(ads_struct && mem_ctx && group_enum && entry);
+
+ *group_enum = _group_enum;
+
+ DEBUG(3,("sam_ads: ads_entry2sam_account_handle\n"));
+
+ if (!ads_pull_sid((ADS_STRUCT *)ads_struct, &entry, "objectSid", &(_group_enum->sid))) {
+ DEBUG(0,("No sid for!?\n"));
+ return ADS_STATUS_UNSUCCESSFUL;
+ }
+
+ if (!(_group_enum->group_name = ads_pull_string((ADS_STRUCT *)ads_struct, mem_ctx, &entry, "sAMAccountName"))) {
+ DEBUG(0,("No groupname found"));
+ return ADS_STATUS_UNSUCCESSFUL;
+ }
+
+ if (!(_group_enum->group_desc = ads_pull_string((ADS_STRUCT *)ads_struct, mem_ctx, &entry, "desciption"))) {
+ DEBUG(0,("No description found"));
+ return ADS_STATUS_UNSUCCESSFUL;
+ }
+
+ DEBUG(0,("sAMAccountName: %s\ndescription: %s\nobjectSid: %s\n",
+ _group_enum->group_name,
+ _group_enum->group_desc,
+ sid_string_static(&(_group_enum->sid))
+ ));
+
+ return ads_status;
+}
+
+static ADS_STATUS sam_ads_access_check(const SAM_METHODS *sam_method, const SEC_DESC *sd, const NT_USER_TOKEN *access_token, uint32 access_desired)
+{
+ ADS_STATUS ads_status = ADS_ERROR_NT(NT_STATUS_ACCESS_DENIED);
+ NTSTATUS nt_status;
+ uint32 acc_granted;
+
+ SAM_ASSERT(sam_method && sd && access_token);
+ /* the steps you need are:
+ 1. get_sec_desc for sid
+ 2. se_map_generic(accessdesired, generic_mapping)
+ 3. se_access_check() */
+
+ if (!se_access_check(sd, access_token, access_desired, &acc_granted, &nt_status)) {
+ DEBUG(3,("sam_ads_access_check: ACCESS DENIED\n"));
+ ads_status = ADS_ERROR_NT(nt_status);
+ return ads_status;
+ }
+ ads_status = ADS_ERROR_NT(nt_status);
+ return ads_status;
+}
+
+static ADS_STATUS sam_ads_get_tree_sec_desc(const SAM_METHODS *sam_method, const char *subtree, SEC_DESC **sd)
+{
+ ADS_STATUS ads_status = ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+ struct sam_ads_privates *privates = (struct sam_ads_privates *)sam_method->private_data;
+ ADS_STRUCT *ads_struct = privates->ads_struct;
+ TALLOC_CTX *mem_ctx = privates->mem_ctx;
+ char *search_path;
+ void *sec_desc_res;
+ void *sec_desc_msg;
+ const char *sec_desc_attrs[] = {"nTSecurityDescriptor",NULL};
+
+ SAM_ASSERT(sam_method && ads_struct && sd);
+ *sd = NULL;
+
+ if (subtree) {
+ asprintf(&search_path, "%s%s",subtree,ads_struct->config.bind_path);
+ } else {
+ asprintf(&search_path, "%s","");
+ }
+ ads_status = sam_ads_do_search(privates, search_path, LDAP_SCOPE_BASE, "(objectClass=*)", sec_desc_attrs, &sec_desc_res);
+ SAFE_FREE(search_path);
+ if (!ADS_ERR_OK(ads_status))
+ return ads_status;
+
+ if ((sec_desc_msg = ads_first_entry(ads_struct, sec_desc_res))==NULL) {
+ ads_status = ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+ return ads_status;
+ }
+
+ if (!ads_pull_sd(ads_struct, mem_ctx, sec_desc_msg, sec_desc_attrs[0], sd)) {
+ *sd = NULL;
+ ads_status = ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+ return ads_status;
+ }
+
+ return ads_status;
+}
+
+static ADS_STATUS sam_ads_account_policy_get(const SAM_METHODS *sam_method, int field, uint32 *value)
+{
+ ADS_STATUS ads_status = ADS_ERROR_NT(NT_STATUS_NOT_IMPLEMENTED);
+ DEBUG(0,("sam_ads: %s needs to be done! %s\n",__FUNCTION__,ads_errstr(ads_status)));
+
+ SAM_ASSERT(sam_method && value);
+
+ /* Fix Me */
+ switch(field) {
+ /* Fix Me */
+ default: *value = 0; break;
+ }
+
+ return ads_status;
+}
+
+/**********************************
+Now the functions off the SAM API
+***********************************/
+
+/* General API */
+static NTSTATUS sam_ads_get_sec_desc(const SAM_METHODS *sam_method, const NT_USER_TOKEN *access_token,
+ const DOM_SID *sid, SEC_DESC **sd)
+{
+ ADS_STATUS ads_status = ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL);
+ struct sam_ads_privates *privates = (struct sam_ads_privates *)sam_method->private_data;
+ ADS_STRUCT *ads_struct = privates->ads_struct;
+ TALLOC_CTX *mem_ctx;
+ char *sidstr,*filter;
+ void *sec_desc_res;
+ void *sec_desc_msg;
+ const char *sec_desc_attrs[] = {"nTSecurityDescriptor",NULL};
+ fstring sid_str;
+ SEC_DESC *my_sd;
+
+ SAM_ASSERT(sam_method && access_token && sid && sd);
+
+ ads_status = sam_ads_get_tree_sec_desc(sam_method, ADS_ROOT_TREE, &my_sd);
+ if (!ADS_ERR_OK(ads_status))
+ return ads_ntstatus(ads_status);
+
+ ads_status = sam_ads_access_check(sam_method, my_sd, access_token, DOMAIN_READ);
+
+ if (!ADS_ERR_OK(ads_status))
+ return ads_ntstatus(ads_status);
+
+ sidstr = sid_binstring(sid);
+ if (asprintf(&filter, "(objectSid=%s)", sidstr) == -1) {
+ SAFE_FREE(sidstr);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ SAFE_FREE(sidstr);
+
+ ads_status = sam_ads_do_search(privates,ads_struct->config.bind_path,
+ LDAP_SCOPE_SUBTREE, filter, sec_desc_attrs,
+ &sec_desc_res);
+ SAFE_FREE(filter);
+
+ if (!ADS_ERR_OK(ads_status)) {
+ return ads_ntstatus(ads_status);
+ }
+
+ sec_desc_msg = ads_first_entry(ads_struct, sec_desc_res);
+
+ if (!(mem_ctx = talloc_init_named("sec_desc parse in sam_ads"))) {
+ DEBUG(1, ("talloc_init_named() failed for sec_desc parse context in sam_ads"));
+ ads_msgfree(ads_struct, sec_desc_res);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ if (!ads_pull_sd(ads_struct, mem_ctx, sec_desc_msg, sec_desc_attrs[0], sd)) {
+ talloc_destroy(mem_ctx);
+ ads_msgfree(ads_struct, sec_desc_res);
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ if (!ADS_ERR_OK(ads_status)) {
+ talloc_destroy(mem_ctx);
+ ads_msgfree(ads_struct, sec_desc_res);
+ return ads_ntstatus(ads_status);
+ }
+
+ if (ads_count_replies(ads_struct, sec_desc_res) != 1) {
+ DEBUG(1,("sam_ads_get_sec_desc: duplicate or 0 results for sid %s\n",
+ sid_to_string(sid_str, sid)));
+ talloc_destroy(mem_ctx);
+ ads_msgfree(ads_struct, sec_desc_res);
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ if (!(sec_desc_msg = ads_first_entry(ads_struct, sec_desc_res))) {
+ talloc_destroy(mem_ctx);
+ ads_msgfree(ads_struct, sec_desc_res);
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ if (!ads_pull_sd(ads_struct, mem_ctx, sec_desc_msg, sec_desc_attrs[0], sd)) {
+ ads_status = ADS_ERROR_NT(NT_STATUS_INVALID_PARAMETER);
+ talloc_destroy(mem_ctx);
+ ads_msgfree(ads_struct, sec_desc_res);
+ return ads_ntstatus(ads_status);
+ }
+
+ /* now, were we allowed to see the SD we just got? */
+
+ ads_msgfree(ads_struct, sec_desc_res);
+ talloc_destroy(mem_ctx);
+ return ads_ntstatus(ads_status);
+}
+
+static NTSTATUS sam_ads_set_sec_desc(const SAM_METHODS *sam_method, const NT_USER_TOKEN *access_token,
+ const DOM_SID *sid, const SEC_DESC *sd)
+{
+ ADS_STATUS ads_status = ADS_STATUS_NOT_IMPLEMENTED;
+ DEBUG(0,("sam_ads: %s was called!\n",__FUNCTION__));
+ SAM_ASSERT(sam_method);
+ return ads_ntstatus(ads_status);
+}
+
+
+static NTSTATUS sam_ads_lookup_sid(const SAM_METHODS *sam_method, const NT_USER_TOKEN *access_token,
+ TALLOC_CTX *mem_ctx, const DOM_SID *sid, char **name,
+ enum SID_NAME_USE *type)
+{
+ struct sam_ads_privates *privates = (struct sam_ads_privates *)sam_method->private_data;
+ ADS_STRUCT *ads_struct = privates->ads_struct;
+ SAM_ASSERT(sam_method);
+
+ /* Ignoring access_token for now */
+
+ return ads_sid_to_name(ads_struct, mem_ctx, sid, name, type);
+}
+
+static NTSTATUS sam_ads_lookup_name(const SAM_METHODS *sam_method, const NT_USER_TOKEN *access_token,
+ const char *name, DOM_SID *sid, enum SID_NAME_USE *type)
+{
+ struct sam_ads_privates *privates = (struct sam_ads_privates *)sam_method->private_data;
+ ADS_STRUCT *ads_struct = privates->ads_struct;
+ SAM_ASSERT(sam_method);
+
+ /* Ignoring access_token for now */
+
+ return ads_name_to_sid(ads_struct, name, sid, type);
+}
+
+
+/* Domain API */
+
+static NTSTATUS sam_ads_update_domain(const SAM_METHODS *sam_method, const SAM_DOMAIN_HANDLE *domain)
+{
+ ADS_STATUS ads_status = ADS_STATUS_NOT_IMPLEMENTED;
+ DEBUG(0,("sam_ads: %s was called!\n",__FUNCTION__));
+ SAM_ASSERT(sam_method);
+ return ads_ntstatus(ads_status);
+}
+
+static NTSTATUS sam_ads_get_domain_handle(const SAM_METHODS *sam_method, const NT_USER_TOKEN *access_token,
+ const uint32 access_desired, SAM_DOMAIN_HANDLE **domain)
+{
+ ADS_STATUS ads_status = ADS_STATUS_NOT_IMPLEMENTED;
+ struct sam_ads_privates *privates = (struct sam_ads_privates *)sam_method->private_data;
+ TALLOC_CTX *mem_ctx = privates->mem_ctx; /*Fix me is this right??? */
+ SAM_DOMAIN_HANDLE *dom_handle = NULL;
+ SEC_DESC *sd;
+ uint32 acc_granted;
+ uint32 tmp_value;
+
+ DEBUG(5,("sam_ads_get_domain_handle: %d\n",__LINE__));
+
+ SAM_ASSERT(sam_method && domain);
+
+ (*domain) = NULL;
+
+ if ((dom_handle = talloc(mem_ctx, sizeof(SAM_DOMAIN_HANDLE))) == NULL) {
+ DEBUG(0,("failed to talloc dom_handle\n"));
+ ads_status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
+ return ads_ntstatus(ads_status);
+ }
+
+ ZERO_STRUCTP(dom_handle);
+
+ dom_handle->mem_ctx = mem_ctx; /*Fix me is this right??? */
+ dom_handle->free_fn = NULL;
+ dom_handle->current_sam_methods = sam_method;
+
+ /* check if access can be granted as requested */
+
+ ads_status = sam_ads_get_tree_sec_desc(sam_method, ADS_ROOT_TREE, &sd);
+ if (!ADS_ERR_OK(ads_status))
+ return ads_ntstatus(ads_status);
+
+ ads_status = sam_ads_access_check(sam_method, sd, access_token, access_desired);
+ if (!ADS_ERR_OK(ads_status))
+ return ads_ntstatus(ads_status);
+
+ dom_handle->access_granted = acc_granted;
+
+ /* fill all the values of dom_handle */
+ sid_copy(&dom_handle->private.sid, &sam_method->domain_sid);
+ dom_handle->private.name = smb_xstrdup(sam_method->domain_name);
+ dom_handle->private.servername = "WHOKNOWS"; /* what is the servername */
+
+ /*Fix me: sam_ads_account_policy_get() return ADS_STATUS! */
+ ads_status = sam_ads_account_policy_get(sam_method, AP_MAX_PASSWORD_AGE, &tmp_value);
+ if (!ADS_ERR_OK(ads_status)) {
+ DEBUG(4,("sam_ads_account_policy_get failed for max password age. Useing default\n"));
+ tmp_value = MAX_PASSWORD_AGE;
+ }
+ unix_to_nt_time_abs(&dom_handle->private.max_passwordage,tmp_value);
+
+ ads_status = sam_ads_account_policy_get(sam_method, AP_MIN_PASSWORD_AGE, &tmp_value);
+ if (!ADS_ERR_OK(ads_status)) {
+ DEBUG(4,("sam_ads_account_policy_get failed for min password age. Useing default\n"));
+ tmp_value = 0;
+ }
+ unix_to_nt_time_abs(&dom_handle->private.min_passwordage, tmp_value);
+
+ ads_status = sam_ads_account_policy_get(sam_method, AP_LOCK_ACCOUNT_DURATION, &tmp_value);
+ if (!ADS_ERR_OK(ads_status)) {
+ DEBUG(4,("sam_ads_account_policy_get failed for lockout duration. Useing default\n"));
+ tmp_value = 0;
+ }
+ unix_to_nt_time_abs(&dom_handle->private.lockout_duration, tmp_value);
+
+ ads_status = sam_ads_account_policy_get(sam_method, AP_RESET_COUNT_TIME, &tmp_value);
+ if (!ADS_ERR_OK(ads_status)) {
+ DEBUG(4,("sam_ads_account_policy_get failed for time till locout count is reset. Useing default\n"));
+ tmp_value = 0;
+ }
+ unix_to_nt_time_abs(&dom_handle->private.reset_count, tmp_value);
+
+ ads_status = sam_ads_account_policy_get(sam_method, AP_MIN_PASSWORD_LEN, &tmp_value);
+ if (!ADS_ERR_OK(ads_status)) {
+ DEBUG(4,("sam_ads_account_policy_get failed for min password length. Useing default\n"));
+ tmp_value = 0;
+ }
+ dom_handle->private.min_passwordlength = (uint16)tmp_value;
+
+ ads_status = sam_ads_account_policy_get(sam_method, AP_PASSWORD_HISTORY, &tmp_value);
+ if (!ADS_ERR_OK(ads_status)) {
+ DEBUG(4,("sam_ads_account_policy_get failed password history. Useing default\n"));
+ tmp_value = 0;
+ }
+ dom_handle->private.password_history = (uint16)tmp_value;
+
+ ads_status = sam_ads_account_policy_get(sam_method, AP_BAD_ATTEMPT_LOCKOUT, &tmp_value);
+ if (!ADS_ERR_OK(ads_status)) {
+ DEBUG(4,("sam_ads_account_policy_get failed for bad attempts till lockout. Useing default\n"));
+ tmp_value = 0;
+ }
+ dom_handle->private.lockout_count = (uint16)tmp_value;
+
+ ads_status = sam_ads_account_policy_get(sam_method, AP_TIME_TO_LOGOUT, &tmp_value);
+ if (!ADS_ERR_OK(ads_status)) {
+ DEBUG(4,("sam_ads_account_policy_get failed for force logout. Useing default\n"));
+ tmp_value = -1;
+ }
+
+ ads_status = sam_ads_account_policy_get(sam_method, AP_USER_MUST_LOGON_TO_CHG_PASS, &tmp_value);
+ if (!ADS_ERR_OK(ads_status)) {
+ DEBUG(4,("sam_ads_account_policy_get failed for user must login to change password. Useing default\n"));
+ tmp_value = 0;
+ }
+
+ /* should the real values of num_accounts, num_groups and num_aliases be retreved?
+ * I think it is to expensive to bother
+ */
+ dom_handle->private.num_accounts = 3;
+ dom_handle->private.num_groups = 4;
+ dom_handle->private.num_aliases = 5;
+
+ *domain = dom_handle;
+
+ ads_status = ADS_ERROR_NT(NT_STATUS_OK);
+ return ads_ntstatus(ads_status);
+}
+
+/* Account API */
+static NTSTATUS sam_ads_create_account(const SAM_METHODS *sam_method,
+ const NT_USER_TOKEN *access_token, uint32 access_desired,
+ TALLOC_CTX *mem_ctx,
+ const char *account_name, uint16 acct_ctrl, SAM_ACCOUNT_HANDLE **account)
+{
+ ADS_STATUS ads_status = ADS_STATUS_NOT_IMPLEMENTED;
+ struct sam_ads_privates *privates = (struct sam_ads_privates *)sam_method->private_data;
+ SEC_DESC *sd = NULL;
+
+ SAM_ASSERT(sam_method && access_token && account_name && account);
+
+ ads_status = sam_ads_get_tree_sec_desc(sam_method, ADS_SUBTREE_USERS, &sd);
+ if (!ADS_ERR_OK(ads_status))
+ return ads_ntstatus(ads_status);
+
+ ads_status = sam_ads_access_check(sam_method, sd, access_token, access_desired);
+ if (!ADS_ERR_OK(ads_status))
+ return ads_ntstatus(ads_status);
+
+ ads_status = ADS_ERROR_NT(sam_init_account_talloc(mem_ctx, account));
+ if (!ADS_ERR_OK(ads_status))
+ return ads_ntstatus(ads_status);
+
+ return ads_ntstatus(ads_status);
+}
+
+static NTSTATUS sam_ads_add_account(const SAM_METHODS *sam_method, const SAM_ACCOUNT_HANDLE *account)
+{
+ ADS_STATUS ads_status = ADS_ERROR(LDAP_NO_MEMORY);
+ struct sam_ads_privates *privates = (struct sam_ads_privates *)sam_method->private_data;
+ ADS_STRUCT *ads_struct = privates->ads_struct;
+ TALLOC_CTX *mem_ctx = privates->mem_ctx;
+ ADS_MODLIST mods;
+ uint16 acct_ctrl;
+ char *new_dn;
+
+ SAM_ASSERT(sam_method && account);
+
+ ads_status = ADS_ERROR_NT(sam_get_account_acct_ctrl(account,&acct_ctrl));
+ if (!ADS_ERR_OK(ads_status))
+ goto done;
+
+ if ((acct_ctrl & ACB_WSTRUST)||(acct_ctrl & ACB_SVRTRUST)) {
+ /* Computer account */
+ char *name,*controlstr;
+ char *hostname,*host_upn,*host_spn;
+ const char *objectClass[] = {"top", "person", "organizationalPerson",
+ "user", "computer", NULL};
+
+ ads_status = ADS_ERROR_NT(sam_get_account_name(account,&name));
+ if (!ADS_ERR_OK(ads_status))
+ goto done;
+
+ if (!(host_upn = talloc_asprintf(mem_ctx, "%s@%s", name, ads_struct->config.realm))) {
+ ads_status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
+ goto done;
+ }
+
+ if (!(new_dn = talloc_asprintf(mem_ctx, "CN=%s,CN=Computers,%s", hostname,
+ ads_struct->config.bind_path))) {
+ ads_status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
+ goto done;
+ }
+
+ if (!(controlstr = talloc_asprintf(mem_ctx, "%u", ads_acb2uf(acct_ctrl)))) {
+ ads_status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
+ goto done;
+ }
+
+ if (!(mods = ads_init_mods(mem_ctx))) {
+ ads_status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
+ goto done;
+ }
+
+ ads_status = ads_mod_str(mem_ctx, &mods, "cn", hostname);
+ if (!ADS_ERR_OK(ads_status))
+ goto done;
+ ads_status = ads_mod_strlist(mem_ctx, &mods, "objectClass", objectClass);
+ if (!ADS_ERR_OK(ads_status))
+ goto done;
+ ads_status = ads_mod_str(mem_ctx, &mods, "userPrincipalName", host_upn);
+ if (!ADS_ERR_OK(ads_status))
+ goto done;
+ ads_status = ads_mod_str(mem_ctx, &mods, "displayName", hostname);
+ if (!ADS_ERR_OK(ads_status))
+ goto done;
+ ads_status = ads_mod_str(mem_ctx, &mods, "sAMAccountName", name);
+ if (!ADS_ERR_OK(ads_status))
+ goto done;
+ ads_status = ads_mod_str(mem_ctx, &mods, "userAccountControl", controlstr);
+ if (!ADS_ERR_OK(ads_status))
+ goto done;
+
+ ads_status = ads_mod_str(mem_ctx, &mods, "servicePrincipalName", host_spn);
+ if (!ADS_ERR_OK(ads_status))
+ goto done;
+ ads_status = ads_mod_str(mem_ctx, &mods, "dNSHostName", hostname);
+ if (!ADS_ERR_OK(ads_status))
+ goto done;
+ ads_status = ads_mod_str(mem_ctx, &mods, "userAccountControl", controlstr);
+ if (!ADS_ERR_OK(ads_status))
+ goto done;
+ /* ads_status = ads_mod_str(mem_ctx, &mods, "operatingSystem", "Samba");
+ if (!ADS_ERR_OK(ads_status))
+ goto done;
+ *//* ads_status = ads_mod_str(mem_ctx, &mods, "operatingSystemVersion", VERSION);
+ if (!ADS_ERR_OK(ads_status))
+ goto done;
+ */
+ /* End Computer account */
+ } else {
+ /* User account*/
+ char *upn, *controlstr;
+ char *name, *fullname;
+ const char *objectClass[] = {"top", "person", "organizationalPerson",
+ "user", NULL};
+
+ ads_status = ADS_ERROR_NT(sam_get_account_name(account,&name));
+ if (!ADS_ERR_OK(ads_status))
+ goto done;
+
+ ads_status = ADS_ERROR_NT(sam_get_account_fullname(account,&fullname));
+ if (!ADS_ERR_OK(ads_status))
+ goto done;
+
+ if (!(upn = talloc_asprintf(mem_ctx, "%s@%s", name, ads_struct->config.realm))) {
+ ads_status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
+ goto done;
+ }
+
+ if (!(new_dn = talloc_asprintf(mem_ctx, "CN=%s,CN=Users,%s", fullname,
+ ads_struct->config.bind_path))) {
+ ads_status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
+ goto done;
+ }
+
+ if (!(controlstr = talloc_asprintf(mem_ctx, "%u", ads_acb2uf(acct_ctrl)))) {
+ ads_status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
+ goto done;
+ }
+
+ if (!(mods = ads_init_mods(mem_ctx))) {
+ ads_status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
+ goto done;
+ }
+
+ ads_status = ads_mod_str(mem_ctx, &mods, "cn", fullname);
+ if (!ADS_ERR_OK(ads_status))
+ goto done;
+ ads_status = ads_mod_strlist(mem_ctx, &mods, "objectClass", objectClass);
+ if (!ADS_ERR_OK(ads_status))
+ goto done;
+ ads_status = ads_mod_str(mem_ctx, &mods, "userPrincipalName", upn);
+ if (!ADS_ERR_OK(ads_status))
+ goto done;
+ ads_status = ads_mod_str(mem_ctx, &mods, "displayName", fullname);
+ if (!ADS_ERR_OK(ads_status))
+ goto done;
+ ads_status = ads_mod_str(mem_ctx, &mods, "sAMAccountName", name);
+ if (!ADS_ERR_OK(ads_status))
+ goto done;
+ ads_status = ads_mod_str(mem_ctx, &mods, "userAccountControl", controlstr);
+ if (!ADS_ERR_OK(ads_status))
+ goto done;
+ }/* End User account */
+
+ /* Finally at the account */
+ ads_status = ads_gen_add(ads_struct, new_dn, mods);
+
+done:
+ return ads_ntstatus(ads_status);
+}
+
+static NTSTATUS sam_ads_update_account(const SAM_METHODS *sam_method, const SAM_ACCOUNT_HANDLE *account)
+{
+ ADS_STATUS ads_status = ADS_STATUS_NOT_IMPLEMENTED;
+ DEBUG(0,("sam_ads: %s was called!\n",__FUNCTION__));
+ SAM_ASSERT(sam_method);
+ return ads_ntstatus(ads_status);
+}
+
+static NTSTATUS sam_ads_delete_account(const SAM_METHODS *sam_method, const SAM_ACCOUNT_HANDLE *account)
+{
+ ADS_STATUS ads_status = ADS_STATUS_NOT_IMPLEMENTED;
+ DEBUG(0,("sam_ads: %s was called!\n",__FUNCTION__));
+ SAM_ASSERT(sam_method);
+
+
+
+ return ads_ntstatus(ads_status);
+}
+
+static NTSTATUS sam_ads_enum_accounts(const SAM_METHODS *sam_method, const NT_USER_TOKEN *access_token, uint16 acct_ctrl, uint32 *account_count, SAM_ACCOUNT_ENUM **accounts)
+{
+ ADS_STATUS ads_status = ADS_STATUS_NOT_IMPLEMENTED;
+ DEBUG(0,("sam_ads: %s was called!\n",__FUNCTION__));
+ SAM_ASSERT(sam_method);
+ return ads_ntstatus(ads_status);
+}
+
+static NTSTATUS sam_ads_get_account_by_sid(const SAM_METHODS *sam_method, const NT_USER_TOKEN *access_token, const uint32 access_desired, const DOM_SID *accountsid, SAM_ACCOUNT_HANDLE **account)
+{
+ ADS_STATUS ads_status = ADS_STATUS_NOT_IMPLEMENTED;
+ DEBUG(0,("sam_ads: %s was called!\n",__FUNCTION__));
+ SAM_ASSERT(sam_method);
+ return ads_ntstatus(ads_status);
+}
+
+static NTSTATUS sam_ads_get_account_by_name(const SAM_METHODS *sam_method, const NT_USER_TOKEN *access_token, const uint32 access_desired, const char *name, SAM_ACCOUNT_HANDLE **account)
+{
+ ADS_STATUS ads_status = ADS_STATUS_NOT_IMPLEMENTED;
+ DEBUG(0,("sam_ads: %s was called!\n",__FUNCTION__));
+ SAM_ASSERT(sam_method);
+ return ads_ntstatus(ads_status);
+}
+
+
+/* Group API */
+static NTSTATUS sam_ads_create_group(const SAM_METHODS *sam_method, const NT_USER_TOKEN *access_token, uint32 access_desired, const char *group_name, uint16 group_ctrl, SAM_GROUP_HANDLE **group)
+{
+ ADS_STATUS ads_status = ADS_STATUS_NOT_IMPLEMENTED;
+ DEBUG(0,("sam_ads: %s was called!\n",__FUNCTION__));
+ SAM_ASSERT(sam_method);
+ return ads_ntstatus(ads_status);
+}
+
+static NTSTATUS sam_ads_add_group(const SAM_METHODS *sam_method, const SAM_GROUP_HANDLE *group)
+{
+ ADS_STATUS ads_status = ADS_STATUS_NOT_IMPLEMENTED;
+ DEBUG(0,("sam_ads: %s was called!\n",__FUNCTION__));
+ SAM_ASSERT(sam_method);
+ return ads_ntstatus(ads_status);
+}
+
+static NTSTATUS sam_ads_update_group(const SAM_METHODS *sam_method, const SAM_GROUP_HANDLE *group)
+{
+ ADS_STATUS ads_status = ADS_STATUS_NOT_IMPLEMENTED;
+ DEBUG(0,("sam_ads: %s was called!\n",__FUNCTION__));
+ SAM_ASSERT(sam_method);
+ return ads_ntstatus(ads_status);
+}
+
+static NTSTATUS sam_ads_delete_group(const SAM_METHODS *sam_method, const SAM_GROUP_HANDLE *group)
+{
+ ADS_STATUS ads_status = ADS_STATUS_NOT_IMPLEMENTED;
+ DEBUG(0,("sam_ads: %s was called!\n",__FUNCTION__));
+ SAM_ASSERT(sam_method);
+ return ads_ntstatus(ads_status);
+}
+
+static NTSTATUS sam_ads_enum_groups(const SAM_METHODS *sam_method, const NT_USER_TOKEN *access_token, const uint16 group_ctrl, uint32 *groups_count, SAM_GROUP_ENUM **groups)
+{
+ ADS_STATUS ads_status = ADS_STATUS_NOT_IMPLEMENTED;
+ struct sam_ads_privates *privates = (struct sam_ads_privates *)sam_method->private_data;
+ ADS_STRUCT *ads_struct = privates->ads_struct;
+ TALLOC_CTX *mem_ctx = privates->mem_ctx;
+ void *res = NULL;
+ void *msg = NULL;
+ char *filter = NULL;
+ int i = 0;
+
+ /* get only these LDAP attributes, witch we really need for a group */
+ const char *group_enum_attrs[] = {"objectSid",
+ "description",
+ "sAMAcountName",
+ NULL};
+
+ SAM_ASSERT(sam_method && access_token && groups_count && groups);
+
+ *groups_count = 0;
+
+ DEBUG(3,("ads: enum_dom_groups\n"));
+
+ /* Fix Me: get only group from the wanted Type */
+ asprintf(&filter, "(&(objectClass=group)(groupType=%s))", "*");
+ ads_status = sam_ads_do_search(privates, ads_struct->config.bind_path, LDAP_SCOPE_SUBTREE, filter, group_enum_attrs, &res);
+ if (!ADS_ERR_OK(ads_status)) {
+ DEBUG(1,("enum_groups ads_search: %s\n", ads_errstr(ads_status)));
+ }
+
+ *groups_count = ads_count_replies(ads_struct, res);
+ if (*groups_count == 0) {
+ DEBUG(1,("enum_groups: No groups found\n"));
+ }
+
+ (*groups) = talloc_zero(mem_ctx, (*groups_count) * sizeof(**groups));
+ if (!*groups) {
+ ads_status = ADS_ERROR_NT(NT_STATUS_NO_MEMORY);
+ }
+
+ for (msg = ads_first_entry(ads_struct, res); msg; msg = ads_next_entry(ads_struct, msg)) {
+ uint32 grouptype;
+
+ if (!ads_pull_uint32(ads_struct, msg, "groupType", &grouptype)) {
+ ;
+ } else {
+ (*groups)->group_ctrl = ads_gtype2gcb(grouptype);
+ }
+
+ if (!((*groups)->group_name = ads_pull_string(ads_struct, mem_ctx, msg, "sAMAccountName"))) {
+ ;
+ }
+
+ if (!((*groups)->group_desc = ads_pull_string(ads_struct, mem_ctx, msg, "description"))) {
+ ;
+ }
+
+ if (!ads_pull_sid(ads_struct, msg, "objectSid", &((*groups)->sid))) {
+ DEBUG(1,("No sid for group %s !?\n", (*groups)->group_name));
+ continue;
+ }
+
+ i++;
+ }
+
+ (*groups_count) = i;
+
+ ads_status = ADS_ERROR_NT(NT_STATUS_OK);
+
+ DEBUG(3,("ads enum_dom_groups gave %d entries\n", (*groups_count)));
+
+ if (res) ads_msgfree(ads_struct, res);
+
+ return ads_ntstatus(ads_status);
+}
+
+static NTSTATUS sam_ads_get_group_by_sid(const SAM_METHODS *sam_method, const NT_USER_TOKEN *access_token, const uint32 access_desired, const DOM_SID *groupsid, SAM_GROUP_HANDLE **group)
+{
+ ADS_STATUS ads_status = ADS_STATUS_NOT_IMPLEMENTED;
+ DEBUG(0,("sam_ads: %s was called!\n",__FUNCTION__));
+ SAM_ASSERT(sam_method);
+ return ads_ntstatus(ads_status);
+}
+
+static NTSTATUS sam_ads_get_group_by_name(const SAM_METHODS *sam_method, const NT_USER_TOKEN *access_token, const uint32 access_desired, const char *name, SAM_GROUP_HANDLE **group)
+{
+ ADS_STATUS ads_status = ADS_STATUS_NOT_IMPLEMENTED;
+ DEBUG(0,("sam_ads: %s was called!\n",__FUNCTION__));
+ SAM_ASSERT(sam_method);
+ return ads_ntstatus(ads_status);
+}
+
+static NTSTATUS sam_ads_add_member_to_group(const SAM_METHODS *sam_method, const SAM_GROUP_HANDLE *group, const SAM_GROUP_MEMBER *member)
+{
+ ADS_STATUS ads_status = ADS_STATUS_NOT_IMPLEMENTED;
+ DEBUG(0,("sam_ads: %s was called!\n",__FUNCTION__));
+ SAM_ASSERT(sam_method);
+ return ads_ntstatus(ads_status);
+}
+
+static NTSTATUS sam_ads_delete_member_from_group(const SAM_METHODS *sam_method, const SAM_GROUP_HANDLE *group, const SAM_GROUP_MEMBER *member)
+{
+ ADS_STATUS ads_status = ADS_STATUS_NOT_IMPLEMENTED;
+ DEBUG(0,("sam_ads: %s was called!\n",__FUNCTION__));
+ SAM_ASSERT(sam_method);
+ return ads_ntstatus(ads_status);
+}
+
+static NTSTATUS sam_ads_enum_groupmembers(const SAM_METHODS *sam_method, const SAM_GROUP_HANDLE *group, uint32 *members_count, SAM_GROUP_MEMBER **members)
+{
+ ADS_STATUS ads_status = ADS_STATUS_NOT_IMPLEMENTED;
+ DEBUG(0,("sam_ads: %s was called!\n",__FUNCTION__));
+ SAM_ASSERT(sam_method);
+ return ads_ntstatus(ads_status);
+}
+
+static NTSTATUS sam_ads_get_groups_of_sid(const SAM_METHODS *sam_method, const NT_USER_TOKEN *access_token, const DOM_SID **sids, const uint16 group_ctrl, uint32 *group_count, SAM_GROUP_ENUM **groups)
+{
+ ADS_STATUS ads_status = ADS_STATUS_NOT_IMPLEMENTED;
+ DEBUG(0,("sam_ads: %s was called!\n",__FUNCTION__));
+ SAM_ASSERT(sam_method);
+ return ads_ntstatus(ads_status);
+}
+
+/**********************************
+Free our private data
+***********************************/
+static void sam_ads_free_private_data(void **vp)
+{
+ struct sam_ads_privates **sam_ads_state = (struct sam_ads_privates **)vp;
+
+ if ((*sam_ads_state)->ads_struct->ld) {
+ ldap_unbind((*sam_ads_state)->ads_struct->ld);
+ }
+
+ ads_destroy(&((*sam_ads_state)->ads_struct));
+
+ talloc_destroy((*sam_ads_state)->mem_ctx);
+ /* Fix me: maybe we must free some other stuff here */
+
+ *sam_ads_state = NULL;
+}
+
+
+
+/*****************************************************
+Init the ADS SAM backend
+******************************************************/
+NTSTATUS sam_init_ads(SAM_METHODS *sam_method, const char *module_params)
+{
+ ADS_STATUS ads_status;
+ NTSTATUS nt_status;
+ struct sam_ads_privates *sam_ads_state;
+ TALLOC_CTX *mem_ctx;
+
+ SAM_ASSERT(sam_method && sam_method->parent);
+
+ mem_ctx = sam_method->parent->mem_ctx;
+
+ /* Here the SAM API functions of the sam_ads module */
+
+ /* General API */
+
+ sam_method->sam_get_sec_desc = sam_ads_get_sec_desc;
+ sam_method->sam_set_sec_desc = sam_ads_set_sec_desc;
+
+ sam_method->sam_lookup_sid = sam_ads_lookup_sid;
+ sam_method->sam_lookup_name = sam_ads_lookup_name;
+
+ /* Domain API */
+
+ sam_method->sam_update_domain = sam_ads_update_domain;
+ sam_method->sam_get_domain_handle = sam_ads_get_domain_handle;
+
+ /* Account API */
+
+ sam_method->sam_create_account = sam_ads_create_account;
+ sam_method->sam_add_account = sam_ads_add_account;
+ sam_method->sam_update_account = sam_ads_update_account;
+ sam_method->sam_delete_account = sam_ads_delete_account;
+ sam_method->sam_enum_accounts = sam_ads_enum_accounts;
+
+ sam_method->sam_get_account_by_sid = sam_ads_get_account_by_sid;
+ sam_method->sam_get_account_by_name = sam_ads_get_account_by_name;
+
+ /* Group API */
+
+ sam_method->sam_create_group = sam_ads_create_group;
+ sam_method->sam_add_group = sam_ads_add_group;
+ sam_method->sam_update_group = sam_ads_update_group;
+ sam_method->sam_delete_group = sam_ads_delete_group;
+ sam_method->sam_enum_groups = sam_ads_enum_groups;
+ sam_method->sam_get_group_by_sid = sam_ads_get_group_by_sid;
+ sam_method->sam_get_group_by_name = sam_ads_get_group_by_name;
+
+ sam_method->sam_add_member_to_group = sam_ads_add_member_to_group;
+ sam_method->sam_delete_member_from_group = sam_ads_delete_member_from_group;
+ sam_method->sam_enum_groupmembers = sam_ads_enum_groupmembers;
+
+ sam_method->sam_get_groups_of_sid = sam_ads_get_groups_of_sid;
+
+ /*Fix me: use talloc !*/
+ sam_ads_state = talloc_zero(mem_ctx, sizeof(struct sam_ads_privates));
+ if (!sam_ads_state) {
+ DEBUG(0, ("talloc() failed for sam_ads private_data!\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ if (!(sam_ads_state->mem_ctx = talloc_init_named("sam_ads_method"))) {
+ DEBUG(0, ("talloc_init_named() failed for sam_ads_state->mem_ctx\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ sam_ads_state->ads_bind_dn = talloc_strdup(sam_ads_state->mem_ctx, lp_parm_string(NULL,"sam_ads","bind as"));
+ sam_ads_state->ads_bind_pw = talloc_strdup(sam_ads_state->mem_ctx, lp_parm_string(NULL,"sam_ads","bind pw"));
+
+ sam_ads_state->bind_plaintext = strequal(lp_parm_string(NULL, "sam_ads", "plaintext bind"), "yes");
+
+ if (!sam_ads_state->ads_bind_dn || !sam_ads_state->ads_bind_pw) {
+ DEBUG(0, ("talloc_strdup() failed for bind dn or password\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ /* Maybe we should not check the result here? Server down on startup? */
+
+ if (module_params && *module_params) {
+ sam_ads_state->ldap_uri = talloc_strdup(sam_ads_state->mem_ctx, module_params);
+ if (!sam_ads_state->ldap_uri) {
+ DEBUG(0, ("talloc_strdup() failed for bind dn or password\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+ } else {
+ sam_ads_state->ldap_uri = "ldapi://";
+ }
+
+ ads_status = sam_ads_cached_connection(sam_ads_state);
+ if (!ADS_ERR_OK(ads_status)) {
+ return ads_ntstatus(ads_status);
+ }
+
+ sam_method->private_data = sam_ads_state;
+ sam_method->free_private_data = sam_ads_free_private_data;
+
+ sam_ads_debug_level = debug_add_class("sam_ads");
+ if (sam_ads_debug_level == -1) {
+ sam_ads_debug_level = DBGC_ALL;
+ DEBUG(0, ("sam_ads: Couldn't register custom debugging class!\n"));
+ } else DEBUG(2, ("sam_ads: Debug class number of 'sam_ads': %d\n", sam_ads_debug_level));
+
+ DEBUG(5, ("Initializing sam_ads\n"));
+ if (module_params)
+ DEBUG(10, ("Module Parameters for Domain %s[%s]: %s\n", sam_method->domain_name, sam_method->domain_name, module_params));
+ return NT_STATUS_OK;
+}
+
+#else /* HAVE_LDAP */
+void sam_ads_dummy(void)
+{
+ DEBUG(0,("sam_ads: not supported!\n"));
+}
+#endif /* HAVE_LDAP */
diff --git a/source3/torture/cmd_sam.c b/source3/torture/cmd_sam.c
index 3d4725c8a8..627a2f59b3 100644
--- a/source3/torture/cmd_sam.c
+++ b/source3/torture/cmd_sam.c
@@ -99,7 +99,7 @@ static NTSTATUS cmd_lookup_sid(struct samtest_state *st, TALLOC_CTX *mem_ctx, in
return NT_STATUS_INVALID_PARAMETER;
}
- if (!NT_STATUS_IS_OK(status = context_sam_lookup_sid(st->context, st->token, &sid, &name, &type))) {
+ if (!NT_STATUS_IS_OK(status = context_sam_lookup_sid(st->context, st->token, mem_ctx, &sid, &name, &type))) {
printf("context_sam_lookup_sid failed!\n");
return status;
}
@@ -112,7 +112,7 @@ static NTSTATUS cmd_lookup_sid(struct samtest_state *st, TALLOC_CTX *mem_ctx, in
static NTSTATUS cmd_lookup_name(struct samtest_state *st, TALLOC_CTX *mem_ctx, int argc, char **argv)
{
- DOM_SID *sid;
+ DOM_SID sid;
uint32 type;
NTSTATUS status;
if (argc != 3) {
@@ -125,7 +125,7 @@ static NTSTATUS cmd_lookup_name(struct samtest_state *st, TALLOC_CTX *mem_ctx, i
return status;
}
- printf("SID: %s\n", sid_string_static(sid));
+ printf("SID: %s\n", sid_string_static(&sid));
printf("Type: %d\n", type);
return NT_STATUS_OK;