static mcon_collection *mongo_filter_candidates_by_credentials(mongo_con_manager *manager, mcon_collection *candidates, mongo_servers *servers) { int i; char *db, *username, *auth_hash, *hashed = NULL; mcon_collection *filtered; mongo_manager_log(manager, MLOG_RS, MLOG_FINE, "limiting by credentials"); filtered = mcon_init_collection(sizeof(mongo_connection*)); for (i = 0; i < candidates->count; i++) { db = username = auth_hash = hashed = NULL; mongo_server_split_hash(((mongo_connection *) candidates->data[i])->hash, NULL, NULL, NULL, &db, &username, &auth_hash, NULL); if (servers->server[0]->username && servers->server[0]->password && servers->server[0]->db) { if (strcmp(db, servers->server[0]->db) != 0) { mongo_manager_log(manager, MLOG_RS, MLOG_FINE, "- skipping '%s', database didn't match ('%s' vs '%s')", ((mongo_connection *) candidates->data[i])->hash, db, servers->server[0]->db); goto skip; } if (strcmp(username, servers->server[0]->username) != 0) { mongo_manager_log(manager, MLOG_RS, MLOG_FINE, "- skipping '%s', username didn't match ('%s' vs '%s')", ((mongo_connection *) candidates->data[i])->hash, username, servers->server[0]->username); goto skip; } hashed = mongo_server_create_hashed_password(username, servers->server[0]->password); if (strcmp(auth_hash, hashed) != 0) { mongo_manager_log(manager, MLOG_RS, MLOG_FINE, "- skipping '%s', authentication hash didn't match ('%s' vs '%s')", ((mongo_connection *) candidates->data[i])->hash, auth_hash, hashed); goto skip; } } mcon_collection_add(filtered, (mongo_connection *) candidates->data[i]); mongo_print_connection_info(manager, (mongo_connection *) candidates->data[i], MLOG_FINE); skip: if (db) { free(db); } if (username) { free(username); } if (auth_hash) { free(auth_hash); } if (hashed) { free(hashed); } } mongo_manager_log(manager, MLOG_RS, MLOG_FINE, "limiting by credentials: done"); return filtered; }
/* Creates a unique hash for a server def with some info from the server config, * but also with the PID to make sure forking works */ char *mongo_server_create_hash(mongo_server_def *server_def) { char *tmp, *hash; int size = 0; /* Host (string) and port (max 5 digits) + 2 separators */ size += strlen(server_def->host) + 1 + 5 + 1; /* Replica set name */ if (server_def->repl_set_name) { size += strlen(server_def->repl_set_name) + 1; } else { size += 2; } /* Database, username and hashed password */ if (server_def->db && server_def->username && server_def->password) { hash = mongo_server_create_hashed_password(server_def->username, server_def->password); size += strlen(server_def->db) + 1 + strlen(server_def->username) + 1 + strlen(hash) + 1; } else { size += 2; } /* PID (assume max size, a signed 32bit int) */ size += 10; /* Add one for the \0 at the end */ size += 1; /* Allocate and fill */ tmp = malloc(size); sprintf(tmp, "%s:%d;", server_def->host, server_def->port); if (server_def->repl_set_name) { sprintf(tmp + strlen(tmp), "%s;", server_def->repl_set_name); } else { sprintf(tmp + strlen(tmp), "-;"); } if (server_def->db && server_def->username && server_def->password) { sprintf(tmp + strlen(tmp), "%s/%s/%s;", server_def->db, server_def->username, hash); free(hash); } else { sprintf(tmp + strlen(tmp), ".;"); } sprintf(tmp + strlen(tmp), "%d", getpid()); return tmp; }