Beispiel #1
0
/**
 * Load the admin users
 *
 * @return Table of users
 */
static USERS *
loadUsers()
{
    USERS *rval;
    FILE  *fp;
    char  fname[1024], *home;
    char  uname[80], passwd[80];

    initialise();
    snprintf(fname,1023, "%s/passwd", get_datadir());
    fname[1023] = '\0';
    if ((fp = fopen(fname, "r")) == NULL)
    {
        return NULL;
    }
    if ((rval = users_alloc()) == NULL)
    {
        fclose(fp);
        return NULL;
    }
    while (fscanf(fp, "%[^:]:%s\n", uname, passwd) == 2)
    {
        users_add(rval, uname, passwd);
    }
    fclose(fp);

    return rval;
}
Beispiel #2
0
/**
 * Allocate a new service for the gateway to support
 *
 *
 * @param servname	The service name
 * @param router	Name of the router module this service uses
 *
 * @return		The newly created service or NULL if an error occured
 */
SERVICE *
service_alloc(char *servname, char *router)
{
SERVICE 	*service;

	if ((service = (SERVICE *)malloc(sizeof(SERVICE))) == NULL)
		return NULL;
	if ((service->router = load_module(router, MODULE_ROUTER)) == NULL)
	{
		free(service);
		return NULL;
	}
	service->name = strdup(servname);
	service->routerModule = strdup(router);
	memset(&service->stats, 0, sizeof(SERVICE_STATS));
	service->ports = NULL;
	service->stats.started = time(0);
	service->state = SERVICE_STATE_ALLOC;
	service->credentials.name = NULL;
	service->credentials.authdata = NULL;
	service->users = users_alloc();
	service->enable_root = 0;
	service->routerOptions = NULL;
	service->databases = NULL;
	spinlock_init(&service->spin);

	spinlock_acquire(&service_spin);
	service->next = allServices;
	allServices = service;
	spinlock_release(&service_spin);

	return service;
}
Beispiel #3
0
/**
 * Add user
 *
 * @param uname         Name of the new user
 * @param passwd        Password for the new user
 * @return      NULL on success or an error string on failure
 */
char *
admin_add_user(char *uname, char *passwd)
{
    FILE *fp;
    char fname[1024], *home, *cpasswd;

    initialise();

    if (access(get_datadir(), F_OK) != 0)
    {
        if (mkdir(get_datadir(), S_IRWXU) != 0 && errno != EEXIST)
        {
            return ADMIN_ERR_PWDFILEOPEN;
        }
    }

    snprintf(fname,1023, "%s/passwd", get_datadir());
    fname[1023] = '\0';
    if (users == NULL)
    {
        MXS_NOTICE("Create initial password file.");

        if ((users = users_alloc()) == NULL)
        {
            return ADMIN_ERR_NOMEM;
        }
        if ((fp = fopen(fname, "w")) == NULL)
        {
            MXS_ERROR("Unable to create password file %s.", fname);
            return ADMIN_ERR_PWDFILEOPEN;
        }
        fclose(fp);
    }
    if (users_fetch(users, uname) != NULL)
    {
        return ADMIN_ERR_DUPLICATE;
    }
    struct crypt_data cdata;
    cdata.initialized = 0;
    cpasswd = crypt_r(passwd, ADMIN_SALT, &cdata);
    users_add(users, uname, cpasswd);
    if ((fp = fopen(fname, "a")) == NULL)
    {
        MXS_ERROR("Unable to append to password file %s.", fname);
        return ADMIN_ERR_FILEAPPEND;
    }
    fprintf(fp, "%s:%s\n", uname, cpasswd);
    fclose(fp);
    return ADMIN_SUCCESS;
}
Beispiel #4
0
/**
 * Add user
 *
 * @param uname		Name of the new user
 * @param passwd	Password for the new user
 * @return	NULL on success or an error string on failure
 */
char *
admin_add_user(char *uname, char *passwd)
{
FILE	*fp;
char	fname[1024], *home, *cpasswd;

	initialise();
    sprintf(fname, "%s/passwd", get_datadir());
        
	if (users == NULL)
	{
                LOGIF(LM,
                      (skygw_log_write(LOGFILE_MESSAGE,
                                       "Create initial password file.")));
                
		if ((users = users_alloc()) == NULL)
			return ADMIN_ERR_NOMEM;
		if ((fp = fopen(fname, "w")) == NULL)
		{
                    LOGIF(LE,
                          (skygw_log_write_flush(
                                  LOGFILE_ERROR,
                                  "Error : Unable to create password file %s.",
                                  fname)));
                    return ADMIN_ERR_PWDFILEOPEN;
		}
		fclose(fp);
	}
	if (users_fetch(users, uname) != NULL)
	{
		return ADMIN_ERR_DUPLICATE;
	}
	cpasswd = crypt(passwd, ADMIN_SALT);
	users_add(users, uname, cpasswd);
	if ((fp = fopen(fname, "a")) == NULL)
	{
            LOGIF(LE,
                  (skygw_log_write_flush(LOGFILE_ERROR,
                                         "Error : Unable to append to password file %s.",
                                         fname)));
            return ADMIN_ERR_FILEAPPEND;
	}
	fprintf(fp, "%s:%s\n", uname, cpasswd);
	fclose(fp);
	return ADMIN_SUCCESS;
}
Beispiel #5
0
/**
 * Start an individual port/protocol pair
 *
 * @param service	The service
 * @param port		The port to start
 * @return		The number of listeners started
 */
static int
serviceStartPort(SERVICE *service, SERV_PROTOCOL *port)
{
int		listeners = 0;
char		config_bind[40];
GWPROTOCOL	*funcs;

        port->listener = dcb_alloc(DCB_ROLE_SERVICE_LISTENER);

        if (port->listener == NULL)
	{
		return 0;
	}
	if (strcmp(port->protocol, "MySQLClient") == 0) {
		int loaded;
		/* Allocate specific data for MySQL users */
		service->users = mysql_users_alloc();
		loaded = load_mysql_users(service);
		/* At service start last update is set to USERS_REFRESH_TIME seconds earlier.
 		 * This way MaxScale could try reloading users' just after startup
 		 */

		service->rate_limit.last=time(NULL) - USERS_REFRESH_TIME;
		service->rate_limit.nloads=1;

		LOGIF(LM, (skygw_log_write(
                        LOGFILE_MESSAGE,
                        "Loaded %d MySQL Users.",
                        loaded)));
	} else {
		/* Generic users table */
		service->users = users_alloc();
	}

	if ((funcs =
             (GWPROTOCOL *)load_module(port->protocol, MODULE_PROTOCOL)) == NULL)
	{
		dcb_free(port->listener);
		port->listener = NULL;
		LOGIF(LE, (skygw_log_write_flush(
                        LOGFILE_ERROR,
			"Error : Unable to load protocol module %s. Listener "
                        "for service %s not started.",
			port->protocol,
                        service->name)));
		return 0;
	}
	memcpy(&(port->listener->func), funcs, sizeof(GWPROTOCOL));
	port->listener->session = NULL;
	if (port->address)
		sprintf(config_bind, "%s:%d", port->address, port->port);
	else
		sprintf(config_bind, "0.0.0.0:%d", port->port);

	if (port->listener->func.listen(port->listener, config_bind)) {
                port->listener->session = session_alloc(service, port->listener);

                if (port->listener->session != NULL) {
                        port->listener->session->state = SESSION_STATE_LISTENER;
                        listeners += 1;
                } else {
                        dcb_close(port->listener);
                }
        } else {
                dcb_close(port->listener);
                
                LOGIF(LE, (skygw_log_write_flush(
                        LOGFILE_ERROR,
			"Error : Unable to start to listen port %d for %s %s.",
			port->port,
                        port->protocol,
                        service->name)));
        }
	return listeners;
}
Beispiel #6
0
/**
 * Start an individual port/protocol pair
 *
 * @param service	The service
 * @param port		The port to start
 * @return		The number of listeners started
 */
