password.c

来自「samba-3.0.22.tar.gz 编译smb服务器的源码」· C语言 代码 · 共 634 行 · 第 1/2 页

C
634
字号
/*    Unix SMB/CIFS implementation.   Password and authentication handling   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.*/#include "includes.h"/* users from session setup */static char *session_userlist = NULL;static int len_session_userlist = 0;/* this holds info on user ids that are already validated for this VC */static user_struct *validated_users;static int next_vuid = VUID_OFFSET;static int num_validated_vuids;extern userdom_struct current_user_info;/**************************************************************************** Check if a uid has been validated, and return an pointer to the user_struct if it has. NULL if not. vuid is biased by an offset. This allows us to tell random client vuid's (normally zero) from valid vuids.****************************************************************************/user_struct *get_valid_user_struct(uint16 vuid){	user_struct *usp;	int count=0;	if (vuid == UID_FIELD_INVALID)		return NULL;	for (usp=validated_users;usp;usp=usp->next,count++) {		if (vuid == usp->vuid && usp->server_info) {			if (count > 10) {				DLIST_PROMOTE(validated_users, usp);			}			return usp;		}	}	return NULL;}/**************************************************************************** Get the user struct of a partial NTLMSSP login****************************************************************************/user_struct *get_partial_auth_user_struct(uint16 vuid){	user_struct *usp;	int count=0;	if (vuid == UID_FIELD_INVALID)		return NULL;	for (usp=validated_users;usp;usp=usp->next,count++) {		if (vuid == usp->vuid && !usp->server_info) {			if (count > 10) {				DLIST_PROMOTE(validated_users, usp);			}			return usp;		}	}	return NULL;}/**************************************************************************** Invalidate a uid.****************************************************************************/void invalidate_vuid(uint16 vuid){	user_struct *vuser = get_valid_user_struct(vuid);	if (vuser == NULL)		return;		SAFE_FREE(vuser->homedir);	SAFE_FREE(vuser->unix_homedir);	SAFE_FREE(vuser->logon_script);		session_yield(vuser);	SAFE_FREE(vuser->session_keystr);	free_server_info(&vuser->server_info);	data_blob_free(&vuser->session_key);	DLIST_REMOVE(validated_users, vuser);	/* clear the vuid from the 'cache' on each connection, and	   from the vuid 'owner' of connections */	conn_clear_vuid_cache(vuid);	SAFE_FREE(vuser->groups);	delete_nt_token(&vuser->nt_user_token);	SAFE_FREE(vuser);	num_validated_vuids--;}/**************************************************************************** Invalidate all vuid entries for this process.****************************************************************************/void invalidate_all_vuids(void){	user_struct *usp, *next=NULL;	for (usp=validated_users;usp;usp=next) {		next = usp->next;				invalidate_vuid(usp->vuid);	}}/** *  register that a valid login has been performed, establish 'session'. *  @param server_info The token returned from the authentication process.  *   (now 'owned' by register_vuid) * *  @param session_key The User session key for the login session (now also 'owned' by register_vuid) * *  @param respose_blob The NT challenge-response, if available.  (May be freed after this call) * *  @param smb_name The untranslated name of the user * *  @return Newly allocated vuid, biased by an offset. (This allows us to *   tell random client vuid's (normally zero) from valid vuids.) * */int register_vuid(auth_serversupplied_info *server_info, DATA_BLOB session_key, DATA_BLOB response_blob, const char *smb_name){	user_struct *vuser = NULL;	/* Ensure no vuid gets registered in share level security. */	if(lp_security() == SEC_SHARE) {		data_blob_free(&session_key);		return UID_FIELD_INVALID;	}	/* Limit allowed vuids to 16bits - VUID_OFFSET. */	if (num_validated_vuids >= 0xFFFF-VUID_OFFSET) {		data_blob_free(&session_key);		return UID_FIELD_INVALID;	}	if((vuser = SMB_MALLOC_P(user_struct)) == NULL) {		DEBUG(0,("Failed to malloc users struct!\n"));		data_blob_free(&session_key);		return UID_FIELD_INVALID;	}	ZERO_STRUCTP(vuser);	/* Allocate a free vuid. Yes this is a linear search... :-) */	while( get_valid_user_struct(next_vuid) != NULL ) {		next_vuid++;		/* Check for vuid wrap. */		if (next_vuid == UID_FIELD_INVALID)			next_vuid = VUID_OFFSET;	}	DEBUG(10,("register_vuid: allocated vuid = %u\n", (unsigned int)next_vuid ));	vuser->vuid = next_vuid;	if (!server_info) {		next_vuid++;		num_validated_vuids++;				vuser->server_info = NULL;				DLIST_ADD(validated_users, vuser);				return vuser->vuid;	}	/* the next functions should be done by a SID mapping system (SMS) as	 * the new real sam db won't have reference to unix uids or gids	 */		vuser->uid = server_info->uid;	vuser->gid = server_info->gid;		vuser->n_groups = server_info->n_groups;	if (vuser->n_groups) {		if (!(vuser->groups = (gid_t *)memdup(server_info->groups, sizeof(gid_t) * vuser->n_groups))) {			DEBUG(0,("register_vuid: failed to memdup vuser->groups\n"));			data_blob_free(&session_key);			free(vuser);			free_server_info(&server_info);			return UID_FIELD_INVALID;		}	}	vuser->guest = server_info->guest;	fstrcpy(vuser->user.unix_name, server_info->unix_name); 	/* This is a potentially untrusted username */	alpha_strcpy(vuser->user.smb_name, smb_name, ". _-$", sizeof(vuser->user.smb_name));	fstrcpy(vuser->user.domain, pdb_get_domain(server_info->sam_account));	fstrcpy(vuser->user.full_name, pdb_get_fullname(server_info->sam_account));	{		/* Keep the homedir handy */		const char *homedir = pdb_get_homedir(server_info->sam_account);		const char *logon_script = pdb_get_logon_script(server_info->sam_account);		if (!IS_SAM_DEFAULT(server_info->sam_account, PDB_UNIXHOMEDIR)) {			const char *unix_homedir = pdb_get_unix_homedir(server_info->sam_account);			if (unix_homedir) {				vuser->unix_homedir = smb_xstrdup(unix_homedir);			}		} else {			struct passwd *passwd = getpwnam_alloc(vuser->user.unix_name);			if (passwd) {				vuser->unix_homedir = smb_xstrdup(passwd->pw_dir);				passwd_free(&passwd);			}		}				if (homedir) {			vuser->homedir = smb_xstrdup(homedir);		}		if (logon_script) {			vuser->logon_script = smb_xstrdup(logon_script);		}	}	vuser->session_key = session_key;	DEBUG(10,("register_vuid: (%u,%u) %s %s %s guest=%d\n", 		  (unsigned int)vuser->uid, 		  (unsigned int)vuser->gid,		  vuser->user.unix_name, vuser->user.smb_name, vuser->user.domain, vuser->guest ));	DEBUG(3, ("User name: %s\tReal name: %s\n",vuser->user.unix_name,vuser->user.full_name));	 	if (server_info->ptok) {		vuser->nt_user_token = dup_nt_token(server_info->ptok);	} else {		DEBUG(1, ("server_info does not contain a user_token - cannot continue\n"));		free_server_info(&server_info);		data_blob_free(&session_key);		SAFE_FREE(vuser->homedir);		SAFE_FREE(vuser->unix_homedir);		SAFE_FREE(vuser->logon_script);		SAFE_FREE(vuser);		return UID_FIELD_INVALID;	}	/* use this to keep tabs on all our info from the authentication */	vuser->server_info = server_info;	DEBUG(3,("UNIX uid %d is UNIX user %s, and will be vuid %u\n",(int)vuser->uid,vuser->user.unix_name, vuser->vuid));	next_vuid++;	num_validated_vuids++;	DLIST_ADD(validated_users, vuser);	if (!session_claim(vuser)) {		DEBUG(1,("Failed to claim session for vuid=%d\n", vuser->vuid));		invalidate_vuid(vuser->vuid);		return -1;	}	/* Register a home dir service for this user iff		   (a) This is not a guest connection,	   (b) we have a home directory defined 	   (c) there s not an existing static share by that name	   	   If a share exists by this name (autoloaded or not) reuse it . */	vuser->homes_snum = -1;	if ( (!vuser->guest) && vuser->unix_homedir && *(vuser->unix_homedir)) 	{		int servicenumber = lp_servicenumber(vuser->user.unix_name);		if ( servicenumber == -1 ) {			DEBUG(3, ("Adding homes service for user '%s' using home directory: '%s'\n", 				vuser->user.unix_name, vuser->unix_homedir));			vuser->homes_snum = add_home_service(vuser->user.unix_name, 						vuser->user.unix_name, vuser->unix_homedir);		} else {			DEBUG(3, ("Using static (or previously created) service for user '%s'; path = '%s'\n", 				vuser->user.unix_name, lp_pathname(servicenumber) ));			vuser->homes_snum = servicenumber;		}	} 		if (srv_is_signing_negotiated() && !vuser->guest && !srv_signing_started()) {		/* Try and turn on server signing on the first non-guest sessionsetup. */		srv_set_signing(vuser->session_key, response_blob);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?