コード例 #1
0
ファイル: connections.c プロジェクト: Absike/mongo-php-driver
/**
 * Authenticates a connection
 *
 * Returns 1 when it worked, or 0 when it didn't - with the error_message set.
 */
int mongo_connection_authenticate(mongo_con_manager *manager, mongo_connection *con, char *database, char *username, char *password, char *nonce, char **error_message)
{
	mcon_str      *packet;
	char          *data_buffer, *errmsg;
	double         ok;
	char          *ptr;
	char          *salted;
	int            length;
	char          *hash, *key;

	mongo_manager_log(manager, MLOG_CON, MLOG_INFO, "authenticate: start");

	/* Calculate hash=md5(${username}:mongo:${password}) */
	length = strlen(username) + 7 + strlen(password) + 1;
	salted = malloc(length);
	snprintf(salted, length, "%s:mongo:%s", username, password);
	hash = mongo_util_md5_hex(salted, length - 1); /* -1 to chop off \0 */
	free(salted);
	mongo_manager_log(manager, MLOG_CON, MLOG_FINE, "authenticate: hash=md5(%s:mongo:%s) = %s", username, password, hash);

	/* Calculate key=md5(${nonce}${username}${hash}) */
	length = strlen(nonce) + strlen(username) + strlen(hash) + 1;
	salted = malloc(length);
	snprintf(salted, length, "%s%s%s", nonce, username, hash);
	key = mongo_util_md5_hex(salted, length - 1); /* -1 to chop off \0 */
	free(salted);
	mongo_manager_log(manager, MLOG_CON, MLOG_FINE, "authenticate: key=md5(%s%s%s) = %s", nonce, username, hash, key);

	packet = bson_create_authenticate_packet(con, database, username, nonce, key);

	free(hash);
	free(key);

	if (!mongo_connect_send_packet(manager, con, packet, &data_buffer, error_message)) {
		free(data_buffer);
		return 0;
	}

	/* Find data fields */
	ptr = data_buffer + sizeof(int32_t); /* Skip the length */

	/* Find errmsg */
	if (bson_find_field_as_double(ptr, "ok", &ok)) {
		if (ok > 0) {
			mongo_manager_log(manager, MLOG_CON, MLOG_INFO, "authentication successful");
		} else {
			mongo_manager_log(manager, MLOG_CON, MLOG_WARN, "authentication failed");
		}
	}
	if (bson_find_field_as_string(ptr, "errmsg", &errmsg)) {
		*error_message = malloc(256);
		snprintf(*error_message, 256, "Authentication failed on database '%s' with username '%s': %s", database, username, errmsg);
		free(data_buffer);
		return 0;
	}

	free(data_buffer);

	return 1;
}
コード例 #2
0
/**
 * Sends the db.authenticate() command packet
 *
 * Returns:
 * 0: when it didn't work - with the error_message set (extracted from the 'errmsg' field if possible)
 * 1: when it worked
 */
