#include "xlator.h" #include "defaults.h" #include "meta-mem-types.h" #include "meta.h" #include "meta-hooks.h" static int option_file_fill (xlator_t *this, inode_t *inode, strfd_t *strfd) { data_t *data = NULL; data = meta_ctx_get (inode, this); strprintf (strfd, "%s\n", data_to_str (data)); return strfd->size; } static struct meta_ops option_file_ops = { .file_fill = option_file_fill }; int meta_option_file_hook (call_frame_t *frame, xlator_t *this, loc_t *loc, dict_t *xdata) { xlator_t *xl = NULL;
static bool disk_scan_part(disk_t *disk, uint64_t offset, void *data, int data_size, struct scan_state *state) { ssize_t ret; struct timespec t_start; struct timespec t_end; uint64_t t; int error = 0; io_result_t io_res; clock_gettime(CLOCK_MONOTONIC, &t_start); ret = disk_dev_read(&disk->dev, offset, data_size, data, &io_res); clock_gettime(CLOCK_MONOTONIC, &t_end); t = (t_end.tv_sec - t_start.tv_sec) * 1000000000 + t_end.tv_nsec - t_start.tv_nsec; const uint64_t t_msec = t / 1000000; // Perform logging data_log_raw(&disk->data_raw, offset/disk->sector_size, data_size/disk->sector_size, &io_res, t); data_log(&disk->data_log, offset/disk->sector_size, data_size/disk->sector_size, &io_res, t); // Handle error or incomplete data if (io_res.data != DATA_FULL || io_res.error != ERROR_NONE) { int s_errno = errno; ERROR("Error when reading at offset %" PRIu64 " size %d read %zd, errno=%d: %s", offset, data_size, ret, errno, strerror(errno)); ERROR("Details: error=%s data=%s %02X/%02X/%02X", error_to_str(io_res.error), data_to_str(io_res.data), io_res.info.sense_key, io_res.info.asc, io_res.info.ascq); report_scan_error(disk, offset, data_size, t); disk->num_errors++; error = 1; if (io_res.error == ERROR_FATAL) { ERROR("Fatal error occurred, bailing out."); return false; } if (io_res.error == ERROR_UNKNOWN) { if (state->num_unknown_errors++ > 500) { ERROR("%u unknown errors occurred, assuming fatal issue.", state->num_unknown_errors); return false; } ERROR("Unknown error occurred, possibly untranslated error by storage layers, trying to continue."); } if (s_errno != EIO && s_errno != 0) abort(); // TODO: What to do when no everything was read but errno is zero? } else { state->num_unknown_errors = 0; // Clear non-consecutive unknown errors report_scan_success(disk, offset, data_size, t); } hdr_record_value(disk->histogram, t / 1000); latency_bucket_add(disk, t_msec, state); if (t_msec > 1000) { VERBOSE("Scanning at offset %" PRIu64 " took %"PRIu64" msec", offset, t_msec); } if (disk->fix && (t_msec > 3000 || error)) { if (io_res.error != ERROR_UNCORRECTED) { INFO("Fixing region by rewriting, offset=%"PRIu64" size=%d", offset, data_size); ret = disk_dev_write(&disk->dev, offset, data_size, data, &io_res); if (ret != data_size) { ERROR("Error while attempting to rewrite the data! ret=%zd errno=%d: %s", ret, errno, strerror(errno)); } } else { // When we correct uncorrectable errors we want to zero it out, this should reduce any confusion later on when the data is read unsigned fix_offset = 0; int fix_size = 4096; if (data_size < fix_size) fix_size = data_size; for (; data_size >= (int)(fix_offset + fix_size); fix_offset += fix_size) { disk_dev_read(&disk->dev, offset+fix_offset, fix_size, data, &io_res); if (io_res.error == ERROR_UNCORRECTED) { INFO("Fixing uncorrectable region by writing zeros, offset=%"PRIu64" size=%d", offset+fix_offset, fix_size); memset(data, 0, fix_size); ret = disk_dev_write(&disk->dev, offset+fix_offset, fix_size, data, &io_res); if (ret != data_size) { ERROR("Error while attempting to overwrite uncorrectable data! ret=%zd errno=%d: %s", ret, errno, strerror(errno)); } } } } } return true; }
auth_result_t gf_auth(dict_t *input_params, dict_t *config_params) { auth_result_t result = AUTH_DONT_CARE; int ret = 0; data_t *allow_user = NULL; data_t *username_data = NULL; data_t *passwd_data = NULL; data_t *password_data = NULL; char *username = NULL; char *password = NULL; char *brick_name = NULL; char *searchstr = NULL; char *username_str = NULL; char *tmp = NULL; char *username_cpy = NULL; gf_boolean_t using_ssl = _gf_false; gf_boolean_t strict_auth = _gf_false; username_data = dict_get(input_params, "ssl-name"); if (username_data) { gf_log("auth/login", GF_LOG_INFO, "connecting user name: %s", username_data->data); using_ssl = _gf_true; } else { ret = dict_get_str_boolean(config_params, "strict-auth-accept", _gf_false); if (ret == -1) strict_auth = _gf_false; else strict_auth = ret; username_data = dict_get(input_params, "username"); if (!username_data) { if (strict_auth) { gf_log("auth/login", GF_LOG_DEBUG, "username not found, strict auth" " configured returning REJECT"); result = AUTH_REJECT; } else { gf_log("auth/login", GF_LOG_DEBUG, "username not found, returning" " DONT-CARE"); } goto out; } password_data = dict_get(input_params, "password"); if (!password_data) { if (strict_auth) { gf_log("auth/login", GF_LOG_DEBUG, "password not found, strict auth" " configured returning REJECT"); result = AUTH_REJECT; } else { gf_log("auth/login", GF_LOG_WARNING, "password not found, returning" " DONT-CARE"); } goto out; } password = data_to_str(password_data); } username = data_to_str(username_data); brick_name = data_to_str(dict_get(input_params, "remote-subvolume")); if (!brick_name) { gf_log("auth/login", GF_LOG_ERROR, "remote-subvolume not specified"); result = AUTH_REJECT; goto out; } ret = gf_asprintf(&searchstr, "auth.login.%s.%s", brick_name, using_ssl ? "ssl-allow" : "allow"); if (-1 == ret) { gf_log("auth/login", GF_LOG_ERROR, "asprintf failed while setting search string, " "returning REJECT"); result = AUTH_REJECT; goto out; } allow_user = dict_get(config_params, searchstr); GF_FREE(searchstr); if (allow_user) { gf_log("auth/login", GF_LOG_INFO, "allowed user names: %s", allow_user->data); /* * There's a subtle difference between SSL and non-SSL behavior * if we can't match anything in the "while" loop below. * Intuitively, we should AUTH_REJECT if there's no match. * However, existing code depends on allowing untrusted users * to connect with *no credentials at all* by falling through * the loop. They're still distinguished from trusted users * who do provide a valid username and password (in fact that's * pretty much the only thing we use non-SSL login auth for), * but they are allowed to connect. It's wrong, but it's not * worth changing elsewhere. Therefore, we do the sane thing * only for SSL here. * * For SSL, if there's a list *you must be on it*. Note that * if there's no list we don't care. In that case (and the * ssl-allow=* case as well) authorization is effectively * disabled, though authentication and encryption are still * active. * * Read NOTE on strict_auth above. */ if (using_ssl || strict_auth) { result = AUTH_REJECT; } username_cpy = gf_strdup(allow_user->data); if (!username_cpy) goto out; username_str = strtok_r(username_cpy, " ,", &tmp); /* * We have to match a user's *authenticated* name to one in the * list. If we're using SSL, they're already authenticated. * Otherwise, they need a matching password to complete the * process. */ while (username_str) { if (!fnmatch(username_str, username, 0)) { if (using_ssl) { result = AUTH_ACCEPT; break; } ret = gf_asprintf(&searchstr, "auth.login.%s.password", username); if (-1 == ret) { gf_log("auth/login", GF_LOG_WARNING, "asprintf failed while setting search string"); goto out; } passwd_data = dict_get(config_params, searchstr); GF_FREE(searchstr); if (!passwd_data) { gf_log("auth/login", GF_LOG_ERROR, "wrong username/password combination"); result = AUTH_REJECT; goto out; } result = !((strcmp(data_to_str(passwd_data), password)) ? AUTH_ACCEPT : AUTH_REJECT); if (result == AUTH_REJECT) gf_log("auth/login", GF_LOG_ERROR, "wrong password for user %s", username); break; } username_str = strtok_r(NULL, " ,", &tmp); } } out: GF_FREE(username_cpy); return result; }
auth_result_t gf_auth (dict_t *input_params, dict_t *config_params) { auth_result_t result = AUTH_DONT_CARE; int ret = 0; char *name = NULL; char *searchstr = NULL; peer_info_t *peer_info = NULL; data_t *peer_info_data = NULL; data_t *allow_addr = NULL; data_t *reject_addr = NULL; char *addr_str = NULL; char *tmp = NULL; char *addr_cpy = NULL; char *service = NULL; uint16_t peer_port = 0; char is_inet_sdp = 0; char negate = 0; char match = 0; char peer_addr[UNIX_PATH_MAX]; char *type = NULL; gf_boolean_t allow_insecure = _gf_false; name = data_to_str (dict_get (input_params, "remote-subvolume")); if (!name) { gf_log ("authenticate/addr", GF_LOG_DEBUG, "remote-subvolume not specified"); goto out; } ret = gf_asprintf (&searchstr, "auth.addr.%s.allow", name); if (-1 == ret) { gf_log ("auth/addr", GF_LOG_DEBUG, "asprintf failed while setting search string"); goto out; } allow_addr = dict_get (config_params, searchstr); GF_FREE (searchstr); ret = gf_asprintf (&searchstr, "auth.addr.%s.reject", name); if (-1 == ret) { gf_log ("auth/addr", GF_LOG_ERROR, "asprintf failed while setting search string"); goto out; } reject_addr = dict_get (config_params, searchstr); GF_FREE (searchstr); if (!allow_addr) { /* TODO: backword compatibility */ ret = gf_asprintf (&searchstr, "auth.ip.%s.allow", name); if (-1 == ret) { gf_log ("auth/addr", GF_LOG_ERROR, "asprintf failed while setting search string"); goto out; } allow_addr = dict_get (config_params, searchstr); GF_FREE (searchstr); } if (!(allow_addr || reject_addr)) { gf_log ("auth/addr", GF_LOG_DEBUG, "none of the options auth.addr.%s.allow or " "auth.addr.%s.reject specified, returning auth_dont_care", name, name); goto out; } peer_info_data = dict_get (input_params, "peer-info"); if (!peer_info_data) { gf_log ("auth/addr", GF_LOG_ERROR, "peer-info not present"); goto out; } peer_info = data_to_ptr (peer_info_data); switch (((struct sockaddr *) &peer_info->sockaddr)->sa_family) { case AF_INET_SDP: is_inet_sdp = 1; ((struct sockaddr *) &peer_info->sockaddr)->sa_family = AF_INET; case AF_INET: case AF_INET6: { strcpy (peer_addr, peer_info->identifier); service = strrchr (peer_addr, ':'); *service = '\0'; service ++; if (is_inet_sdp) { ((struct sockaddr *) &peer_info->sockaddr)->sa_family = AF_INET_SDP; } ret = dict_get_str (config_params, "rpc-auth-allow-insecure", &type); if (ret == 0) { ret = gf_string2boolean (type, &allow_insecure); if (ret < 0) { gf_log ("auth/addr", GF_LOG_WARNING, "rpc-auth-allow-insecure option %s " "is not a valid bool option", type); goto out; } } peer_port = atoi (service); if (peer_port >= PRIVILEGED_PORT_CEILING && !allow_insecure) { gf_log ("auth/addr", GF_LOG_ERROR, "client is bound to port %d which is not privileged", peer_port); goto out; } break; case AF_UNIX: strcpy (peer_addr, peer_info->identifier); break; default: gf_log ("authenticate/addr", GF_LOG_ERROR, "unknown address family %d", ((struct sockaddr *) &peer_info->sockaddr)->sa_family); goto out; } } if (reject_addr) { addr_cpy = gf_strdup (reject_addr->data); if (!addr_cpy) goto out; addr_str = strtok_r (addr_cpy, ADDR_DELIMITER, &tmp); while (addr_str) { gf_log (name, GF_LOG_DEBUG, "rejected = \"%s\", received addr = \"%s\"", addr_str, peer_addr); if (addr_str[0] == '!') { negate = 1; addr_str++; } match = fnmatch (addr_str, peer_addr, 0); if (negate ? match : !match) { result = AUTH_REJECT; goto out; } addr_str = strtok_r (NULL, ADDR_DELIMITER, &tmp); } GF_FREE (addr_cpy); } if (allow_addr) { addr_cpy = gf_strdup (allow_addr->data); if (!addr_cpy) goto out; addr_str = strtok_r (addr_cpy, ADDR_DELIMITER, &tmp); while (addr_str) { gf_log (name, GF_LOG_DEBUG, "allowed = \"%s\", received addr = \"%s\"", addr_str, peer_addr); if (addr_str[0] == '!') { negate = 1; addr_str++; } match = fnmatch (addr_str, peer_addr, 0); if (negate ? match : !match) { result = AUTH_ACCEPT; goto out; } addr_str = strtok_r (NULL, ADDR_DELIMITER, &tmp); } } out: if (addr_cpy) GF_FREE (addr_cpy); return result; }
auth_result_t gf_auth (dict_t *input_params, dict_t *config_params) { auth_result_t result = AUTH_DONT_CARE; int ret = 0; char *name = NULL; char *searchstr = NULL; peer_info_t *peer_info = NULL; data_t *peer_info_data = NULL; data_t *allow_addr = NULL; data_t *reject_addr = NULL; char *service = NULL; uint16_t peer_port = 0; char peer_addr[UNIX_PATH_MAX] = {0,}; char *type = NULL; gf_boolean_t allow_insecure = _gf_false; char *subdir = NULL; name = data_to_str (dict_get (input_params, "remote-subvolume")); if (!name) { gf_log ("authenticate/addr", GF_LOG_DEBUG, "remote-subvolume not specified"); goto out; } ret = gf_asprintf (&searchstr, "auth.addr.%s.allow", name); if (-1 == ret) { gf_log ("auth/addr", GF_LOG_DEBUG, "asprintf failed while setting search string"); goto out; } allow_addr = dict_get (config_params, searchstr); GF_FREE (searchstr); ret = gf_asprintf (&searchstr, "auth.addr.%s.reject", name); if (-1 == ret) { gf_log ("auth/addr", GF_LOG_ERROR, "asprintf failed while setting search string"); goto out; } reject_addr = dict_get (config_params, searchstr); GF_FREE (searchstr); if (!allow_addr) { /* TODO: backward compatibility */ ret = gf_asprintf (&searchstr, "auth.ip.%s.allow", name); if (-1 == ret) { gf_log ("auth/addr", GF_LOG_ERROR, "asprintf failed while setting search string"); goto out; } allow_addr = dict_get (config_params, searchstr); GF_FREE (searchstr); } if (!(allow_addr || reject_addr)) { gf_log ("auth/addr", GF_LOG_DEBUG, "none of the options auth.addr.%s.allow or " "auth.addr.%s.reject specified, returning auth_dont_care", name, name); goto out; } peer_info_data = dict_get (input_params, "peer-info"); if (!peer_info_data) { gf_log ("auth/addr", GF_LOG_ERROR, "peer-info not present"); goto out; } ret = dict_get_str (input_params, "subdir-mount", &subdir); if (ret) { subdir = "/"; } peer_info = data_to_ptr (peer_info_data); switch (((struct sockaddr *) &peer_info->sockaddr)->sa_family) { case AF_INET_SDP: case AF_INET: case AF_INET6: strcpy (peer_addr, peer_info->identifier); service = strrchr (peer_addr, ':'); *service = '\0'; service++; ret = dict_get_str (config_params, "rpc-auth-allow-insecure", &type); if (ret == 0) { ret = gf_string2boolean (type, &allow_insecure); if (ret < 0) { gf_log ("auth/addr", GF_LOG_WARNING, "rpc-auth-allow-insecure option %s " "is not a valid bool option", type); goto out; } } peer_port = atoi (service); if (peer_port >= PRIVILEGED_PORT_CEILING && !allow_insecure) { gf_log ("auth/addr", GF_LOG_ERROR, "client is bound to port %d which is not privileged", peer_port); result = AUTH_REJECT; goto out; } break; case AF_UNIX: strcpy (peer_addr, peer_info->identifier); break; default: gf_log ("authenticate/addr", GF_LOG_ERROR, "unknown address family %d", ((struct sockaddr *) &peer_info->sockaddr)->sa_family); goto out; } if (reject_addr) { parse_entries_and_compare (reject_addr->data, peer_addr, name, subdir, &result, AUTH_REJECT); if (result == AUTH_REJECT) goto out; } if (allow_addr) { parse_entries_and_compare (allow_addr->data, peer_addr, name, subdir, &result, AUTH_ACCEPT); } out: return result; }
static bool disk_scan_part(disk_t *disk, uint64_t offset, void *data, int data_size, struct scan_state *state) { ssize_t ret; struct timespec t_start; struct timespec t_end; uint64_t t; int error = 0; io_result_t io_res; clock_gettime(CLOCK_MONOTONIC, &t_start); ret = disk_dev_read(&disk->dev, offset, data_size, data, &io_res); clock_gettime(CLOCK_MONOTONIC, &t_end); t = (t_end.tv_sec - t_start.tv_sec) * 1000000000 + t_end.tv_nsec - t_start.tv_nsec; const uint64_t t_msec = t / 1000000; // Perform logging data_log_raw(&disk->data_raw, offset/disk->sector_size, data_size/disk->sector_size, &io_res, t); data_log(&disk->data_log, offset/disk->sector_size, data_size/disk->sector_size, &io_res, t); // Handle error or incomplete data if (io_res.data != DATA_FULL || io_res.error != ERROR_NONE) { int s_errno = errno; ERROR("Error when reading at offset %" PRIu64 " size %d read %zd: %m", offset, data_size, ret); ERROR("Details: error=%s data=%s %02X/%02X/%02X", error_to_str(io_res.error), data_to_str(io_res.data), io_res.info.sense_key, io_res.info.asc, io_res.info.ascq); report_scan_error(disk, offset, data_size, t); disk->num_errors++; error = 1; if (io_res.error == ERROR_FATAL) { ERROR("Fatal error occurred, bailing out."); return false; } if (io_res.error == ERROR_UNKNOWN) { if (state->num_unknown_errors++ > 500) { ERROR("%u unknown errors occurred, assuming fatal issue.", state->num_unknown_errors); return false; } ERROR("Unknown error occurred, possibly untranslated error by storage layers, trying to continue."); } if (s_errno != EIO && s_errno != 0) abort(); // TODO: What to do when no everything was read but errno is zero? } else { state->num_unknown_errors = 0; // Clear non-consecutive unknown errors report_scan_success(disk, offset, data_size, t); } unsigned hist_idx = 0; while (t_msec >= histogram_time[hist_idx].top_val && hist_idx < ARRAY_SIZE(disk->histogram) - 1) { hist_idx++; } disk->histogram[hist_idx]++; latency_bucket_add(disk, t_msec, state); if (t_msec > 1000) { VERBOSE("Scanning at offset %" PRIu64 " took %"PRIu64" msec", offset, t_msec); } if (disk->fix && (t_msec > 3000 || error)) { INFO("Fixing region by rewriting, offset=%"PRIu64" size=%d", offset, data_size); ret = disk_dev_write(&disk->dev, offset, data_size, data, &io_res); if (ret != data_size) { ERROR("Error while attempting to rewrite the data! ret=%zd errno=%d: %m", ret, errno); } } return true; }
transport_t * transport_load (dict_t *options, xlator_t *xl, event_notify_fn_t notify) { struct transport *trans = calloc (1, sizeof (struct transport)); data_t *type_data; char *name = NULL; void *handle = NULL; char *type = "ERROR"; if (!options) { freee (trans); gf_log ("transport", GF_LOG_ERROR, "options is NULL"); return NULL; } if (!xl) { freee (trans); gf_log ("transport", GF_LOG_ERROR, "xl is NULL"); return NULL; } if (!notify) { freee (trans); gf_log ("transport", GF_LOG_ERROR, "notify is NULL"); return NULL; } type_data = dict_get (options, "transport-type"); // transport type, e.g., "tcp" trans->xl = xl; trans->notify = notify; if (type_data) { type = data_to_str (type_data); } else { freee (trans); gf_log ("transport", GF_LOG_ERROR, "'option transport-type <xxxx/_____>' missing in specification"); return NULL; } asprintf (&name, "%s/%s.so", TRANSPORTDIR, type); gf_log ("transport", GF_LOG_DEBUG, "attempt to load file %s", name); handle = dlopen (name, RTLD_NOW|RTLD_GLOBAL); if (!handle) { gf_log ("transport", GF_LOG_ERROR, "dlopen (%s): %s", name, dlerror ()); freee (name); freee (trans); return NULL; }; freee (name); if (!(trans->ops = dlsym (handle, "transport_ops"))) { gf_log ("transport", GF_LOG_ERROR, "dlsym (transport_ops) on %s", dlerror ()); freee (trans); return NULL; } if (!(trans->init = dlsym (handle, "gf_transport_init"))) { gf_log ("transport", GF_LOG_ERROR, "dlsym (gf_transport_init) on %s", dlerror ()); freee (trans); return NULL; } if (!(trans->fini = dlsym (handle, "gf_transport_fini"))) { gf_log ("transport", GF_LOG_ERROR, "dlsym (gf_transport_fini) on %s", dlerror ()); freee (trans); return NULL; } if (trans->init (trans, options, notify) != 0) { gf_log ("transport", GF_LOG_ERROR, "'%s' initialization failed", type); freee (trans); return NULL; } pthread_mutex_init (&trans->lock, NULL); return trans; }
auth_result_t gf_auth (dict_t *input_params, dict_t *config_params) { char *username = NULL, *password = NULL; data_t *allow_user = NULL, *username_data = NULL, *password_data = NULL; int32_t result = AUTH_DONT_CARE; char *brick_name = NULL, *searchstr = NULL; username_data = dict_get (input_params, "username"); if (!username_data) return AUTH_DONT_CARE; username = data_to_str (username_data); password_data = dict_get (input_params, "password"); if (!password_data) return AUTH_DONT_CARE; password = data_to_str (password_data); brick_name = data_to_str (dict_get (input_params, "remote-subvolume")); if (!brick_name) { gf_log ("auth/login", GF_LOG_ERROR, "remote-subvolume not specified"); return AUTH_REJECT; } asprintf (&searchstr, "auth.login.%s.allow", brick_name); allow_user = dict_get (config_params, searchstr); free (searchstr); if (allow_user) { char *username_str = NULL; char *tmp; char *username_cpy = strdup (allow_user->data); username_str = strtok_r (username_cpy, " ,", &tmp); while (username_str) { data_t *passwd_data = NULL; if (!fnmatch (username_str, username, 0)) { asprintf (&searchstr, "auth.login.%s.password", username); passwd_data = dict_get (config_params, searchstr); if (!passwd_data) { gf_log ("auth/login", GF_LOG_DEBUG, "wrong username/password combination"); result = AUTH_REJECT; } else result = !strcmp (data_to_str (passwd_data), password) ? AUTH_ACCEPT : AUTH_REJECT; break; } username_str = strtok_r (NULL, " ,", &tmp); } free (username_cpy); } return result; }
auth_result_t gf_auth (dict_t *input_params, dict_t *config_params) { auth_result_t result = AUTH_DONT_CARE; int ret = 0; data_t *allow_user = NULL; data_t *username_data = NULL; data_t *passwd_data = NULL; data_t *password_data = NULL; char *username = NULL; char *password = NULL; char *brick_name = NULL; char *searchstr = NULL; char *username_str = NULL; char *tmp = NULL; char *username_cpy = NULL; username_data = dict_get (input_params, "username"); if (!username_data) { gf_log ("auth/login", GF_LOG_DEBUG, "username not found, returning DONT-CARE"); goto out; } username = data_to_str (username_data); password_data = dict_get (input_params, "password"); if (!password_data) { gf_log ("auth/login", GF_LOG_WARNING, "password not found, returning DONT-CARE"); goto out; } password = data_to_str (password_data); brick_name = data_to_str (dict_get (input_params, "remote-subvolume")); if (!brick_name) { gf_log ("auth/login", GF_LOG_ERROR, "remote-subvolume not specified"); result = AUTH_REJECT; goto out; } ret = gf_asprintf (&searchstr, "auth.login.%s.allow", brick_name); if (-1 == ret) { gf_log ("auth/login", GF_LOG_WARNING, "asprintf failed while setting search string, " "returning DONT-CARE"); goto out; } allow_user = dict_get (config_params, searchstr); GF_FREE (searchstr); if (allow_user) { username_cpy = gf_strdup (allow_user->data); if (!username_cpy) goto out; username_str = strtok_r (username_cpy, " ,", &tmp); while (username_str) { if (!fnmatch (username_str, username, 0)) { ret = gf_asprintf (&searchstr, "auth.login.%s.password", username); if (-1 == ret) { gf_log ("auth/login", GF_LOG_WARNING, "asprintf failed while setting search string"); goto out; } passwd_data = dict_get (config_params, searchstr); GF_FREE (searchstr); if (!passwd_data) { gf_log ("auth/login", GF_LOG_ERROR, "wrong username/password combination"); result = AUTH_REJECT; goto out; } result = !((strcmp (data_to_str (passwd_data), password)) ? AUTH_ACCEPT : AUTH_REJECT); if (result == AUTH_REJECT) gf_log ("auth/login", GF_LOG_ERROR, "wrong password for user %s", username); break; } username_str = strtok_r (NULL, " ,", &tmp); } } out: if (username_cpy) GF_FREE (username_cpy); return result; }