struct auth_master_connection *conn = auth_request->context;
struct auth_stream_reply *reply = auth_request->userdb_reply;
string_t *str;
+ const char *value;
if (auth_request->userdb_lookup_failed)
result = USERDB_RESULT_INTERNAL_FAILURE;
switch (result) {
case USERDB_RESULT_INTERNAL_FAILURE:
str_printfa(str, "FAIL\t%u", auth_request->id);
+ if (auth_request->userdb_lookup_failed) {
+ value = auth_stream_reply_find(reply, "reason");
+ if (value != NULL)
+ str_printfa(str, "\treason=%s", value);
+ }
break;
case USERDB_RESULT_USER_UNKNOWN:
str_printfa(str, "NOTFOUND\t%u", auth_request->id);
{
struct auth_request_handler *handler = request->context;
struct auth_stream_reply *reply;
+ const char *value;
i_assert(request->state == AUTH_REQUEST_STATE_USERDB);
case USERDB_RESULT_INTERNAL_FAILURE:
auth_stream_reply_add(reply, "FAIL", NULL);
auth_stream_reply_add(reply, NULL, dec2str(request->id));
+ if (request->userdb_lookup_failed) {
+ value = auth_stream_reply_find(request->userdb_reply,
+ "reason");
+ if (value != NULL)
+ auth_stream_reply_add(reply, "reason", value);
+ }
break;
case USERDB_RESULT_USER_UNKNOWN:
auth_stream_reply_add(reply, "NOTFOUND", NULL);
}
}
-void auth_stream_reply_remove(struct auth_stream_reply *reply, const char *key)
+static bool
+auth_stream_reply_find_area(struct auth_stream_reply *reply, const char *key,
+ unsigned int *idx_r, unsigned int *len_r)
{
const char *str = str_c(reply->str);
unsigned int i, start, key_len = strlen(key);
while (str[i] != '\0') {
start = i;
for (; str[i] != '\0'; i++) {
- if (str[i] == '\t') {
- i++;
+ if (str[i] == '\t')
break;
- }
}
if (strncmp(str+start, key, key_len) == 0 &&
(str[start+key_len] == '=' ||
str[start+key_len] == '\t' ||
str[start+key_len] == '\0')) {
- str_delete(reply->str, start, i-start);
- if (str_len(reply->str) == start && start > 0)
- str_delete(reply->str, start - 1, 1);
- break;
+ *idx_r = start;
+ *len_r = i - start;
+ return TRUE;
}
+ if (str[i] == '\t')
+ i++;
+ }
+ return FALSE;
+}
+
+void auth_stream_reply_remove(struct auth_stream_reply *reply, const char *key)
+{
+ unsigned int idx, len;
+
+ if (!auth_stream_reply_find_area(reply, key, &idx, &len))
+ return;
+
+ if (str_len(reply->str) < idx + len) {
+ /* remove also trailing tab */
+ len++;
+ } else if (str_len(reply->str) == idx + len && idx > 0) {
+ /* removing last item, remove preceding tab */
+ len++;
+ idx--;
+ }
+
+ str_delete(reply->str, idx, len);
+}
+
+const char *auth_stream_reply_find(struct auth_stream_reply *reply,
+ const char *key)
+{
+ unsigned int idx, len, keylen;
+
+ if (!auth_stream_reply_find_area(reply, key, &idx, &len))
+ return NULL;
+ else {
+ keylen = strlen(key);
+ i_assert(len > keylen);
+ idx += keylen + 1;
+ len -= keylen + 1;
+ return t_strndup(str_c(reply->str) + idx, len);
}
}
void auth_stream_reply_reset(struct auth_stream_reply *reply);
void auth_stream_reply_remove(struct auth_stream_reply *reply, const char *key);
+const char *auth_stream_reply_find(struct auth_stream_reply *reply,
+ const char *key);
+
void auth_stream_reply_import(struct auth_stream_reply *reply, const char *str);
const char *auth_stream_reply_export(struct auth_stream_reply *reply);
bool auth_stream_is_empty(struct auth_stream_reply *reply);
struct auth_worker_client *client = request->context;
struct auth_stream_reply *reply;
string_t *str;
+ const char *value;
if (request->passdb_failure && result == PASSDB_RESULT_OK)
result = PASSDB_RESULT_PASSWORD_MISMATCH;
auth_stream_reply_export(request->extra_cache_fields);
auth_stream_reply_import(reply, fields);
}
+ } else if (request->userdb_lookup_failed) {
+ value = auth_stream_reply_find(request->extra_fields, "reason");
+ if (value != NULL) {
+ auth_stream_reply_add(reply, NULL, "");
+ auth_stream_reply_add(reply, NULL, "");
+ auth_stream_reply_add(reply, "reason", value);
+ }
}
str = auth_stream_reply_get_str(reply);
str_append_c(str, '\n');
struct auth_worker_client *client = request->context;
struct auth_stream_reply *reply;
string_t *str;
+ const char *value;
if (request->passdb_failure && result == PASSDB_RESULT_OK)
result = PASSDB_RESULT_PASSWORD_MISMATCH;
auth_stream_reply_add(reply, "FAIL", NULL);
auth_stream_reply_add(reply, NULL,
t_strdup_printf("%d", result));
+ value = auth_stream_reply_find(request->extra_fields, "reason");
+ if (request->userdb_lookup_failed && value != NULL) {
+ auth_stream_reply_add(reply, NULL, "");
+ auth_stream_reply_add(reply, NULL, "");
+ auth_stream_reply_add(reply, "reason", value);
+ }
} else {
auth_stream_reply_add(reply, "OK", NULL);
auth_stream_reply_add(reply, NULL, request->user);
struct auth_worker_client *client = auth_request->context;
struct auth_stream_reply *reply = auth_request->userdb_reply;
string_t *str;
+ const char *value;
if (auth_request->userdb_lookup_failed)
result = USERDB_RESULT_INTERNAL_FAILURE;
switch (result) {
case USERDB_RESULT_INTERNAL_FAILURE:
str_append(str, "FAIL\t");
+ if (auth_request->userdb_lookup_failed) {
+ value = auth_stream_reply_find(reply, "reason");
+ if (value != NULL)
+ str_printfa(str, "reason=%s", value);
+ }
break;
case USERDB_RESULT_USER_UNKNOWN:
str_append(str, "NOTFOUND\t");
/* internal failure most likely */
return ret;
} else if (args[3] != NULL) {
- auth_request_set_field(request, "user", args[2], NULL);
+ if (*args[2] != '\0') {
+ auth_request_set_field(request, "user",
+ args[2], NULL);
+ }
auth_worker_reply_parse_args(request, args + 3);
return ret;
}
{
struct auth_request *request = context;
enum userdb_result result;
+ const char *args;
- if (strncmp(reply, "FAIL\t", 5) == 0)
+ if (strncmp(reply, "FAIL\t", 5) == 0) {
result = USERDB_RESULT_INTERNAL_FAILURE;
- else if (strncmp(reply, "NOTFOUND\t", 9) == 0)
+ args = reply + 5;
+ } else if (strncmp(reply, "NOTFOUND\t", 9) == 0) {
result = USERDB_RESULT_USER_UNKNOWN;
- else if (strncmp(reply, "OK\t", 3) == 0) {
+ args = reply + 9;
+ } else if (strncmp(reply, "OK\t", 3) == 0) {
result = USERDB_RESULT_OK;
- request->userdb_reply = auth_stream_reply_init(request->pool);
- auth_stream_reply_import(request->userdb_reply, reply + 3);
+ args = reply + 3;
} else {
result = USERDB_RESULT_INTERNAL_FAILURE;
i_error("BUG: auth-worker sent invalid user reply");
+ args = "";
+ }
+
+ if (*args != '\0') {
+ request->userdb_reply = auth_stream_reply_init(request->pool);
+ auth_stream_reply_import(request->userdb_reply, args);
}
auth_request_userdb_callback(result, request);