int mongo_connection_authenticate_cmd(mongo_con_manager *manager, mongo_connection *con, mongo_server_options *options, char *database, char *username, mcon_str *packet, char **error_message)
{
	char          *data_buffer, *errmsg;
	double         ok;
	char          *ptr;

	if (!mongo_connect_send_packet(manager, con, options, packet, &data_buffer, error_message)) {
		return 0;
	}

	/* Find data fields */
	ptr = data_buffer + sizeof(int32_t); /* Skip the length */

	/* Find errmsg */
	if (bson_find_field_as_double(ptr, "ok", &ok)) {
		if (ok > 0) {
			mongo_manager_log(manager, MLOG_CON, MLOG_INFO, "authentication successful");
		} else {
			mongo_manager_log(manager, MLOG_CON, MLOG_WARN, "authentication failed");
		}
	}
	if (bson_find_field_as_string(ptr, "errmsg", &errmsg)) {
		*error_message = malloc(256);
		snprintf(*error_message, 256, "Authentication failed on database '%s' with username '%s': %s", database, username, errmsg);
		free(data_buffer);
		return 0;
	}

	free(data_buffer);

	return 1;
}
コード例 #3
0
int mongo_connection_authenticate_saslcontinue(mongo_con_manager *manager, mongo_connection *con, mongo_server_options *options, mongo_server_def *server_def, int32_t conversation_id, char *payload, int payload_len, char **out_payload, int *out_payload_len, unsigned char *done, char **error_message)
{
	mcon_str      *packet;
	char          *data_buffer;
	char          *ptr;
	double         ok;
	char          *errmsg;
	int32_t       out_conversation_id;

	mongo_manager_log(manager, MLOG_CON, MLOG_INFO, "connection_authenticate_saslcontinue: continuing SASL authentication to '%s'", con->hash);

	packet = bson_create_saslcontinue_packet(con, conversation_id, payload, payload_len);

	if (!mongo_connect_send_packet(manager, con, options, packet, &data_buffer, error_message)) {
		return 0;
	}

	/* Find data fields */
	ptr = data_buffer + sizeof(int32_t); /* Skip the length */

	if (bson_find_field_as_double(ptr, "ok", &ok)) {
		if (ok > 0) {
			mongo_manager_log(manager, MLOG_CON, MLOG_INFO, "SASL continue successful");
		} else {
			mongo_manager_log(manager, MLOG_CON, MLOG_WARN, "SASL continue failed");
			if (bson_find_field_as_string(ptr, "errmsg", &errmsg)) {
				int errlen = strlen("SASL Authentication failed on database '': ") + strlen(server_def->db) + strlen(errmsg);
				*error_message = malloc(errlen);
				snprintf(*error_message, errlen, "SASL Authentication failed on database '%s': %s", server_def->db, errmsg);
			} else {
				int errlen = strlen("SASL Authentication failed on database ''") + strlen(server_def->db);
				*error_message = malloc(errlen);
				snprintf(*error_message, errlen, "SASL Authentication failed on database '%s'", server_def->db);
			}

			free(data_buffer);
			return 0;
		}
	}

	if (bson_find_field_as_int32(ptr, "conversationId", &out_conversation_id)) {
		if (out_conversation_id != conversation_id) {
			mongo_manager_log(manager, MLOG_CON, MLOG_WARN, "SASL continue failed: Got wrong conversation_id back! Expected %d but got %d", conversation_id, out_conversation_id);
			free(data_buffer);
			return 0;
		}
		bson_find_field_as_stringl(ptr, "payload", out_payload, out_payload_len, 1);
		bson_find_field_as_bool(ptr, "done", done);
	}
	free(data_buffer);

	return (int)ok;
}
コード例 #4
0
int mongo_connection_authenticate_saslstart(mongo_con_manager *manager, mongo_connection *con, mongo_server_options *options, mongo_server_def *server_def, char *mechanism, char *payload, unsigned int payload_len, char **out_payload, int *out_payload_len, int32_t *out_conversation_id, char **error_message)
{
	mcon_str      *packet;
	char          *data_buffer;
	char          *ptr;
	char          *smechanism;
	double         ok;
	char          *errmsg;

	mongo_manager_log(manager, MLOG_CON, MLOG_INFO, "connection_authenticate_sasl: Starting SASL authentication process to '%s'", con->hash);

	if (server_def->mechanism == MONGO_AUTH_MECHANISM_MONGODB_CR) {
		*error_message = strdup("Invalid authentication mechanism. Expected SASL mechanism, got MongoDB-CR");
		return 0;
	}

	packet = bson_create_saslstart_packet(con, server_def->authdb ? server_def->authdb : server_def->db, mechanism, payload, payload_len);

	if (!mongo_connect_send_packet(manager, con, options, packet, &data_buffer, error_message)) {
		return 0;
	}

	/* Find data fields */
	ptr = data_buffer + sizeof(int32_t); /* Skip the length */

	if (bson_find_field_as_double(ptr, "ok", &ok)) {
		if (ok > 0) {
			mongo_manager_log(manager, MLOG_CON, MLOG_INFO, "SASL request successful");
		} else {
			mongo_manager_log(manager, MLOG_CON, MLOG_WARN, "SASL request failed");
			if (bson_find_field_as_string(ptr, "errmsg", &errmsg)) {
				*error_message = malloc(256);
				snprintf(*error_message, 256, "SASL Authentication failed on database '%s': %s", server_def->db, errmsg);
			} else {
				*error_message = "SASL Authentication failed";
			}
			if (bson_find_field_as_document(ptr, "supportedMechanisms", (char**) &smechanism)) {
				/* TODO: Retrieve a list of supportedMechanisms and return it somehow */
			}

			free(data_buffer);
			return 0;
		}
	}

	if (bson_find_field_as_int32(ptr, "conversationId", out_conversation_id)) {
		bson_find_field_as_stringl(ptr, "payload", out_payload, out_payload_len, 1);
	}
	free(data_buffer);

	return 1;
}