static int user_verify_restricted_uid(struct auth_request *auth_request) { struct auth_master_connection *conn = auth_request->master; struct auth_fields *reply = auth_request->userdb_reply; const char *value, *reason; uid_t uid; if (conn->userdb_restricted_uid == 0) return 0; value = auth_fields_find(reply, "uid"); if (value == NULL) reason = "userdb reply doesn't contain uid"; else if (str_to_uid(value, &uid) < 0) reason = "userdb reply contains invalid uid"; else if (uid != conn->userdb_restricted_uid) { reason = t_strdup_printf( "userdb uid (%s) doesn't match peer uid (%s)", dec2str(uid), dec2str(conn->userdb_restricted_uid)); } else { return 0; } auth_request_log_error(auth_request, "userdb", "client doesn't have lookup permissions for this user: %s " "(to bypass this check, set: service auth { unix_listener %s { mode=0777 } })", reason, conn->path); return -1; }
static void user_callback(enum userdb_result result, struct auth_request *auth_request) { struct auth_master_connection *conn = auth_request->master; string_t *str; const char *value; if (auth_request->userdb_lookup_tempfailed) result = USERDB_RESULT_INTERNAL_FAILURE; if (result == USERDB_RESULT_OK) { if (user_verify_restricted_uid(auth_request) < 0) result = USERDB_RESULT_INTERNAL_FAILURE; } str = t_str_new(128); switch (result) { case USERDB_RESULT_INTERNAL_FAILURE: str_printfa(str, "FAIL\t%u", auth_request->id); if (auth_request->userdb_lookup_tempfailed) { value = auth_fields_find(auth_request->userdb_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); break; case USERDB_RESULT_OK: str_printfa(str, "USER\t%u\t", auth_request->id); str_append_tabescaped(str, auth_request->user); str_append_c(str, '\t'); auth_fields_append(auth_request->userdb_reply, str, AUTH_FIELD_FLAG_HIDDEN, 0); break; } if (conn->auth->set->debug) { i_debug("userdb out: %s", auth_master_reply_hide_passwords(conn, str_c(str))); } str_append_c(str, '\n'); o_stream_nsend(conn->output, str_data(str), str_len(str)); auth_request_unref(&auth_request); auth_master_connection_unref(&conn); }
static void user_callback(enum userdb_result result, struct auth_request *auth_request) { struct auth_postfix_connection *conn = auth_request->context; string_t *str; const char *value; if (auth_request->userdb_lookup_tempfailed) result = USERDB_RESULT_INTERNAL_FAILURE; str = t_str_new(128); switch (result) { case USERDB_RESULT_INTERNAL_FAILURE: if (auth_request->userdb_lookup_tempfailed) value = auth_fields_find(auth_request->userdb_reply, "reason"); else value = NULL; str_printfa(str, "400 %s", value != NULL ? value: "Internal failure"); break; case USERDB_RESULT_USER_UNKNOWN: str_append(str, "500 User not found"); break; case USERDB_RESULT_OK: str_append(str, "200 1"); break; } if (conn->auth->set->debug) i_debug("postfix out: %s", str_c(str)); str_append_c(str, '\n'); o_stream_nsend(conn->output, str_data(str), str_len(str)); i_assert(conn->io == NULL); if (!conn->destroyed) conn->io = io_add(conn->fd, IO_READ, postfix_input, conn); auth_request_unref(&auth_request); auth_postfix_connection_unref(&conn); }
static void userdb_callback(enum userdb_result result, struct auth_request *request) { struct auth_request_handler *handler = request->handler; string_t *str; const char *value; i_assert(request->state == AUTH_REQUEST_STATE_USERDB); auth_request_set_state(request, AUTH_REQUEST_STATE_FINISHED); if (request->userdb_lookup_tempfailed) result = USERDB_RESULT_INTERNAL_FAILURE; str = t_str_new(128); switch (result) { case USERDB_RESULT_INTERNAL_FAILURE: str_printfa(str, "FAIL\t%u", request->id); if (request->userdb_lookup_tempfailed) { value = auth_fields_find(request->userdb_reply, "reason"); if (value != NULL) auth_str_add_keyvalue(str, "reason", value); } break; case USERDB_RESULT_USER_UNKNOWN: str_printfa(str, "NOTFOUND\t%u", request->id); break; case USERDB_RESULT_OK: str_printfa(str, "USER\t%u\t", request->id); str_append_tabescaped(str, request->user); auth_str_append_userdb_extra_fields(request, str); break; } handler->master_callback(str_c(str), request->master); auth_master_connection_unref(&request->master); auth_request_unref(&request); auth_request_handler_unref(&handler); }
bool auth_fields_exists(struct auth_fields *fields, const char *key) { return auth_fields_find(fields, key) != NULL; }