📄 pdb_interface.c
字号:
/* Unix SMB/CIFS implementation. Password and authentication handling Copyright (C) Andrew Bartlett 2002 Copyright (C) Jelmer Vernooij 2002 Copyright (C) Simo Sorce 2003 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"#undef DBGC_CLASS#define DBGC_CLASS DBGC_PASSDBstatic struct pdb_init_function_entry *backends = NULL;static void lazy_initialize_passdb(void){ static BOOL initialized = False; if(initialized)return; static_init_pdb; initialized = True;}static struct pdb_init_function_entry *pdb_find_backend_entry(const char *name);/******************************************************************* Clean up uninitialised passwords. The only way to tell that these values are not 'real' is that they do not have a valid last set time. Instead, the value is fixed at 0. Therefore we use that as the key for 'is this a valid password'. However, it is perfectly valid to have a 'default' last change time, such LDAP with a missing attribute would produce.********************************************************************/static void pdb_force_pw_initialization(SAM_ACCOUNT *pass) { const uint8 *lm_pwd, *nt_pwd; /* only reset a password if the last set time has been explicitly been set to zero. A default last set time is ignored */ if ( (pdb_get_init_flags(pass, PDB_PASSLASTSET) != PDB_DEFAULT) && (pdb_get_pass_last_set_time(pass) == 0) ) { if (pdb_get_init_flags(pass, PDB_LMPASSWD) != PDB_DEFAULT) { lm_pwd = pdb_get_lanman_passwd(pass); if (lm_pwd) pdb_set_lanman_passwd(pass, NULL, PDB_CHANGED); } if (pdb_get_init_flags(pass, PDB_NTPASSWD) != PDB_DEFAULT) { nt_pwd = pdb_get_nt_passwd(pass); if (nt_pwd) pdb_set_nt_passwd(pass, NULL, PDB_CHANGED); } } return;}NTSTATUS smb_register_passdb(int version, const char *name, pdb_init_function init) { struct pdb_init_function_entry *entry = backends; if(version != PASSDB_INTERFACE_VERSION) { DEBUG(0,("Can't register passdb backend!\n" "You tried to register a passdb module with PASSDB_INTERFACE_VERSION %d, " "while this version of samba uses version %d\n", version,PASSDB_INTERFACE_VERSION)); return NT_STATUS_OBJECT_TYPE_MISMATCH; } if (!name || !init) { return NT_STATUS_INVALID_PARAMETER; } DEBUG(5,("Attempting to register passdb backend %s\n", name)); /* Check for duplicates */ if (pdb_find_backend_entry(name)) { DEBUG(0,("There already is a passdb backend registered with the name %s!\n", name)); return NT_STATUS_OBJECT_NAME_COLLISION; } entry = SMB_XMALLOC_P(struct pdb_init_function_entry); entry->name = smb_xstrdup(name); entry->init = init; DLIST_ADD(backends, entry); DEBUG(5,("Successfully added passdb backend '%s'\n", name)); return NT_STATUS_OK;}static struct pdb_init_function_entry *pdb_find_backend_entry(const char *name){ struct pdb_init_function_entry *entry = backends; while(entry) { if (strcmp(entry->name, name)==0) return entry; entry = entry->next; } return NULL;}static NTSTATUS context_setsampwent(struct pdb_context *context, BOOL update, uint16 acb_mask){ NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; if (!context) { DEBUG(0, ("invalid pdb_context specified!\n")); return ret; } context->pwent_methods = context->pdb_methods; if (!context->pwent_methods) { /* No passdbs at all */ return ret; } while (NT_STATUS_IS_ERR(ret = context->pwent_methods->setsampwent(context->pwent_methods, update, acb_mask))) { context->pwent_methods = context->pwent_methods->next; if (context->pwent_methods == NULL) return NT_STATUS_UNSUCCESSFUL; } return ret;}static void context_endsampwent(struct pdb_context *context){ if ((!context)){ DEBUG(0, ("invalid pdb_context specified!\n")); return; } if (context->pwent_methods && context->pwent_methods->endsampwent) context->pwent_methods->endsampwent(context->pwent_methods); /* So we won't get strange data when calling getsampwent now */ context->pwent_methods = NULL;}static NTSTATUS context_getsampwent(struct pdb_context *context, SAM_ACCOUNT *user){ NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; if ((!context) || (!context->pwent_methods)) { DEBUG(0, ("invalid pdb_context specified!\n")); return ret; } /* Loop until we find something useful */ while (NT_STATUS_IS_ERR(ret = context->pwent_methods->getsampwent(context->pwent_methods, user))) { context->pwent_methods->endsampwent(context->pwent_methods); context->pwent_methods = context->pwent_methods->next; /* All methods are checked now. There are no more entries */ if (context->pwent_methods == NULL) return ret; context->pwent_methods->setsampwent(context->pwent_methods, False, 0); } user->methods = context->pwent_methods; pdb_force_pw_initialization(user); return ret;}static NTSTATUS context_getsampwnam(struct pdb_context *context, SAM_ACCOUNT *sam_acct, const char *username){ NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; struct pdb_methods *curmethods; if ((!context)) { DEBUG(0, ("invalid pdb_context specified!\n")); return ret; } curmethods = context->pdb_methods; while (curmethods){ if (NT_STATUS_IS_OK(ret = curmethods->getsampwnam(curmethods, sam_acct, username))) { pdb_force_pw_initialization(sam_acct); sam_acct->methods = curmethods; return ret; } curmethods = curmethods->next; } return ret;}static NTSTATUS context_getsampwsid(struct pdb_context *context, SAM_ACCOUNT *sam_acct, const DOM_SID *sid){ NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; struct pdb_methods *curmethods; if ((!context)) { DEBUG(0, ("invalid pdb_context specified!\n")); return ret; } curmethods = context->pdb_methods; while (curmethods){ if (NT_STATUS_IS_OK(ret = curmethods->getsampwsid(curmethods, sam_acct, sid))) { pdb_force_pw_initialization(sam_acct); sam_acct->methods = curmethods; return ret; } curmethods = curmethods->next; } return ret;}static NTSTATUS context_add_sam_account(struct pdb_context *context, SAM_ACCOUNT *sam_acct){ NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; const uint8 *lm_pw, *nt_pw; uint16 acb_flags; if ((!context) || (!context->pdb_methods)) { DEBUG(0, ("invalid pdb_context specified!\n")); return ret; } /* disable acccounts with no passwords (that has not been allowed by the ACB_PWNOTREQ bit */ lm_pw = pdb_get_lanman_passwd( sam_acct ); nt_pw = pdb_get_nt_passwd( sam_acct ); acb_flags = pdb_get_acct_ctrl( sam_acct ); if ( !lm_pw && !nt_pw && !(acb_flags&ACB_PWNOTREQ) ) { acb_flags |= ACB_DISABLED; pdb_set_acct_ctrl( sam_acct, acb_flags, PDB_CHANGED ); } /** @todo This is where a 're-read on add' should be done */ /* We now add a new account to the first database listed. * Should we? */ return context->pdb_methods->add_sam_account(context->pdb_methods, sam_acct);}static NTSTATUS context_update_sam_account(struct pdb_context *context, SAM_ACCOUNT *sam_acct){ NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; const uint8 *lm_pw, *nt_pw; uint16 acb_flags; if (!context) { DEBUG(0, ("invalid pdb_context specified!\n")); return ret; } if (!sam_acct || !sam_acct->methods){ DEBUG(0, ("invalid sam_acct specified\n")); return ret; } /* disable acccounts with no passwords (that has not been allowed by the ACB_PWNOTREQ bit */ lm_pw = pdb_get_lanman_passwd( sam_acct ); nt_pw = pdb_get_nt_passwd( sam_acct ); acb_flags = pdb_get_acct_ctrl( sam_acct ); if ( !lm_pw && !nt_pw && !(acb_flags&ACB_PWNOTREQ) ) { acb_flags |= ACB_DISABLED; pdb_set_acct_ctrl( sam_acct, acb_flags, PDB_CHANGED ); } /** @todo This is where a 're-read on update' should be done */ return sam_acct->methods->update_sam_account(sam_acct->methods, sam_acct);}static NTSTATUS context_delete_sam_account(struct pdb_context *context, SAM_ACCOUNT *sam_acct){ NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; struct pdb_methods *pdb_selected; if (!context) { DEBUG(0, ("invalid pdb_context specified!\n")); return ret; } if (!sam_acct->methods){ pdb_selected = context->pdb_methods; /* There's no passdb backend specified for this account. * Try to delete it in every passdb available * Needed to delete accounts in smbpasswd that are not * in /etc/passwd. */ while (pdb_selected){ if (NT_STATUS_IS_OK(ret = pdb_selected->delete_sam_account(pdb_selected, sam_acct))) { return ret; } pdb_selected = pdb_selected->next; } return ret; } if (!sam_acct->methods->delete_sam_account){ DEBUG(0,("invalid sam_acct->methods->delete_sam_account\n")); return ret; } return sam_acct->methods->delete_sam_account(sam_acct->methods, sam_acct);}static NTSTATUS context_rename_sam_account(struct pdb_context *context, SAM_ACCOUNT *oldname, const char *newname){ NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; struct pdb_methods *pdb_selected; if (!context) { DEBUG(0, ("invalid pdb_context specified!\n")); return ret; } if (!oldname->methods){ pdb_selected = context->pdb_methods; /* There's no passdb backend specified for this account. * Try to delete it in every passdb available * Needed to delete accounts in smbpasswd that are not * in /etc/passwd. */ while (pdb_selected){ if (NT_STATUS_IS_OK(ret = pdb_selected->rename_sam_account(pdb_selected, oldname, newname))) { return ret; } pdb_selected = pdb_selected->next; } return ret; } if (!oldname->methods->rename_sam_account){ DEBUG(0,("invalid oldname->methods->rename_sam_account\n")); return ret; } return oldname->methods->rename_sam_account(oldname->methods, oldname, newname);}static NTSTATUS context_update_login_attempts(struct pdb_context *context, SAM_ACCOUNT *sam_acct, BOOL success){ NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; if (!context) { DEBUG(0, ("invalid pdb_context specified!\n")); return ret; } if (!sam_acct || !sam_acct->methods){ DEBUG(0, ("invalid sam_acct specified\n")); return ret; } return sam_acct->methods->update_login_attempts(sam_acct->methods, sam_acct, success);}static NTSTATUS context_getgrsid(struct pdb_context *context, GROUP_MAP *map, DOM_SID sid){ NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; struct pdb_methods *curmethods; if ((!context)) { DEBUG(0, ("invalid pdb_context specified!\n")); return ret; } curmethods = context->pdb_methods; while (curmethods){ ret = curmethods->getgrsid(curmethods, map, sid); if (NT_STATUS_IS_OK(ret)) { map->methods = curmethods; return ret; } curmethods = curmethods->next; } return ret;}static NTSTATUS context_getgrgid(struct pdb_context *context, GROUP_MAP *map, gid_t gid){ NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; struct pdb_methods *curmethods; if ((!context)) { DEBUG(0, ("invalid pdb_context specified!\n")); return ret; } curmethods = context->pdb_methods; while (curmethods){ ret = curmethods->getgrgid(curmethods, map, gid); if (NT_STATUS_IS_OK(ret)) { map->methods = curmethods; return ret; } curmethods = curmethods->next; } return ret;}static NTSTATUS context_getgrnam(struct pdb_context *context, GROUP_MAP *map, const char *name){ NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; struct pdb_methods *curmethods; if ((!context)) { DEBUG(0, ("invalid pdb_context specified!\n")); return ret; } curmethods = context->pdb_methods; while (curmethods){ ret = curmethods->getgrnam(curmethods, map, name); if (NT_STATUS_IS_OK(ret)) { map->methods = curmethods; return ret; } curmethods = curmethods->next; } return ret;}static NTSTATUS context_add_group_mapping_entry(struct pdb_context *context, GROUP_MAP *map){ NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; if ((!context) || (!context->pdb_methods)) { DEBUG(0, ("invalid pdb_context specified!\n")); return ret; } return context->pdb_methods->add_group_mapping_entry(context->pdb_methods, map);}static NTSTATUS context_update_group_mapping_entry(struct pdb_context *context, GROUP_MAP *map){ NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; if ((!context) || (!context->pdb_methods)) { DEBUG(0, ("invalid pdb_context specified!\n")); return ret; } return context-> pdb_methods->update_group_mapping_entry(context->pdb_methods, map);}static NTSTATUS context_delete_group_mapping_entry(struct pdb_context *context, DOM_SID sid){ NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; if ((!context) || (!context->pdb_methods)) { DEBUG(0, ("invalid pdb_context specified!\n")); return ret; } return context-> pdb_methods->delete_group_mapping_entry(context->pdb_methods, sid);}static NTSTATUS context_enum_group_mapping(struct pdb_context *context, enum SID_NAME_USE sid_name_use, GROUP_MAP **pp_rmap, size_t *p_num_entries, BOOL unix_only){ NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; if ((!context) || (!context->pdb_methods)) { DEBUG(0, ("invalid pdb_context specified!\n")); return ret; } return context->pdb_methods->enum_group_mapping(context->pdb_methods, sid_name_use, pp_rmap, p_num_entries, unix_only);}static NTSTATUS context_enum_group_members(struct pdb_context *context, TALLOC_CTX *mem_ctx, const DOM_SID *group, uint32 **pp_member_rids, size_t *p_num_members){ NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; if ((!context) || (!context->pdb_methods)) { DEBUG(0, ("invalid pdb_context specified!\n")); return ret; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -