summaryrefslogtreecommitdiff
path: root/source3/passdb
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2002-01-20 14:30:58 +0000
committerAndrew Bartlett <abartlet@samba.org>2002-01-20 14:30:58 +0000
commit1a74d8d1f0758d15c5c35d20e33d9868565812cf (patch)
tree7a0f62e8228770198cc5bb36de355c290ac77b44 /source3/passdb
parent32101155d4a0c80faf392f56a6baa7b91847dd99 (diff)
downloadsamba-1a74d8d1f0758d15c5c35d20e33d9868565812cf.tar.gz
samba-1a74d8d1f0758d15c5c35d20e33d9868565812cf.tar.bz2
samba-1a74d8d1f0758d15c5c35d20e33d9868565812cf.zip
This is another *BIG* change...
Samba now features a pluggable passdb interface, along the same lines as the one in use in the auth subsystem. In this case, only one backend may be active at a time by the 'normal' interface, and only one backend per passdb_context is permitted outside that. This pluggable interface is designed to allow any number of passdb backends to be compiled in, with the selection at runtime. The 'passdb backend' paramater has been created (and documented!) to support this. As such, configure has been modfied to allow (for example) --with-ldap and the old smbpasswd to be selected at the same time. This patch also introduces two new backends: smbpasswd_nua and tdbsam_nua. These two backends accept 'non unix accounts', where the user does *not* exist in /etc/passwd. These accounts' don't have UIDs in the unix sense, but to avoid conflicts in the algroitmic mapping of RIDs, they use the values specified in the 'non unix account range' paramter - in the same way as the winbind ranges are specifed. While I was at it, I cleaned up some of the code in pdb_tdb (code copied directly from smbpasswd and not really considered properly). Most of this was to do with % macro expansion on stored data. It isn't easy to get the macros into the tdb, and the first password change will 'expand' them. tdbsam needs to use a similar system to pdb_ldap in this regard. This patch only makes minor adjustments to pdb_nisplus and pdb_ldap, becouse I don't have the test facilities for these. I plan to incoroprate at least pdb_ldap into this scheme after consultation with Jerry. Each (converted) passdb module now no longer has any 'static' variables, and only exports 1 init function outside its .c file. The non-unix-account support in this patch has been proven! It is now possible to join a win2k machine to a Samba PDC without an account in /etc/passwd! Other changes: Minor interface adjustments: pdb_delete_sam_account() now takes a SAM_ACCOUNT, not a char*. pdb_update_sam_account() no longer takes the 'override' argument that was being ignored so often (every other passdb backend). Extra checks have been added in some places. Minor code changes: smbpasswd no longer attempts to initialise the passdb at startup, this is now done on first use. pdbedit has lost some of its 'machine account' logic, as this behaviour is now controlled by the passdb subsystem directly. The samr subsystem no longer calls 'local password change', but does the pdb interactions directly. This allow the ACB_ flags specifed to be transferred direct to the backend, without interference. Doco: I've updated the doco to reflect some of the changes, and removed some paramters no longer applicable to HEAD. (This used to be commit ff354c99c585068af6dc1ff35a1f109a806b326b)
Diffstat (limited to 'source3/passdb')
-rw-r--r--source3/passdb/passdb.c80
-rw-r--r--source3/passdb/pdb_interface.c368
-rw-r--r--source3/passdb/pdb_ldap.c14
-rw-r--r--source3/passdb/pdb_nisplus.c16
-rw-r--r--source3/passdb/pdb_smbpasswd.c532
-rw-r--r--source3/passdb/pdb_tdb.c421
6 files changed, 992 insertions, 439 deletions
diff --git a/source3/passdb/passdb.c b/source3/passdb/passdb.c
index 4460af0545..2bb4ee0a75 100644
--- a/source3/passdb/passdb.c
+++ b/source3/passdb/passdb.c
@@ -32,28 +32,6 @@
extern DOM_SID global_sam_sid;
-struct passdb_ops *pdb_ops;
-
-#if 0 /* JERRY */
-static void* pdb_handle = NULL;
-#endif
-
-/***************************************************************
- Initialize the password db operations.
-***************************************************************/
-
-BOOL initialize_password_db(BOOL reload)
-{
- /*
- * This function is unfinished right now, so just
- * ignore the details and always return True. It
- * is here only as a placeholder --jerry
- */
- return True;
-
-}
-
-
/************************************************************
Fill the SAM_ACCOUNT with default values.
***********************************************************/
@@ -639,6 +617,7 @@ BOOL local_lookup_name(const char *c_domain, const char *c_user, DOM_SID *psid,
DOM_SID local_sid;
fstring user;
fstring domain;
+ SAM_ACCOUNT *sam_account = NULL;
*psid_name_use = SID_NAME_UNKNOWN;
@@ -671,9 +650,20 @@ BOOL local_lookup_name(const char *c_domain, const char *c_user, DOM_SID *psid,
(void)map_username(user);
- if((pass = Get_Pwnam(user))) {
+ if (!NT_STATUS_IS_OK(pdb_init_sam(&sam_account))) {
+ return False;
+ }
+
+ if (pdb_getsampwnam(sam_account, user)) {
+ sid_append_rid( &local_sid, pdb_get_user_rid(sam_account));
+ *psid_name_use = SID_NAME_USER;
+ pdb_free_sam(&sam_account);
+
+ } else if((pass = Get_Pwnam(user))) {
sid_append_rid( &local_sid, pdb_uid_to_user_rid(pass->pw_uid));
*psid_name_use = SID_NAME_USER;
+ pdb_free_sam(&sam_account);
+
} else {
/*
* Maybe it was a group ?
@@ -681,6 +671,8 @@ BOOL local_lookup_name(const char *c_domain, const char *c_user, DOM_SID *psid,
struct group *grp;
GROUP_MAP map;
+ pdb_free_sam(&sam_account);
+
/* check if it's a mapped group */
if (get_group_map_from_ntname(user, &map, MAPPING_WITHOUT_PRIV)) {
if (map.gid!=-1) {
@@ -1021,29 +1013,33 @@ BOOL local_password_change(const char *user_name, int local_flags,
pdb_free_sam(&sam_pass);
if (local_flags & LOCAL_ADD_USER) {
- /*
- * Check for a local account - if we're adding only.
- */
-
- if(!(pwd = getpwnam_alloc(user_name))) {
- slprintf(err_str, err_str_len - 1, "User %s does not \
-exist in system password file (usually /etc/passwd). Cannot add \
-account without a valid local system user.\n", user_name);
- return False;
- }
+ pwd = getpwnam_alloc(user_name);
} else {
slprintf(err_str, err_str_len-1,"Failed to find entry for user %s.\n", user_name);
return False;
}
-
- if (!NT_STATUS_IS_OK(pdb_init_sam_pw(&sam_pass, pwd))){
- slprintf(err_str, err_str_len-1, "Failed initialise SAM_ACCOUNT for user %s.\n", user_name);
+
+ if (pwd) {
+ /* Local user found, so init from this */
+ if (!NT_STATUS_IS_OK(pdb_init_sam_pw(&sam_pass, pwd))){
+ slprintf(err_str, err_str_len-1, "Failed initialise SAM_ACCOUNT for user %s.\n", user_name);
+ passwd_free(&pwd);
+ return False;
+ }
+
passwd_free(&pwd);
- return False;
+ } else {
+ if (!NT_STATUS_IS_OK(pdb_init_sam(&sam_pass))){
+ slprintf(err_str, err_str_len-1, "Failed initialise SAM_ACCOUNT for user %s.\n", user_name);
+ return False;
+ }
+
+ if (!pdb_set_username(sam_pass, user_name)) {
+ slprintf(err_str, err_str_len - 1, "Failed to set username for user %s.\n", user_name);
+ pdb_free_sam(&sam_pass);
+ return False;
+ }
}
-
- passwd_free(&pwd);
-
if (local_flags & LOCAL_TRUST_ACCOUNT) {
if (!pdb_set_acct_ctrl(sam_pass, ACB_WSTRUST)) {
slprintf(err_str, err_str_len - 1, "Failed to set 'trusted workstation account' flags for user %s.\n", user_name);
@@ -1135,14 +1131,14 @@ account without a valid local system user.\n", user_name);
return False;
}
} else if (local_flags & LOCAL_DELETE_USER) {
- if (!pdb_delete_sam_account(user_name)) {
+ if (!pdb_delete_sam_account(sam_pass)) {
slprintf(err_str,err_str_len-1, "Failed to delete entry for user %s.\n", user_name);
pdb_free_sam(&sam_pass);
return False;
}
slprintf(msg_str, msg_str_len-1, "Deleted user %s.\n", user_name);
} else {
- if(!pdb_update_sam_account(sam_pass, True)) {
+ if(!pdb_update_sam_account(sam_pass)) {
slprintf(err_str, err_str_len-1, "Failed to modify entry for user %s.\n", user_name);
pdb_free_sam(&sam_pass);
return False;
diff --git a/source3/passdb/pdb_interface.c b/source3/passdb/pdb_interface.c
new file mode 100644
index 0000000000..b5e7273520
--- /dev/null
+++ b/source3/passdb/pdb_interface.c
@@ -0,0 +1,368 @@
+/*
+ Unix SMB/Netbios implementation.
+ Version 3.0
+ Password and authentication handling
+ 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"
+
+/** List of various built-in passdb modules */
+
+const struct pdb_init_function builtin_pdb_init_functions[] = {
+ { "smbpasswd", pdb_init_smbpasswd },
+ { "smbpasswd_nua", pdb_init_smbpasswd_nua },
+ { "tdbsam", pdb_init_tdbsam },
+ { "tdbsam_nua", pdb_init_tdbsam_nua },
+#if 0
+ { "ldap", pdb_init_ldap },
+ { "nisplus", pdb_init_nisplus },
+ { "unix", pdb_init_unix },
+#endif
+ { NULL, NULL}
+};
+
+static BOOL context_setsampwent(struct pdb_context *context, BOOL update)
+{
+ if ((!context) || (!context->pdb_selected)) {
+ DEBUG(0, ("invalid pdb_context specified!\n"));
+ return False;
+ }
+
+ return context->pdb_selected->setsampwent(context, update);
+}
+
+static void context_endsampwent(struct pdb_context *context)
+{
+ if ((!context) || (!context->pdb_selected)) {
+ DEBUG(0, ("invalid pdb_context specified!\n"));
+ return;
+ }
+
+ context->pdb_selected->endsampwent(context);
+}
+
+static BOOL context_getsampwent(struct pdb_context *context, SAM_ACCOUNT *user)
+{
+ if ((!context) || (!context->pdb_selected)) {
+ DEBUG(0, ("invalid pdb_context specified!\n"));
+ return False;
+ }
+
+ return context->pdb_selected->getsampwent(context, user);
+}
+
+static BOOL context_getsampwnam(struct pdb_context *context, SAM_ACCOUNT *sam_acct, const char *username)
+{
+ if ((!context) || (!context->pdb_selected)) {
+ DEBUG(0, ("invalid pdb_context specified!\n"));
+ return False;
+ }
+
+ return context->pdb_selected->getsampwnam(context, sam_acct, username);
+}
+
+static BOOL context_getsampwrid(struct pdb_context *context, SAM_ACCOUNT *sam_acct, uint32 rid)
+{
+ if ((!context) || (!context->pdb_selected)) {
+ DEBUG(0, ("invalid pdb_context specified!\n"));
+ return False;
+ }
+
+ return context->pdb_selected->getsampwrid(context, sam_acct, rid);
+}
+
+static BOOL context_add_sam_account(struct pdb_context *context, SAM_ACCOUNT *sam_acct)
+{
+ if ((!context) || (!context->pdb_selected)) {
+ DEBUG(0, ("invalid pdb_context specified!\n"));
+ return False;
+ }
+
+ /** @todo This is where a 're-read on add' should be done */
+
+ return context->pdb_selected->add_sam_account(context, sam_acct);
+}
+
+static BOOL context_update_sam_account(struct pdb_context *context, SAM_ACCOUNT *sam_acct)
+{
+ if ((!context) || (!context->pdb_selected)) {
+ DEBUG(0, ("invalid pdb_context specified!\n"));
+ return False;
+ }
+
+ /** @todo This is where a 're-read on update' should be done */
+
+ return context->pdb_selected->update_sam_account(context, sam_acct);
+}
+
+static BOOL context_delete_sam_account(struct pdb_context *context, SAM_ACCOUNT *sam_acct)
+{
+ if ((!context) || (!context->pdb_selected)) {
+ DEBUG(0, ("invalid pdb_context specified!\n"));
+ return False;
+ }
+
+ return context->pdb_selected->delete_sam_account(context, sam_acct);
+}
+
+static void free_pdb_context(struct pdb_context **context)
+{
+ if (((*context)->pdb_selected) && ((*context)->pdb_selected->free_private_data)) {
+ (*context)->pdb_selected->free_private_data((*context)->pdb_selected->private_data);
+ }
+
+ talloc_destroy((*context)->mem_ctx);
+ *context = NULL;
+}
+
+/******************************************************************
+ Make a pdb_context from scratch.
+*******************************************************************/
+
+static NTSTATUS make_pdb_context(struct pdb_context **context)
+{
+ TALLOC_CTX *mem_ctx;
+
+ mem_ctx = talloc_init_named("pdb_context internal allocation context");
+
+ if (!mem_ctx) {
+ DEBUG(0, ("make_pdb_context: talloc init failed!\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ *context = talloc(mem_ctx, sizeof(**context));
+ if (!*context) {
+ DEBUG(0, ("make_pdb_context: talloc failed!\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ ZERO_STRUCTP(*context);
+
+ (*context)->mem_ctx = mem_ctx;
+
+ (*context)->pdb_setsampwent = context_setsampwent;
+ (*context)->pdb_endsampwent = context_endsampwent;
+ (*context)->pdb_getsampwent = context_getsampwent;
+ (*context)->pdb_getsampwnam = context_getsampwnam;
+ (*context)->pdb_getsampwrid = context_getsampwrid;
+ (*context)->pdb_add_sam_account = context_add_sam_account;
+ (*context)->pdb_update_sam_account = context_update_sam_account;
+ (*context)->pdb_delete_sam_account = context_delete_sam_account;
+
+ (*context)->free_fn = free_pdb_context;
+
+ return NT_STATUS_OK;
+}
+
+
+/******************************************************************
+ Make a pdb_context, given a text string.
+*******************************************************************/
+
+NTSTATUS make_pdb_context_name(struct pdb_context **context, char *selected)
+{
+ /* HINT: Don't store 'selected' becouse its often an lp_ string and will 'go away' */
+ NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
+ int i;
+
+ if (!NT_STATUS_IS_OK(nt_status = make_pdb_context(context))) {
+ return nt_status;
+ }
+
+ DEBUG(5,("Attempting to find an passdb backend to match %s\n", selected));
+ for (i = 0; builtin_pdb_init_functions[i].name; i++)
+ {
+ if (strequal(builtin_pdb_init_functions[i].name, selected))
+ {
+ DEBUG(5,("Found pdb backend %s (at pos %d)\n", selected, i));
+ if (NT_STATUS_IS_OK(nt_status
+ = builtin_pdb_init_functions[i].init(*context, &(*context)->pdb_selected, NULL))) {
+ DEBUG(5,("pdb backend %s has a valid init\n", selected));
+ (*context)->pdb_selected->name = builtin_pdb_init_functions[i].name;
+ } else {
+ DEBUG(0,("pdb backend %s did not correctly init (error was %s)\n", selected, get_nt_error_msg(nt_status)));
+ (*context)->pdb_selected = NULL;
+ }
+ break;
+ }
+ }
+
+ if (!(*context)->pdb_selected) {
+ DEBUG(0,("failed to select passdb backed!\n"));
+ talloc_destroy((*context)->mem_ctx);
+ *context = NULL;
+ return nt_status;
+ }
+
+ return NT_STATUS_OK;
+}
+
+
+/******************************************************************
+ Return an already initilised pdb_context, to facilitate backward
+ compatiablity (see functions below).
+*******************************************************************/
+
+static struct pdb_context *pdb_get_static_context(BOOL reload)
+{
+ static struct pdb_context *pdb_context = NULL;
+
+ if ((pdb_context) && (reload)) {
+ pdb_context->free_fn(&pdb_context);
+ if (!NT_STATUS_IS_OK(make_pdb_context_name(&pdb_context, lp_passdb_backend()))) {
+ return NULL;
+ }
+ }
+
+ if (!pdb_context) {
+ if (!NT_STATUS_IS_OK(make_pdb_context_name(&pdb_context, lp_passdb_backend()))) {
+ return NULL;
+ }
+ }
+
+ return pdb_context;
+}
+
+#if !defined(WITH_LDAP_SAM) && !defined(WITH_NISPLUS_SAM)
+
+/******************************************************************
+ Backward compatability functions for the original passdb interface
+*******************************************************************/
+
+BOOL pdb_setsampwent(BOOL update)
+{
+ struct pdb_context *pdb_context = pdb_get_static_context(False);
+
+ if (!pdb_context) {
+ return False;
+ }
+
+ return pdb_context->pdb_setsampwent(pdb_context, update);
+}
+
+void pdb_endsampwent(void)
+{
+ struct pdb_context *pdb_context = pdb_get_static_context(False);
+
+ if (!pdb_context) {
+ return;
+ }
+
+ pdb_context->pdb_endsampwent(pdb_context);
+}
+
+BOOL pdb_getsampwent(SAM_ACCOUNT *user)
+{
+ struct pdb_context *pdb_context = pdb_get_static_context(False);
+
+ if (!pdb_context) {
+ return False;
+ }
+
+ return pdb_context->pdb_getsampwent(pdb_context, user);
+}
+
+BOOL pdb_getsampwnam(SAM_ACCOUNT *sam_acct, const char *username)
+{
+ struct pdb_context *pdb_context = pdb_get_static_context(False);
+
+ if (!pdb_context) {
+ return False;
+ }
+
+ return pdb_context->pdb_getsampwnam(pdb_context, sam_acct, username);
+}
+
+BOOL pdb_getsampwrid(SAM_ACCOUNT *sam_acct, uint32 rid)
+{
+ struct pdb_context *pdb_context = pdb_get_static_context(False);
+
+ if (!pdb_context) {
+ return False;
+ }
+
+ return pdb_context->pdb_getsampwrid(pdb_context, sam_acct, rid);
+}
+
+BOOL pdb_add_sam_account(SAM_ACCOUNT *sam_acct)
+{
+ struct pdb_context *pdb_context = pdb_get_static_context(False);
+
+ if (!pdb_context) {
+ return False;
+ }
+
+ return pdb_context->pdb_add_sam_account(pdb_context, sam_acct);
+}
+
+BOOL pdb_update_sam_account(SAM_ACCOUNT *sam_acct)
+{
+ struct pdb_context *pdb_context = pdb_get_static_context(False);
+
+ if (!pdb_context) {
+ return False;
+ }
+
+ return pdb_context->pdb_update_sam_account(pdb_context, sam_acct);
+}
+
+BOOL pdb_delete_sam_account(SAM_ACCOUNT *sam_acct)
+{
+ struct pdb_context *pdb_context = pdb_get_static_context(False);
+
+ if (!pdb_context) {
+ return False;
+ }
+
+ return pdb_context->pdb_delete_sam_account(pdb_context, sam_acct);
+}
+
+#endif /* !defined(WITH_LDAP_SAM) && !defined(WITH_NISPLUS_SAM) */
+
+/***************************************************************
+ Initialize the static context (at smbd startup etc).
+
+ If uninitialised, context will auto-init on first use.
+***************************************************************/
+
+BOOL initialize_password_db(BOOL reload)
+{
+ return (pdb_get_static_context(reload) != NULL);
+}
+
+
+NTSTATUS make_pdb_methods(TALLOC_CTX *mem_ctx, PDB_METHODS **methods)
+{
+ *methods = talloc(mem_ctx, sizeof(struct pdb_methods));
+
+ if (!*methods) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ ZERO_STRUCTP(*methods);
+
+ return NT_STATUS_OK;
+}
+
+
+
+
+
+
+
+
diff --git a/source3/passdb/pdb_ldap.c b/source3/passdb/pdb_ldap.c
index b687f494cc..4e602cae40 100644
--- a/source3/passdb/pdb_ldap.c
+++ b/source3/passdb/pdb_ldap.c
@@ -840,14 +840,22 @@ BOOL pdb_getsampwrid(SAM_ACCOUNT * user, uint32 rid)
/**********************************************************************
Delete entry from LDAP for username
*********************************************************************/
-BOOL pdb_delete_sam_account(const char *sname)
+BOOL pdb_delete_sam_account(SAM_ACCOUNT * sam_acct)
{
+ const char *sname;
int rc;
char *dn;
LDAP *ldap_struct;
LDAPMessage *entry;
LDAPMessage *result;
+ if (!sam_acct) {
+ DEBUG(0, ("sam_acct was NULL!\n"));
+ return False;
+ }
+
+ sname = pdb_get_username(sam_acct);
+
if (!ldap_open_connection (&ldap_struct))
return False;
@@ -891,7 +899,7 @@ BOOL pdb_delete_sam_account(const char *sname)
/**********************************************************************
Update SAM_ACCOUNT
*********************************************************************/
-BOOL pdb_update_sam_account(const SAM_ACCOUNT * newpwd, BOOL override)
+BOOL pdb_update_sam_account(SAM_ACCOUNT * newpwd)
{
int rc;
char *dn;
@@ -952,7 +960,7 @@ BOOL pdb_update_sam_account(const SAM_ACCOUNT * newpwd, BOOL override)
/**********************************************************************
Add SAM_ACCOUNT to LDAP
*********************************************************************/
-BOOL pdb_add_sam_account(const SAM_ACCOUNT * newpwd)
+BOOL pdb_add_sam_account(SAM_ACCOUNT * newpwd)
{
int rc;
pstring filter;
diff --git a/source3/passdb/pdb_nisplus.c b/source3/passdb/pdb_nisplus.c
index 446ba0ce39..687115733a 100644
--- a/source3/passdb/pdb_nisplus.c
+++ b/source3/passdb/pdb_nisplus.c
@@ -1039,14 +1039,22 @@ BOOL pdb_getsampwrid(SAM_ACCOUNT * user, uint32 rid)
/*************************************************************************
Routine to remove entry from the nisplus smbpasswd table
*************************************************************************/
-BOOL pdb_delete_sam_account(const char *sname)
+BOOL pdb_delete_sam_account(SAM_ACCOUNT * user)
{
+ const char *sname;
char *pfile = lp_smb_passwd_file();
pstring nisname;
nis_result *result, *delresult;
nis_object *obj;
int i;
-
+
+ if (!user) {
+ DEBUG(0, ("no SAM_ACCOUNT specified!\n"));
+ return False;
+ }
+
+ suser = pdb_get_username(user);
+
if (!*pfile)
{
DEBUG(0, ("no SMB password file set\n"));
@@ -1095,7 +1103,7 @@ BOOL pdb_delete_sam_account(const char *sname)
/************************************************************************
Routine to add an entry to the nisplus passwd file.
*************************************************************************/
-BOOL pdb_add_sam_account(const SAM_ACCOUNT * newpwd)
+BOOL pdb_add_sam_account(SAM_ACCOUNT * newpwd)
{
int local_user = 0;
char *pfile;
@@ -1290,7 +1298,7 @@ BOOL pdb_add_sam_account(const SAM_ACCOUNT * newpwd)
/************************************************************************
Routine to modify the nisplus passwd entry.
************************************************************************/
-BOOL pdb_update_sam_account(const SAM_ACCOUNT * newpwd, BOOL override)
+BOOL pdb_update_sam_account(SAM_ACCOUNT * newpwd)
{
nis_result *result, *addresult;
nis_object *obj;
diff --git a/source3/passdb/pdb_smbpasswd.c b/source3/passdb/pdb_smbpasswd.c
index a464312ad6..3039e6681c 100644
--- a/source3/passdb/pdb_smbpasswd.c
+++ b/source3/passdb/pdb_smbpasswd.c
@@ -4,6 +4,7 @@
* Copyright (C) Andrew Tridgell 1992-1998
* Modified by Jeremy Allison 1995.
* Modified by Gerald (Jerry) Carter 2000-2001
+ * Modified by 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
@@ -22,8 +23,6 @@
#include "includes.h"
-#ifdef WITH_SMBPASSWD_SAM
-
/*
smb_passwd is analogous to sam_passwd used everywhere
@@ -33,7 +32,8 @@
struct smb_passwd
{
- uid_t smb_userid; /* this is actually the unix uid_t */
+ BOOL smb_userid_set; /* this is actually the unix uid_t */
+ uint32 smb_userid; /* this is actually the unix uid_t */
const char *smb_name; /* username string */
const unsigned char *smb_passwd; /* Null if no password */
@@ -43,13 +43,29 @@ struct smb_passwd
time_t pass_last_set_time; /* password last set time */
};
+struct smbpasswd_privates
+{
+ /* used for maintain locks on the smbpasswd file */
+ int pw_file_lock_depth;
+
+ /* Global File pointer */
+ FILE *pw_file;
+
+ /* formerly static variables */
+ struct smb_passwd pw_buf;
+ pstring user_name;
+ unsigned char smbpwd[16];
+ unsigned char smbntpwd[16];
-extern struct passdb_ops pdb_ops;
+ /* retrive-once info */
+ const char *smbpasswd_file;
-/* used for maintain locks on the smbpasswd file */
-static int pw_file_lock_depth;
-static void *global_vp;
+ BOOL permit_non_unix_accounts;
+ uint32 low_nua_userid;
+ uint32 high_nua_userid;
+
+};
enum pwf_access_type { PWF_READ, PWF_UPDATE, PWF_CREATE };
@@ -116,7 +132,7 @@ static void pdb_init_smb(struct smb_passwd *user)
been granted to prevent race conditions. JRA.
****************************************************************/
-static void *startsmbfilepwent(const char *pfile, enum pwf_access_type type, int *lock_depth)
+static FILE *startsmbfilepwent(const char *pfile, enum pwf_access_type type, int *lock_depth)
{
FILE *fp = NULL;
const char *open_mode = NULL;
@@ -238,15 +254,14 @@ Error was %s\n.", pfile, strerror(errno) ));
}
/* We have a lock on the file. */
- return (void *)fp;
+ return fp;
}
/***************************************************************
End enumeration of the smbpasswd list.
****************************************************************/
-static void endsmbfilepwent(void *vp, int *lock_depth)
+static void endsmbfilepwent(FILE *fp, int *lock_depth)
{
- FILE *fp = (FILE *)vp;
pw_file_unlock(fileno(fp), lock_depth);
fclose(fp);
@@ -257,14 +272,13 @@ static void endsmbfilepwent(void *vp, int *lock_depth)
Routine to return the next entry in the smbpasswd list.
*************************************************************************/
-static struct smb_passwd *getsmbfilepwent(void *vp)
+static struct smb_passwd *getsmbfilepwent(struct smbpasswd_privates *smbpasswd_state, FILE *fp)
{
/* Static buffers we will return. */
- static struct smb_passwd pw_buf;
- static pstring user_name;
- static unsigned char smbpwd[16];
- static unsigned char smbntpwd[16];
- FILE *fp = (FILE *)vp;
+ struct smb_passwd *pw_buf = &smbpasswd_state->pw_buf;
+ char *user_name = smbpasswd_state->user_name;
+ unsigned char *smbpwd = smbpasswd_state->smbpwd;
+ unsigned char *smbntpwd = smbpasswd_state->smbntpwd;
char linebuf[256];
unsigned char c;
unsigned char *p;
@@ -276,9 +290,9 @@ static struct smb_passwd *getsmbfilepwent(void *vp)
return NULL;
}
- pdb_init_smb(&pw_buf);
+ pdb_init_smb(pw_buf);
- pw_buf.acct_ctrl = ACB_NORMAL;
+ pw_buf->acct_ctrl = ACB_NORMAL;
/*
* Scan the file, a line at a time and check if the name matches.
@@ -370,8 +384,8 @@ static struct smb_passwd *getsmbfilepwent(void *vp)
continue;
}
- pw_buf.smb_name = user_name;
- pw_buf.smb_userid = uidval;
+ pw_buf->smb_name = user_name;
+ pw_buf->smb_userid = uidval;
/*
* Now get the password value - this should be 32 hex digits
@@ -385,10 +399,10 @@ static struct smb_passwd *getsmbfilepwent(void *vp)
if (*p == '*' || *p == 'X') {
/* Password deliberately invalid - end here. */
DEBUG(10, ("getsmbfilepwent: entry invalidated for user %s\n", user_name));
- pw_buf.smb_nt_passwd = NULL;
- pw_buf.smb_passwd = NULL;
- pw_buf.acct_ctrl |= ACB_DISABLED;
- return &pw_buf;
+ pw_buf->smb_nt_passwd = NULL;
+ pw_buf->smb_passwd = NULL;
+ pw_buf->acct_ctrl |= ACB_DISABLED;
+ return pw_buf;
}
if (linebuf_len < (PTR_DIFF(p, linebuf) + 33)) {
@@ -402,28 +416,28 @@ static struct smb_passwd *getsmbfilepwent(void *vp)
}
if (!strncasecmp((char *) p, "NO PASSWORD", 11)) {
- pw_buf.smb_passwd = NULL;
- pw_buf.acct_ctrl |= ACB_PWNOTREQ;
+ pw_buf->smb_passwd = NULL;
+ pw_buf->acct_ctrl |= ACB_PWNOTREQ;
} else {
if (!pdb_gethexpwd((char *)p, smbpwd)) {
DEBUG(0, ("getsmbfilepwent: Malformed Lanman password entry (non hex chars)\n"));
continue;
}
- pw_buf.smb_passwd = smbpwd;
+ pw_buf->smb_passwd = smbpwd;
}
/*
* Now check if the NT compatible password is
* available.
*/
- pw_buf.smb_nt_passwd = NULL;
+ pw_buf->smb_nt_passwd = NULL;
p += 33; /* Move to the first character of the line after
the lanman password. */
if ((linebuf_len >= (PTR_DIFF(p, linebuf) + 33)) && (p[32] == ':')) {
if (*p != '*' && *p != 'X') {
if(pdb_gethexpwd((char *)p,smbntpwd))
- pw_buf.smb_nt_passwd = smbntpwd;
+ pw_buf->smb_nt_passwd = smbntpwd;
}
p += 33; /* Move to the first character of the line after
the NT password. */
@@ -435,11 +449,11 @@ static struct smb_passwd *getsmbfilepwent(void *vp)
if (*p == '[')
{
unsigned char *end_p = (unsigned char *)strchr_m((char *)p, ']');
- pw_buf.acct_ctrl = pdb_decode_acct_ctrl((char*)p);
+ pw_buf->acct_ctrl = pdb_decode_acct_ctrl((char*)p);
/* Must have some account type set. */
- if(pw_buf.acct_ctrl == 0)
- pw_buf.acct_ctrl = ACB_NORMAL;
+ if(pw_buf->acct_ctrl == 0)
+ pw_buf->acct_ctrl = ACB_NORMAL;
/* Now try and get the last change time. */
if(end_p)
@@ -459,7 +473,7 @@ static struct smb_passwd *getsmbfilepwent(void *vp)
* read into a time_t as the seconds since
* 1970 that the password was last changed.
*/
- pw_buf.pass_last_set_time = (time_t)strtol((char *)p, NULL, 16);
+ pw_buf->pass_last_set_time = (time_t)strtol((char *)p, NULL, 16);
}
}
}
@@ -470,13 +484,13 @@ static struct smb_passwd *getsmbfilepwent(void *vp)
* password file as 'normal accounts'. If this changes
* we will have to fix this code. JRA.
*/
- if(pw_buf.smb_name[strlen(pw_buf.smb_name) - 1] == '$') {
- pw_buf.acct_ctrl &= ~ACB_NORMAL;
- pw_buf.acct_ctrl |= ACB_WSTRUST;
+ if(pw_buf->smb_name[strlen(pw_buf->smb_name) - 1] == '$') {
+ pw_buf->acct_ctrl &= ~ACB_NORMAL;
+ pw_buf->acct_ctrl |= ACB_WSTRUST;
}
}
- return &pw_buf;
+ return pw_buf;
}
DEBUG(5,("getsmbfilepwent: end of file reached.\n"));
@@ -547,9 +561,9 @@ static char *format_new_smbpasswd_entry(const struct smb_passwd *newpwd)
Routine to add an entry to the smbpasswd file.
*************************************************************************/
-static BOOL add_smbfilepwd_entry(const struct smb_passwd *newpwd)
+static BOOL add_smbfilepwd_entry(struct smbpasswd_privates *smbpasswd_state, struct smb_passwd *newpwd)
{
- char *pfile = lp_smb_passwd_file();
+ const char *pfile = smbpasswd_state->smbpasswd_file;
struct smb_passwd *pwd = NULL;
FILE *fp = NULL;
int wr_len;
@@ -557,13 +571,14 @@ static BOOL add_smbfilepwd_entry(const struct smb_passwd *newpwd)
size_t new_entry_length;
char *new_entry;
SMB_OFF_T offpos;
-
+ uint32 max_found_uid = 0;
+
/* Open the smbpassword file - for update. */
- fp = startsmbfilepwent(pfile, PWF_UPDATE, &pw_file_lock_depth);
+ fp = startsmbfilepwent(pfile, PWF_UPDATE, &(smbpasswd_state->pw_file_lock_depth));
if (fp == NULL && errno == ENOENT) {
/* Try again - create. */
- fp = startsmbfilepwent(pfile, PWF_CREATE, &pw_file_lock_depth);
+ fp = startsmbfilepwent(pfile, PWF_CREATE, &(smbpasswd_state->pw_file_lock_depth));
}
if (fp == NULL) {
@@ -575,18 +590,45 @@ static BOOL add_smbfilepwd_entry(const struct smb_passwd *newpwd)
* Scan the file, a line at a time and check if the name matches.
*/
- while ((pwd = getsmbfilepwent(fp)) != NULL)
+ while ((pwd = getsmbfilepwent(smbpasswd_state, fp)) != NULL)
{
if (strequal(newpwd->smb_name, pwd->smb_name))
{
DEBUG(0, ("add_smbfilepwd_entry: entry with name %s already exists\n", pwd->smb_name));
- endsmbfilepwent(fp, &pw_file_lock_depth);
+ endsmbfilepwent(fp, &(smbpasswd_state->pw_file_lock_depth));
return False;
}
- }
+
+ /* Look for a free uid for use in non-unix accounts */
+ if (pwd->smb_userid > max_found_uid) {
+ max_found_uid = pwd->smb_userid;
+ }
+ }
/* Ok - entry doesn't exist. We can add it */
+ /* Account not in /etc/passwd hack!!! */
+ if (!newpwd->smb_userid_set) {
+ if (!smbpasswd_state->permit_non_unix_accounts) {
+ DEBUG(0, ("add_smbfilepwd_entry: cannot add account %s without unix identity\n", pwd->smb_name));
+ endsmbfilepwent(fp, &(smbpasswd_state->pw_file_lock_depth));
+ return False;
+ }
+
+ if (max_found_uid < smbpasswd_state->low_nua_userid) {
+ newpwd->smb_userid = smbpasswd_state->low_nua_userid;
+ newpwd->smb_userid_set = True;
+ } else if (max_found_uid >= smbpasswd_state->high_nua_userid) {
+ DEBUG(0, ("add_smbfilepwd_entry: cannot add machine %s, no uids are free! \n", newpwd->smb_name));
+ endsmbfilepwent(fp, &(smbpasswd_state->pw_file_lock_depth));
+ return False;
+ } else {
+ newpwd->smb_userid = max_found_uid + 1;
+ newpwd->smb_userid_set = True;
+ }
+ }
+
+
/* Create a new smb passwd entry and set it to the given password. */
/*
* The add user write needs to be atomic - so get the fd from
@@ -598,7 +640,7 @@ static BOOL add_smbfilepwd_entry(const struct smb_passwd *newpwd)
{
DEBUG(0, ("add_smbfilepwd_entry(sys_lseek): Failed to add entry for user %s to file %s. \
Error was %s\n", newpwd->smb_name, pfile, strerror(errno)));
- endsmbfilepwent(fp, &pw_file_lock_depth);
+ endsmbfilepwent(fp, &(smbpasswd_state->pw_file_lock_depth));
return False;
}
@@ -606,7 +648,7 @@ Error was %s\n", newpwd->smb_name, pfile, strerror(errno)));
{
DEBUG(0, ("add_smbfilepwd_entry(malloc): Failed to add entry for user %s to file %s. \
Error was %s\n", newpwd->smb_name, pfile, strerror(errno)));
- endsmbfilepwent(fp, &pw_file_lock_depth);
+ endsmbfilepwent(fp, &(smbpasswd_state->pw_file_lock_depth));
return False;
}
@@ -630,13 +672,13 @@ Error was %s. Password file may be corrupt ! Please examine by hand !\n",
newpwd->smb_name, strerror(errno)));
}
- endsmbfilepwent(fp, &pw_file_lock_depth);
+ endsmbfilepwent(fp, &(smbpasswd_state->pw_file_lock_depth));
free(new_entry);
return False;
}
free(new_entry);
- endsmbfilepwent(fp, &pw_file_lock_depth);
+ endsmbfilepwent(fp, &(smbpasswd_state->pw_file_lock_depth));
return True;
}
@@ -649,10 +691,10 @@ Error was %s. Password file may be corrupt ! Please examine by hand !\n",
override = True, override XXXXXXXX'd out password or NO PASS
************************************************************************/
-static BOOL mod_smbfilepwd_entry(const struct smb_passwd* pwd, BOOL override)
+static BOOL mod_smbfilepwd_entry(struct smbpasswd_privates *smbpasswd_state, const struct smb_passwd* pwd)
{
/* Static buffers we will return. */
- static pstring user_name;
+ char * user_name = smbpasswd_state->user_name;
char linebuf[256];
char readbuf[1024];
@@ -663,7 +705,7 @@ static BOOL mod_smbfilepwd_entry(const struct smb_passwd* pwd, BOOL override)
size_t linebuf_len = 0;
FILE *fp;
int lockfd;
- char *pfile = lp_smb_passwd_file();
+ const char *pfile = smbpasswd_state->smbpasswd_file;
BOOL found_entry = False;
BOOL got_pass_last_set_time = False;
@@ -690,7 +732,7 @@ static BOOL mod_smbfilepwd_entry(const struct smb_passwd* pwd, BOOL override)
lockfd = fileno(fp);
- if (!pw_file_lock(lockfd, F_WRLCK, 5, &pw_file_lock_depth)) {
+ if (!pw_file_lock(lockfd, F_WRLCK, 5, &(smbpasswd_state->pw_file_lock_depth))) {
DEBUG(0, ("mod_smbfilepwd_entry: unable to lock file %s\n", pfile));
fclose(fp);
return False;
@@ -710,7 +752,7 @@ static BOOL mod_smbfilepwd_entry(const struct smb_passwd* pwd, BOOL override)
fgets(linebuf, sizeof(linebuf), fp);
if (ferror(fp)) {
- pw_file_unlock(lockfd, &pw_file_lock_depth);
+ pw_file_unlock(lockfd, &(smbpasswd_state->pw_file_lock_depth));
fclose(fp);
return False;
}
@@ -779,7 +821,7 @@ static BOOL mod_smbfilepwd_entry(const struct smb_passwd* pwd, BOOL override)
}
if (!found_entry) {
- pw_file_unlock(lockfd, &pw_file_lock_depth);
+ pw_file_unlock(lockfd, &(smbpasswd_state->pw_file_lock_depth));
fclose(fp);
return False;
}
@@ -791,7 +833,7 @@ static BOOL mod_smbfilepwd_entry(const struct smb_passwd* pwd, BOOL override)
if (!isdigit(*p)) {
DEBUG(0, ("mod_smbfilepwd_entry: malformed password entry (uid not number)\n"));
- pw_file_unlock(lockfd, &pw_file_lock_depth);
+ pw_file_unlock(lockfd, &(smbpasswd_state->pw_file_lock_depth));
fclose(fp);
return False;
}
@@ -800,7 +842,7 @@ static BOOL mod_smbfilepwd_entry(const struct smb_passwd* pwd, BOOL override)
p++;
if (*p != ':') {
DEBUG(0, ("mod_smbfilepwd_entry: malformed password entry (no : after uid)\n"));
- pw_file_unlock(lockfd, &pw_file_lock_depth);
+ pw_file_unlock(lockfd, &(smbpasswd_state->pw_file_lock_depth));
fclose(fp);
return False;
}
@@ -815,30 +857,16 @@ static BOOL mod_smbfilepwd_entry(const struct smb_passwd* pwd, BOOL override)
/* Record exact password position */
pwd_seekpos += PTR_DIFF(p, linebuf);
- if (!override && (*p == '*' || *p == 'X')) {
- /* Password deliberately invalid - end here. */
- DEBUG(10, ("mod_smbfilepwd_entry: entry invalidated for user %s\n", user_name));
- pw_file_unlock(lockfd, &pw_file_lock_depth);
- fclose(fp);
- return False;
- }
-
if (linebuf_len < (PTR_DIFF(p, linebuf) + 33)) {
DEBUG(0, ("mod_smbfilepwd_entry: malformed password entry (passwd too short)\n"));
- pw_file_unlock(lockfd,&pw_file_lock_depth);
+ pw_file_unlock(lockfd,&(smbpasswd_state->pw_file_lock_depth));
fclose(fp);
return (False);
}
if (p[32] != ':') {
DEBUG(0, ("mod_smbfilepwd_entry: malformed password entry (no terminating :)\n"));
- pw_file_unlock(lockfd,&pw_file_lock_depth);
- fclose(fp);
- return False;
- }
-
- if (!override && (*p == '*' || *p == 'X')) {
- pw_file_unlock(lockfd,&pw_file_lock_depth);
+ pw_file_unlock(lockfd,&(smbpasswd_state->pw_file_lock_depth));
fclose(fp);
return False;
}
@@ -849,14 +877,14 @@ static BOOL mod_smbfilepwd_entry(const struct smb_passwd* pwd, BOOL override)
the lanman password. */
if (linebuf_len < (PTR_DIFF(p, linebuf) + 33)) {
DEBUG(0, ("mod_smbfilepwd_entry: malformed password entry (passwd too short)\n"));
- pw_file_unlock(lockfd,&pw_file_lock_depth);
+ pw_file_unlock(lockfd,&(smbpasswd_state->pw_file_lock_depth));
fclose(fp);
return (False);
}
if (p[32] != ':') {
DEBUG(0, ("mod_smbfilepwd_entry: malformed password entry (no terminating :)\n"));
- pw_file_unlock(lockfd,&pw_file_lock_depth);
+ pw_file_unlock(lockfd,&(smbpasswd_state->pw_file_lock_depth));
fclose(fp);
return False;
}
@@ -966,7 +994,7 @@ static BOOL mod_smbfilepwd_entry(const struct smb_passwd* pwd, BOOL override)
if(wr_len > sizeof(linebuf)) {
DEBUG(0, ("mod_smbfilepwd_entry: line to write (%d) is too long.\n", wr_len+1));
- pw_file_unlock(lockfd,&pw_file_lock_depth);
+ pw_file_unlock(lockfd,&(smbpasswd_state->pw_file_lock_depth));
fclose(fp);
return (False);
}
@@ -984,7 +1012,7 @@ static BOOL mod_smbfilepwd_entry(const struct smb_passwd* pwd, BOOL override)
if (sys_lseek(fd, pwd_seekpos - 1, SEEK_SET) != pwd_seekpos - 1) {
DEBUG(0, ("mod_smbfilepwd_entry: seek fail on file %s.\n", pfile));
- pw_file_unlock(lockfd,&pw_file_lock_depth);
+ pw_file_unlock(lockfd,&(smbpasswd_state->pw_file_lock_depth));
fclose(fp);
return False;
}
@@ -992,33 +1020,33 @@ static BOOL mod_smbfilepwd_entry(const struct smb_passwd* pwd, BOOL override)
/* Sanity check - ensure the areas we are writing are framed by ':' */
if (read(fd, linebuf, wr_len+1) != wr_len+1) {
DEBUG(0, ("mod_smbfilepwd_entry: read fail on file %s.\n", pfile));
- pw_file_unlock(lockfd,&pw_file_lock_depth);
+ pw_file_unlock(lockfd,&(smbpasswd_state->pw_file_lock_depth));
fclose(fp);
return False;
}
if ((linebuf[0] != ':') || (linebuf[wr_len] != ':')) {
DEBUG(0, ("mod_smbfilepwd_entry: check on passwd file %s failed.\n", pfile));
- pw_file_unlock(lockfd,&pw_file_lock_depth);
+ pw_file_unlock(lockfd,&(smbpasswd_state->pw_file_lock_depth));
fclose(fp);
return False;
}
if (sys_lseek(fd, pwd_seekpos, SEEK_SET) != pwd_seekpos) {
DEBUG(0, ("mod_smbfilepwd_entry: seek fail on file %s.\n", pfile));
- pw_file_unlock(lockfd,&pw_file_lock_depth);
+ pw_file_unlock(lockfd,&(smbpasswd_state->pw_file_lock_depth));
fclose(fp);
return False;
}
if (write(fd, ascii_p16, wr_len) != wr_len) {
DEBUG(0, ("mod_smbfilepwd_entry: write failed in passwd file %s\n", pfile));
- pw_file_unlock(lockfd,&pw_file_lock_depth);
+ pw_file_unlock(lockfd,&(smbpasswd_state->pw_file_lock_depth));
fclose(fp);
return False;
}
- pw_file_unlock(lockfd,&pw_file_lock_depth);
+ pw_file_unlock(lockfd,&(smbpasswd_state->pw_file_lock_depth));
fclose(fp);
return True;
}
@@ -1027,9 +1055,9 @@ static BOOL mod_smbfilepwd_entry(const struct smb_passwd* pwd, BOOL override)
Routine to delete an entry in the smbpasswd file by name.
*************************************************************************/
-static BOOL del_smbfilepwd_entry(const char *name)
+static BOOL del_smbfilepwd_entry(struct smbpasswd_privates *smbpasswd_state, const char *name)
{
- char *pfile = lp_smb_passwd_file();
+ const char *pfile = smbpasswd_state->smbpasswd_file;
pstring pfile2;
struct smb_passwd *pwd = NULL;
FILE *fp = NULL;
@@ -1044,7 +1072,7 @@ static BOOL del_smbfilepwd_entry(const char *name)
* it.
*/
- if((fp = startsmbfilepwent(pfile, PWF_UPDATE, &pw_file_lock_depth)) == NULL) {
+ if((fp = startsmbfilepwent(pfile, PWF_UPDATE, &(smbpasswd_state->pw_file_lock_depth))) == NULL) {
DEBUG(0, ("del_smbfilepwd_entry: unable to open file %s.\n", pfile));
return False;
}
@@ -1054,7 +1082,7 @@ static BOOL del_smbfilepwd_entry(const char *name)
*/
if((fp_write = startsmbfilepwent(pfile2, PWF_CREATE, &pfile2_lockdepth)) == NULL) {
DEBUG(0, ("del_smbfilepwd_entry: unable to open file %s.\n", pfile));
- endsmbfilepwent(fp, &pw_file_lock_depth);
+ endsmbfilepwent(fp, &(smbpasswd_state->pw_file_lock_depth));
return False;
}
@@ -1062,7 +1090,7 @@ static BOOL del_smbfilepwd_entry(const char *name)
* Scan the file, a line at a time and check if the name matches.
*/
- while ((pwd = getsmbfilepwent(fp)) != NULL) {
+ while ((pwd = getsmbfilepwent(smbpasswd_state, fp)) != NULL) {
char *new_entry;
size_t new_entry_length;
@@ -1080,7 +1108,7 @@ static BOOL del_smbfilepwd_entry(const char *name)
DEBUG(0, ("del_smbfilepwd_entry(malloc): Failed to copy entry for user %s to file %s. \
Error was %s\n", pwd->smb_name, pfile2, strerror(errno)));
unlink(pfile2);
- endsmbfilepwent(fp, &pw_file_lock_depth);
+ endsmbfilepwent(fp, &(smbpasswd_state->pw_file_lock_depth));
endsmbfilepwent(fp_write, &pfile2_lockdepth);
return False;
}
@@ -1092,7 +1120,7 @@ Error was %s\n", pwd->smb_name, pfile2, strerror(errno)));
DEBUG(0, ("del_smbfilepwd_entry(write): Failed to copy entry for user %s to file %s. \
Error was %s\n", pwd->smb_name, pfile2, strerror(errno)));
unlink(pfile2);
- endsmbfilepwent(fp, &pw_file_lock_depth);
+ endsmbfilepwent(fp, &(smbpasswd_state->pw_file_lock_depth));
endsmbfilepwent(fp_write, &pfile2_lockdepth);
free(new_entry);
return False;
@@ -1108,7 +1136,7 @@ Error was %s\n", pwd->smb_name, pfile2, strerror(errno)));
if(fflush(fp_write) != 0)
{
DEBUG(0, ("del_smbfilepwd_entry: Failed to flush file %s. Error was %s\n", pfile2, strerror(errno)));
- endsmbfilepwent(fp, &pw_file_lock_depth);
+ endsmbfilepwent(fp, &(smbpasswd_state->pw_file_lock_depth));
endsmbfilepwent(fp_write,&pfile2_lockdepth);
return False;
}
@@ -1121,7 +1149,7 @@ Error was %s\n", pwd->smb_name, pfile2, strerror(errno)));
unlink(pfile2);
}
- endsmbfilepwent(fp, &pw_file_lock_depth);
+ endsmbfilepwent(fp, &(smbpasswd_state->pw_file_lock_depth));
endsmbfilepwent(fp_write,&pfile2_lockdepth);
return True;
}
@@ -1134,21 +1162,27 @@ Error was %s\n", pwd->smb_name, pfile2, strerror(errno)));
static BOOL build_smb_pass (struct smb_passwd *smb_pw, const SAM_ACCOUNT *sampass)
{
uid_t uid;
- gid_t gid;
if (sampass == NULL)
return False;
- uid = pdb_get_uid(sampass);
- gid = pdb_get_gid(sampass);
- if (!IS_SAM_UNIX_USER(sampass)) {
- DEBUG(0,("build_sam_pass: Failing attempt to store user without a UNIX uid or gid. \n"));
- return False;
- }
+ ZERO_STRUCTP(smb_pw);
+
+ if (!IS_SAM_UNIX_USER(sampass)) {
+ smb_pw->smb_userid_set = False;
+ DEBUG(5,("build_sam_pass: storing user without a UNIX uid or gid. \n"));
+ } else {
+ smb_pw->smb_userid_set = True;
+ uid = pdb_get_uid(sampass);
- ZERO_STRUCTP(smb_pw);
+ if (uid != pdb_user_rid_to_uid(pdb_get_user_rid(sampass))) {
+ DEBUG(0,("build_sam_pass: Failing attempt to store user with non-uid based user RID. \n"));
+ return False;
+ }
+
+ smb_pw->smb_userid=uid;
+ }
- smb_pw->smb_userid=uid;
smb_pw->smb_name=(const char*)pdb_get_username(sampass);
smb_pw->smb_passwd=pdb_get_lanman_passwd(sampass);
@@ -1157,11 +1191,6 @@ static BOOL build_smb_pass (struct smb_passwd *smb_pw, const SAM_ACCOUNT *sampas
smb_pw->acct_ctrl=pdb_get_acct_ctrl(sampass);
smb_pw->pass_last_set_time=pdb_get_pass_last_set_time(sampass);
- if (uid != pdb_user_rid_to_uid(pdb_get_user_rid(sampass))) {
- DEBUG(0,("build_sam_pass: Failing attempt to store user with non-uid based user RID. \n"));
- return False;
- }
-
#if 0
/*
* ifdef'out by JFM on 11/29/2001.
@@ -1187,7 +1216,7 @@ static BOOL build_smb_pass (struct smb_passwd *smb_pw, const SAM_ACCOUNT *sampas
/*********************************************************************
Create a SAM_ACCOUNT from a smb_passwd struct
********************************************************************/
-static BOOL build_sam_account(SAM_ACCOUNT *sam_pass, const struct smb_passwd *pw_buf)
+static BOOL build_sam_account(struct smbpasswd_privates *smbpasswd_state, SAM_ACCOUNT *sam_pass, const struct smb_passwd *pw_buf)
{
struct passwd *pwfile;
@@ -1196,34 +1225,76 @@ static BOOL build_sam_account(SAM_ACCOUNT *sam_pass, const struct smb_passwd *pw
return False;
}
- /* Verify in system password file...
- FIXME!!! This is where we should look up an internal
- mapping of allocated uid for machine accounts as well
- --jerry */
- pwfile = getpwnam_alloc(pw_buf->smb_name);
- if (pwfile == NULL) {
- DEBUG(0,("build_sam_account: smbpasswd database is corrupt! username %s not in unix passwd database!\n", pw_buf->smb_name));
- return False;
- }
-
- pdb_set_uid (sam_pass, pwfile->pw_uid);
- pdb_set_gid (sam_pass, pwfile->pw_gid);
+ if ((smbpasswd_state->permit_non_unix_accounts)
+ && (pw_buf->smb_userid >= smbpasswd_state->low_nua_userid)
+ && (pw_buf->smb_userid <= smbpasswd_state->high_nua_userid)) {
+
+ pdb_set_user_rid(sam_pass, pdb_uid_to_user_rid (pw_buf->smb_userid));
+
+ /* lkclXXXX this is OBSERVED behaviour by NT PDCs, enforced here.
+
+ This was down the bottom for machines, but it looks pretty good as
+ a general default for non-unix users. --abartlet 2002-01-08
+ */
+ pdb_set_group_rid (sam_pass, DOMAIN_GROUP_RID_USERS);
- pdb_set_fullname(sam_pass, pwfile->pw_gecos);
-
- pdb_set_user_rid(sam_pass, pdb_uid_to_user_rid (pwfile->pw_uid));
+ } else {
- {
- uint32 rid;
+ uint32 grid;
GROUP_MAP map;
+ /* Verify in system password file...
+ FIXME!!! This is where we should look up an internal
+ mapping of allocated uid for machine accounts as well
+ --jerry */
+ pwfile = getpwnam_alloc(pw_buf->smb_name);
+ if (pwfile == NULL) {
+ DEBUG(0,("build_sam_account: smbpasswd database is corrupt! username %s not in unix passwd database!\n", pw_buf->smb_name));
+ return False;
+ }
+
+ pdb_set_uid (sam_pass, pwfile->pw_uid);
+ pdb_set_gid (sam_pass, pwfile->pw_gid);
+
+ pdb_set_fullname(sam_pass, pwfile->pw_gecos);
+
+ pdb_set_user_rid(sam_pass, pdb_uid_to_user_rid (pwfile->pw_uid));
+
if (get_group_map_from_gid(pwfile->pw_gid, &map, MAPPING_WITHOUT_PRIV)) {
- sid_peek_rid(&map.sid, &rid);
+ sid_peek_rid(&map.sid, &grid);
+ } else {
+ grid=pdb_gid_to_group_rid(pwfile->pw_gid);
}
- else
- rid=pdb_gid_to_group_rid(pwfile->pw_gid);
- pdb_set_group_rid(sam_pass, rid);
+ pdb_set_group_rid(sam_pass, grid);
+
+ /* check if this is a user account or a machine account */
+ if (pw_buf->smb_name[strlen(pw_buf->smb_name)-1] != '$')
+ {
+ pstring str;
+
+ pstrcpy(str, lp_logon_path());
+ standard_sub_advanced(-1, pwfile->pw_name, "", pwfile->pw_gid, pw_buf->smb_name, str);
+ pdb_set_profile_path(sam_pass, str, False);
+
+ pstrcpy(str, lp_logon_home());
+ standard_sub_advanced(-1, pwfile->pw_name, "", pwfile->pw_gid, pw_buf->smb_name, str);
+ pdb_set_homedir(sam_pass, str, False);
+
+ pstrcpy(str, lp_logon_drive());
+ standard_sub_advanced(-1, pwfile->pw_name, "", pwfile->pw_gid, pw_buf->smb_name, str);
+ pdb_set_dir_drive(sam_pass, str, False);
+
+ pstrcpy(str, lp_logon_script());
+ standard_sub_advanced(-1, pwfile->pw_name, "", pwfile->pw_gid, pw_buf->smb_name, str);
+ pdb_set_logon_script(sam_pass, str, False);
+
+ } else {
+ /* lkclXXXX this is OBSERVED behaviour by NT PDCs, enforced here. */
+ /*pdb_set_group_rid (sam_pass, DOMAIN_GROUP_RID_USERS); */
+ }
+
+ passwd_free(&pwfile);
}
pdb_set_username (sam_pass, pw_buf->smb_name);
@@ -1243,84 +1314,61 @@ static BOOL build_sam_account(SAM_ACCOUNT *sam_pass, const struct smb_passwd *pw
*/
pdb_set_pass_must_change_time (sam_pass, pw_buf->pass_last_set_time + MAX_PASSWORD_AGE);
#endif
- /* check if this is a user account or a machine account */
- if (pw_buf->smb_name[strlen(pw_buf->smb_name)-1] != '$')
- {
- pstring str;
-
- pstrcpy(str, lp_logon_path());
- standard_sub_advanced(-1, pwfile->pw_name, "", pwfile->pw_gid, pw_buf->smb_name, str);
- pdb_set_profile_path(sam_pass, str, False);
-
- pstrcpy(str, lp_logon_home());
- standard_sub_advanced(-1, pwfile->pw_name, "", pwfile->pw_gid, pw_buf->smb_name, str);
- pdb_set_homedir(sam_pass, str, False);
-
- pstrcpy(str, lp_logon_drive());
- standard_sub_advanced(-1, pwfile->pw_name, "", pwfile->pw_gid, pw_buf->smb_name, str);
- pdb_set_dir_drive(sam_pass, str, False);
-
- pstrcpy(str, lp_logon_script());
- standard_sub_advanced(-1, pwfile->pw_name, "", pwfile->pw_gid, pw_buf->smb_name, str);
- pdb_set_logon_script(sam_pass, str, False);
-
- } else {
- /* lkclXXXX this is OBSERVED behaviour by NT PDCs, enforced here. */
- /*pdb_set_group_rid (sam_pass, DOMAIN_GROUP_RID_USERS); */
- }
-
- passwd_free(&pwfile);
-
return True;
}
+
/*****************************************************************
Functions to be implemented by the new passdb API
****************************************************************/
-BOOL pdb_setsampwent (BOOL update)
+static BOOL smbpasswd_setsampwent (struct pdb_context *context, BOOL update)
{
- global_vp = startsmbfilepwent(lp_smb_passwd_file(),
- update ? PWF_UPDATE : PWF_READ,
- &pw_file_lock_depth);
+ struct smbpasswd_privates *smbpasswd_state = (struct smbpasswd_privates*)context->pdb_selected->private_data;
+
+ smbpasswd_state->pw_file = startsmbfilepwent(smbpasswd_state->smbpasswd_file,
+ update ? PWF_UPDATE : PWF_READ,
+ &(smbpasswd_state->pw_file_lock_depth));
/* did we fail? Should we try to create it? */
- if (!global_vp && update && errno == ENOENT)
+ if (!smbpasswd_state->pw_file && update && errno == ENOENT)
{
FILE *fp;
/* slprintf(msg_str,msg_str_len-1,
- "smbpasswd file did not exist - attempting to create it.\n"); */
+ "smbpasswd file did not exist - attempting to create it.\n"); */
DEBUG(0,("smbpasswd file did not exist - attempting to create it.\n"));
- fp = sys_fopen(lp_smb_passwd_file(), "w");
+ fp = sys_fopen(smbpasswd_state->smbpasswd_file, "w");
if (fp)
{
fprintf(fp, "# Samba SMB password file\n");
fclose(fp);
}
- global_vp = startsmbfilepwent(lp_smb_passwd_file(),
- update ? PWF_UPDATE : PWF_READ,
- &pw_file_lock_depth);
+ smbpasswd_state->pw_file = startsmbfilepwent(smbpasswd_state->smbpasswd_file,
+ update ? PWF_UPDATE : PWF_READ,
+ &(smbpasswd_state->pw_file_lock_depth));
}
- return (global_vp != NULL);
+ return (smbpasswd_state->pw_file != NULL);
}
-void pdb_endsampwent (void)
+static void smbpasswd_endsampwent (struct pdb_context *context)
{
- endsmbfilepwent(global_vp, &pw_file_lock_depth);
+ struct smbpasswd_privates *smbpasswd_state = (struct smbpasswd_privates*)context->pdb_selected->private_data;
+ endsmbfilepwent(smbpasswd_state->pw_file, &(smbpasswd_state->pw_file_lock_depth));
}
/*****************************************************************
****************************************************************/
-BOOL pdb_getsampwent(SAM_ACCOUNT *user)
+static BOOL smbpasswd_getsampwent(struct pdb_context *context, SAM_ACCOUNT *user)
{
+ struct smbpasswd_privates *smbpasswd_state = (struct smbpasswd_privates*)context->pdb_selected->private_data;
struct smb_passwd *pw_buf=NULL;
BOOL done = False;
DEBUG(5,("pdb_getsampwent\n"));
if (user==NULL) {
- DEBUG(5,("pdb_getsampwent: user is NULL\n"));
+ DEBUG(5,("pdb_getsampwent (smbpasswd): user is NULL\n"));
#if 0
- smb_panic("NULL pointer passed to pdb_getsampwent\n");
+ smb_panic("NULL pointer passed to getsampwent (smbpasswd)\n");
#endif
return False;
}
@@ -1328,18 +1376,18 @@ BOOL pdb_getsampwent(SAM_ACCOUNT *user)
while (!done)
{
/* do we have an entry? */
- pw_buf = getsmbfilepwent(global_vp);
+ pw_buf = getsmbfilepwent(smbpasswd_state, smbpasswd_state->pw_file);
if (pw_buf == NULL)
return False;
/* build the SAM_ACCOUNT entry from the smb_passwd struct.
We loop in case the user in the pdb does not exist in
the local system password file */
- if (build_sam_account(user, pw_buf))
+ if (build_sam_account(smbpasswd_state, user, pw_buf))
done = True;
}
- DEBUG(5,("pdb_getsampwent:done\n"));
+ DEBUG(5,("getsampwent (smbpasswd): done\n"));
/* success */
return True;
@@ -1351,15 +1399,16 @@ BOOL pdb_getsampwent(SAM_ACCOUNT *user)
call getpwnam() for unix account information until we have found
the correct entry
***************************************************************/
-BOOL pdb_getsampwnam(SAM_ACCOUNT *sam_acct, const char *username)
+static BOOL smbpasswd_getsampwnam(struct pdb_context *context, SAM_ACCOUNT *sam_acct, const char *username)
{
+ struct smbpasswd_privates *smbpasswd_state = (struct smbpasswd_privates*)context->pdb_selected->private_data;
struct smb_passwd *smb_pw;
void *fp = NULL;
char *domain = NULL;
char *user = NULL;
fstring name;
- DEBUG(10, ("pdb_getsampwnam: search by name: %s\n", username));
+ DEBUG(10, ("getsampwnam (smbpasswd): search by name: %s\n", username));
/* break the username from the domain if we have
@@ -1379,7 +1428,7 @@ BOOL pdb_getsampwnam(SAM_ACCOUNT *sam_acct, const char *username)
/* startsmbfilepwent() is used here as we don't want to lookup
the UNIX account in the local system password file until
we have a match. */
- fp = startsmbfilepwent(lp_smb_passwd_file(), PWF_READ, &pw_file_lock_depth);
+ fp = startsmbfilepwent(smbpasswd_state->smbpasswd_file, PWF_READ, &(smbpasswd_state->pw_file_lock_depth));
if (fp == NULL) {
DEBUG(0, ("unable to open passdb database.\n"));
@@ -1391,20 +1440,20 @@ BOOL pdb_getsampwnam(SAM_ACCOUNT *sam_acct, const char *username)
if ( domain )
map_username(user);
- while ( ((smb_pw=getsmbfilepwent(fp)) != NULL)&& (!strequal(smb_pw->smb_name, username)) )
+ while ( ((smb_pw=getsmbfilepwent(smbpasswd_state, fp)) != NULL)&& (!strequal(smb_pw->smb_name, username)) )
/* do nothing....another loop */ ;
- endsmbfilepwent(fp, &pw_file_lock_depth);
+ endsmbfilepwent(fp, &(smbpasswd_state->pw_file_lock_depth));
/* did we locate the username in smbpasswd */
if (smb_pw == NULL)
return False;
- DEBUG(10, ("pdb_getsampwnam: found by name: %s\n", smb_pw->smb_name));
+ DEBUG(10, ("getsampwnam (smbpasswd): found by name: %s\n", smb_pw->smb_name));
if (!sam_acct) {
- DEBUG(10,("pdb_getsampwnam:SAM_ACCOUNT is NULL\n"));
+ DEBUG(10,("getsampwnam (smbpasswd): SAM_ACCOUNT is NULL\n"));
#if 0
smb_panic("NULL pointer passed to pdb_getsampwnam\n");
#endif
@@ -1412,7 +1461,7 @@ BOOL pdb_getsampwnam(SAM_ACCOUNT *sam_acct, const char *username)
}
/* now build the SAM_ACCOUNT */
- if (!build_sam_account(sam_acct, smb_pw))
+ if (!build_sam_account(smbpasswd_state, sam_acct, smb_pw))
return False;
/* success */
@@ -1420,35 +1469,36 @@ BOOL pdb_getsampwnam(SAM_ACCOUNT *sam_acct, const char *username)
}
-BOOL pdb_getsampwrid(SAM_ACCOUNT *sam_acct,uint32 rid)
+static BOOL smbpasswd_getsampwrid(struct pdb_context *context, SAM_ACCOUNT *sam_acct,uint32 rid)
{
+ struct smbpasswd_privates *smbpasswd_state = (struct smbpasswd_privates*)context->pdb_selected->private_data;
struct smb_passwd *smb_pw;
void *fp = NULL;
DEBUG(10, ("pdb_getsampwrid: search by rid: %d\n", rid));
/* Open the sam password file - not for update. */
- fp = startsmbfilepwent(lp_smb_passwd_file(), PWF_READ, &pw_file_lock_depth);
+ fp = startsmbfilepwent(smbpasswd_state->smbpasswd_file, PWF_READ, &(smbpasswd_state->pw_file_lock_depth));
if (fp == NULL) {
DEBUG(0, ("unable to open passdb database.\n"));
return False;
}
- while ( ((smb_pw=getsmbfilepwent(fp)) != NULL) && (pdb_uid_to_user_rid(smb_pw->smb_userid) != rid) )
+ while ( ((smb_pw=getsmbfilepwent(smbpasswd_state, fp)) != NULL) && (pdb_uid_to_user_rid(smb_pw->smb_userid) != rid) )
/* do nothing */ ;
- endsmbfilepwent(fp, &pw_file_lock_depth);
+ endsmbfilepwent(fp, &(smbpasswd_state->pw_file_lock_depth));
/* did we locate the username in smbpasswd */
if (smb_pw == NULL)
return False;
- DEBUG(10, ("pdb_getsampwrid: found by name: %s\n", smb_pw->smb_name));
+ DEBUG(10, ("getsampwrid (smbpasswd): found by name: %s\n", smb_pw->smb_name));
if (!sam_acct) {
- DEBUG(10,("pdb_getsampwrid:SAM_ACCOUNT is NULL\n"));
+ DEBUG(10,("getsampwrid: (smbpasswd) SAM_ACCOUNT is NULL\n"));
#if 0
smb_panic("NULL pointer passed to pdb_getsampwrid\n");
#endif
@@ -1456,15 +1506,16 @@ BOOL pdb_getsampwrid(SAM_ACCOUNT *sam_acct,uint32 rid)
}
/* now build the SAM_ACCOUNT */
- if (!build_sam_account (sam_acct, smb_pw))
+ if (!build_sam_account (smbpasswd_state, sam_acct, smb_pw))
return False;
/* success */
return True;
}
-BOOL pdb_add_sam_account(const SAM_ACCOUNT *sampass)
+static BOOL smbpasswd_add_sam_account(struct pdb_context *context, const SAM_ACCOUNT *sampass)
{
+ struct smbpasswd_privates *smbpasswd_state = (struct smbpasswd_privates*)context->pdb_selected->private_data;
struct smb_passwd smb_pw;
/* convert the SAM_ACCOUNT */
@@ -1473,15 +1524,16 @@ BOOL pdb_add_sam_account(const SAM_ACCOUNT *sampass)
}
/* add the entry */
- if(!add_smbfilepwd_entry(&smb_pw)) {
+ if(!add_smbfilepwd_entry(smbpasswd_state, &smb_pw)) {
return False;
}
-
+
return True;
}
-BOOL pdb_update_sam_account(const SAM_ACCOUNT *sampass, BOOL override)
+static BOOL smbpasswd_update_sam_account(struct pdb_context *context, const SAM_ACCOUNT *sampass)
{
+ struct smbpasswd_privates *smbpasswd_state = (struct smbpasswd_privates*)context->pdb_selected->private_data;
struct smb_passwd smb_pw;
/* convert the SAM_ACCOUNT */
@@ -1489,19 +1541,97 @@ BOOL pdb_update_sam_account(const SAM_ACCOUNT *sampass, BOOL override)
return False;
/* update the entry */
- if(!mod_smbfilepwd_entry(&smb_pw, override))
+ if(!mod_smbfilepwd_entry(smbpasswd_state, &smb_pw))
return False;
return True;
}
-BOOL pdb_delete_sam_account (const char* username)
+static BOOL smbpasswd_delete_sam_account (struct pdb_context *context, const SAM_ACCOUNT *sampass)
{
- return del_smbfilepwd_entry(username);
+ struct smbpasswd_privates *smbpasswd_state = (struct smbpasswd_privates*)context->pdb_selected->private_data;
+
+ const char *username = pdb_get_username(sampass);
+
+ return del_smbfilepwd_entry(smbpasswd_state, username);
+}
+
+static void free_private_data(void **vp)
+{
+ struct smbpasswd_privates **privates = (struct smbpasswd_privates**)vp;
+
+ endsmbfilepwent((*privates)->pw_file, &((*privates)->pw_file_lock_depth));
+
+ *privates = NULL;
+ /* No need to free any further, as it is talloc()ed */
}
-#else
- /* Do *NOT* make this function static. It breaks the compile on gcc. JRA */
- void smbpass_dummy_function(void) { } /* stop some compilers complaining */
-#endif /* WTH_SMBPASSWD_SAM*/
+NTSTATUS pdb_init_smbpasswd(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
+{
+ NTSTATUS nt_status;
+ struct smbpasswd_privates *privates;
+
+ if (!NT_STATUS_IS_OK(nt_status = make_pdb_methods(pdb_context->mem_ctx, pdb_method))) {
+ return nt_status;
+ }
+
+ (*pdb_method)->setsampwent = smbpasswd_setsampwent;
+ (*pdb_method)->endsampwent = smbpasswd_endsampwent;
+ (*pdb_method)->getsampwent = smbpasswd_getsampwent;
+ (*pdb_method)->getsampwnam = smbpasswd_getsampwnam;
+ (*pdb_method)->getsampwrid = smbpasswd_getsampwrid;
+ (*pdb_method)->add_sam_account = smbpasswd_add_sam_account;
+ (*pdb_method)->update_sam_account = smbpasswd_update_sam_account;
+ (*pdb_method)->delete_sam_account = smbpasswd_delete_sam_account;
+
+ /* Setup private data and free function */
+
+ privates = talloc_zero(pdb_context->mem_ctx, sizeof(struct smbpasswd_privates));
+
+ if (!privates) {
+ DEBUG(0, ("talloc() failed for smbpasswd private_data!\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ /* Store some config details */
+
+ if (location) {
+ privates->smbpasswd_file = talloc_strdup(pdb_context->mem_ctx, location);
+ } else {
+ privates->smbpasswd_file = talloc_strdup(pdb_context->mem_ctx, lp_smb_passwd_file());
+ }
+
+ if (!privates->smbpasswd_file) {
+ DEBUG(0, ("talloc_strdp() failed for storing smbpasswd location!\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ (*pdb_method)->private_data = privates;
+
+
+ (*pdb_method)->free_private_data = free_private_data;
+
+ return NT_STATUS_OK;
+}
+
+NTSTATUS pdb_init_smbpasswd_nua(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
+{
+ NTSTATUS nt_status;
+ struct smbpasswd_privates *privates;
+
+ if (!NT_STATUS_IS_OK(nt_status = pdb_init_smbpasswd(pdb_context, pdb_method, location))) {
+ return nt_status;
+ }
+
+ privates = (*pdb_method)->private_data;
+
+ privates->permit_non_unix_accounts = True;
+
+ if (!lp_non_unix_account_range(&privates->low_nua_userid, &privates->high_nua_userid)) {
+ DEBUG(0, ("cannot use smbpasswd_nua without 'non unix account range' in smb.conf!\n"));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ return NT_STATUS_OK;
+}
diff --git a/source3/passdb/pdb_tdb.c b/source3/passdb/pdb_tdb.c
index b33e684c7a..0e0bf541e3 100644
--- a/source3/passdb/pdb_tdb.c
+++ b/source3/passdb/pdb_tdb.c
@@ -4,6 +4,7 @@
* Copyright (C) Simo Sorce 2000
* Copyright (C) Gerald Carter 2000
* Copyright (C) Jeremy Allison 2001
+ * 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
@@ -30,21 +31,25 @@
#define USERPREFIX "USER_"
#define RIDPREFIX "RID_"
-extern int DEBUGLEVEL;
-
-struct tdb_enum_info {
+struct tdbsam_privates {
TDB_CONTEXT *passwd_tdb;
TDB_DATA key;
-};
-static struct tdb_enum_info global_tdb_ent;
-/*static SAM_ACCOUNT global_sam_pass;*/
+ /* retrive-once info */
+ const char *tdbsam_location;
+
+ BOOL permit_non_unix_accounts;
+
+ uint32 low_nua_rid;
+ uint32 high_nua_rid;
+};
/**********************************************************************
Intialize a SAM_ACCOUNT struct from a BYTE buffer of size len
*********************************************************************/
-static BOOL init_sam_from_buffer (SAM_ACCOUNT *sampass, uint8 *buf, uint32 buflen)
+static BOOL init_sam_from_buffer (struct tdbsam_privates *tdb_state,
+ SAM_ACCOUNT *sampass, uint8 *buf, uint32 buflen)
{
/* times are stored as 32bit integer
@@ -150,8 +155,6 @@ static BOOL init_sam_from_buffer (SAM_ACCOUNT *sampass, uint8 *buf, uint32 bufle
goto done;
}
- /*pdb_set_uid(sampass, uid);
- pdb_set_gid(sampass, gid);*/
pdb_set_user_rid(sampass, user_rid);
pdb_set_group_rid(sampass, group_rid);
pdb_set_unknown_3(sampass, unknown_3);
@@ -162,6 +165,28 @@ static BOOL init_sam_from_buffer (SAM_ACCOUNT *sampass, uint8 *buf, uint32 bufle
pdb_set_logon_divs(sampass, logon_divs);
pdb_set_hours(sampass, hours);
+ if ((tdb_state->permit_non_unix_accounts)
+ && (pdb_get_user_rid(sampass) >= tdb_state->low_nua_rid)
+ && (pdb_get_user_rid(sampass) <= tdb_state->high_nua_rid)) {
+
+ } else {
+ struct passwd *pw;
+ /* validate the account and fill in UNIX uid and gid. sys_getpwnam()
+ is used instaed of Get_Pwnam() as we do not need to try case
+ permutations */
+
+ if ((pw=getpwnam_alloc(pdb_get_username(sampass))) == NULL) {
+ DEBUG(0,("init_sam_from_buffer: (tdbsam) getpwnam(%s) return NULL. User does not exist!\n",
+ pdb_get_username(sampass)));
+ return False;
+ }
+
+ pdb_set_uid(sampass, pw->pw_uid);
+ pdb_set_gid(sampass, pw->pw_gid);
+
+ passwd_free(&pw);
+ }
+
done:
SAFE_FREE(username);
@@ -182,7 +207,8 @@ done:
/**********************************************************************
Intialize a BYTE buffer from a SAM_ACCOUNT struct
*********************************************************************/
-static uint32 init_buffer_from_sam (uint8 **buf, const SAM_ACCOUNT *sampass)
+static uint32 init_buffer_from_sam (struct tdbsam_privates *tdb_state, uint8 **buf,
+ const SAM_ACCOUNT *sampass, uint32 user_rid, uint32 group_rid)
{
size_t len, buflen;
@@ -321,8 +347,8 @@ static uint32 init_buffer_from_sam (uint8 **buf, const SAM_ACCOUNT *sampass)
workstations_len, workstations,
unknown_str_len, unknown_str,
munged_dial_len, munged_dial,
- pdb_get_user_rid(sampass),
- pdb_get_group_rid(sampass),
+ user_rid,
+ group_rid,
lm_pw_len, lm_pw,
nt_pw_len, nt_pw,
pdb_get_acct_ctrl(sampass),
@@ -360,8 +386,8 @@ static uint32 init_buffer_from_sam (uint8 **buf, const SAM_ACCOUNT *sampass)
workstations_len, workstations,
unknown_str_len, unknown_str,
munged_dial_len, munged_dial,
- pdb_get_user_rid(sampass),
- pdb_get_group_rid(sampass),
+ user_rid,
+ group_rid,
lm_pw_len, lm_pw,
nt_pw_len, nt_pw,
pdb_get_acct_ctrl(sampass),
@@ -375,6 +401,8 @@ static uint32 init_buffer_from_sam (uint8 **buf, const SAM_ACCOUNT *sampass)
/* check to make sure we got it correct */
if (buflen != len) {
+ DEBUG(0, ("init_buffer_from_sam: somthing odd is going on here: bufflen (%d) != len (%d) in tdb_pack operations!\n",
+ buflen, len));
/* error */
SAFE_FREE (*buf);
return (-1);
@@ -387,35 +415,38 @@ static uint32 init_buffer_from_sam (uint8 **buf, const SAM_ACCOUNT *sampass)
Open the TDB passwd database for SAM account enumeration.
****************************************************************/
-BOOL pdb_setsampwent(BOOL update)
+static BOOL tdbsam_setsampwent(struct pdb_context *context, BOOL update)
{
- pstring tdbfile;
-
- get_private_directory(tdbfile);
- pstrcat (tdbfile, PASSDB_FILE_NAME);
+ struct tdbsam_privates *tdb_state = (struct tdbsam_privates *)context->pdb_selected->private_data;
/* Open tdb passwd */
- if (!(global_tdb_ent.passwd_tdb = tdb_open_log(tdbfile, 0, TDB_DEFAULT, update?(O_RDWR|O_CREAT):O_RDONLY, 0600)))
+ if (!(tdb_state->passwd_tdb = tdb_open_log(tdb_state->tdbsam_location, 0, TDB_DEFAULT, update?(O_RDWR|O_CREAT):O_RDONLY, 0600)))
{
DEBUG(0, ("Unable to open/create TDB passwd\n"));
return False;
}
- global_tdb_ent.key = tdb_firstkey(global_tdb_ent.passwd_tdb);
+ tdb_state->key = tdb_firstkey(tdb_state->passwd_tdb);
return True;
}
+static void close_tdb(struct tdbsam_privates *tdb_state)
+{
+ if (tdb_state->passwd_tdb) {
+ tdb_close(tdb_state->passwd_tdb);
+ tdb_state->passwd_tdb = NULL;
+ }
+}
+
/***************************************************************
End enumeration of the TDB passwd list.
****************************************************************/
-void pdb_endsampwent(void)
+static void tdbsam_endsampwent(struct pdb_context *context)
{
- if (global_tdb_ent.passwd_tdb) {
- tdb_close(global_tdb_ent.passwd_tdb);
- global_tdb_ent.passwd_tdb = NULL;
- }
+ struct tdbsam_privates *tdb_state = (struct tdbsam_privates *)context->pdb_selected->private_data;
+ close_tdb(tdb_state);
DEBUG(7, ("endtdbpwent: closed sam database.\n"));
}
@@ -424,17 +455,13 @@ void pdb_endsampwent(void)
Get one SAM_ACCOUNT from the TDB (next in line)
*****************************************************************/
-BOOL pdb_getsampwent(SAM_ACCOUNT *user)
+static BOOL tdbsam_getsampwent(struct pdb_context *context, SAM_ACCOUNT *user)
{
+ struct tdbsam_privates *tdb_state = (struct tdbsam_privates *)context->pdb_selected->private_data;
TDB_DATA data;
- struct passwd *pw;
- uid_t uid;
- gid_t gid;
char *prefix = USERPREFIX;
int prefixlen = strlen (prefix);
- const char *sam_user;
- pstring sam_subst;
if (user==NULL) {
DEBUG(0,("pdb_get_sampwent: SAM_ACCOUNT is NULL.\n"));
@@ -442,62 +469,32 @@ BOOL pdb_getsampwent(SAM_ACCOUNT *user)
}
/* skip all non-USER entries (eg. RIDs) */
- while ((global_tdb_ent.key.dsize != 0) && (strncmp(global_tdb_ent.key.dptr, prefix, prefixlen)))
+ while ((tdb_state->key.dsize != 0) && (strncmp(tdb_state->key.dptr, prefix, prefixlen)))
/* increment to next in line */
- global_tdb_ent.key = tdb_nextkey(global_tdb_ent.passwd_tdb, global_tdb_ent.key);
+ tdb_state->key = tdb_nextkey(tdb_state->passwd_tdb, tdb_state->key);
/* do we have an valid interation pointer? */
- if(global_tdb_ent.passwd_tdb == NULL) {
+ if(tdb_state->passwd_tdb == NULL) {
DEBUG(0,("pdb_get_sampwent: Bad TDB Context pointer.\n"));
return False;
}
- data = tdb_fetch(global_tdb_ent.passwd_tdb, global_tdb_ent.key);
+ data = tdb_fetch(tdb_state->passwd_tdb, tdb_state->key);
if (!data.dptr) {
DEBUG(5,("pdb_getsampwent: database entry not found.\n"));
return False;
}
/* unpack the buffer */
- if (!init_sam_from_buffer(user, data.dptr, data.dsize)) {
+ if (!init_sam_from_buffer(tdb_state, user, data.dptr, data.dsize)) {
DEBUG(0,("pdb_getsampwent: Bad SAM_ACCOUNT entry returned from TDB!\n"));
SAFE_FREE(data.dptr);
return False;
}
SAFE_FREE(data.dptr);
- /* validate the account and fill in UNIX uid and gid. sys_getpwnam()
- is used instaed of Get_Pwnam() as we do not need to try case
- permutations */
- if ((pw=getpwnam_alloc(pdb_get_username(user))) == NULL) {
- DEBUG(0,("pdb_getsampwent: getpwnam(%s) return NULL. User does not exist!\n",
- pdb_get_username(user)));
- return False;
- }
-
- uid = pw->pw_uid;
- gid = pw->pw_gid;
- pdb_set_uid(user, uid);
- pdb_set_gid(user, gid);
-
- passwd_free(&pw);
-
- /* 21 days from present */
- pdb_set_pass_must_change_time(user, time(NULL)+1814400);
-
- sam_user = pdb_get_username(user);
- pstrcpy(sam_subst, pdb_get_logon_script(user));
- standard_sub_advanced(-1, sam_user, "", gid, sam_user, sam_subst);
- if (!pdb_set_logon_script(user, sam_subst, True)) return False;
- pstrcpy(sam_subst, pdb_get_profile_path(user));
- standard_sub_advanced(-1, pdb_get_username(user), "", gid, pdb_get_username(user), sam_subst);
- if (!pdb_set_profile_path(user, sam_subst, True)) return False;
- pstrcpy(sam_subst, pdb_get_homedir(user));
- standard_sub_advanced(-1, pdb_get_username(user), "", gid, pdb_get_username(user), sam_subst);
- if (!pdb_set_homedir(user, sam_subst, True)) return False;
-
/* increment to next in line */
- global_tdb_ent.key = tdb_nextkey(global_tdb_ent.passwd_tdb, global_tdb_ent.key);
+ tdb_state->key = tdb_nextkey(tdb_state->passwd_tdb, tdb_state->key);
return True;
}
@@ -506,19 +503,13 @@ BOOL pdb_getsampwent(SAM_ACCOUNT *user)
Lookup a name in the SAM TDB
******************************************************************/
-BOOL pdb_getsampwnam (SAM_ACCOUNT *user, const char *sname)
+static BOOL tdbsam_getsampwnam (struct pdb_context *context, SAM_ACCOUNT *user, const char *sname)
{
+ struct tdbsam_privates *tdb_state = (struct tdbsam_privates *)context->pdb_selected->private_data;
TDB_CONTEXT *pwd_tdb;
TDB_DATA data, key;
fstring keystr;
- struct passwd *pw;
- pstring tdbfile;
fstring name;
- uid_t uid;
- gid_t gid;
-
- const char *sam_user;
- pstring sam_subst;
if (user==NULL) {
DEBUG(0,("pdb_getsampwnam: SAM_ACCOUNT is NULL.\n"));
@@ -528,17 +519,14 @@ BOOL pdb_getsampwnam (SAM_ACCOUNT *user, const char *sname)
/* Data is stored in all lower-case */
unix_strlower(sname, -1, name, sizeof(name));
- get_private_directory(tdbfile);
- pstrcat(tdbfile, PASSDB_FILE_NAME);
-
/* set search key */
slprintf(keystr, sizeof(keystr)-1, "%s%s", USERPREFIX, name);
key.dptr = keystr;
key.dsize = strlen(keystr) + 1;
/* open the accounts TDB */
- if (!(pwd_tdb = tdb_open_log(tdbfile, 0, TDB_DEFAULT, O_RDONLY, 0600))) {
- DEBUG(0, ("pdb_getsampwnam: Unable to open TDB passwd!\n"));
+ if (!(pwd_tdb = tdb_open_log(tdb_state->tdbsam_location, 0, TDB_DEFAULT, O_RDONLY, 0600))) {
+ DEBUG(0, ("pdb_getsampwnam: Unable to open TDB passwd (%s)!\n", tdb_state->tdbsam_location));
return False;
}
@@ -547,12 +535,13 @@ BOOL pdb_getsampwnam (SAM_ACCOUNT *user, const char *sname)
if (!data.dptr) {
DEBUG(5,("pdb_getsampwnam (TDB): error fetching database.\n"));
DEBUGADD(5, (" Error: %s\n", tdb_errorstr(pwd_tdb)));
+ DEBUGADD(5, (" Key: %s\n", keystr));
tdb_close(pwd_tdb);
return False;
}
/* unpack the buffer */
- if (!init_sam_from_buffer(user, data.dptr, data.dsize)) {
+ if (!init_sam_from_buffer(tdb_state, user, data.dptr, data.dsize)) {
DEBUG(0,("pdb_getsampwent: Bad SAM_ACCOUNT entry returned from TDB!\n"));
SAFE_FREE(data.dptr);
tdb_close(pwd_tdb);
@@ -563,37 +552,6 @@ BOOL pdb_getsampwnam (SAM_ACCOUNT *user, const char *sname)
/* no further use for database, close it now */
tdb_close(pwd_tdb);
- /* validate the account and fill in UNIX uid and gid. sys_getpwnam()
- is used instead of Get_Pwnam() as we do not need to try case
- permutations */
- if ((pw=getpwnam_alloc(pdb_get_username(user)))) {
- uid = pw->pw_uid;
- gid = pw->pw_gid;
- pdb_set_uid(user, uid);
- pdb_set_gid(user, gid);
-
- /* 21 days from present */
- pdb_set_pass_must_change_time(user, time(NULL)+1814400);
-
- sam_user = pdb_get_username(user);
- pstrcpy(sam_subst, pdb_get_logon_script(user));
- standard_sub_advanced(-1, sam_user, "", gid, sam_user, sam_subst);
- if (!pdb_set_logon_script(user, sam_subst, True)) return False;
- pstrcpy(sam_subst, pdb_get_profile_path(user));
- standard_sub_advanced(-1, pdb_get_username(user), "", gid, pdb_get_username(user), sam_subst);
- if (!pdb_set_profile_path(user, sam_subst, True)) return False;
- pstrcpy(sam_subst, pdb_get_homedir(user));
- standard_sub_advanced(-1, pdb_get_username(user), "", gid, pdb_get_username(user), sam_subst);
- if (!pdb_set_homedir(user, sam_subst, True)) return False;
- }
- else {
- DEBUG(0,("pdb_getsampwent: getpwnam(%s) return NULL. User does not exist!\n",
- pdb_get_username(user)));
- return False;
- }
-
- passwd_free(&pw);
-
return True;
}
@@ -601,12 +559,12 @@ BOOL pdb_getsampwnam (SAM_ACCOUNT *user, const char *sname)
Search by rid
**************************************************************************/
-BOOL pdb_getsampwrid (SAM_ACCOUNT *user, uint32 rid)
+static BOOL tdbsam_getsampwrid (struct pdb_context *context, SAM_ACCOUNT *user, uint32 rid)
{
+ struct tdbsam_privates *tdb_state = (struct tdbsam_privates *)context->pdb_selected->private_data;
TDB_CONTEXT *pwd_tdb;
TDB_DATA data, key;
fstring keystr;
- pstring tdbfile;
fstring name;
if (user==NULL) {
@@ -614,16 +572,13 @@ BOOL pdb_getsampwrid (SAM_ACCOUNT *user, uint32 rid)
return False;
}
- get_private_directory(tdbfile);
- pstrcat (tdbfile, PASSDB_FILE_NAME);
-
/* set search key */
slprintf(keystr, sizeof(keystr)-1, "%s%.8x", RIDPREFIX, rid);
key.dptr = keystr;
key.dsize = strlen (keystr) + 1;
/* open the accounts TDB */
- if (!(pwd_tdb = tdb_open_log(tdbfile, 0, TDB_DEFAULT, O_RDONLY, 0600))) {
+ if (!(pwd_tdb = tdb_open_log(tdb_state->tdbsam_location, 0, TDB_DEFAULT, O_RDONLY, 0600))) {
DEBUG(0, ("pdb_getsampwrid: Unable to open TDB rid database!\n"));
return False;
}
@@ -642,30 +597,26 @@ BOOL pdb_getsampwrid (SAM_ACCOUNT *user, uint32 rid)
tdb_close (pwd_tdb);
- return pdb_getsampwnam (user, name);
+ return tdbsam_getsampwnam (context, user, name);
}
/***************************************************************************
Delete a SAM_ACCOUNT
****************************************************************************/
-BOOL pdb_delete_sam_account(const char *sname)
+static BOOL tdbsam_delete_sam_account(struct pdb_context *context, const SAM_ACCOUNT *sam_pass)
{
- SAM_ACCOUNT *sam_pass = NULL;
+ struct tdbsam_privates *tdb_state = (struct tdbsam_privates *)context->pdb_selected->private_data;
TDB_CONTEXT *pwd_tdb;
- TDB_DATA key, data;
+ TDB_DATA key;
fstring keystr;
- pstring tdbfile;
uint32 rid;
fstring name;
- unix_strlower(sname, -1, name, sizeof(name));
+ unix_strlower(pdb_get_username(sam_pass), -1, name, sizeof(name));
- get_private_directory(tdbfile);
- pstrcat (tdbfile, PASSDB_FILE_NAME);
-
/* open the TDB */
- if (!(pwd_tdb = tdb_open_log(tdbfile, 0, TDB_DEFAULT, O_RDWR, 0600))) {
+ if (!(pwd_tdb = tdb_open_log(tdb_state->tdbsam_location, 0, TDB_DEFAULT, O_RDWR, 0600))) {
DEBUG(0, ("Unable to open TDB passwd!"));
return False;
}
@@ -675,33 +626,8 @@ BOOL pdb_delete_sam_account(const char *sname)
key.dptr = keystr;
key.dsize = strlen (keystr) + 1;
- /* get the record */
- data = tdb_fetch (pwd_tdb, key);
- if (!data.dptr) {
- DEBUG(5,("pdb_delete_sam_account (TDB): error fetching database.\n"));
- DEBUGADD(5, (" Error: %s\n", tdb_errorstr(pwd_tdb)));
- tdb_close (pwd_tdb);
- return False;
- }
-
- /* unpack the buffer */
- if (!NT_STATUS_IS_OK(pdb_init_sam (&sam_pass))) {
- tdb_close (pwd_tdb);
- return False;
- }
-
- if (!init_sam_from_buffer (sam_pass, data.dptr, data.dsize)) {
- DEBUG(0,("pdb_getsampwent: Bad SAM_ACCOUNT entry returned from TDB!\n"));
- tdb_close (pwd_tdb);
- SAFE_FREE(data.dptr);
- return False;
- }
- SAFE_FREE(data.dptr);
-
rid = pdb_get_user_rid(sam_pass);
- pdb_free_sam (&sam_pass);
-
/* it's outaa here! 8^) */
if (tdb_delete(pwd_tdb, key) != TDB_SUCCESS) {
DEBUG(5, ("Error deleting entry from tdb passwd database!\n"));
@@ -734,27 +660,62 @@ BOOL pdb_delete_sam_account(const char *sname)
Update the TDB SAM
****************************************************************************/
-static BOOL tdb_update_sam(const SAM_ACCOUNT* newpwd, BOOL override, int flag)
+static BOOL tdb_update_sam(struct pdb_context *context, const SAM_ACCOUNT* newpwd, int flag)
{
+ struct tdbsam_privates *tdb_state = (struct tdbsam_privates *)context->pdb_selected->private_data;
TDB_CONTEXT *pwd_tdb = NULL;
TDB_DATA key, data;
uint8 *buf = NULL;
fstring keystr;
- pstring tdbfile;
fstring name;
BOOL ret = True;
-
- get_private_directory(tdbfile);
- pstrcat (tdbfile, PASSDB_FILE_NAME);
-
- /* if we don't have a RID, then FAIL */
- if (!pdb_get_user_rid(newpwd))
- DEBUG (0,("tdb_update_sam: Failing to store a SAM_ACCOUNT for [%s] without a RID\n",pdb_get_username(newpwd)));
- if (!pdb_get_group_rid(newpwd))
- DEBUG (0,("tdb_update_sam: Failing to store a SAM_ACCOUNT for [%s] without a primary group RID\n",pdb_get_username(newpwd)));
+ uint32 user_rid;
+ uint32 group_rid;
+ int32 tdb_ret;
+
+ /* invalidate the existing TDB iterator if it is open */
+ if (tdb_state->passwd_tdb) {
+ tdb_close(tdb_state->passwd_tdb);
+ tdb_state->passwd_tdb = NULL;
+ }
+
+ /* open the account TDB passwd*/
+ pwd_tdb = tdb_open_log(tdb_state->tdbsam_location, 0, TDB_DEFAULT, O_RDWR | O_CREAT, 0600);
+ if (!pwd_tdb)
+ {
+ DEBUG(0, ("tdb_update_sam: Unable to open TDB passwd (%s)!\n", tdb_state->tdbsam_location));
+ return False;
+ }
+
+ /* if we don't have a RID, then make them up. */
+ if (!(user_rid = pdb_get_user_rid(newpwd))) {
+ if (!tdb_state->permit_non_unix_accounts) {
+ DEBUG (0,("tdb_update_sam: Failing to store a SAM_ACCOUNT for [%s] without a RID\n",pdb_get_username(newpwd)));
+ ret = False;
+ goto done;
+ } else {
+ user_rid = tdb_state->low_nua_rid;
+ tdb_ret = tdb_change_int32_atomic(pwd_tdb, "NUA_NEXT_RID", &user_rid, RID_MULTIPLIER);
+ if (tdb_ret == -1) {
+ ret = False;
+ goto done;
+ }
+ }
+ }
+
+ if (!(group_rid = pdb_get_group_rid(newpwd))) {
+ if (!tdb_state->permit_non_unix_accounts) {
+ DEBUG (0,("tdb_update_sam: Failing to store a SAM_ACCOUNT for [%s] without a primary group RID\n",pdb_get_username(newpwd)));
+ ret = False;
+ goto done;
+ } else {
+ /* This seems like a good default choice for non-unix users */
+ group_rid = DOMAIN_GROUP_RID_USERS;
+ }
+ }
/* copy the SAM_ACCOUNT struct into a BYTE buffer for storage */
- if ((data.dsize=init_buffer_from_sam (&buf, newpwd)) == -1) {
+ if ((data.dsize=init_buffer_from_sam (tdb_state, &buf, newpwd, user_rid, group_rid)) == -1) {
DEBUG(0,("tdb_update_sam: ERROR - Unable to copy SAM_ACCOUNT info BYTE buffer!\n"));
ret = False;
goto done;
@@ -763,29 +724,18 @@ static BOOL tdb_update_sam(const SAM_ACCOUNT* newpwd, BOOL override, int flag)
unix_strlower(pdb_get_username(newpwd), -1, name, sizeof(name));
+ DEBUG(5, ("Storing %saccount %s with RID %d\n", flag == TDB_INSERT ? "(new) " : "", name, user_rid));
+
/* setup the USER index key */
slprintf(keystr, sizeof(keystr)-1, "%s%s", USERPREFIX, name);
key.dptr = keystr;
key.dsize = strlen (keystr) + 1;
- /* invalidate the existing TDB iterator if it is open */
- if (global_tdb_ent.passwd_tdb) {
- tdb_close(global_tdb_ent.passwd_tdb);
- global_tdb_ent.passwd_tdb = NULL;
- }
-
- /* open the account TDB passwd*/
- pwd_tdb = tdb_open_log(tdbfile, 0, TDB_DEFAULT, O_RDWR | O_CREAT, 0600);
- if (!pwd_tdb)
- {
- DEBUG(0, ("tdb_update_sam: Unable to open TDB passwd!\n"));
- return False;
- }
-
/* add the account */
if (tdb_store(pwd_tdb, key, data, flag) != TDB_SUCCESS) {
DEBUG(0, ("Unable to modify passwd TDB!"));
- DEBUGADD(0, (" Error: %s\n", tdb_errorstr(pwd_tdb)));
+ DEBUGADD(0, (" Error: %s", tdb_errorstr(pwd_tdb)));
+ DEBUGADD(0, (" occured while storing the main record (%s)\n", keystr));
ret = False;
goto done;
}
@@ -795,7 +745,7 @@ static BOOL tdb_update_sam(const SAM_ACCOUNT* newpwd, BOOL override, int flag)
data.dptr = name;
/* setup the RID index key */
- slprintf(keystr, sizeof(keystr)-1, "%s%.8x", RIDPREFIX, pdb_get_user_rid(newpwd));
+ slprintf(keystr, sizeof(keystr)-1, "%s%.8x", RIDPREFIX, user_rid);
key.dptr = keystr;
key.dsize = strlen (keystr) + 1;
@@ -803,6 +753,7 @@ static BOOL tdb_update_sam(const SAM_ACCOUNT* newpwd, BOOL override, int flag)
if (tdb_store(pwd_tdb, key, data, flag) != TDB_SUCCESS) {
DEBUG(0, ("Unable to modify TDB passwd !"));
DEBUGADD(0, (" Error: %s\n", tdb_errorstr(pwd_tdb)));
+ DEBUGADD(0, (" occured while storing the RID index (%s)\n", keystr));
ret = False;
goto done;
}
@@ -819,21 +770,113 @@ done:
Modifies an existing SAM_ACCOUNT
****************************************************************************/
-BOOL pdb_update_sam_account (const SAM_ACCOUNT *newpwd, BOOL override)
+static BOOL tdbsam_update_sam_account (struct pdb_context *context, const SAM_ACCOUNT *newpwd)
{
- return (tdb_update_sam(newpwd, override, TDB_MODIFY));
+ return (tdb_update_sam(context, newpwd, TDB_MODIFY));
}
/***************************************************************************
Adds an existing SAM_ACCOUNT
****************************************************************************/
-BOOL pdb_add_sam_account (const SAM_ACCOUNT *newpwd)
+static BOOL tdbsam_add_sam_account (struct pdb_context *context, const SAM_ACCOUNT *newpwd)
+{
+ return (tdb_update_sam(context, newpwd, TDB_INSERT));
+}
+
+static void free_private_data(void **vp)
{
- return (tdb_update_sam(newpwd, True, TDB_INSERT));
+ struct tdbsam_privates **tdb_state = (struct tdbsam_privates **)vp;
+ close_tdb(*tdb_state);
+ *tdb_state = NULL;
+
+ /* No need to free any further, as it is talloc()ed */
}
+
+NTSTATUS pdb_init_tdbsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
+{
+ NTSTATUS nt_status;
+ struct tdbsam_privates *tdb_state;
+
+ if (!NT_STATUS_IS_OK(nt_status = make_pdb_methods(pdb_context->mem_ctx, pdb_method))) {
+ return nt_status;
+ }
+
+ (*pdb_method)->setsampwent = tdbsam_setsampwent;
+ (*pdb_method)->endsampwent = tdbsam_endsampwent;
+ (*pdb_method)->getsampwent = tdbsam_getsampwent;
+ (*pdb_method)->getsampwnam = tdbsam_getsampwnam;
+ (*pdb_method)->getsampwrid = tdbsam_getsampwrid;
+ (*pdb_method)->add_sam_account = tdbsam_add_sam_account;
+ (*pdb_method)->update_sam_account = tdbsam_update_sam_account;
+ (*pdb_method)->delete_sam_account = tdbsam_delete_sam_account;
+
+ /* TODO: Setup private data and free */
+
+ tdb_state = talloc_zero(pdb_context->mem_ctx, sizeof(struct tdbsam_privates));
+
+ if (!tdb_state) {
+ DEBUG(0, ("talloc() failed for tdbsam private_data!\n"));
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ if (location) {
+ tdb_state->tdbsam_location = talloc_strdup(pdb_context->mem_ctx, location);
+ } else {
+ pstring tdbfile;
+ get_private_directory(tdbfile);
+ pstrcat (tdbfile, PASSDB_FILE_NAME);
+ tdb_state->tdbsam_location = talloc_strdup(pdb_context->mem_ctx, tdbfile);
+ }
+
+ (*pdb_method)->private_data = tdb_state;
+
+ (*pdb_method)->free_private_data = free_private_data;
+
+ return NT_STATUS_OK;
+}
+
+NTSTATUS pdb_init_tdbsam_nua(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
+{
+ NTSTATUS nt_status;
+ struct tdbsam_privates *tdb_state;
+ uint32 low_nua_uid, high_nua_uid;
+
+ if (!NT_STATUS_IS_OK(nt_status = pdb_init_tdbsam(pdb_context, pdb_method, location))) {
+ return nt_status;
+ }
+
+ tdb_state = (*pdb_method)->private_data;
+
+ tdb_state->permit_non_unix_accounts = True;
+
+ if (!lp_non_unix_account_range(&low_nua_uid, &high_nua_uid)) {
+ DEBUG(0, ("cannot use tdbsam_nua without 'non unix account range' in smb.conf!\n"));
+ return NT_STATUS_UNSUCCESSFUL;
+ }
+
+ tdb_state->low_nua_rid=pdb_uid_to_user_rid(low_nua_uid);
+
+ tdb_state->high_nua_rid=pdb_uid_to_user_rid(high_nua_uid);
+
+ return NT_STATUS_OK;
+}
+
+
#else
- /* Do *NOT* make this function static. It breaks the compile on gcc. JRA */
- void samtdb_dummy_function(void) { } /* stop some compilers complaining */
-#endif /* WITH_TDB_SAM */
+
+NTSTATUS pdb_init_tdbsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
+{
+ DEBUG(0, ("tdbsam not compiled in!\n"));
+ return NT_STATUS_UNSUCCESSFUL;
+}
+
+NTSTATUS pdb_init_tdbsam_nua(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, const char *location)
+{
+ DEBUG(0, ("tdbsam_nua not compiled in!\n"));
+ return NT_STATUS_UNSUCCESSFUL;
+}
+
+
+#endif