215 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			215 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * This file is distributed as part of the MariaDB Corporation MaxScale.  It 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,
 | |
|  * version 2.
 | |
|  *
 | |
|  * 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., 51
 | |
|  * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 | |
|  *
 | |
|  * Copyright MariaDB Corporation Ab 2013-2014
 | |
|  */
 | |
| #include <stdio.h>
 | |
| #include <stdlib.h>
 | |
| #include <string.h>
 | |
| #include <users.h>
 | |
| #include <atomic.h>
 | |
| 
 | |
| /**
 | |
|  * @file users.c User table maintenance routines
 | |
|  *
 | |
|  * @verbatim
 | |
|  * Revision History
 | |
|  *
 | |
|  * Date		Who			Description
 | |
|  * 23/06/2013	Mark Riddoch		Initial implementation
 | |
|  * 08/01/2014	Massimiliano Pinto	In user_alloc now we can pass function pointers for
 | |
|  *					copying/freeing keys and values	independently via
 | |
|  *					hashtable_memory_fns() routine
 | |
|  *
 | |
|  * @endverbatim
 | |
|  */
 | |
| 
 | |
| /**
 | |
|  * The hash function we user for storing users.
 | |
|  *
 | |
|  * @param key	The key value, i.e. username
 | |
|  * @return The hash key
 | |
|  */
 | |
| static int
 | |
| user_hash(char *key)
 | |
| {
 | |
| 	return (*key + *(key + 1));
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Allocate a new users table
 | |
|  *
 | |
|  * @return The users table
 | |
|  */
 | |
| USERS *
 | |
| users_alloc()
 | |
| {
 | |
| USERS 	*rval;
 | |
| 
 | |
|         if ((rval = calloc(1, sizeof(USERS))) == NULL)
 | |
| 		return NULL;
 | |
| 
 | |
| 	if ((rval->data = hashtable_alloc(USERS_HASHTABLE_DEFAULT_SIZE, user_hash, strcmp)) == NULL)
 | |
| 	{
 | |
| 		free(rval);
 | |
| 		return NULL;
 | |
| 	}
 | |
| 
 | |
| 	hashtable_memory_fns(rval->data, (HASHMEMORYFN)strdup, (HASHMEMORYFN)strdup, (HASHMEMORYFN)free, (HASHMEMORYFN)free);
 | |
| 
 | |
| 	return rval;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Remove the users table
 | |
|  *
 | |
|  * @param users	The users table to remove
 | |
|  */
 | |
| void
 | |
| users_free(USERS *users)
 | |
| {
 | |
| 	hashtable_free(users->data);
 | |
| 	free(users);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Add a new user to the user table. The user name must be unique
 | |
|  *
 | |
|  * @param users		The users table
 | |
|  * @param user		The user name
 | |
|  * @param auth		The authentication data
 | |
|  * @return	The number of users added to the table
 | |
|  */
 | |
| int
 | |
| users_add(USERS *users, char *user, char *auth)
 | |
| {
 | |
| int	add;
 | |
| 
 | |
| 	atomic_add(&users->stats.n_adds, 1);
 | |
| 	add = hashtable_add(users->data, user, auth);
 | |
| 	atomic_add(&users->stats.n_entries, add);
 | |
| 	return add;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Delete a user from the user table.
 | |
|  *
 | |
|  * The last user in the table can not be deleted
 | |
|  *
 | |
|  * @param users		The users table
 | |
|  * @param user		The user name
 | |
|  * @return	The number of users deleted from the table
 | |
|  */
 | |
| int
 | |
| users_delete(USERS *users, char *user)
 | |
| {
 | |
| int	del;
 | |
| 
 | |
|         if (users->stats.n_entries == 1) {
 | |
|             return 0;
 | |
|         }
 | |
| 	atomic_add(&users->stats.n_deletes, 1);
 | |
| 	del = hashtable_delete(users->data, user);
 | |
| 	atomic_add(&users->stats.n_entries, -del);
 | |
| 	return del;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Fetch the authentication data for a particular user from the users table
 | |
|  *
 | |
|  * @param users		The users table
 | |
|  * @param user		The user name
 | |
|  * @return	The authentication data or NULL on error
 | |
|  */
 | |
| char
 | |
| *users_fetch(USERS *users, char *user)  
 | |
| {
 | |
| 	atomic_add(&users->stats.n_fetches, 1);
 | |
| 	return hashtable_fetch(users->data, user);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Change the password data associated with a user in the users
 | |
|  * table.
 | |
|  *
 | |
|  * @param users		The users table
 | |
|  * @param user		The user name
 | |
|  * @param auth		The new authentication details
 | |
|  * @return Number of users updated
 | |
|  */
 | |
| int
 | |
| users_update(USERS *users, char *user, char *auth)
 | |
| {
 | |
| 	if (hashtable_delete(users->data, user) == 0)
 | |
| 		return 0;
 | |
| 	return hashtable_add(users->data, user, auth);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Print details of the users storage mechanism
 | |
|  *
 | |
|  * @param users		The users table
 | |
|  */
 | |
| void
 | |
| usersPrint(USERS *users)
 | |
| {
 | |
| 	printf("Users table data\n");
 | |
| 	hashtable_stats(users->data);
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Print details of the users storage mechanism to a DCB
 | |
|  *
 | |
|  * @param dcb		DCB to print to
 | |
|  * @param users		The users table
 | |
|  */
 | |
| void
 | |
| dcb_usersPrint(DCB *dcb, USERS *users)
 | |
| {
 | |
| HASHITERATOR	*iter;
 | |
| char		*sep;
 | |
| void		*user;
 | |
| 
 | |
| 	dcb_printf(dcb, "Users table data\n");
 | |
| 	dcb_hashtable_stats(dcb, users->data);
 | |
| 	if ((iter = hashtable_iterator(users->data)) != NULL)
 | |
| 	{
 | |
| 		dcb_printf(dcb, "User names: ");
 | |
| 		sep = "";
 | |
| 
 | |
| 		if (users->usersCustomUserFormat != NULL) {
 | |
| 			while ((user = hashtable_next(iter)) != NULL)
 | |
| 			{
 | |
| 				char *custom_user;
 | |
| 				custom_user = users->usersCustomUserFormat(user);
 | |
| 				if (custom_user) {
 | |
| 					dcb_printf(dcb, "%s%s", sep, custom_user);
 | |
| 					free(custom_user);
 | |
| 					sep = ", ";
 | |
| 				}
 | |
| 			}
 | |
| 		} else {
 | |
| 			while ((user = hashtable_next(iter)) != NULL)
 | |
| 			{
 | |
| 				dcb_printf(dcb, "%s%s", sep, (char *)user);
 | |
| 				sep = ", ";
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		dcb_printf(dcb, "\n");
 | |
|                 hashtable_iterator_free(iter);
 | |
| 	}
 | |
| }
 | 
