コード例 #1
0
ファイル: mysql_common.c プロジェクト: rasmushoj/MaxScale
/**
 * gw_check_mysql_scramble_data
 *
 * Check authentication token received against stage1_hash and scramble
 *
 * @param dcb The current dcb
 * @param token 	The token sent by the client in the authentication request
 * @param token_len 	The token size in bytes
 * @param scramble 	The scramble data sent by the server during handshake
 * @param scramble_len 	The scrable size in bytes
 * @param username	The current username in the authentication request
 * @param stage1_hash	The SHA1(candidate_password) decoded by this routine
 * @return 0 on succesful check or != 0 on failure
 *
 */
int gw_check_mysql_scramble_data(DCB *dcb, uint8_t *token, unsigned int token_len, uint8_t *scramble, unsigned int scramble_len, char *username, uint8_t *stage1_hash) {
	uint8_t step1[GW_MYSQL_SCRAMBLE_SIZE]="";
	uint8_t step2[GW_MYSQL_SCRAMBLE_SIZE +1]="";
	uint8_t check_hash[GW_MYSQL_SCRAMBLE_SIZE]="";
	char hex_double_sha1[2 * GW_MYSQL_SCRAMBLE_SIZE + 1]="";
	uint8_t password[GW_MYSQL_SCRAMBLE_SIZE]="";
	int ret_val = 1;

	if ((username == NULL) || (scramble == NULL) || (stage1_hash == NULL)) {
		return 1;
	}

	/*<
	 * get the user's password from repository in SHA1(SHA1(real_password));
	 * please note 'real_password' is unknown!
	 */

	ret_val = gw_find_mysql_user_password_sha1(username, password, dcb);

	if (ret_val) {
		return 1;
	}

	if (token && token_len) {
		/*<
		 * convert in hex format: this is the content of mysql.user table.
		 * The field password is without the '*' prefix and it is 40 bytes long
		 */

		gw_bin2hex(hex_double_sha1, password, SHA_DIGEST_LENGTH);
	} else {
		/* check if the password is not set in the user table */
		if (!strlen((char *)password)) {
			/* Username without password */
			return 0;
		} else {
			return 1;
		}
	}

	/*<
	 * Auth check in 3 steps
	 *
	 * Note: token = XOR (SHA1(real_password), SHA1(CONCAT(scramble, SHA1(SHA1(real_password)))))
	 * the client sends token
	 *
	 * Now, server side:
	 *
	 *
	 * step 1: compute the STEP1 = SHA1(CONCAT(scramble, gateway_password))
	 * the result in step1 is SHA_DIGEST_LENGTH long
	 */

	gw_sha1_2_str(scramble, scramble_len, password, SHA_DIGEST_LENGTH, step1);

	/*<
	 * step2: STEP2 = XOR(token, STEP1)
	 *
	 * token is trasmitted form client and it's based on the handshake scramble and SHA1(real_passowrd)
	 * step1 has been computed in the previous step
	 * the result STEP2 is SHA1(the_password_to_check) and is SHA_DIGEST_LENGTH long
	 */

	gw_str_xor(step2, token, step1, token_len);

	/*<
	 * copy the stage1_hash back to the caller
	 * stage1_hash will be used for backend authentication
	 */
	
	memcpy(stage1_hash, step2, SHA_DIGEST_LENGTH);

	/*<
	 * step 3: prepare the check_hash
	 *	
	 * compute the SHA1(STEP2) that is SHA1(SHA1(the_password_to_check)), and is SHA_DIGEST_LENGTH long
	 */
	
	gw_sha1_str(step2, SHA_DIGEST_LENGTH, check_hash);


#ifdef GW_DEBUG_CLIENT_AUTH
	{
		char inpass[128]="";
		gw_bin2hex(inpass, check_hash, SHA_DIGEST_LENGTH);
		
		fprintf(stderr, "The CLIENT hex(SHA1(SHA1(password))) for \"%s\" is [%s]", username, inpass);
	}
#endif

	/* now compare SHA1(SHA1(gateway_password)) and check_hash: return 0 is MYSQL_AUTH_OK */
	return memcmp(password, check_hash, SHA_DIGEST_LENGTH);
}
コード例 #2
0
ファイル: test_mysql_users.c プロジェクト: AAAAAK/MaxScale
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;
}