mirror of
				https://github.com/MariaDB/server.git
				synced 2025-11-03 14:33:32 +03:00 
			
		
		
		
	
		
			
				
	
	
		
			177 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			177 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/* Copyright (C) 2003 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
 | 
						|
 | 
						|
   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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 | 
						|
 | 
						|
#ifdef __GNUC__
 | 
						|
#pragma interface 
 | 
						|
#endif
 | 
						|
 | 
						|
#include "user_map.h"
 | 
						|
 | 
						|
#include <mysql_com.h>
 | 
						|
#include <m_string.h>
 | 
						|
 | 
						|
#include "log.h"
 | 
						|
 | 
						|
struct User
 | 
						|
{
 | 
						|
  char user[USERNAME_LENGTH + 1];
 | 
						|
  uint8 user_length;
 | 
						|
  uint8 salt[SCRAMBLE_LENGTH];
 | 
						|
  int init(const char *line);
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
int User::init(const char *line)
 | 
						|
{
 | 
						|
  const char *name_begin, *name_end, *password;
 | 
						|
 | 
						|
  if (line[0] == '\'' || line[0] == '"')
 | 
						|
  {
 | 
						|
    name_begin= line + 1;
 | 
						|
    name_end= strchr(name_begin, line[0]);
 | 
						|
    if (name_end == 0 || name_end[1] != ':')
 | 
						|
      goto err;
 | 
						|
    password= name_end + 2;
 | 
						|
  }
 | 
						|
  else
 | 
						|
  {
 | 
						|
    name_begin= line;
 | 
						|
    name_end= strchr(name_begin, ':');
 | 
						|
    if (name_end == 0)
 | 
						|
      goto err;
 | 
						|
    password= name_end + 1;
 | 
						|
  }
 | 
						|
  user_length= name_end - name_begin;
 | 
						|
  if (user_length > USERNAME_LENGTH)
 | 
						|
    goto err;
 | 
						|
 | 
						|
  /* assume that newline characater is present */
 | 
						|
  if (strlen(password) != SCRAMBLED_PASSWORD_CHAR_LENGTH + 1)
 | 
						|
    goto err;
 | 
						|
 | 
						|
  memcpy(user, name_begin, user_length);
 | 
						|
  user[user_length]= 0;
 | 
						|
  get_salt_from_password(salt, password);
 | 
						|
  log_info("loaded user %s", user);
 | 
						|
 | 
						|
  return 0;
 | 
						|
err:
 | 
						|
  log_error("error parsing user and password at line %s", line);
 | 
						|
  return 1;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
C_MODE_START
 | 
						|
 | 
						|
static byte* get_user_key(const byte* u, uint* len,
 | 
						|
                          my_bool __attribute__((unused)) t)
 | 
						|
{
 | 
						|
  const User *user= (const User *) u;
 | 
						|
  *len= user->user_length;
 | 
						|
  return (byte *) user->user;
 | 
						|
}
 | 
						|
 | 
						|
static void delete_user(void *u)
 | 
						|
{
 | 
						|
  User *user= (User *) u;
 | 
						|
  delete user;
 | 
						|
}
 | 
						|
 | 
						|
C_MODE_END
 | 
						|
 | 
						|
 | 
						|
int User_map::init()
 | 
						|
{
 | 
						|
  enum { START_HASH_SIZE = 16 };
 | 
						|
  if (hash_init(&hash, default_charset_info, START_HASH_SIZE, 0, 0,
 | 
						|
      get_user_key, delete_user, 0))
 | 
						|
    return 1;
 | 
						|
  return 0;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
User_map::~User_map()
 | 
						|
{
 | 
						|
  hash_free(&hash);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*
 | 
						|
  Load all users from the password file. Must be called once right after
 | 
						|
  construction.
 | 
						|
  In case of failure, puts error message to the log file and returns 1
 | 
						|
*/
 | 
						|
 | 
						|
int User_map::load(const char *password_file_name)
 | 
						|
{
 | 
						|
  FILE *file;
 | 
						|
  char line[USERNAME_LENGTH + SCRAMBLED_PASSWORD_CHAR_LENGTH +
 | 
						|
            2 +                               /* for possible quotes */
 | 
						|
            1 +                               /* for ':' */
 | 
						|
            1 +                               /* for newline */
 | 
						|
            1];                               /* for trailing zero */
 | 
						|
  User *user;
 | 
						|
  int rc= 1;
 | 
						|
 | 
						|
  if ((file= my_fopen(password_file_name, O_RDONLY | O_BINARY, MYF(0))) == 0)
 | 
						|
  {
 | 
						|
    /* Probably the password file wasn't specified. Try to leave without it */
 | 
						|
    log_info("[WARNING] can't open password file %s: errno=%d, %s", password_file_name,
 | 
						|
              errno, strerror(errno));
 | 
						|
    return 0;
 | 
						|
  }
 | 
						|
 | 
						|
  while (fgets(line, sizeof(line), file))
 | 
						|
  {
 | 
						|
    /* skip comments and empty lines */
 | 
						|
    if (line[0] == '#' || line[0] == '\n' &&
 | 
						|
        (line[1] == '\0' || line[1] == '\r'))
 | 
						|
      continue;
 | 
						|
    if ((user= new User) == 0)
 | 
						|
      goto done;
 | 
						|
    if (user->init(line) || my_hash_insert(&hash, (byte *) user))
 | 
						|
      goto err_init_user;
 | 
						|
  }
 | 
						|
  if (feof(file))
 | 
						|
    rc= 0;
 | 
						|
  goto done;
 | 
						|
err_init_user:
 | 
						|
  delete user;
 | 
						|
done:
 | 
						|
  my_fclose(file, MYF(0));
 | 
						|
  return rc;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*
 | 
						|
    Check if user exists and password is correct
 | 
						|
  RETURN VALUE
 | 
						|
    0 - user found and password OK
 | 
						|
    1 - password mismatch
 | 
						|
    2 - user not found
 | 
						|
*/
 | 
						|
 | 
						|
int User_map::authenticate(const char *user_name, uint length,
 | 
						|
                           const char *scrambled_password,
 | 
						|
                           const char *scramble) const
 | 
						|
{
 | 
						|
  const User *user= (const User *) hash_search((HASH *) &hash,
 | 
						|
                                               (byte *) user_name, length);
 | 
						|
  if (user)
 | 
						|
    return check_scramble(scrambled_password, scramble, user->salt);
 | 
						|
  return 2;
 | 
						|
}
 |