pass_check.c
来自「samba-3.0.22.tar.gz 编译smb服务器的源码」· C语言 代码 · 共 784 行 · 第 1/2 页
C
784 行
/* Unix SMB/CIFS implementation. Password checking Copyright (C) Andrew Tridgell 1992-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.*//* this module is for checking a username/password against a system password database. The SMB encrypted password support is elsewhere */#include "includes.h"#undef DBGC_CLASS#define DBGC_CLASS DBGC_AUTH/* these are kept here to keep the string_combinations function simple */static fstring this_user;#if !defined(WITH_PAM) static fstring this_salt;static fstring this_crypted;#endif#ifdef WITH_AFS#include <afs/stds.h>#include <afs/kautils.h>/*******************************************************************check on AFS authentication********************************************************************/static BOOL afs_auth(char *user, char *password){ long password_expires = 0; char *reason; /* For versions of AFS prior to 3.3, this routine has few arguments, */ /* but since I can't find the old documentation... :-) */ setpag(); if (ka_UserAuthenticateGeneral (KA_USERAUTH_VERSION + KA_USERAUTH_DOSETPAG, user, (char *)0, /* instance */ (char *)0, /* cell */ password, 0, /* lifetime, default */ &password_expires, /*days 'til it expires */ 0, /* spare 2 */ &reason) == 0) { return (True); } DEBUG(1, ("AFS authentication for \"%s\" failed (%s)\n", user, reason)); return (False);}#endif#ifdef WITH_DFS#include <dce/dce_error.h>#include <dce/sec_login.h>/***************************************************************** This new version of the DFS_AUTH code was donated by Karsten Muuss <muuss@or.uni-bonn.de>. It fixes the following problems with the old code : - Server credentials may expire - Client credential cache files have wrong owner - purge_context() function is called with invalid argument This new code was modified to ensure that on exit the uid/gid is still root, and the original directory is restored. JRA.******************************************************************/sec_login_handle_t my_dce_sec_context;int dcelogin_atmost_once = 0;/*******************************************************************check on a DCE/DFS authentication********************************************************************/static BOOL dfs_auth(char *user, char *password){ error_status_t err; int err2; int prterr; signed32 expire_time, current_time; boolean32 password_reset; struct passwd *pw; sec_passwd_rec_t passwd_rec; sec_login_auth_src_t auth_src = sec_login_auth_src_network; unsigned char dce_errstr[dce_c_error_string_len]; gid_t egid; if (dcelogin_atmost_once) return (False);#ifdef HAVE_CRYPT /* * We only go for a DCE login context if the given password * matches that stored in the local password file.. * Assumes local passwd file is kept in sync w/ DCE RGY! */ if (strcmp((char *)crypt(password, this_salt), this_crypted)) { return (False); }#endif sec_login_get_current_context(&my_dce_sec_context, &err); if (err != error_status_ok) { dce_error_inq_text(err, dce_errstr, &err2); DEBUG(0, ("DCE can't get current context. %s\n", dce_errstr)); return (False); } sec_login_certify_identity(my_dce_sec_context, &err); if (err != error_status_ok) { dce_error_inq_text(err, dce_errstr, &err2); DEBUG(0, ("DCE can't get current context. %s\n", dce_errstr)); return (False); } sec_login_get_expiration(my_dce_sec_context, &expire_time, &err); if (err != error_status_ok) { dce_error_inq_text(err, dce_errstr, &err2); DEBUG(0, ("DCE can't get expiration. %s\n", dce_errstr)); return (False); } time(¤t_time); if (expire_time < (current_time + 60)) { struct passwd *pw; sec_passwd_rec_t *key; sec_login_get_pwent(my_dce_sec_context, (sec_login_passwd_t *) & pw, &err); if (err != error_status_ok) { dce_error_inq_text(err, dce_errstr, &err2); DEBUG(0, ("DCE can't get pwent. %s\n", dce_errstr)); return (False); } sec_login_refresh_identity(my_dce_sec_context, &err); if (err != error_status_ok) { dce_error_inq_text(err, dce_errstr, &err2); DEBUG(0, ("DCE can't refresh identity. %s\n", dce_errstr)); return (False); } sec_key_mgmt_get_key(rpc_c_authn_dce_secret, NULL, (unsigned char *)pw->pw_name, sec_c_key_version_none, (void **)&key, &err); if (err != error_status_ok) { dce_error_inq_text(err, dce_errstr, &err2); DEBUG(0, ("DCE can't get key for %s. %s\n", pw->pw_name, dce_errstr)); return (False); } sec_login_valid_and_cert_ident(my_dce_sec_context, key, &password_reset, &auth_src, &err); if (err != error_status_ok) { dce_error_inq_text(err, dce_errstr, &err2); DEBUG(0, ("DCE can't validate and certify identity for %s. %s\n", pw->pw_name, dce_errstr)); } sec_key_mgmt_free_key(key, &err); if (err != error_status_ok) { dce_error_inq_text(err, dce_errstr, &err2); DEBUG(0, ("DCE can't free key.\n", dce_errstr)); } } if (sec_login_setup_identity((unsigned char *)user, sec_login_no_flags, &my_dce_sec_context, &err) == 0) { dce_error_inq_text(err, dce_errstr, &err2); DEBUG(0, ("DCE Setup Identity for %s failed: %s\n", user, dce_errstr)); return (False); } sec_login_get_pwent(my_dce_sec_context, (sec_login_passwd_t *) & pw, &err); if (err != error_status_ok) { dce_error_inq_text(err, dce_errstr, &err2); DEBUG(0, ("DCE can't get pwent. %s\n", dce_errstr)); return (False); } sec_login_purge_context(&my_dce_sec_context, &err); if (err != error_status_ok) { dce_error_inq_text(err, dce_errstr, &err2); DEBUG(0, ("DCE can't purge context. %s\n", dce_errstr)); return (False); } /* * NB. I'd like to change these to call something like change_to_user() * instead but currently we don't have a connection * context to become the correct user. This is already * fairly platform specific code however, so I think * this should be ok. I have added code to go * back to being root on error though. JRA. */ egid = getegid(); set_effective_gid(pw->pw_gid); set_effective_uid(pw->pw_uid); if (sec_login_setup_identity((unsigned char *)user, sec_login_no_flags, &my_dce_sec_context, &err) == 0) { dce_error_inq_text(err, dce_errstr, &err2); DEBUG(0, ("DCE Setup Identity for %s failed: %s\n", user, dce_errstr)); goto err; } sec_login_get_pwent(my_dce_sec_context, (sec_login_passwd_t *) & pw, &err); if (err != error_status_ok) { dce_error_inq_text(err, dce_errstr, &err2); DEBUG(0, ("DCE can't get pwent. %s\n", dce_errstr)); goto err; } passwd_rec.version_number = sec_passwd_c_version_none; passwd_rec.pepper = NULL; passwd_rec.key.key_type = sec_passwd_plain; passwd_rec.key.tagged_union.plain = (idl_char *) password; sec_login_validate_identity(my_dce_sec_context, &passwd_rec, &password_reset, &auth_src, &err); if (err != error_status_ok) { dce_error_inq_text(err, dce_errstr, &err2); DEBUG(0, ("DCE Identity Validation failed for principal %s: %s\n", user, dce_errstr)); goto err; } sec_login_certify_identity(my_dce_sec_context, &err); if (err != error_status_ok) { dce_error_inq_text(err, dce_errstr, &err2); DEBUG(0, ("DCE certify identity failed: %s\n", dce_errstr)); goto err; } if (auth_src != sec_login_auth_src_network) { DEBUG(0, ("DCE context has no network credentials.\n")); } sec_login_set_context(my_dce_sec_context, &err); if (err != error_status_ok) { dce_error_inq_text(err, dce_errstr, &err2); DEBUG(0, ("DCE login failed for principal %s, cant set context: %s\n", user, dce_errstr)); sec_login_purge_context(&my_dce_sec_context, &err); goto err; } sec_login_get_pwent(my_dce_sec_context, (sec_login_passwd_t *) & pw, &err); if (err != error_status_ok) { dce_error_inq_text(err, dce_errstr, &err2); DEBUG(0, ("DCE can't get pwent. %s\n", dce_errstr)); goto err; } DEBUG(0, ("DCE login succeeded for principal %s on pid %d\n", user, sys_getpid())); DEBUG(3, ("DCE principal: %s\n" " uid: %d\n" " gid: %d\n", pw->pw_name, pw->pw_uid, pw->pw_gid)); DEBUG(3, (" info: %s\n" " dir: %s\n" " shell: %s\n", pw->pw_gecos, pw->pw_dir, pw->pw_shell)); sec_login_get_expiration(my_dce_sec_context, &expire_time, &err); if (err != error_status_ok) { dce_error_inq_text(err, dce_errstr, &err2); DEBUG(0, ("DCE can't get expiration. %s\n", dce_errstr)); goto err; } set_effective_uid(0); set_effective_gid(0); DEBUG(0, ("DCE context expires: %s", asctime(localtime(&expire_time)))); dcelogin_atmost_once = 1; return (True); err: /* Go back to root, JRA. */ set_effective_uid(0); set_effective_gid(egid); return (False);}void dfs_unlogin(void){ error_status_t err; int err2; unsigned char dce_errstr[dce_c_error_string_len]; sec_login_purge_context(&my_dce_sec_context, &err); if (err != error_status_ok) { dce_error_inq_text(err, dce_errstr, &err2); DEBUG(0, ("DCE purge login context failed for server instance %d: %s\n", sys_getpid(), dce_errstr)); }}#endif#ifdef LINUX_BIGCRYPT/****************************************************************************an enhanced crypt for Linux to handle password longer than 8 characters****************************************************************************/static int linux_bigcrypt(char *password, char *salt1, char *crypted){#define LINUX_PASSWORD_SEG_CHARS 8 char salt[3]; int i; StrnCpy(salt, salt1, 2); crypted += 2; for (i = strlen(password); i > 0; i -= LINUX_PASSWORD_SEG_CHARS) { char *p = crypt(password, salt) + 2; if (strncmp(p, crypted, LINUX_PASSWORD_SEG_CHARS) != 0) return (0); password += LINUX_PASSWORD_SEG_CHARS;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?