,---------------------------------------------------------------------------------, | [005] | | Csocket #1 | : so called : ; La nouvelle mode de faire des article a 2 ezine : , . . : ++------------------------------++ ++ C Socket Programming part #1 ++ par Cub1c (cub1c@hotmail.com) ++------------------------------++ [99.11.03] Pré-requis: - connaissance de la programmation C environnement Unix. ===== Intro ===== En premier lieu, dans ce texte nous allons apprendre, tout d'abord ce qu'est un socket et ensuite à programmer des sockets en langage C. NOTE: Ce texte s'adresse aux newbies! Je vais faire beaucoup de comparaisons ...... (téléphone...) bon je suis revenu...comme je disait, je vais faire beaucoup de comparaisons aux téléphones (que je suis comique!). Pourquoi? Parce-que batir un socket c'est comme installer une ligne téléphonique (ou presque). Tu dois commencer par l'installer, ensuite choisir le type de fils, etc... ============ Explications ============ Les sockets sur internet ont le même concept de base que les téléphones: établir une connection entre 2 hôtes pour ainsi pouvoir y passer des conversations, dans notre cas des packets. Les sockets sont comme des téléphones dont le fil utilisé pour la communication est Internet en utilisant le protocole TCP/IP (Transmission Control Protocol/Internet Protocol). Comprennez vous? Récapitulons... SOCKET == TELEPHONE INTERNET(TCP/IP) == FILS DE CUIVRE En espèrant que vous le savez, TCP/IP est le protocole utilisé pour la transmition de données numériques sur Internet. if(reaction == "IPIT/CTPTTI?!?!") exit(1); L'information circulant sur Internet avec le protocole TCP/IP est divisée en packets. Les packets sont des branches de données ayant une grandeur en bits égale. Les packets sont au TCP/IP ce que les mots d'une conversation sont au téléphone. Pour établir une conversation avec quelqu'un au téléphone il faut son numéro! Pour les socket, c'est le même principe. On appele cela une adresse. Il existe plusieur mode d'adressage, mais je vais seulement vous introduire au plus important lorsque l'on parle de socket pour TCP/IP: le mode d'adressage AF_INET. Les adresses AF_INET sont ceux que vous connaissez bien: les adresses IP. Un autre point important est le type de socket. La aussi il y en a plusieurs, mais les 2 plus commun sont: SOCK_STREAM et SOCK_DGRAM. Une connection stream (SOCK_STREAM) est le fait d'avoir une connection où les caractères vont parvenir en flot, sans interruptions. Le meilleur exemple d'une connection SOCK_STREAM est telnet. Tandis que SOCK_DGRAM indique une connection où les packets vont arriver en gang. UDP (User Datagram Protocol) est le protocole utilisé pour transmettre des packets de type SOCK_DGRAM. Le plus facile à utiliser est SOCK_STREAM, et c'est aussi le seul dont je vais vous parler dans ce texte. ================== Data Encapsulation ================== Avouez que vous n'aimer pas ce mot. Vous voulez même pas savoir ce que c'est que l'encapsulation de données juste parce-que le mot vous semble compliqué. Détrompez-vous, ce n'est pas si sorcier. L'encapsulation consiste à la transformation de données dans un format spécial qui permettra leur transmission à une autre machine qui elle effectuera une décapsulation. Schéma: DONNEE-->ENCAPSULATION-->TRANSMISSION-->DECAPSULATION-->LECTURE DE LA DONNEE Exemple: Vous voulez transmettre une commande FTP à un serveur. Dans ce processus il va y avoir 4 étapes à l'encapsulation(transformation) de la commande pour la transformer en packet: 1) la commande sera transformée(encapsuler) par le premier protocole, dans notre cas: FTP (File Transfer Protocol) 2) le tout sera retransformé par le deuxième protocol: TCP (Transmission Control Protocol) 3) le tout sera reretransformé par le troisième protocol: IP (Internet Protocol) 4) le tout sera rereretransformer par le quatrième protocol: le hardware (modem) ou: physical layer Schéma: COMMANDE-->TRANS.FTP-->TRANS.TCP-->TRANS.IP-->TRANS.PHYSICAL-LAYER Quand l'autre machine recoit ce packet, elle vas faire une décapsulation qui est le résultat du procédé inverse de l'encapsulation (effectuer les 4 étapes en commencant par la dernière jusqu'à la première). Cette partie qui explique l'encapsulation n'est pas nécessaire pour la programmation des sockets. Mais ceci explique en gros ce que vont faire les fonctions qui serviront à transmettre des caractères. Si vous voulez en savoir plus sur les différents protocoles et comment ils fonctionnent réellement, je vous conseil d'aller lire des RFC (Request For Comment) qui sont disponibles à l'adresse mentionnée à la fin de ce texte. ============= Programmation ============= Une fois que tu as un téléphone et le numéro d'une personne, que fais-tu après? Et oui! Tu compose! On appele ce processus se connecter. Dans notre cas, je vais seulement vous expliquer comment faire pour vous connecter à un serveur distant, et non pas comment vous ouvrir un port sur votre machine. Peut-être que j'en discuterai dans un article à venir. Premièrement, nous devons inclure dans notre programme les fichiers qui contiendront les modèles des fonctions dont nous aurons besoin pour la programmation de sockets: #include #include La fonction pour établir une connection à l'aide de socket est: socket(). int socket(int domaine, int type, int protocole); Cette ligne défini la facon selon laquelle socket() sera appelé. Elle contiendra 3 arguments: 1) domaine: cet argument dans notre cas sera "setté" à "AF_INET". 2) type: cet argument définira le type de socket utilisé, dans notre cas: "SOCK_STREAM". 3) protocole: et puis "setter" ce dernier argument à "0". Ce qui donnera: socket(AF_INET, SOCK_STREAM, 0); Nous devons ensuite insèrer ce socket dans une variable pour utilisation éventuelle: scktest = socket(AF_INET, SOCK_STREAM, 0); NOTE: si vous avez lu la section des explications, vous devriez être en mesure de comprendre pourquoi on attribut un domaine, un type et un protocole à un socket. Cette fonction va vous retourner un socket (scktest) qui sera utilisable plus tard dans le reste du programme. Si il y a difficultés à créer ce socket pour n'importe quelle raison, la valeur de la variable socket (scktest) sera -1. Ce qui vous permettra d'implémenter vous-même une routine de traitement d'erreurs de connection. La prochaine étape sera d'établir la connection. La fonction qui sera utilisé pour établir la connection sera connect(). Ceci permettra de vous connecter à une machine distante. int connect(int socketvar, struct sockaddr serv_addr, int addrlen); La fonction connect() contient 3 arguments: 1) socketvar: la variable qui contient le socket que nous avons ouvert à l'aide de socket(). 2) serv_addr: c'est la variable de l'adresse du serveur dont la structure est sockaddr. Cette variable vas contenir l'adresse du serveur et le port de destination. 3) addrlen: c'est la longeur de l'adresse du serveur. Dans notre cas, la longeur de l'adresse du serveur distant sera la longeur de la variable serv_addr: addrlen = sizeof(serv_addr) Bon, maintenant que vous savez comment utiliser les fonctions socket() pour ouvrir un socket et connect() pour connecter ce socket, codons tous en coeur un petit exemple. ----------Début---------- /* Exemple de programme utilisant des sockets */ #include #include /* On commence par inclure les fichiers contenant */ #include /* les prototypes */ #define DST_IP "134.232.11.21" /* Déclaration de variables globales */ #define DST_PORT 23 /* DST = Destination */ main() { int scktest; /* Déclaration de la variable du socket */ struct sockaddr_in dest_addr; /* dest_addr est la variable qui vas contenir l'adresse */ scktest = socket(AF_INET, SOCK_STREAM, 0); /* Ouverture du socket */ /* Bon, ici on devrais faire une routine qui vas vérifier si le socket est capable d'être ouvert ou non. Je ne vais pas vous écrire le code parce-que vous devriez être capable de le faire. Il faut juste faire un IF qui vas vérifier si la valeur de scktest == -1. Si elle égale -1, c'est qu'il y a une erreur et qu'il est impossible d'ouvrir le socket. */ dest_addr.sin_family = AF_INET; /* On dit à la variable qui contient l'adresse du serveur (dest_addr) quel mode d'adressage elle devra utiliser à l'aide de la propriété sin_family (sin signifie: "s" pour socket et "in" pour internet. Dans ce cas ci: AF_INET */ dest_addr.sin_port = htons(DEST_PORT); /* On défini la propriété sin_port de la variable dest_addr pour indiquer sur quel port se connecter. "htons" signifie Host TO Network Short. */ dest_addr.sin_addr.s_addr = inet_addr(DEST_IP); /* On défini la propriété s_addr de la variable dest_addr.sin_addr qui contiendra l'adresse IP du serveur distant. */ connect(scktest, (struct sockaddr *)&dest_addr, sizeof(struct dest_addr)); /* On se connecte à l'hote distant en utilisant la fonction connect(). Le deuxième argument est la troncature des variables sockaddr et dest_addr pour ainsi former le 3ième argument tout en 1 qui indiquera l'adresse du serveur.*/ } ----------Fin---------- NOTE: N'essayez pas d'exécuter ce petit programme. Il n'est là qu'a titre d'exemple. Il ne marchera pas. <__2> des exemple qui marche pas??? spa un peu useless ca ? ===== Outro ===== Il se peut que vous n'ayez pas compris tout les petits détails ou autres code dans le programme. C'est normal si vous avez qu'une petite base en C. Alors pratiquez-vous, pratiquez-vous encore et encore...Si vous voulez un petit conseil en attendant la prochaine partie de ce texte, regardez du code, regardez comment sont codés les exploits et regardez le code ligne par ligne en essayant de comprendre la signification. Pratiquez-vous. Next part: - Utilisation des fonctions send() et recv(). - Le reste, on verra. - Peut-être coder un petit remote buffer overflow ;). "The only place where success comes before work, it's in the dictionary." ------------- RFC: http://www.cis.ohio-state.edu/htbin/rfc/INDEX.rfc.html ------------- Texte écrit par Cub1c, pour IGA, terminé le 4 novembre 1999. Version finale terminé le 14 novembre 1999 - Cub1c(cub1c@hotmail.com) ; ' . : ; : ' ; Cub1c : | (jpense kon sent doutais :]) : |_________________________________________________________________________________| ===================================