Пример #1
0
int set_and_get_single_mysql_users(char *username, char *hostname, char *password) {
        struct sockaddr_in serv_addr;
        MYSQL_USER_HOST key;
	USERS *mysql_users;
	char ret_ip[200]="";
	char *fetch_data;
	char *db="";
	
	mysql_users = mysql_users_alloc();

        /* prepare the user@host data struct */
	memset(&serv_addr, 0, sizeof(serv_addr));
	memset(&key, 0, sizeof(key));

	
	if (hostname)	
		if(!setipaddress(&serv_addr.sin_addr, hostname)) {
			fprintf(stderr, "setipaddress failed for host [%s]\n", hostname);
			users_free(mysql_users);
			return 1;
		}
	if (username)
		key.user = username;

	memcpy(&key.ipv4, &serv_addr, sizeof(serv_addr));
	key.resource = db;

	inet_ntop(AF_INET, &(serv_addr).sin_addr, ret_ip, INET_ADDRSTRLEN);

	fprintf(stderr, "set/get [%s@%s]: IPV4 %lu is [%u].[%u].[%u].[%u]\n", username, hostname, (unsigned long) serv_addr.sin_addr.s_addr, serv_addr.sin_addr.s_addr&0xFF, (serv_addr.sin_addr.s_addr&0xFF00), (serv_addr.sin_addr.s_addr&0xFF0000), ((serv_addr.sin_addr.s_addr & 0xFF000000) / (256*256*256)));

	/* add user@host as key and passwd as value in the MySQL users hash table */
	if (!mysql_users_add(mysql_users, &key, password)) {
		fprintf(stderr, "mysql_users_add() failed for %s@%s\n", username, hostname);
		users_free(mysql_users);
		return 1;
	}

	memset(&serv_addr, 0, sizeof(serv_addr));

	if (hostname)
		if(!setipaddress(&serv_addr.sin_addr, hostname)) {
			fprintf(stderr, "setipaddress failed for host [%s]\n", hostname);
			users_free(mysql_users);
			return 1;
		}
	key.user = username;
	memcpy(&key.ipv4, &serv_addr, sizeof(serv_addr));
	key.resource = db;

	fetch_data = mysql_users_fetch(mysql_users, &key);

	users_free(mysql_users);

	if (!fetch_data)
		return 1;
	
	return 0;
}
/**
 * Connect to the MaxScale server
 *
 * @param hostname	The hostname to connect to
 * @param port		The port to use for the connection
 * @return		The connected socket or -1 on error
 */
int
connectMaxScale(char *hostname, char *port)
{
struct sockaddr_in	addr;
int			so;
int			keepalive = 1;

	if ((so = socket(AF_INET, SOCK_STREAM, 0)) < 0)
	{
		fprintf(stderr, "Unable to create socket: %s\n",
				strerror(errno));
		return -1;
	}
	memset(&addr, 0, sizeof addr);
	addr.sin_family = AF_INET;
	setipaddress(&addr.sin_addr, hostname);
	addr.sin_port = htons(atoi(port));
	if (connect(so, (struct sockaddr *)&addr, sizeof(addr)) < 0)
	{
		fprintf(stderr, "Unable to connect to MaxScale at %s, %s: %s\n",
				hostname, port, strerror(errno));
        close(so);
		return -1;
	}
	if (setsockopt(so, SOL_SOCKET,
			SO_KEEPALIVE, &keepalive , sizeof(keepalive )))
		perror("setsockopt");

	return so;
}
Пример #3
0
/**
 * Load the user/passwd form mysql.user table into the service users' hashtable
 * environment.
 *
 * @param service	The current service
 * @param users		The users table into which to load the users
 * @return      -1 on any error or the number of users inserted (0 means no users at all)
 */
static int
getUsers(SERVICE *service, struct users *users)
{
	MYSQL			*con = NULL;
	MYSQL_ROW		row;
	MYSQL_RES		*result = NULL;
	int			num_fields = 0;
	char			*service_user = NULL;
	char			*service_passwd = NULL;
	char			*dpwd;
	int			total_users = 0;
	SERVER			*server;
	char			*users_query;
	unsigned char		hash[SHA_DIGEST_LENGTH]="";
	char			*users_data = NULL;
	int 			nusers = 0;
	int			users_data_row_len = MYSQL_USER_MAXLEN + MYSQL_HOST_MAXLEN + MYSQL_PASSWORD_LEN;
	struct sockaddr_in	serv_addr;
	MYSQL_USER_HOST		key;

	/* enable_root for MySQL protocol module means load the root user credentials from backend databases */
	if(service->enable_root) {
		users_query = LOAD_MYSQL_USERS_QUERY " ORDER BY HOST DESC";
	} else {
		users_query = LOAD_MYSQL_USERS_QUERY USERS_QUERY_NO_ROOT " ORDER BY HOST DESC";
	}

	serviceGetUser(service, &service_user, &service_passwd);

	/** multi-thread environment requires that thread init succeeds. */
	if (mysql_thread_init()) {
		LOGIF(LE, (skygw_log_write_flush(
                        LOGFILE_ERROR,
                        "Error : mysql_thread_init failed.")));
		return -1;
	}
    
	con = mysql_init(NULL);

 	if (con == NULL) {
		LOGIF(LE, (skygw_log_write_flush(
                        LOGFILE_ERROR,
                        "Error : mysql_init: %s",
                        mysql_error(con))));
		return -1;
	}

	if (mysql_options(con, MYSQL_OPT_USE_REMOTE_CONNECTION, NULL)) {
		LOGIF(LE, (skygw_log_write_flush(
                        LOGFILE_ERROR,
                        "Error : failed to set external connection. "
                        "It is needed for backend server connections. "
                        "Exiting.")));
		return -1;
	}
	/*
	 * Attempt to connect to each database in the service in turn until
	 * we find one that we can connect to or until we run out of databases
	 * to try
	 */
	server = service->databases;
	dpwd = decryptPassword(service_passwd);
	while (server != NULL && mysql_real_connect(con,
                                                    server->name,
                                                    service_user,
                                                    dpwd,
                                                    NULL,
                                                    server->port,
                                                    NULL,
                                                    0) == NULL)
	{
                server = server->nextdb;
	}
	free(dpwd);

	if (server == NULL)
	{
		LOGIF(LE, (skygw_log_write_flush(
                        LOGFILE_ERROR,
                        "Error : Unable to get user data from backend database "
                        "for service %s. Missing server information.",
                        service->name)));
		mysql_close(con);
		return -1;
	}

	if (mysql_query(con, MYSQL_USERS_COUNT)) {
		LOGIF(LE, (skygw_log_write_flush(
                        LOGFILE_ERROR,
                        "Error : Loading users for service %s encountered "
                        "error: %s.",
                        service->name,
                        mysql_error(con))));
		mysql_close(con);
		return -1;
	}
	result = mysql_store_result(con);

	if (result == NULL) {
		LOGIF(LE, (skygw_log_write_flush(
                        LOGFILE_ERROR,
                        "Error : Loading users for service %s encountered "
                        "error: %s.",
                        service->name,
                        mysql_error(con))));
		mysql_close(con);
		return -1;
	}
	num_fields = mysql_num_fields(result);
	row = mysql_fetch_row(result);

	nusers = atoi(row[0]);

	mysql_free_result(result);

	if (!nusers) {
		LOGIF(LE, (skygw_log_write_flush(
                        LOGFILE_ERROR,
                        "Error : Counting users for service %s returned 0",
                        service->name)));
		mysql_close(con);
		return -1;
	}

	if (mysql_query(con, users_query)) {
		LOGIF(LE, (skygw_log_write_flush(
                        LOGFILE_ERROR,
                        "Error : Loading users for service %s encountered "
                        "error: %s.",
                        service->name,
                        mysql_error(con))));
		mysql_close(con);
		return -1;
	}

	result = mysql_store_result(con);
  
	if (result == NULL) {
		LOGIF(LE, (skygw_log_write_flush(
                        LOGFILE_ERROR,
                        "Error : Loading users for service %s encountered "
                        "error: %s.",
                        service->name,
                        mysql_error(con))));
		mysql_close(con);
		return -1;
	}
	num_fields = mysql_num_fields(result);
	
	users_data = (char *)malloc(nusers * (users_data_row_len * sizeof(char)) + 1);

	if(users_data == NULL)
		return -1;

	while ((row = mysql_fetch_row(result))) { 
		/**
                 * Four fields should be returned.
                 * user and passwd+1 (escaping the first byte that is '*') are
                 * added to hashtable.
                 */
		
		char ret_ip[INET_ADDRSTRLEN + 1]="";
		const char *rc;

		/* prepare the user@host data struct */
		memset(&serv_addr, 0, sizeof(serv_addr));
		memset(&key, 0, sizeof(key));

		/* if host == '%', 0 is passed */
		if (setipaddress(&serv_addr.sin_addr, strcmp(row[1], "%") ? row[1] : "0.0.0.0")) {

			key.user = strdup(row[0]);

			if(key.user == NULL) {
				LOGIF(LE, (skygw_log_write_flush(
					LOGFILE_ERROR,
					"%lu [getUsers()] strdup() failed for user %s",
					pthread_self(),
					row[0])));

				continue;
			}

			memcpy(&key.ipv4, &serv_addr, sizeof(serv_addr));
			
			rc = inet_ntop(AF_INET, &(serv_addr).sin_addr, ret_ip, INET_ADDRSTRLEN);

			/* add user@host as key and passwd as value in the MySQL users hash table */
			if (mysql_users_add(users, &key, strlen(row[2]) ? row[2]+1 : row[2])) {
				LOGIF(LD, (skygw_log_write_flush(
					LOGFILE_DEBUG,
					"%lu [mysql_users_add()] Added user %s@%s(%s)",
					pthread_self(),
					row[0],
					row[1],
					rc == NULL ? "NULL" : ret_ip)));
		
				/* Append data in the memory area for SHA1 digest */	
				strncat(users_data, row[3], users_data_row_len);

				total_users++;
			} else {
				LOGIF(LE, (skygw_log_write_flush(
					LOGFILE_ERROR,
					"%lu [mysql_users_add()] Failed adding user %s@%s(%s)",
					pthread_self(),
					row[0],
					row[1],
					rc == NULL ? "NULL" : ret_ip)));

				continue;
			}

		} else {
			/* setipaddress() failed, skip user add and log this*/
			LOGIF(LE, (skygw_log_write_flush(
				LOGFILE_ERROR,
				"%lu [getUsers()] setipaddress failed: user %s@%s not added",
				pthread_self(),
				row[0],
				row[1])));
		}
	}

	/* compute SHA1 digest for users' data */
        SHA1((const unsigned char *) users_data, strlen(users_data), hash);

	memcpy(users->cksum, hash, SHA_DIGEST_LENGTH);

	free(users_data);

	mysql_free_result(result);
	mysql_close(con);
	mysql_thread_end();

	return total_users;
}
Пример #4
0
/**
 * gw_do_connect_to_backend
 *
 * This routine creates socket and connects to a backend server.
 * Connect it non-blocking operation. If connect fails, socket is closed.
 *
 * @param host The host to connect to
 * @param port The host TCP/IP port 
 * @param *fd where connected fd is copied
 * @return 0/1 on success and -1 on failure
 * If succesful, fd has file descriptor to socket which is connected to
 * backend server. In failure, fd == -1 and socket is closed.
 *
 */
int gw_do_connect_to_backend(
        char          *host,
        int           port,
        int*          fd)
{
	struct sockaddr_in serv_addr;
	int rv;
	int so = 0;
        
	memset(&serv_addr, 0, sizeof serv_addr);
	serv_addr.sin_family = AF_INET;
	so = socket(AF_INET,SOCK_STREAM,0);
        
	if (so < 0) {
                int eno = errno;
                errno = 0;
                LOGIF(LE, (skygw_log_write_flush(
                        LOGFILE_ERROR,
                        "Error: Establishing connection to backend server "
                        "%s:%d failed. Socket creation failed due "
                        "%d, %s.",
                        host,
                        port,
                        eno,
                        strerror(eno))));
                rv = -1;
                goto return_rv;
	}
	/* prepare for connect */
	setipaddress(&serv_addr.sin_addr, host);
	serv_addr.sin_port = htons(port);
	/* set socket to as non-blocking here */
	setnonblocking(so);
        rv = connect(so, (struct sockaddr *)&serv_addr, sizeof(serv_addr));

        if (rv != 0) {
                int eno = errno;
                errno = 0;
                
                if (eno == EINPROGRESS) {
                        rv = 1;
                } else {
                        int rc;
                        int oldfd = so;
                        
                        LOGIF(LE, (skygw_log_write_flush(
                                LOGFILE_ERROR,
                                "Error:  Failed to connect backend server %s:%d, "
                                "due %d, %s.",
                                host,
                                port,
                                eno,
                                strerror(eno))));
                        /*< Close newly created socket. */
                        rc = close(so);

                        if (rc != 0) {
                                int eno = errno;
                                errno = 0;
                                LOGIF(LE, (skygw_log_write_flush(
                                        LOGFILE_ERROR,
                                        "Error: Failed to "
                                        "close socket %d due %d, %s.",
                                        oldfd,
                                        eno,
                                        strerror(eno))));
                        }
                        goto return_rv;
                }
	}
        *fd = so;
        LOGIF(LD, (skygw_log_write_flush(
                LOGFILE_DEBUG,
                "%lu [gw_do_connect_to_backend] Connected to backend server "
                "%s:%d, fd %d.",
                pthread_self(),
                host,
                port,
                so)));
#if defined(SS_DEBUG)
        conn_open[so] = true;
#endif
return_rv:
	return rv;
}
Пример #5
0
int set_and_get_mysql_users_wildcards(char *username, char *hostname, char *password, char *from, char *anydb, char *db, char *db_from) {
	USERS *mysql_users;
	int ret = -1;
	struct sockaddr_in client_addr;
	DCB	*dcb;
	SERVICE *service;
	MYSQL_session *data;

	dcb = dcb_alloc(DCB_ROLE_INTERNAL);

	if (dcb == NULL) {
		fprintf(stderr, "dcb_alloc() failed\n");
		return ret;
	}
        if ((service = (SERVICE *)calloc(1, sizeof(SERVICE))) == NULL) {
		fprintf(stderr, "service_alloc() failed\n");
		dcb_free(dcb);
		return ret;
	}

        memset(&client_addr, 0, sizeof(client_addr));

        if (hostname) {
		if(!setipaddress(&client_addr.sin_addr, from)) {
			fprintf(stderr, "setipaddress failed for host [%s]\n", from);
			free(service);
			dcb_free(dcb);
			return ret;
		}
	}

	if ((data = (MYSQL_session *) calloc(1, sizeof(MYSQL_session))) == NULL) {
		fprintf(stderr, "MYSQL_session alloc failed\n");
		free(service);
		dcb_free(dcb);
		return ret;
	}

	
	/* client IPv4 in raw data*/
	memcpy(&dcb->ipv4, (struct sockaddr_in *)&client_addr, sizeof(struct sockaddr_in));

	dcb->service = service;

	mysql_users = mysql_users_alloc();

	service->users = mysql_users;

	if (db_from != NULL)
		strncpy(data->db, db_from,MYSQL_DATABASE_MAXLEN);
	else
		strncpy(data->db, "",MYSQL_DATABASE_MAXLEN);

	/* freed by dcb_free(dcb) */
	dcb->data = data;

	// the routine returns 1 on success
	if (anydb != NULL) {
		if (strcmp(anydb, "N") == 0) {
			ret = add_mysql_users_with_host_ipv4(mysql_users, username, hostname, password, anydb, db);
		} else if (strcmp(anydb, "Y") == 0) {
			ret = add_mysql_users_with_host_ipv4(mysql_users, username, hostname, password, "Y", "");
		} else {
			ret = add_mysql_users_with_host_ipv4(mysql_users, username, hostname, password, "N", NULL);
		}
	} else {
		ret = add_mysql_users_with_host_ipv4(mysql_users, username, hostname, password, "N", NULL);
	}
	
	if (ret == 0) {
		fprintf(stderr, "add_mysql_users_with_host_ipv4 (%s@%s, %s) FAILED\n", username, hostname, password);
	} else {
		unsigned char db_passwd[100]="";

		dcb->remote=strdup(from);

		// returns 0 on success
		ret = gw_find_mysql_user_password_sha1(username, db_passwd, dcb);
	}

	users_free(mysql_users);
	free(service);
	dcb_free(dcb);

	return ret;
}