static void auth_server_connection_input(struct auth_server_connection *conn) { struct istream *input; const char *line, *error; int ret; switch (i_stream_read(conn->input)) { case 0: return; case -1: /* disconnected */ error = conn->input->stream_errno != 0 ? strerror(conn->input->stream_errno) : "EOF"; auth_server_connection_reconnect(conn, error); return; case -2: /* buffer full - can't happen unless auth is buggy */ i_error("BUG: Auth server sent us more than %d bytes of data", AUTH_SERVER_CONN_MAX_LINE_LENGTH); auth_server_connection_disconnect(conn, "buffer full"); return; } if (!conn->version_received) { line = i_stream_next_line(conn->input); if (line == NULL) return; /* make sure the major version matches */ if (strncmp(line, "VERSION\t", 8) != 0 || !str_uint_equals(t_strcut(line + 8, '\t'), AUTH_CLIENT_PROTOCOL_MAJOR_VERSION)) { i_error("Authentication server not compatible with " "this client (mixed old and new binaries?)"); auth_server_connection_disconnect(conn, "incompatible server"); return; } conn->version_received = TRUE; } input = conn->input; i_stream_ref(input); while ((line = i_stream_next_line(input)) != NULL && !input->closed) { T_BEGIN { ret = auth_server_connection_input_line(conn, line); } T_END; if (ret < 0) { auth_server_connection_disconnect(conn, t_strdup_printf( "Received broken input: %s", line)); break; } } i_stream_unref(&input); }
static void master_login_auth_input(struct master_login_auth *auth) { const char *line; bool ret; switch (i_stream_read(auth->input)) { case 0: return; case -1: /* disconnected. stop accepting new connections, because in default configuration we no longer have permissions to connect back to auth-master */ master_service_stop_new_connections(master_service); master_login_auth_disconnect(auth); return; case -2: /* buffer full */ i_error("Auth server sent us too long line"); master_login_auth_disconnect(auth); return; } if (!auth->version_received) { line = i_stream_next_line(auth->input); if (line == NULL) return; /* make sure the major version matches */ if (strncmp(line, "VERSION\t", 8) != 0 || !str_uint_equals(t_strcut(line + 8, '\t'), AUTH_MASTER_PROTOCOL_MAJOR_VERSION)) { i_error("Authentication server not compatible with " "master process (mixed old and new binaries?)"); master_login_auth_disconnect(auth); return; } auth->version_received = TRUE; } if (!auth->spid_received) { line = i_stream_next_line(auth->input); if (line == NULL) return; if (strncmp(line, "SPID\t", 5) != 0 || str_to_pid(line + 5, &auth->auth_server_pid) < 0) { i_error("Authentication server didn't " "send valid SPID as expected: %s", line); master_login_auth_disconnect(auth); return; } auth->spid_received = TRUE; master_login_auth_check_spids(auth); } auth->refcount++; while ((line = i_stream_next_line(auth->input)) != NULL) { if (strncmp(line, "USER\t", 5) == 0) ret = master_login_auth_input_user(auth, line + 5); else if (strncmp(line, "NOTFOUND\t", 9) == 0) ret = master_login_auth_input_notfound(auth, line + 9); else if (strncmp(line, "FAIL\t", 5) == 0) ret = master_login_auth_input_fail(auth, line + 5); else ret = TRUE; if (!ret || auth->input == NULL) { master_login_auth_disconnect(auth); break; } } master_login_auth_unref(&auth); }
static void auth_client_input(struct auth_client_connection *conn) { char *line; bool ret; switch (i_stream_read(conn->input)) { case 0: return; case -1: /* disconnected */ auth_client_disconnected(&conn); return; case -2: /* buffer full */ i_error("BUG: Auth client %u sent us more than %d bytes", conn->pid, (int)AUTH_CLIENT_MAX_LINE_LENGTH); auth_client_connection_destroy(&conn); return; } while (conn->request_handler == NULL) { /* still handshaking */ line = i_stream_next_line(conn->input); if (line == NULL) return; if (!conn->version_received) { /* make sure the major version matches */ if (strncmp(line, "VERSION\t", 8) != 0 || !str_uint_equals(t_strcut(line + 8, '\t'), AUTH_CLIENT_PROTOCOL_MAJOR_VERSION)) { i_error("Authentication client " "not compatible with this server " "(mixed old and new binaries?)"); auth_client_connection_destroy(&conn); return; } conn->version_received = TRUE; continue; } if (strncmp(line, "CPID\t", 5) == 0) { if (!auth_client_input_cpid(conn, line + 5)) { auth_client_connection_destroy(&conn); return; } } else { i_error("BUG: Authentication client sent " "unknown handshake command: %s", str_sanitize(line, 80)); auth_client_connection_destroy(&conn); return; } } conn->refcount++; while ((line = i_stream_next_line(conn->input)) != NULL) { T_BEGIN { ret = auth_client_handle_line(conn, line); safe_memset(line, 0, strlen(line)); } T_END; if (!ret) { struct auth_client_connection *tmp_conn = conn; auth_client_connection_destroy(&tmp_conn); break; } } auth_client_connection_unref(&conn); }