Netzwerkprogrammierung auf C oder C++?
-
Jodocus schrieb:
Das schreit nach Bufferoverlows und noch mehr Netzwerk-Exploits,
Genau, denn er wird bestimmt gleich ein relevantes Netzwerkprogramm schreiben, für das dann Exploits entwickelt werden.
Jodocus schrieb:
weil immer wieder von vorne das selbe programmiert wird und dabei (besonders bei recv()) dramatische Fehler gemacht werden.
Jau, bei recv() kann man super viel falsch machen.

-
Dann werde ich mich mit Heldenmut dafür einsetzen dass durch recv keine Bufferoverflows mehr geschehen.
std::vector<char> read_socket(int sock, std::size_t amount) { std::vector<char> buffer(amount); std::size_t read_total = 0; while(read_total != amount) { int this_read = recv(sock, &buffer[0] + read_total, buffer.size() - read_total, MSG_WAITALL); if(this_read == -1) throw std::runtime_error("socket recv error"); if(this_read == 0) { buffer.resize(read_total); break; } read_total += this_read; } return buffer; }Verflixt war das schwer.
-
> Er möchte lernen und nicht zwingend gleich eine voll ausgestattete Anwendung schreiben.
Aber er möchte das lernen, um sowas zu machen. Was denkst du, wo die Exploits in den "großen Anwendungen" herkommen? Genau, weil Leute dachten, sie hätten es in ihren Spielchen verstanden und dann Software "fürs echte Leben" geschrieben haben.
> Und wie das Ganze funktioniert lernt man doch deutlich besser mit den Low-Level Sockets, er kann ja immer noch auf Asio wechseln.
Ist genau die selbe Logik in der "Zuerst C-Strings oder C++-Strings"-Debatte. Und ich bleibe dabei. Besser erst C++-Strings, besser erst eine Socket-Abstraktionsebene höher. Sich vertiefen kann man immernoch, wenn man es braucht. Dann kann man auch eine eigene Abstraktion schreiben und die Low-Level-Sachen durchprogrammieren, um zu sehen, wie sie funktioniert aber dann wieder die fertige und gut getestete Library nehmen (wie bei std::string). Und Socket-Librarys verschleiern GANZ sicher nicht die Socket-Semantik. Sie vereinfachen lediglich die API. Wenn 5 von 8 Funktionsparametern für einen Anfänger nicht relevant sind (z.B. QoS, diverse Flags etc.), dann hilft ihm das nicht, Sockets zu verstehen. Es geht schließlich ums wesentliche, und gute Library-Interfaces nötigen einen nichts unwesentliches auf, behalten dem Programmierer aber auch keine Details vor, wenn sie sie benötigen.
> Genau, denn er wird bestimmt gleich ein relevantes Netzwerkprogramm schreiben, für das dann Exploits entwickelt werden.
Gleiches wie oben. Manche dachten, sie hätten recv() und deren Rückgabewert verstanden und programmierten damit dann "echte" Software.
> Jau, bei recv() kann man super viel falsch machen.

Ich hoffe dass das keine Ironie war.
-
Ethon schrieb:
Dann werde ich mich mit Heldenmut dafür einsetzen dass durch recv keine Bufferoverflows mehr geschehen.
std::vector<char> read_socket(int sock, std::size_t amount) { std::vector<char> buffer(amount); std::size_t read_total = 0; while(read_total != amount) { int this_read = recv(sock, &buffer[0] + read_total, buffer.size() - read_total, MSG_WAITALL); if(this_read == -1) throw std::runtime_error("socket recv error"); if(this_read == 0) { buffer.resize(read_total); break; } read_total += this_read; } return buffer; }Verflixt war das schwer.
Toll. Dann können Anfänger ja gleich eine Library nutzen, wenn sie statt recv() read_socket() nehmen sollten. Und da haben sie auch mehr Kontrolle über Flags, denn deine Funktion hier ist schon eine Einschränkung des Interface.
Und es geht außerdem nicht nur um recv(). Andere Gefahrenquellen wären etwa conditional Accept (SYN-Flood) und exklusive Adressen, die Servern ihren Port klauen.
-
Jodocus schrieb:
Ich hoffe dass das keine Ironie war.
Natürlich war das Ironie. Aber ich bin gespannt auf ein Beispiel, das die komplexen Fehler die bei recv() gemacht werden können veranschaulicht.
-
Schau dir mal Ethons Code an und schau dir an, was man da alles falsch machen kann. Google "recv() buffer overflow" sollte genug anschauliche Resultate liefern.
-
recv liefert nicht unbedingt die Anzahl an Bytes zurück, die man angegeben hat. Vorallem auch nicht in der Aufteilung, wie sie versendet wurden. Das ist tatsächlich ein großes Fehlerpotential. Weiß aber nicht, ob er das meint.
-
Jodocus schrieb:
Schau dir mal Ethons Code an und schau dir an, was man da alles falsch machen kann. Google "recv() buffer overflow" sollte genug anschauliche Resultate liefern.
Ernsthaft, bei den Beispielen die ich da finde, kannst du auch sagen memcpy oder strlen wären super gefährlich. Also entweder ich sehe den Fehler gerade nicht, oder man sollte einfach mal davon ausgehen, dass man ein Volldepp sein muss um recv() falsch zu nutzen.
Ich habe jedenfalls noch kein Beispiel gesehen, bei dem der Fehler nicht sofort in's Auge springen würde.
-
asio vorzuschlagen is echt das dümmste was man nur machen kann. Zum Lernen einfach ein winsocket Tutorial durcharbeiten und dann ne kleine Klasse basteln.
-
Grund?
-
Normalerweise gibt man die Buffergroesse an und nicht die Bytes, die man empfangen moechte. Wo sollte es da Probleme geben? Das gepostete Beispiel finde ich haesslich. Darueber hinaus verstehe ich die Aufregung in Bezug auf Pufferueberlaeufe nicht. Alles bloss geflame.
-
knivil schrieb:
Normalerweise gibt man die Buffergroesse an und nicht die Bytes, die man empfangen moechte.
So ein Schwachsinn. Jedes Mal, wenn ich die C-API verwende, ärgere ich mich darüber.