static int
serviceStartPort(SERVICE *service, SERV_PROTOCOL *port)
{
int		listeners = 0;
char		config_bind[40];
GWPROTOCOL	*funcs;

        port->listener = dcb_alloc(DCB_ROLE_SERVICE_LISTENER);

        if (port->listener == NULL)
	{
		LOGIF(LE, (skygw_log_write_flush(
			LOGFILE_ERROR,
			"Error : Failed to create listener for service %s.",
			service->name)));
		goto retblock;
	}
	
	if (strcmp(port->protocol, "MySQLClient") == 0) {
		int loaded;

		if (service->users == NULL) {
			/*
			 * Allocate specific data for MySQL users
			 * including hosts and db names
			 */
			service->users = mysql_users_alloc();
	
			if ((loaded = load_mysql_users(service)) < 0)
			{
				LOGIF(LE, (skygw_log_write_flush(
					LOGFILE_ERROR,
					"Error : Unable to load users from %s:%d for "
					"service %s.",
					(port->address == NULL ? "0.0.0.0" : port->address),
					port->port,
					service->name)));
				
				{
					/* Try loading authentication data from file cache */
					char	*ptr, path[4097];
					strcpy(path, "/usr/local/mariadb-maxscale");
					if ((ptr = getenv("MAXSCALE_HOME")) != NULL)
					{
						strncpy(path, ptr, 4096);
					}
					strncat(path, "/", 4096);
					strncat(path, service->name, 4096);
					strncat(path, "/.cache/dbusers", 4096);
					loaded = dbusers_load(service->users, path);
					if (loaded != -1)
					{
						LOGIF(LE, (skygw_log_write_flush(
							LOGFILE_ERROR,
							"Using cached credential information.")));
					}
				}
				if (loaded == -1)
				{
					hashtable_free(service->users->data);
					free(service->users);
					dcb_free(port->listener);
					port->listener = NULL;
					goto retblock;
				}
			}
			else
			{
				/* Save authentication data to file cache */
				char	*ptr, path[4097];
                                int mkdir_rval = 0;
				strcpy(path, "/usr/local/mariadb-maxscale");
				if ((ptr = getenv("MAXSCALE_HOME")) != NULL)
				{
					strncpy(path, ptr, 4096);
				}
				strncat(path, "/", 4096);
				strncat(path, service->name, 4096);
				if (access(path, R_OK) == -1)
                                {
					mkdir_rval = mkdir(path, 0777);
                                }

                                if(mkdir_rval)
                                {
                                    skygw_log_write(LOGFILE_ERROR,"Error : Failed to create directory '%s': [%d] %s",
                                                    path,
                                                    errno,
                                                    strerror(errno));
                                    mkdir_rval = 0;
                                }

				strncat(path, "/.cache", 4096);
				if (access(path, R_OK) == -1)
                                {
					mkdir_rval = mkdir(path, 0777);
                                }

                                if(mkdir_rval)
                                {
                                    skygw_log_write(LOGFILE_ERROR,"Error : Failed to create directory '%s': [%d] %s",
                                                    path,
                                                    errno,
                                                    strerror(errno));
                                    mkdir_rval = 0;
                                }
				strncat(path, "/dbusers", 4096);
				dbusers_save(service->users, path);
			}
			if (loaded == 0)
			{
				LOGIF(LE, (skygw_log_write_flush(
					LOGFILE_ERROR,
					"Service %s: failed to load any user "
					"information. Authentication will "
					"probably fail as a result.",
					service->name)));
			}

			/* At service start last update is set to USERS_REFRESH_TIME seconds earlier.
 			 * This way MaxScale could try reloading users' just after startup
 			 */
			service->rate_limit.last=time(NULL) - USERS_REFRESH_TIME;
			service->rate_limit.nloads=1;

			LOGIF(LM, (skygw_log_write(
				LOGFILE_MESSAGE,
				"Loaded %d MySQL Users for service [%s].",
				loaded, service->name)));
		}
	} 
	else 
	{
		if (service->users == NULL) {
			/* Generic users table */
			service->users = users_alloc();
		}
	}

	if ((funcs=(GWPROTOCOL *)load_module(port->protocol, MODULE_PROTOCOL)) 
		== NULL)
	{
		if (service->users->data)
		{
			hashtable_free(service->users->data);
		}
		free(service->users);
		dcb_free(port->listener);
		port->listener = NULL;
		LOGIF(LE, (skygw_log_write_flush(
                        LOGFILE_ERROR,
			"Error : Unable to load protocol module %s. Listener "
                        "for service %s not started.",
			port->protocol,
                        service->name)));
		goto retblock;
	}
	memcpy(&(port->listener->func), funcs, sizeof(GWPROTOCOL));
	port->listener->session = NULL;
	
	if (port->address)
		sprintf(config_bind, "%s:%d", port->address, port->port);
	else
		sprintf(config_bind, "0.0.0.0:%d", port->port);

	if (port->listener->func.listen(port->listener, config_bind)) 
	{
                port->listener->session = session_alloc(service, port->listener);

                if (port->listener->session != NULL) 
		{
                        port->listener->session->state = SESSION_STATE_LISTENER;
                        listeners += 1;
                } 
                else 
		{
			LOGIF(LE, (skygw_log_write_flush(
				LOGFILE_ERROR,
				"Error : Failed to create session to service %s.",
				service->name)));
			
			if (service->users->data)
			{
				hashtable_free(service->users->data);
			}
			free(service->users);
                        dcb_close(port->listener);
			port->listener = NULL;
			goto retblock;
                }
        } 
        else 
	{       
                LOGIF(LE, (skygw_log_write_flush(
                        LOGFILE_ERROR,
			"Error : Unable to start to listen port %d for %s %s.",
			port->port,
                        port->protocol,
                        service->name)));
		if (service->users->data)
		{
			hashtable_free(service->users->data);
		}
		free(service->users);
		dcb_close(port->listener);
		port->listener = NULL;
        }
        
retblock:
	return listeners;
}