mirror of
https://github.com/samba-team/samba.git
synced 2024-12-24 21:34:56 +03:00
236cea4efa
Copyright (C) Benjamin Kuit <bj@mcs.uts.edu.au> 1999.
(This used to be commit fdf61e1dab
)
329 lines
9.5 KiB
C
329 lines
9.5 KiB
C
/*
|
|
Unix SMB/Netbios implementation.
|
|
Version 1.9.
|
|
Password and authentication handling
|
|
Copyright (C) Jeremy Allison 1996-1998
|
|
Copyright (C) Luke Kenneth Casson Leighton 1996-1998
|
|
|
|
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"
|
|
#include "nterr.h"
|
|
|
|
extern int DEBUGLEVEL;
|
|
extern DOM_SID global_sam_sid;
|
|
|
|
/*
|
|
* NOTE. All these functions are abstracted into a structure
|
|
* that points to the correct function for the selected database. JRA.
|
|
*
|
|
* NOTE. for the get/mod/add functions, there are two sets of functions.
|
|
* one supports struct sam_passwd, the other supports struct smb_passwd.
|
|
* for speed optimisation it is best to support both these sets.
|
|
*
|
|
* it is, however, optional to support one set but not the other: there
|
|
* is conversion-capability built in to passdb.c, and run-time error
|
|
* detection for when neither are supported.
|
|
*
|
|
* password database writers are recommended to implement the sam_passwd
|
|
* functions in a first pass, as struct sam_passwd contains more
|
|
* information, needed by the NT Domain support.
|
|
*
|
|
* an API writer is expected to create either one set (struct smb_passwd) or
|
|
* the other (struct sam_passwd) OR both, and optionally also to write display
|
|
* info routines * (struct sam_disp_info). functions which the API writer
|
|
* chooses NOT to write must be wrapped in conversion functions (pwdb_x_to_y)
|
|
* such that API users can call any function and still get valid results.
|
|
*
|
|
* the password API does NOT fill in the gaps if you set an API function
|
|
* to NULL: it will deliberately attempt to call the NULL function.
|
|
*
|
|
*/
|
|
|
|
static struct smb_passdb_ops *pwdb_ops;
|
|
|
|
/***************************************************************
|
|
Initialise the password db operations.
|
|
***************************************************************/
|
|
|
|
BOOL initialise_password_db(void)
|
|
{
|
|
if (pwdb_ops)
|
|
{
|
|
return True;
|
|
}
|
|
|
|
#ifdef WITH_NISPLUS
|
|
pwdb_ops = nisplus_initialise_password_db();
|
|
#elif defined(WITH_LDAP)
|
|
pwdb_ops = ldap_initialise_password_db();
|
|
#elif defined(WITH_MYSQL) || defined(WITH_MYSQLSAM)
|
|
pwdb_ops = mysql_initialise_password_db();
|
|
#elif defined(USE_SMBPASS_DB)
|
|
pwdb_ops = file_initialise_password_db();
|
|
#endif
|
|
|
|
return (pwdb_ops != NULL);
|
|
}
|
|
|
|
/*
|
|
* Functions that return/manipulate a struct smb_passwd.
|
|
*/
|
|
|
|
/************************************************************************
|
|
Utility function to search smb passwd by uid. use this if your database
|
|
does not have search facilities.
|
|
*************************************************************************/
|
|
|
|
struct smb_passwd *iterate_getsmbpwuid(uid_t unix_uid)
|
|
{
|
|
struct smb_passwd *pwd = NULL;
|
|
void *fp = NULL;
|
|
|
|
DEBUG(10, ("search by unix_uid: %x\n", (int)unix_uid));
|
|
|
|
/* Open the smb password database - not for update. */
|
|
fp = startsmbpwent(False);
|
|
|
|
if (fp == NULL)
|
|
{
|
|
DEBUG(0, ("unable to open smb password database.\n"));
|
|
return NULL;
|
|
}
|
|
|
|
while ((pwd = getsmbpwent(fp)) != NULL && pwd->unix_uid != unix_uid)
|
|
{
|
|
}
|
|
|
|
if (pwd != NULL)
|
|
{
|
|
DEBUG(10, ("found by unix_uid: %x\n", (int)unix_uid));
|
|
}
|
|
|
|
endsmbpwent(fp);
|
|
return pwd;
|
|
}
|
|
|
|
/************************************************************************
|
|
Utility function to search smb passwd by name. use this if your database
|
|
does not have search facilities.
|
|
*************************************************************************/
|
|
|
|
struct smb_passwd *iterate_getsmbpwnam(const char *name)
|
|
{
|
|
struct smb_passwd *pwd = NULL;
|
|
void *fp = NULL;
|
|
|
|
DEBUG(10, ("search by name: %s\n", name));
|
|
|
|
/* Open the sam password file - not for update. */
|
|
fp = startsmbpwent(False);
|
|
|
|
if (fp == NULL)
|
|
{
|
|
DEBUG(0, ("unable to open smb password database.\n"));
|
|
return NULL;
|
|
}
|
|
|
|
while ((pwd = getsmbpwent(fp)) != NULL && !strequal(pwd->unix_name, name))
|
|
{
|
|
DEBUG(10, ("iterate: %s 0x%x\n", pwd->unix_name, pwd->unix_uid));
|
|
}
|
|
|
|
if (pwd != NULL)
|
|
{
|
|
DEBUG(10, ("found by name: %s\n", name));
|
|
}
|
|
|
|
endsmbpwent(fp);
|
|
return pwd;
|
|
}
|
|
|
|
/***************************************************************
|
|
Start to enumerate the smb or sam passwd list. Returns a void pointer
|
|
to ensure no modification outside this module.
|
|
|
|
Note that currently it is being assumed that a pointer returned
|
|
from this function may be used to enumerate struct sam_passwd
|
|
entries as well as struct smb_passwd entries. This may need
|
|
to change. JRA.
|
|
|
|
****************************************************************/
|
|
|
|
void *startsmbpwent(BOOL update)
|
|
{
|
|
return pwdb_ops->startsmbpwent(update);
|
|
}
|
|
|
|
/***************************************************************
|
|
End enumeration of the smb or sam passwd list.
|
|
|
|
Note that currently it is being assumed that a pointer returned
|
|
from this function may be used to enumerate struct sam_passwd
|
|
entries as well as struct smb_passwd entries. This may need
|
|
to change. JRA.
|
|
|
|
****************************************************************/
|
|
|
|
void endsmbpwent(void *vp)
|
|
{
|
|
pwdb_ops->endsmbpwent(vp);
|
|
}
|
|
|
|
SMB_BIG_UINT getsmbpwpos(void *vp)
|
|
{
|
|
return pwdb_ops->getsmbpwpos(vp);
|
|
}
|
|
|
|
BOOL setsmbpwpos(void *vp, SMB_BIG_UINT tok)
|
|
{
|
|
return pwdb_ops->setsmbpwpos(vp, tok);
|
|
}
|
|
|
|
/*************************************************************************
|
|
Routine to return the next entry in the smb passwd list.
|
|
*************************************************************************/
|
|
|
|
struct smb_passwd *getsmbpwent(void *vp)
|
|
{
|
|
return pwdb_smb_map_names(pwdb_ops->getsmbpwent(vp));
|
|
}
|
|
|
|
/************************************************************************
|
|
Routine to add an entry to the smb passwd file.
|
|
*************************************************************************/
|
|
|
|
BOOL add_smbpwd_entry(struct smb_passwd *newpwd)
|
|
{
|
|
return pwdb_ops->add_smbpwd_entry(pwdb_smb_map_names(newpwd));
|
|
}
|
|
|
|
/************************************************************************
|
|
Routine to search the smb passwd file for an entry matching the username.
|
|
and then modify its password entry. We can't use the startsampwent()/
|
|
getsampwent()/endsampwent() interfaces here as we depend on looking
|
|
in the actual file to decide how much room we have to write data.
|
|
override = False, normal
|
|
override = True, override XXXXXXXX'd out password or NO PASS
|
|
************************************************************************/
|
|
|
|
BOOL mod_smbpwd_entry(struct smb_passwd* pwd, BOOL override)
|
|
{
|
|
return pwdb_ops->mod_smbpwd_entry(pwdb_smb_map_names(pwd), override);
|
|
}
|
|
|
|
/************************************************************************
|
|
Routine to search smb passwd by name.
|
|
*************************************************************************/
|
|
|
|
struct smb_passwd *getsmbpwnam(const char *name)
|
|
{
|
|
return pwdb_smb_map_names(pwdb_ops->getsmbpwnam(name));
|
|
}
|
|
|
|
/************************************************************************
|
|
Routine to search smb passwd by uid.
|
|
*************************************************************************/
|
|
|
|
struct smb_passwd *getsmbpwuid(uid_t unix_uid)
|
|
{
|
|
return pwdb_smb_map_names(pwdb_ops->getsmbpwuid(unix_uid));
|
|
}
|
|
|
|
/*************************************************************
|
|
initialises a struct smb_passwd.
|
|
**************************************************************/
|
|
void pwdb_init_smb(struct smb_passwd *user)
|
|
{
|
|
if (user == NULL) return;
|
|
bzero(user, sizeof(*user));
|
|
user->pass_last_set_time = (time_t)-1;
|
|
user->unix_uid = (uid_t)-1;
|
|
user->user_rid = 0xffffffff;
|
|
}
|
|
|
|
/*************************************************************
|
|
fills in missing details. one set of details _must_ exist.
|
|
**************************************************************/
|
|
struct smb_passwd *pwdb_smb_map_names(struct smb_passwd *smb)
|
|
{
|
|
DOM_NAME_MAP gmep;
|
|
BOOL found = False;
|
|
DOM_SID sid;
|
|
static fstring unix_name;
|
|
static fstring nt_name;
|
|
|
|
DEBUG(10,("pwdb_smb_map_names\n"));
|
|
|
|
if (smb == NULL)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
if (smb->unix_name == NULL && smb->nt_name == NULL &&
|
|
smb->unix_uid == (uid_t)-1 && smb->user_rid == 0xffffffff)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
if (!found && smb->unix_name != NULL)
|
|
{
|
|
found = lookupsmbpwnam(smb->unix_name, &gmep);
|
|
}
|
|
if (!found && smb->unix_uid != (uid_t)-1)
|
|
{
|
|
found = lookupsmbpwuid(smb->unix_uid , &gmep);
|
|
}
|
|
|
|
if (!found)
|
|
{
|
|
sid_copy(&sid, &global_sam_sid);
|
|
sid_append_rid(&sid, smb->user_rid);
|
|
}
|
|
|
|
if (!found && smb->user_rid != 0xffffffff)
|
|
{
|
|
found = lookupsmbpwsid (&sid , &gmep);
|
|
}
|
|
if (!found && smb->nt_name != NULL)
|
|
{
|
|
found = lookupsmbpwntnam(smb->nt_name, &gmep);
|
|
}
|
|
|
|
if (!found)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
if (!sid_front_equal(&global_sam_sid, &gmep.sid))
|
|
{
|
|
fstring sid_str;
|
|
sid_to_string(sid_str, &gmep.sid);
|
|
DEBUG(0,("UNIX User %s Primary Group is in the wrong domain! %s\n",
|
|
smb->unix_name, sid_str));
|
|
return NULL;
|
|
}
|
|
|
|
fstrcpy(unix_name, gmep.unix_name);
|
|
fstrcpy(nt_name , gmep.nt_name );
|
|
if (smb->unix_name == NULL ) smb->unix_name = unix_name;
|
|
if (smb->nt_name == NULL ) smb->nt_name = nt_name ;
|
|
if (smb->unix_uid == (uid_t)-1 ) smb->unix_uid = (uid_t)gmep.unix_id;
|
|
if (smb->user_rid == 0xffffffff) sid_split_rid(&gmep.sid, &smb->user_rid);
|
|
|
|
return smb;
|
|
}
|