Modelul Client Server In Distributia Bazelor de Date pe Web

Aspecte ale modelului client-server în

programarea distribuită

1.Prezentarea generală a modelului client-server

Modelul client-server este cea mai cunoscută și folosită paradigmă în programarea distribuită.

Conform acestei paradigme, un proces server (în sensul de servant) îndeplinește un anumit serviciu

pentru un proces client. Clientul cere serviciul prin emiterea unui mesaj către server. Serverul , la rândul lui, execută ciclic următoarele acțiuni: recepționează o cerere de serviciu de la un client, îndeplinește serviciul și emite un mesaj de răspuns către client. Acest model, în care informația circulă în ambele sensuri între procesele implicate este, evident, asimetric.

Procesul server este un proces “persistent”; el există întodeauna în sistem, așteptând pasiv ca un proces client să-I utilizeze serviciile. Paradigma client-server divizează deci procesele care își transferă informații în două categorii: client și server, în funcție de acțiunea pe care procesul o execută – fie așteaptă o comunicație (server), fie inițiază o comunicație (client). De fapt, motivația fundamentală a paradigmei client–server provine din cunoscuta problemă de “ rendez-vous ”. Modelul client-server rezolvă această problemă impunând ca dintre oricare două procese care vor să comunice, unul să-și înceapă execuția și să aștepte (un timp nedefinit) până la contactarea sa de către alt proces.

Soluția este importantă mai ales în rețelele în care se face prin TPC/IP deoarece TCP/IP nu furnizează nici un mecanism care să creeze automat procese la primirea unui mesaj. Serverul este inițiat ca un proces autonom în rețea. Structura de bază a unui proces server este reprezentată în figura 1 :

{

initializari;

while (TRUE)

{

asteapta_o_cerere(…);

trateaza_cererea(…);

}

}

Această structură de bază sugerează o interfață prin data grame deoarece serverul poate accepta o cerere de la orice client. Este posibil, în această implementare a procesului server ca deservirea unei cereri să necesite un timp destul de mare, deoarece, pe de o parte este necesar să se stabilească un circuit virtual între client și server și, pe de altă parte, un proces client poate monopoliza serverul un timp nedefinit. De aceea nodul care implementează serverul ar trebui să memoreze cererile către server care sosesc în timp ce acesta tratează o cerere (într-un context de multiprogramare).

Modelul poate fi însă extins astfel încât să folosească multiprogramarea. Se inițiază întâi un proces special, “listener” ,a cărui singură sarcină este de a accepta cereri de servicii și de a le transmite altor procese care deservesc cererile. Structura de bază a procesului server obținut în această implementare este prezentată în figură:

listener ()

{

socket client, server;

virtual_ circuit virt_circ;

initializari;

while (TRUE)

{

client <– asteapta_o_cerere(soket_impus);

server <– creare_soket();

virt_circ <– accept_virtual_circuit(client, server);

creare_proces(server, …, virt_circ, …);

}

close_virtual_circuit(virt_circ); }

Fiecare cerere a unui client generează crearea unui nou proces server conectat la procesul client printr-un circuit virtual. Clientul poate monopoliza acest server într-un timp nedefinit, fără a provoca blocarea altor clienți care pot emite în același timp cereri către procesul listener; acesta creează câte un proces server pentru fiecare cerere.

În acest al doilea model, procesele server sunt de fapt proceduri identice care se execută asupra unor structuri de date partajate (tabloul de cereri recepționate). Comutarea contextului între procesele server poate deveni un factor dominant și perturbator în deservirea cererilor. De aceea modelul poate fi perfecționat prin folosirea firelor (“treads” sau procese “lightweight”).

Firele nu au alocate resursele necesare unui proces; ele pot opera însă asupra resurselor alocate procesului care îl încapsulează.

În figura 2 clientul își transmite cererea la un “socket impus”, în sensul de o adresă cunoscută în rețea. Astfel, se impune proceselor client să “cunoască” o adresă fixată în rețea, pentru a-și putea adresa cererile de servicii la acea adresă.

Dacă adresa este cunoscută atunci ea se poate specifica direct în programul sursă al clientului – dar, în acest caz, o dată compilat programul client, serverul nu mai poate fi mutat pe un alt nod – sau poate fi returnată de un server de nume.

Dacă procesul client intenționează să trimită o cerere de servicii unui server de nume, pentru a proiecta numele serverului dorit într-o adresă, atunci serverul de nume trebuie să memoreze un catalog de servere și adresele lor. Acest scenariu pentru luarea contactului cu un server și pentru adresarea cererilor este descris în figură:

{

message msg;

socket client, server;

virtual_circuit virt_circ;

send_datagram(NAME_SERVER, “nume server”);

msg = receive(NAME_SERVER);

server = msg.adr_server;

client = creare_socket();

while();

{

write(virt_circ,…);

read(virt_circ,…);

trateaza();

}

close_virtual_circuit(virt_circ);

}

În diverse aplicații software, serverele trebuie să poată avea acces la fișiere, porturi, la care în mod normal sistemul de operare interzice accesul unui client obișnuit. În aceste cazuri serverele se execută cu privilegii speciale și trebuie luate măsuri de protecție ca aceste privilegii speciale să nu fie transmise clienților care apelează aceste servere.

De exemplu, un server care se execută ca un program privilegiat trebuie să conțină o funcție care să verifice dacă un fișier poate fi accesat de un client sau nu.

În general, serverul trebuie să asigure verificări pentru:

1.Autentificarea clienților – verificarea identității unui client;

2.Autorizarea clienților – determină dacă unui client îi este permis accesul la serviciul pe care serverul îl furnizează;

3.Securitatea datelor – garantarea păstrării integrității datelor(ele pot fi compromise de clienți în mod intenționat sau neinteționat);

4.Păstrarea secretului datelor – garantarea interzicerii accesului unor clienți la datele particulare ale unui client;

5.Protecția datelor – garantarea că aplicațiile nu pot abuza de resursele sistemului.

2.Sisteme client-server

Se poate considera că, în aplicațiile distribuite, unul sau mai mulți clienți, sau unul sau mai multe servere, împreună cu suportul pentru comunicarea interprocese formează un sistem compus (Client Server System sau, pe scurt, CSS) care permite efectuarea de calcule și prelucrări distribuite, analiza și vizualizarea datelor. Într-un astfel de sistem un client este un proces care interacționează cu utilizatorul și are următoarele caracteristici:

1. Prezintă o interfață cu utilizatorul. (User Interface UI), singurul mijloc prin care utilizatorul î-și poate prezenta cererile de consultare și regăsire a datelor, Dar și de vizualizare a rezultatelor cererilor sale. În mod tipic, clienții interacționează cu utilizatorii printr-o interfață grafică (Graphical User Interface GUI). Deoarece întru-un CSS pot coexista mai mulți clienți, pot exista astfel și mai multe variante de GUI. Unele CSS-uri pot fi prevăzute și cu o interfață pentru controlul resurselor sistemului.

Tipic, interfața grafică a sistemului de operare definește interfața GUI dintre client și utilizator . Astfel, într-un mediu UNIX, sistemul XÎWindow a devenit, “de facto”, interfața grafică standard.

2. Formează, pentru una sau mai multe comenzi ale utilizatorului una sau mai multe cereri către server. Serverul și clintul pot utiliza un limbaj comun pentru prezentarea cererilor. Nu toate comenzile utilizatorului se regăsesc, într-o corespondență de 1 la 1 cu cererile adresate serverului.

Un client poate utiliza un mecanism de “caching” și diverse tehnici de optimizare pentru a reduce fluxul de cereri către server ; de asemenea poate realiza verificările legate de autentificare și autorizare (controlul accesului la date).

3. Comunică cu serverul printr-un mecanism de comunicație între procese. Un client ideal ascunde complet utilizatorului mecanismul de comunicație interprocese.

4. Execută o analiză a datelor trimise ca răspuns către server în urma unei cereri și apoi le prezintă utilizatorului. Complexitatea acestei analize variază de la un CSS la altul .

Într-un CSS, un server este un proces sau un set de procese, toate aflate pe același nod care furnizează un anumit serviciu unuia sau mai multor clienți. Serverul are următoarele caracteristici :

a) Un server furnizează un serviciu unui client. Natura și complexitatea acestui serviciu este definit de scopul fiecărui CSS. Astfel, un server poate efectua prelucrări minore ale datelor un server de fișier sau un server de imprimante), sau prelucrări complexe ale datelor (un server pentru baze de date sau pentru procesarea imaginilor).

b) Un server răspunde la cererile și comenzile pe care le primește de la clienții săi. astfel, un server nu va iniția niciodată un dialog cu unul dintre clienții săi. El acționează astfel ca un depozit de date (server de fișiere), de

cunoștințe (server de baze de date) sau furnizor de servicii (server de imprimante).

Cu toate acestea, un server poate adresa la rândul său cereri de servicii altui server, deci devine la rândul său, un client pentru un alt server. De exemplu, un server de fișier poate cere obținerea date și timpului curent (pe care le asociază unui fișier) unui server de dată și timp. Situația serverului care devine astfel client este ilustrată în figură.

c) Un server ideal ascunde întreaga componență a unui sistem CSS clienților și utilizatorilor săi. Un astfel de server poate comunica cu clienții săi indiferent de tehnologia de comunicație (hardware sau software). Astfel, un client DOS ar trebui să poată comunica cu un server UNIX, indiferent deci de sistemul de operare și de tehnologia de conectare a clienților la server.

Fig: Server care devine clientul altui server

d) Un server poate memora informații relative la interacțiunile sale cu clienții (“ stateful server”) sau poate să nu păstreze nici o astfel de informație de stare (“stateless server”). Severele “stateful” sunt motivate de următoarele observații:

– prin păstrarea unor informații în server se reduce dimensiunea mesajelor pe care clientul și serverul le interschimbă și serverul răspunde mai rapid cererilor;

– informațiile de stare memorate permit serverelor să-și “amintească” cererea precedentă unei cereri curente și să construiască un răspuns incremental.

În schimb, serverele “stateless” oferă o fiabilitate mai mare decât serverele “stateful”, pentru că, în cazul ultimelor, informațiile de stare devin incorecte când se pierd sau se duplică mesaje sau când nodul clientului este oprit și repornit.

Ca o concluzie a celor de mai sus se poate spune că arhitectura client-server divide o aplicație distribuită în procese separate, localizate pe noduri diferite, conectate într-o rețea formând astfel ceea ce se cheamă “loosey coupled system”. Un proiectant al unei aplicații divide aplicația sa în subtaskuri care urmează să fie executate fie de procese client, fie de procese server în condițiile unor restricții impuse de sistemul CSS însuși și cu o funcționalitate dependentă de sistemul de operare.

Cu cât API-urile puse la dispoziția sistemului de operare sunt mai avansate, cu atât codul aplicației va fi mai mic. Pentru proiectantul care dezvoltă o aplicație într-o rețea de calculatoare, folosind modelul client-server, prezintă deci o mare importanță interfața de programare (API-urile) pusă la dispoziție de sistemul de operare. În figură se prezintă plasarea unor astfel de interfețe de programare cunoscute în nivelele modelului OSI.

Fig : Plasarea API-urilor față de nivelele mate să nu păstreze nici o astfel de informație de stare (“stateless server”). Severele “stateful” sunt motivate de următoarele observații:

– prin păstrarea unor informații în server se reduce dimensiunea mesajelor pe care clientul și serverul le interschimbă și serverul răspunde mai rapid cererilor;

– informațiile de stare memorate permit serverelor să-și “amintească” cererea precedentă unei cereri curente și să construiască un răspuns incremental.

În schimb, serverele “stateless” oferă o fiabilitate mai mare decât serverele “stateful”, pentru că, în cazul ultimelor, informațiile de stare devin incorecte când se pierd sau se duplică mesaje sau când nodul clientului este oprit și repornit.

Ca o concluzie a celor de mai sus se poate spune că arhitectura client-server divide o aplicație distribuită în procese separate, localizate pe noduri diferite, conectate într-o rețea formând astfel ceea ce se cheamă “loosey coupled system”. Un proiectant al unei aplicații divide aplicația sa în subtaskuri care urmează să fie executate fie de procese client, fie de procese server în condițiile unor restricții impuse de sistemul CSS însuși și cu o funcționalitate dependentă de sistemul de operare.

Cu cât API-urile puse la dispoziția sistemului de operare sunt mai avansate, cu atât codul aplicației va fi mai mic. Pentru proiectantul care dezvoltă o aplicație într-o rețea de calculatoare, folosind modelul client-server, prezintă deci o mare importanță interfața de programare (API-urile) pusă la dispoziție de sistemul de operare. În figură se prezintă plasarea unor astfel de interfețe de programare cunoscute în nivelele modelului OSI.

Fig : Plasarea API-urilor față de nivelele modelului OSI.

3. Comunicarea prin socluri în rețelele UNIX

Soclurile (“sockets”) sunt un mecanism de comunicație interprocese în rețelele UNIX, introdus de 4.3 BSD ca o extensie sau generalizare a comunicației prin conducte (“pipes”). Conductele facilitează comunicarea între procese de pe același sistem; soclurile facilitează comunicarea între procese de pe sisteme diferite sau de pe același sistem. O dată cu introducerea comunicării prin socluri și în System V Relase 4, soclurile au devenit cea mai importantă interfață de programare (API) pentru rețelele UNIX. Deoarece foarte multe companii de calculatoare precum Sun Microsystem, Digital Equipment Corporation și Tektronic au adoptat această interfață de programare soclurile au devenit “de facto” un mecanism standard de comunicație interprocese în rețele UNIX.

Structura sistemului de comunicație prin socluri, într-un sistem de operare UNIX :

Subsistemul conține trei părți: nivelul soclurilor, nivelul protocoalelor și nivelul driverelor.

Nivelul soclurilor furnizează interfața dintre apelurile sistem și nivelele inferioare. Nivelul protocoalelor conține modulele utilizate pentru comunicație ( TCP și IP în figură), iar nivelul driverelor conține driverele care controlează plăcile de conectare în rețea.

Comunicare între procese prin socluri utilizează modelul client-server: un proces server (“ listener”) ascultă pe un soclu (un capăt al unei linii de comunicație între două procese) – iar un proces client comunică cu serverul la celălalt capăt al liniei de comunicație, pe un alt soclu, care poate fi situat pe un alt nod. Nucleul sistemului de operare memorează date despre linia de comunicație deschisă între cele două procese.

Se poate face o analogie între apelurile sistem pentru lucrul cu fișiere în UNIX și structurile de date pe care le generează nucleul pentru gestiunea fișierelor cu apelurile sistem pentru comunicația între procese prin socluri și structurile de date pe care le menține nucleul relativ la liniile de comunicație.

Astfel, analog descriptorilor de fișiere care se obțin de la sistemul de operare ca urmare a unor apeluri open() sau create() există descriptori de socluri care se obțin ca urmare a unui apel sistem socket(). Nucleul UNIX alocă descriptorii de socluri în aceeași tabelă de descriptori în care alocă descriptorii de fișiere.

Deci o aplicație nu poate avea un descriptor de fișier și un descriptor de soclu de aceeași valoare. Când o aplicație apelează socket(), nucleul alocă o structură de date pentru noua linie de comunicație și completează într-o intrare liberă din tabela de descriptori un pointer la această structură de date.

În figură se exemplifică acest procedeu:

În urma apelului socket(), structura de date creată este completetă doar parțial, aplicația fiind obligată să apeleze în continuare și alte funcții pentru a completa în întregime această atructură de date înainte de a utiliza soclul.

Soclurile care au caracteristici comune în ceea ce privește comunicația, precum convenții de nume, formatul adreselor utilizate de protocoalele de comunicație se grupează în domenii (familii). Există astfel, pentru comunicația în rețele, “ Internet domain “ și “Xerox NS domain”, iar pentru comunicația între procese de pe acelasi sistem UNIX, “ Unix system domain”. Fiecare soclu are un tip specificat care determină modul de transfer al datelor, în mod obișnuit, printr-un circuit virtual (transfer orientat pe conexiune, STREAM SOCKET în terminologia Berkeley), sau prin datagrame (transfer neorientat pe conexiune).

Un circuit virtual permite transferul garantat (bidirecțional) al datelor, fără duplicarea și cu secvențierea pachetelor.Datagramele nu garantează nici transmisia în secvență a pachetelor nici neduplicarea lor, dar au avantajul că nu necesită stabilirea conexiunii.

Mecanismul de comunicație prin socluri asociază implicit anumite protocoale de comunicație pentru fiecare combinație domeniu-tip soclu validă.

De exemplu, protocolul TCP furnizează un transfer orientat pe conexiune (circuit vital), iar UDP funizează un transfer bazat pe datagrame.

Cuplul de informații {domeniu,tip_soclu,protocol} relative la un soclu se furnizează sistemului ca parametrii ai apelului socket() care returnează un descriptor de soclu. Soclul astfel creat nu are însă asociat nici un proces nu I se asociază la creare nici adresa sistemului local nici a celei de la distanță). Pentru a specifica adresa proprie la un capăt al liniei de comunicație între două procese, procesul servere trebuie să execute apelul sistem bind(). Când se creează un soclu nu se specifică dacă ste activ (pentru a fi utilizat de un client), sau pasiv (pentru a fi utilizat de un server). Serverele care folosesc o transmisie orientată pe conexiune trebuie să execute (după bind())apelul sistem listen() pentru a pune soclurile lor într-o stare pasivă, gata să primească cereri de stabilire a unei conexiuni.

Majoritatea serverelor constau într-o buclă infinită n care preiau o cerere, o tratează și returnează un răspuns. Chiar dacă tratarea cererii durează foarte puțin, câteva milisecunde, se poate ca o altă cerere să sosească exact în acest interval. Pentru a se evita pierderea cererilor sosite la nivelul serverului, acesta trebuie să transmită apelului listen() un argument prin care se cere sistemului de operare să înlănțuie cererile primite pe un soclu. Astfel, argumentele apelului bind() specifică ce soclu se setează ca pasiv și dimensiunea maximă a cozii de cereri pentru acel soclu. În scopul recepționării cererilor de conectare de clienți, un server trebuie să execute în continuare un apel accept().

Accept() creează câte un soclu nou pentru fiecare cerere de conexiune și returnează apelantului descriptorul noului soclu creat. Serverul utilizează noul soclu exclusiv pentru comunicația cu clientul respectiv, în timp ce pe noul soclu acceptă noi cereri de conectare.

Referitor la client, acesta trebuie să execute un apel connect() pentru a stabili o conexiune cu un server. Clientul trebuie să furnizeze sistemului informații despre identitatea serverului (adresa IP și numărul portlui, de exemplu).

După stabilirea conexiunii, schimbul de informații dintre client și server se poate face cu apelurile read() / write(), iar în final, distrugerea conexiunii se face cu apelul close().

Figura ilustrează secvența de apeluri sistem executată de un server și un client în cazul comunicării prin TCP:

Pentru o transmisie prin UDP cliemtul nu trebuie să se conecteze la server; el trebuie doar să trimită către server un mesaj sub forma unei datagrame cu ajutorul unui sistem sendto()care primește ca parametru adresa sistemului destinație. Analog, serverul nu trebuie să accepte o conexiune ci doar să recepționeze mesaje datagrame de la un client, cu ajutorul apelului recvform(), care blochează serverul până la primirea unui mesaj.

Succesiunea apelurilor sistem în cazul unui transfer fără conexiune:

Pentru ilustrarea interfeței de programare arătate, se prezintă în continuare un exemplu de o aplicație client-server:

/*Serverul TCP- Severul selanseaza in background cu iesirea redirectata

*la un fisier xxx; dupa executie se poate cerceta continutul acestui

*fisier. Serverul trebuie lansat in executie inainte de lansarea orcarui

*client si distrus la terminarea utilizarii lui.

*Dupa lansarea serverului pe un nod, se pot lansa clientii pe alte noduri.

*Serverul trateaza concurent cererile; el trebuie inregistrat in sistem

*sub numele "exemplu"

*Cererea primita de la un client consta intr-un mesaj de o dimensiune

*fixa; raspunsul servereului consta intr-un mesaj care contine timpul local

*/

#include <unistd.h>

#include <stdio.h>

#include <string.h>

#include <stdlib.h>

#include <siganl.h>

#include <sys/types.h>

#include <sys/socket.h>

#include <netinet/in.h>

#include <netdb.h>

#define DIM 100

static void sig_chld(int);

struct sockaddr_in local;

struct sockaddr_in remonte;

struct hostent *hptr;

struct servent *sptr;

main(int argc,char *argv[]){

struct sigaction act;

int lgclient;

/* initializarea structurilor de adrese */

memset((char*)&local,0,sizeof(struct sockaddr_in));

memset((char*)&remonte,0,sizeof(struct sockaddr_in));

/* se completeaza structura adresa pentru server;

*serverul trebuie sa receptioneze cereri de la orice client

*/

local.sin_addr.s_addr=INADDR_ANY;

local.sin_family=AF_INET;

/* se cauta informatii desore server */

sptr=getservbyname("exemplu',"tcp");

if(sptr==null){

fprint(stderr,"*s:eroare getservbyname\n",argv[0]);

exit(1);

}

/* se completeaz portul */

local.sin_port=sptr->s_potr;

/* se deschide un socket pentru ascultare */

consock=socket(AF_INET,SOCK_STREAM,0));

if(consock==-1){

fprint(stderr,"*s socket:nu se poate deschide soclul\n");

exit(1);

}

if(bind(consock,(struct sockaddr *)&local,

sizeof(struct sockaddr_in))==-1){

fprint(stderr,"*s:eroare bind\n",argv[0]);

exit(1);

}

/* se asteapta o cerere a unui client */

if(listen(consock,5)==-1){

fprint(stderr,"*s:eroare listen\n",argv[0]);

exit(1);

}

/* se lanseaza un proces daemon */

setpgid(0,0);

switch(fork()){

case -1:fprint(stderr,"*s:eroare fork\n",argv[0]);

exit(1);

case 0:close(STDIN_FILENO);

close(STDERR_FILENO);

/* se trateaza zombie */

act.sa_handler=sig_chld;

act.sa_flags=0;

sigemptyset(&act.sa_mask);

sigaction(SIGCHLD,&act, NULL);

for(;;){

lgclient=sizeof(struct sockaddr_in);

/* procesul se autoblocheaza in asteptarea

* unei cereri de conexiune

*/

again:

sock=accept(consock,(struct sockaddr *)&remote,

&lgclient);

if(sock==-1){

if (errno==EINTR)

goto again;

exit(1);

}

switch(fork()){

case -1:exit(1);

/* se trateaza cererea pentru un serviciu */

case 0:service();

exit(0);

default:close(sock);

}

}

default:exit(0);

}

}

sevice(){

char *numenod;

int mesaj,rest;

char buf[100];

time_t timp;

long opt;

/* se inchide soclul mostenit */

close(consock);

/* se preiau informatii despre noodul care a lansat cererea */

hptr=gethostbyaddr((char*)&remonte.sin_addr,

sizeof(struct in_addr),remonte.sin_family);

if(hptr==NULL)

numenod=(char *)inet_ntoa(remonte.sin_addr);

else numenod=(char *)hptr->_name;

/* se inregistreaza in fisierul de iesire identitatea clientului

* si data conectarii

*/

time(&timp);

printf("Clientul *s s-a conectat la portul *u la data de *s\n",

numenod,ntohs(remonte.sin_port),ctime(&timp));

if(setsockopt(sock,SOL_SOCKET,SO_LINGER,(char*)&opt,

sizeof(long))==-1){

printf("server:eroare setsockopt la *s \n",numenod);

exit(1);

}

/* se intra intr-o bucla de receptie mesaj de la client */

mesaj=recv(sock,buf,DIM,0);

if(mesaj==-1){

printf("server:eroare recv\n");

exit;

}

while(mesaj<DIM){

rest=recv(sock,&buf[mesaj],dim-mesaj,0);

if(rest==-1){

printf('server:eroare recv\n");

exit;

}

mesaj+=rest;

}

/* procesarea cererii primita de la client */

sleep(1);

strcpy(buf,(char *)ctime(&timp));

if(send(sock,buf,DIM,0)!=DIM){

printf("server:eroare send\n");

exit;

}

close(sock);

time(&time);

printf("Clientul *s de la portul *u a terminat la data *s\n",

numenod,ntohs(remonte.sin_port),ctime(&timp));

}

static void sig_chld(int sem){

white(NULL);

}

/* Client TCP- Clientul se lanseaza dupa lansarea serverului;

* clientul apeleaza serviciul "exemplu"

* deci acesta trebuie sa existe in sistem

*/

#include <stdio.h>

#include <string.h>

#include <sys/types.h>

#include <sys/socket.h>

#include <netinet/in.h>

#include <netdb.h>

#define DIM 100

main(int argc, char *argv[]){

struct sockaddr_in local;

struct sockaddr_in remote;

struct hostent *hptr;

struct servent *sptr;

int sock;

time_t timp;

int lgadr,dim,rest;

char buf[DIM];

if(argc!=2){

fprint(stderr,"Utilizati :*s <hostremote>\n",argv[0]);

exit(1);

}

/* initializarea structurior de adrese */

memset((char*)&local,0,sizeof(struct sockaddr_in));

memset((char*)&remote,0,sizeof(struct sockaddr_in));

remote.sin_family=AF_INET;

/* se cauta informatii despre client */

hptr=gethostbyname(argv[1]);

if(hptr==NULL){

fprintf(stderr,"*s :*s nu este gasit in /etc/hosts\n"

,argv[0],argv[1]);

exit(1);

}

remote.sin_addr.s_addr=((struct in_addr*)hptr->h_addr)->s_addr;

/* se cauta informatii despre server */

sptr=getservbyname("exemplu","tcp");

if(sptr==NULL){

fprintf(stderr,"*s: eroare getservbyname\n",argv[0]);

exit(1);

}

remote.sin_port=sptr->s_port;

sock=socket(AF_INET,SOCK_STREAM,0);

if(sock==-1){

fprintf(stderr,"*s:eroare socket\n",argv[0]);

exit(1);

}

/* se incearca o conectare la server */

if(connect(sock,(struct sockaddr *)&remote,sizeof(struct sockaddr_in))==-1){

fprintf(stderr,"*s: eroare connect\n",argv[0]);

exit(1);

}

lgadr=sizeof(struct sockaddr_in);

if(getsockname(sock,(struct sockaddr *)&local,&lgad)==-1) {

fprintf(stderr,"*s: eroare sockname\n",argv[0]);

exit(1);

}

/* se afiseaza momentul conectarii la server */

time(&timp);

printf("\nConectat la *s pe portul *u la *s\n",

argv[1],ntohs(local.sin_port),(char *)ctime(&timp));

sleep(2);

/* se trimite cererea la server */

strcpy(buf,"Cerere de data curenta\n");

if(send(sock,buf,DIM,0)!=DIM) {

fprintf(stderr,"*s: eroare send ;",argv[0]);

exit(1);

}

if(shutdown(sock,1)==-1){

fprintf(stderr,"*s: nu se poate inchide socket\n”,

argv[0]);

exit(1);

}

/* se receptioneaza raspunsul de la server */

dim=recv(sock,buf,DIM,0);

if(dim==-1){

fprintf(stderr,"*s eroare recv\n",argv[0]);

exit(1);

}

while(dim<DIM){

rest=recv(sock,&buf[dim],DIM-dim,0);

if(rest==-1){

fprintf(stderr,”*s eroare recv\n”,argv[0]);

exit(1);

}

dim+=rest;

}

printf("Client-mesaj primit: *s\n",buf);

time(&timp);

printf("Terminat cu succes la data de *s\n",ctime(&timp));

}

4. Comunicarea prin IPX (Internetwork Packet

Exchange) și SPX (Sequenced Packet Exchange)

Aceste două protocoale au fost introduse cu succes de Novell în produsele NetWare. IPX este protocolul de bază Novell NetWare și este recomandat de Novell ca protocolul de comunicație pentru aplicațiile client-server.Protocolul IPX este o implementare a protocolului Internetwork Datagram Packet (IDP) proiectat de Xerox Corporation. Este un protocol neorientat pe conexiune și suportă numai mesaje de tip datagrame. Pe de altă parte, protocolul SPX este orientat pe conexiune; livrarea pachetelor necesită stabilirea unei conexiuni, emisia/recepția mesajelor printr-un dialog adecvat și închiderea sesiunii. Astfel, se poate spune că interfața de programare în IPX corespunde nivelului rețea iar interfața de programare în SPX corespunde nivelului sesiune .

Structura unui pachet IPX este identică cu structura unui pachet Xerox Internetwork Standard (XNS) care constă într-un header de 30 octeți urmat de 0 până la 576 octeți în zona de date.

Structura unui pachet IPX:

unsigned short checksum; /*high-low 1-s complement*/

unsigned short packetLen; /*high-low*/

unsigned char transpotrControl;

unsigned char packettzpe;

unsigned long destNetwok; /*high-low*/

unsigned char destNode[6];

unsigned short destSocket; /*high-low*/

unsigned long sourceNetwork[6] /*high-low*/

unsigned char sourceNode[6] /*high-low*/

unsigned short sourceSocket; /*high-low

Header-ul unui pachet SPX are în plus 7 câmpuri:

unsigned char connectionControl; /*bit flags*/

unsigned char dataStreamtzpe,

unsigned short sourceConnectionID; /*high-low*/

unsigned short destConnectionID; /*high-low*/

unsigned short sequenceNumber; /*high-low*/

unsigned short acknowledgeNumber; /*high-low*/

unsigned short allocationNumber /*high-low*/

Un mesaj pote fi trimis către orice nod din rețea prin plasarea lui în zona de date a unuib pachet. Fiecare pachet trebuie să specifice adresa de destinație, sub forma unui cuplu (rețea destinație,adresa nod,soclu). Rețeaua destinație (câmpul destNet din structura IPX) este un număr de 4 octeți care specifică numărul rețelei locale și este 0 pentru un nod pe aceeași rețea locală ca și nodul emițător. Adresa nodului destinație (câmpul destNode din structura IPX) este un număr pe 6 octeți care conține adresa fizică a nodului destinație și care poate fi setată la 0x FF FF FF FF FF FF pentru a trimite un pachet broadcast. Soclul destinație (câmplul destSocket din structura IPX) este un câmp pe 2 octeți conținând adresa soclului procesului destinație.

Un pachet SPX conține în plus în header 12 octeți pentru a urmări secvența pachetelor și numărul confirmărilor și poate conține până la 534 octeți de date. Aplicațiile care transmit pachete SPX trebuie să stabilească conexiuni cu aplicațiile destinație; pachetele transmise pentru care nu s-a primit confirmare sunt retransmise după expirarea unui interval de timeout. După un anumit număr de retransmisii neconfirmate se presupune că aplicația destinație nu mai “ascultă” sosirea pachetelor și întrerupe conexiunea.

Înainte de a utiliza fie funcțiile IPX fie funcțiile SPX aplicațiile trebuie să pregătească și să completeze o structură de date numită EventControlBlock(ECB). Numai după aceea se pot apela funcțiile IPX sau SPX cu pointeri către ECB, care conține adresa pachetului IPX sau SPX.

Un sistem client-server tipic constă într-un proces server care deschide un soclu (Novell IPX API: IPXOpenSocket) și așteaptă să recepționeze un pachet de la orice client (Novell IPX API: IPXListenForPacket). Serverul poate de asemenea să “anunțe” prezența sa (Novell Bindery API: AdvertiseService) astfel încât atunci când un client trebuie să se conecteze la server, el poate să găsească serverul (Novell Bindery API: ScanBindery) și să determine adresa sa (Novell IPX API: IPXGetLocalTarget). în final, clientul poate trimite o cerere de serviciu la server (Novell IPX API: IPXSendPacket).

Se prezintă în continuare un exemplu de comunicație prin IPX; exemplul constă în două programe (unul emițător și celălalt receptor) care se execută pe două stații într-o rețea Novell: programul emițător (clientul) determină adresa stației pe care se execută celălalt program (serverul) cunoscând numele sub care s-a făcut conectarea (numele de “login”) și îi trimite apoi un mesaj.

Serverul, care poate primi un pachet de la orice stație afișează adresa stației de la care s-a primit pachetul, lungimea și conținutul mesajului primit.

Ambele programe, la începutul execuției afișează adresa propriei stații.

/* Programul emitator are rol de client si se lanseaza in executie inaintea

* serverului. Programul transmite un mesaj unei statii cunoscind numele

* utilizatorului car a deschis sesiunea de lucru la statia destinatie

*La inceput, se afiseaza adresa locala.

*/

#include <stdio.h>

#include <bios.h>

#include <ntx.h>

#include <mem.h>

#include <nit.h>

#include <string.h>

#define DATA_LENGTH 500

int main (void) {

BYTE netAddress[10];

int i,status;

ECB ecb;

IPXHeader headerPacket;

unsigned char dataPacket[DATA_LENGTH];

WORD sessionSocket=0x5000;

WORD targetSocket=0x5000,Socket;

BYTE targetNode[6]={0xff,0xff,0xff,0xff,0xff,0xff};

BYTE targetNetwok[4]={0x00,0x00,0x00,0x00};

int connectionNumber;

void FindDestinationAddress( int *connectionNumber );

/* initializare IPX */

if(IPXInitialize()!=0) {

printf("\nIPX nu este instalat!");

return 1;

}

/* afisarea adresei statiei */

IPXGetInternetWorkAddress(netAddress);

printf("\n\nAdresa de retea: ");

for (i=0;i<4;i++)

printf("*02hx ",netAddress[i]);

printf("\nadresa de nod: ");

for (i=4;i<10;i++)

printf("*02hx ",netAddress[i]);

/* determinarea statiei pe care se executa programul receptor

*/

FindDestinationAddress(&connectionNumber);

GetInternetAddress(connectionNumber,(char *) targetNetwork,

(char *)targetNode,&Socket);

/* initializarea structurilor de date */

movmem(targetNetwork,headerPacket.destination.network,4);

movmem(targetode,headerPacket.destination.node,6);

movmem(&targetSocket,headerPacket.destination.socket,2);

movmem(targetNode,ecb.immediateAddress,6);

sprintf(dataPacket,"*s","Mesaj de la sursa la destinatie.")

ecb.ESRAddress=NULL;

ecb.inUseFlag=0;

ecb.fragmentCount=2;

ecb.socketNumber=sessionSocket;

ecb.fragmentDescriptor[0].address=&headerPacket;

ecb.fragmentDescriptor[0].size=sizeof(IPXHeader);

ecb.fragmentDescriptor[1].address=(BYTE *) dataPacket;

ecb.fragmentDescriptor[1].size=strlen(dataPacket)+1;

/* deschiderea soclului si transmisia mesajului*/

if((status=IPXOpenSocket((BYTE*)&sessionSocket,0x00))==0) {

IPXSendPacket(&ecb);

printf("Asteptare in emisie…");

while(ecb.inUseFlag!=0) {

IPXRelinquishControl();

}

if(ecb.completionCode==0)

printf("\nMesajul care a fost trimis este\"*s\"",

dataPacket);

else

printf("\nEroare IPXSendPacket: *x",ecb.completionCode);

}else {

printf("\nEroare IPXOpenSocket: *h",status);

return 1;

}

/* inchiderea soclului */

IPXCloseSocket(sessionSocket);

return 0;

}

void FindDestinationAddress( int *connectionNumber ){

/* determina adresa unei statii cunoscind numele de login */

char name[40] ;

WORD numberOfConnections ;

WORD connectionsList[1] ;

WORD maxCconnections = 1 ;

printf("\nDati numele de login al statiei

destinatie:");

scanf("*s",name);

GetObjectConnectionNumbers(name,OT_USER,

&numberOfConnections,connectionList,

maxConnections) ;

*connectionNumber = *connectionList ;

}

/* Programul receptor- are rol de server si se lanseaza inaintea

* clientului; programul receptioneaza un mesaj de la orice statie

* din reteaua locala;

* La inceput afiseaza adresa locala;

* dupa primirea unui pachet afiseaza:

* – adresa statiei care a transmis masajul

* – lungimea si continutul mesajului (pentru calculu lungimii

* se ia in considerare si hederul pachetului IPX)

*/

#include <stdio.h>

#include <bios.h>

#include <ntx.h>

#include <string.h>

#define DATA_LENGTH 500

int main(void) {

BYTE netaddress[10];

int i,status;

WORD length;

ECB ecb;

IPXHeader headerPacket;

unsigned char dataPacket[DATA_LENGTH];

WORD sessionocket=0x5000;

/* initializarea IPX */

if(IPXInitialize()!=0) {

printf("\nIPX nu este instalat.");

return 1;

}

/* afisarea adresei statiei */

IPXGetInternetworkAddress(netAddress);

printf("\nAdresa de retea: ");

for (i=0;i<4;i++)

printf("%02hx ",netaddress[i]);

printf("\Adresa de nod: ");

for (i=4;i<10;i++)

printf("*20hx ",netaddress[i]);

/* initializarea structurilor de date */

ecb.ESRAddress=NULL;

ecb.inUseFlag=0;

ecb.fragmentCount=2;

ecb.socketNumber=sessionSocket;

ecb.fragmentDescriptor[0].address=&headerPacket;

ecb.fragmentDescriptor[0].size=sizeof(IPXHeader);

ecb.fragmentDescriptor[1].address=(BYTE *) dataPacket;

ecb.fragmentDescriptor[1].size=DATA_LENGTH;

/* deschiderea soclului si intrarea in "ascultare" de pachete */

if((status=IPXOpenSocket((BYTE*)&sessionSocket,0x00))=) {

IPXListenForPacket(&ecb);

printf("\nAsteptare la receptie…");

while(ecb.inUseFlag!=0) {

IPXRelinquishControl();

if(bioskey(1)) {

printf("\nReceptie anulata.");

IPXCancelEvent(&ecb);

IPXCloseSocket(sessionSocket);

return 1;

}

}

/* dupa primirea unui pachet, afisarea adresei statiei care

* a transmis mesajul, a lungimii pachetului si a

* continutului sau

*/

if(ecb.completionCode==0) {

printf("\nS-a primit de la statia ");

for (i=0;i<6;i++)

printf(" 02hx ",((IPXHeader*)&headerPacket)>source.node[i]);

length=((IPXHeader*)&headerPacket)->length;

length=(length*256)*256+length/256;

printf("un mesaj de *d octeti.\nMesajul este:*s",

length,dataPacket);

}else

printf('\nEroare receptie: *x",ecb.completionCode);

}else{

printf('\nEroare OpenSocket: *h",status);

return1;

}

/* inchiderea soclului */

IPXCloseSocket(sessionSocket);

return 0;

}

IPX furnizează o rapidă și eficientă interfață de comunicație datorită regiei de sistem scăzute asociate transmisiei fiecărui pachet și simplității modelului bazat pe datagrame. SPX, pe de altă paret, furnizează o interfață de comunicație stabilă, orientată pe conexiune care câștigă în viteză datorită integrării cu IPX.

Ambele protocoale IPX și SPX prezintă dezavantajul interfeței de programare mult prea apropiată de sistem.

Făcând o comparație între interfața de programare prin socluri în UNIX și interfața de programare în IPX și SPX, se poate că interfața de programare prin socluri este mult mai aproape de un nivel abstract de programare (nivel API) deoarece fiecare funcție furnizează un grad mai mare de abstractizare în sistem; și mai mult, interfața de programare prin socluri furnizează un mecanism de multiplexare a cererilor la nivelul serverului și tehnici avansate pentru transferul asincron al datelor.

5. Proiectarea unui sistem distribuit bazat pe modelul

client-server

DOSTP este un sistem experimental care oferă, la nivelul sistemului de operare, un suport pentru dezvoltarea aplicațiilor distribuite bazate pe acțiunea tranzacțiilor atomice asupra unor obiecte partajate într-o rețea de calculatoare.

Până în momentul de față, DOSTP a fost implementat într-o rețea locală de calculatoare care cuprinde o stație DEC Alpha OSF/1 vers.1.34 și patru calculatoare PC486DX2/66 cu Linux, și într-o rețea Novell NetWare 3.11 (rețele Ethernet).

DOSTP are 6 componente; două dintre acestea sunt programabile de utilizatori. Funcțiile lor sunt descrise pe scurt mai jos:

1. Serverul de comunicație este un singur proces în fiecare nod; rolul său este de a asigura comunicarea aplicațiilor de pe acel nod cu restul sistemului. Serverul de comunicații asigură independența aplicațiilor față de localizarea serverelor de obiecte. Pentru a determina localizarea unui obiect în rețea, serverul de comunicații interoghează serverul de nume local.

2. Serverul de nume, un singur proces în fiecare nod, are rolul de a memora și determina plasarea managerilor de obiecte din rețea.

3. Managerul tranzacțiilor, un singur proces în fiecare nod, are rolul de a recepționa și trata toate apelurile BeginTransaction, EndTransaction și AbortTransaction. Acest proces este cel ce coordonează protocolul “two-phase commit” pentru tranzacțiile distribuite.

4. Serverele de obiecte sunt module programabie de utilizator, pe baza unor funcții de bază livrate cu DOSTP, într-o billitecă de funcții. Rolul lor este de a implementa operațțile asupra obiectelor partajate și de a rezolva concurnța la nivelul obictelor. DOSTP nu limitează numărul serverelor de obiecte dintr.un nod.

5. Serverele de recuperare sunt legate de serverele de obiecte; ele asigură, câte unul pentru fiecare tip de obiect, recuperarea tranzacțiilor abordate voluntar de aplivațții (AbortTransaction) sau involuntar (datorită problemelor de concurență sau căderii unui nod).

6. Aplicațiile sunt scrise de utilizatori. DOSTP pune la dispoziția utilizatorilor un set de funcții apelabile din aplicații pentru accesul la obiectele partajate în rețea.

Varinta Unix a sistemului DOSTP folosește modelul client-server atât pentru comunicația în rețea cât și pentru comunicația într procesele locale. Modelul client-server apare astfel implementat în comunicația prin socluri dar și în comunicația prin comenzi de mesaje, structuri FIFO și stream pipes.

Varianta Novell NetWare 3.11 a sistemului DOSTP se bazează pe un nucleu multitasking local dezvoltat pentru fiecare situație.

6. Java – o alternativă de care trebuie să se țină seama

In momentul de față, ca orice “ vedetă “, Java are fani și adversari. Primii consideră că Java rezolvă orice, cei din urmă spun că Java nu este nimic altceva decât o jucărie, încă un limbaj orientat obiect, că tot ce se poate face în Java se poate realiza și în Visual Basic, Java nefiind nimic altceva decât un CGI mai evoluat. Un alt grup speră că Java este soluția care va detrona viitorul tiran mondial Microsoft.

Utilizarea Java este una din alternativele care trebuie să fie luate în considerare la demararea oricărui proiect, mai ales dacă proiectul are în vedere utilizarea accesului la Internet sau realizarea unui intranet .

Pentru a înțelege ce înseamnă Java, trebuie să avem în vedere tendința pe care o are Internetul de a deveni un bun de folosință comună, o piață imensă, un teren de încheiere, de desfășurare a afacerilor, ceea ce a focalizat interesul firmelor și al cercetătorilor din domeniul calculatoarelor. O altă tendință semnificativă constă din utilizarea tot mai frecventă a soluțiilor de tip intranet pentru implementarea sistemului informatic în cele mai diferite companii, cu alte cuvinte utilizarea tehnologiilor elaborate pentru rețeaua “ mare ” (Internet) în rețeaua internă .

În condițiile în care într-o instituție trebuie să circule informații, acestea pot să circule ca documente pe hârtie (purtată de curieri umani), ca fișiere pe dischetă (tot curieri umani ); urmează apoi faza în care se transferă fișiere prin rețea (curierul devine o rețea de date, care poate să utilizeze diferite tipuri de tehnologii ), iar cea mai nouă soluție este că ceea ce se transmite este un URL (o adresă în Internet ) de la care se poate prelua dacă este de interes informația respectivă (în acest caz curierul este o rețea de date de tip Internet ) . Cea mai bună compresie de fișiere este să transmiți a adresă în loc de conținutul unui fișier.

Cam tot ce se realizează acum sub eticheta tehnologiei informației este să fie legat de Internet, fie accesibil și din Internet, fie este de tip Internet (intranet). Coincidența apariției Java cu acest fenomen a făcut din Java un instrument fundamental pentru dezvoltarea soluțiilor legate de Internet. In momentul de față mașina virtuală Java este implementată (și deci se pot executa orice fel de programe) pe majoritatea platformelor Sun™ , IBM™, Microsoft™, HP™ , Apple™, Novell™, SCO™, Hitachi™, Tandem™ și SGI™ .

Legătura care s-a creat între Internet și Java a condus la situația în care majoritatea companiilor care și-au propus să dezvolte aplicații care să aibă legătură cu Internetul să considere Java ca limbaj de implementare. Corespunzător, o serie de noi concepte și tehnologii au apărut întâi în soluții bazate pe Java . Astfel încât , în acest moment numele Java nu mai desemnează pur și simplu un limbaj de programare, ci un ansamblu de tehnologii care permit trecerea de la o abordare a aplicațiilor de tip desk- centric la una network – centric, realizându-se platforme de calcul deschise și universale accesibile din Internet.

Java – un model client / server

Se poate vorbi acum de un model de calcul reprezentativ pentru Java. Este vorba de un model care la bază este client / server. În Internet se poate considera că există producători de informație (sau deținători de informație ) și consumatori de informație.

Prima categorie o reprezintă serverele de date, implicit aici este nevoie de resurse mai puternice ( memorie, spațiu pe disc, administrare profesională pentru că aici apar probleme de protecție, de asigurare a unei disponibilități totale, a accesului unui număr semnificativ de utilizatori etc.). Consumatorii de informație sunt clienții și au nevoie de resurse tot mai puține. În condițiile în care nu numai informațiile, dar și programele sunt păstrate pe servere, pe client se poate rula numai un singur program, și anume un navigator în Internet care să “ știe “ să aducă informații și programe din Internet. Și, evident, să fie în stare să le execute pe cele din urmă. Se spune despre servere că se “ îngrașă ” , iar despre clienții că “slăbesc “.

S-a ajuns astfel la noțiunea de calculator de rețea ( Network Computer ), care nu este altceva decât un terminal la marea mașină de calcul, care este Internetul. Un astfel de calculator are costuri de administrare zero, pentru că administrarea sa se face de la server. Un sistem mai puțin democratic, dar mai eficient și foarte potrivit pentru sistemele informatice la care majoritatea utilizatorilor trebuie să folosească calculatoarele numai pentru pregătirea de documente, transmiterea respectiv primirea de mesaje sau informații.

Modelul Java reprezintă acum o combinație de tehnologii care asigură accesul uniform la date ( prin intermediul interfeței prezentate de programele de navigare în rețea și o reprezentare a informațiilor în formatul HTML ), la programe ( scrise în limbajul Java )și la rețea ( protocoale TCP/IP, HTTP, IIOP etc.) .

Un termen care a apărut în legătură cu Java este termenul de applet. Reprezintă un program care poate fi invocat din cadrul unei pagini aduse din Internet. Ceea ce se aduce din Internet este codul binar al programului care urmează să se execute. Pentru acest program drepturile de acces la resursele sistemului sunt mult mai reduse, deoarece un applet este suspectat că ar putea să facă ceva rău (aici nu poate funcționa prezumția de nevinovăție). Înainte de a se trece la execuția programului se face o verificare a codului binar, pentru a identifica eventualele secvențe periculoase. A apărut și termenul de servlet care este diminutivul celui de server, așa cum applet este diminutivul termenului application (aplicație).Dacă applet-ul este ceva ce se execută pe calculatorul local în beneficiul clientului, servlet-ul este un program care se execută pe server în beneficiul aceluiași client. Dar în Java se pot elabora și aplicații “obișnuite”.

Avantajele utilizării soluției Java în acest caz constau din faptul că ele se pot executa oriunde există implementată mașina virtuală: Netscape, Internet Explorer, HotJava.

Deoarece Java este independent de platformă, clienții Java se pot executa pe clienți care sunt înglobați în aparatură electronică inteligentă ca, de exemplu, în telefoane mobile, smart card-uri, remonte-control etc.

Se poate observa că tehnologia dezvoltată pentru Java poate fi utilizată într-o manieră elegantă pentru realizarea obiectivului inițial al limbajului .

Un limbaj în evoluție

Ca limbaj, Java este încă în plină evoluție din punct de vedere al bibliotecilor standard de metode utilizate. versiunea curentă este 1.1, iar versiunea 1.2 este deja disponibilă în varianta beta.

Pentru 1.2, majoritatea API-urilor (Application Programming Interfaces ) au fost extinse și au fost adăugate altele noi (de exemplu, swing – Java Foundation Classes ).

toate extinderile s-au făcut cu păstrarea compatibilității înapoi (back – wards ).

În momentul de față s-a făcut o clasificare a interfețelor în funcție de domeniul de aplicații, numai o parte din aceste interfețe vor fi definite de către JavaSoft , pentru restul se așteaptă contribuția dezvoltatorilor de aplicații. Deocamdată se consideră următoarele familii de interfețe :

Core – reprezintă biblioteca ce conține nucleul de clase Java. Clasele din această bibliotecă sunt dezvoltate de către JavaSoft și sunt distribuite odată cu JDK ( Java Development Kit ). Este vorba de operațiile legate de interfața grafică, de implementarea structurilor de date, operații de intrare – ieșire, utilizarea rețelei. În acest grup este conținut un nucleu care trebuie să fie implementat de toți cei care vor să construiască un interpretor pentru mașina virtuală. Acest nucleu se referă numai la sintaxa de bază a limbajului. Această reducere a nucleului la un set minimal s-a făcut pentru a permite implementarea mașinii virtuale și pe calculatoare de tip “main-frame” care nu au facilități de grafică.

Enterprise – reprezintă un grup de interfețe care sunt utilizate pentru realizarea de aplicații de tip informatizarea companiilor.

JDBC (Java Database Connectivity ) – reprezintă un set de interfețe pentru accesul la baze de date de tip relațional.

RMI, CORBA IDL – biblioteci pentru programarea distribuită.

Transaction Services – servicii în timp real pentru procesarea tranzacțiilor.

Object Serialization, ODBMS – interfață de comunicare cu Object Database Management Systems.

Management – bibliotecă de clase pentru supravegherea și gestiunea rețelelor.

Embedded – bibliotecă pentru clase pentru aparatură electronică inteligentă.

Security – un grup de biblioteci utilizate pentru transmiterea aplicațiilor în Internet într-o manieră sigură.

Media – reprezintă un grup de biblioteci care sunt focalizate pe publicare, animație, sunet etc. : Media Famework, java.2D – grafică 2D, java.3D – grafică 3D, Telephony, SRaPI – Speech Recognition aPi, VRML – Virtual Reality Modeling Language.

Commerce – este un pachet care face parte dintr-o inițiativă mai largă, numit Java Electronic Commerce Framework (JEFC) , care are drept obiectiv crearea unui mediu standard pentru comerțul electronic.

Server – bibliotecă de clase pentru scrierea de aplicații de tip server.

Pentru a mări eficiența producerii de programe în Java, compania Sun Microsystems ™ a introdus o standardizare a tehnologiei de reutilizare a componentelor de program ; este vorba de Java Beans. După ce s-a găsit factorul comun la nivelul mașinii virtuale, care transcede arhitecturile calculatoarelor și sistemelor de operare, arhitectura Java Beans are ca scop să transceadă comportările posibile de programe. Așa cum plăcile de calculator se construiesc acum din componente standard, și programele se pot construi utilizând “componente de pe raft”

clase și metode din biblioteci de componente, utilizând medii de programare care știu să asambleze automat aceste componente.

Java Beans este un standard pentru crearea de obiecte care au o comportare descrisă utilizând un mecanism special, numit Integrated Development Environment. Pe baza IDE, instrumentele de proiectare “ știu “ cum să lucreze cu obiectele. Un bean este o componentă software care poate să fie manipulată vizual de un instrument de proiectare Java Beans ; seamănă într-un fel cu componentele activeX (pentru care specificarea este făcută în Visual Basic, generându-se cod C++ ) , dar au fost dezvoltate pentru platforma Java , adică pot să fie utilizate pe orice platformă de calcul. Există deja mii de clase disponibile în Internet sau comerciale care pot să fie reutilizate.

Java – dezavantaje

Nu am face o analiză corectă a soluției Java dacă nu am discuta și problemele, dezavantajele pe care le prezintă soluția Java. Principalul dezavantaj constă din viteza de execuție a programelor scrise în Java fie ele applet-uri sau aplicații care sunt mai lente decât cele scrise într-un limbaj pentru care execuția nu este interpretată.

Este prețul plătit pentru utilizarea interpretării ca soluție de asigurare a securității programelor.

Această situație poate să fie ameliorată prin utilizarea compilării la momentul execuției (Just in Time Compiling ), care permite și realizarea unei optimizări specifice configurației pe care urmează să se execute programul.

O altă problemă, despre care se discută foarte mult, este cea legată de nivelul de încredere care poate să fie asigurat în condițiile aduceri și execuției unui program din Internet. Este important de remarcat faptul că soluția Java nu introduce probleme noi, ci doar încearcă să rezolve probleme care există oricum.

Faptul că a existat acces liber la informațiile legate de Java (inclusiv la nivel de surse de compilatoare ) a permis atât identificarea unor erori de proiectare , cât și realizarea unor atacuri în cunoștință de cauză . Se lucrează destul de mult în această direcție, se utilizează metode de autentificare, criptare , introducerea conceptului de niveluri de încredere care au asociate diferite niveluri de acces la resurse etc.

Dacă în urmă cu doi ani, în mod democratic, Java era soluția programatorului “sărac”, care avea acces la aceleași instrumente de proiectare ca orice alt programator ( este vorba de conținutul pachetului de programe JDK ), acum lucrurile s-au mai schimbat. Au apărut medii de proiectare care nu sunt chiar ieftine, Dar care asigură o mare productivitate pentru programatori. Printre cele mai cunoscute medii se pot aminti Java Workshop, Java Studio (Sun Microsystems ), VisualAge (IBM), Symatec Cafee etc. De asemenea există o cantitate imensă de biblioteci de clase comerciale pe cele mai diferite subiecte.

Activitatea artizanală poate concura cu succes activitatea industrială .

Java™ – o soluție pentru programarea în Internet și nu

numai

Java™ a fost conceput inițial (1995) ca un limbaj pentru programarea aparaturii electronice inteligente , în condițiile în care se dorea ca această aparatură să funcționeze în rețea , în proiecte ca televiziune interactivă sau casă inteligentă . Pe vremea aceea se numea Oak si era soluția la care o echipă a companiei Sun Microsystems™ a ajuns pentru a își crește șan-sele de a elabora programe corecte utilizând un limbaj orientat obiect. Soluția considerată inițial a fost limbajul C++ (acțiunea se petrecea în mediul industrial) . Dar limbajul C++ a fost construit prin extinderea limbajului C și moștenește de la acesta o serie de elemente care favorizează apariția de erori de programare (aritmetica pe pointeri, eliberarea explicită a memoriei etc.).

Pe de altă parte, în C++ există mecanisme, cum ar fi, de exemplu, cel de moștenire multiplă, care chiar dacă sunt foarte elegante din punct de vedere conceptual, produc programe în legătură cu care este dificil de construit raționamente de tip demonstrare a corectitudinii .

După ce a fost utilizat pentru realizarea unor proiecte, s-a constatat că în momentul respectiv (1996) exista un interes modest pentru aplicații de tip aparatură electronică conectată în rețea, smart card-uri, telefoane mobile inteligente etc. Ceea ce părea “ încă un proiect ratat ” așa cum are orice companie care este în căutare de piețe, în general de idei noi, printr-o acțiune care s-a bazat mai mult pe aspecte de marketing decât pe cele tehnice, s-a transformat într-un mare succes.

Din punct de vedere tehnic, salvarea s-a numit utilizarea limbajului, rebotezat acum Java, pentru o aplicație foarte la modă, și anume un program de navigare în Internet. La vremea ceea cele două programe de navigare în Internet – Netscape si Internet Explorer nu goniseră complet concurența în domeniu. Navigatorul se numea HotJava si chiar dacă nu s-a impus la nivelul celor două programe menționate , a impus o scriere de idei noi.

Din punct de vedere marketing, soluția s-a numit tot Internet. Ideea de bază este că toate cheltuielile de marketing legate de promovarea si distribuția acestui limbaj au fost utilizate pentru campania de publicitate care a însoțit lansarea sa. Au fost făcute publice în Internet toate informațiile necesare pentru dezvoltarea de aplicații în Java: documentație destul de bună, un pachet de programe pentru dezvoltarea aplicațiilor(compilator, depanator,genera- tor de documentație pe baza textului programului, interpretoare etc.) , biblioteci de clase utile, exemple etc. Să mai menționăm și faptul că de la început a fost posibil să se dezvolte aplicații atât pentru platformele Sun, cât și pentru platformele Windows. Și totuși, numai atât nu ar fi fost de ajuns, în Internet se găsește doar atâta informație de care nu a auzit ni-meni și nu o să audă nimeni. Chiar și campania de marketing care a urmat și care a făcut din Java un subiect pentru emisiuni de televiziune și articole în reviste financiare , nu ar fi fost de ajuns pentru ceea ce a urmat.

Discuția despre limbajul Java trebuie să se poarte atât la calitățile limbajului în sine , ca limbaj de programare , cât și la soluția de implementare care a fost gândită pentru a permite utilizarea pentru transferul și exploatarea programelor în Internet . Calitatea principală a acestei soluții constă din posibilitatea îndeplinirii condiției : “write once, run everywhere “ .

Implementarea limbajului Java presupune existența unui “factor comun “ – o mașină virtuală.

Trecerea la o platformă nouă însemnă implementarea unui simulator pentru mașina virtuală. Ceea ce se difuzează în Internet este formatul binar pentru mașina virtuală.

Desigur, o serie de aspecte care țin de definiția limbajului susțin calitatea soluției .

Putem enumera acum câteva dintre problemele pe care soluția de implementare bazată pe mașina virtuală a limbajului Java le rezolvă.

Există numeroase scenarii conform cărora se ajunge în situația în care trebuie să se execute pe calculatorul local programe aduse din Internet. Orice astfel de program trebuie să fie considerat ca suspect. Istoria ultimilor ani este plină de povești de groază cu viruși, cai Troieni, spionaj etc. Utilizarea unei interpretări în loc de execuție directă permite o verificare a codului care urmează să se execute, impunerea unor restricții specifice condițiilor de execuție pentru accesul la resursele calculatorului local.

Utilizarea Internetului ca mediu pentru difuzarea de informații, dar și de programe

conduce la ideea de factor comun, de platformă comună pentru care să fie dezvoltate aplicațiile. De la aplicații pentru Internet, extinderea acestui concept la orice tip de aplicație este imediată. Costurile implicate de dezvoltarea de aplicații pot să scadă dramatic dacă nu sunt necesare adaptării de soluții pentru fiecare tip sau versiune de hardware sau de sistem de operare existent în lume.

Se păstrează încă foarte multe baze de date cu informații acumulate în decenii (legacy systems). Se dorește exploatarea acestora utilizând sisteme de calcul și subsisteme de operare din generații mai noi. Efortul de a rescrie programele corespunzătoare în limbaje de programare mai noi este foarte mare. Soluția creării unui înveliș prin care aplicațiile corespunzătoare să devină accesibile din Internet într-o manieră transparentă reprezintă o soluție foarte bună.

În momentul de față nu se mai poate concepe funcționarea unei companii sau întreprinderi fără un sistem informatic computerizat.

Costurile administrării calculatoarelor pe care se bazează sistemul informatic sunt foarte mari, mai ales într-un mediu străin de lumea calculatoarelor. Meseria de administrator de sistem, care este ceva între artă și magie neagră, a devenit una dintre cele mai bune plătite meserii.

Acest aspect și altele conduc la situația în care costurile exploatării unui sistem de calcul să devină tot mai mari, uneori (în cazul PC-urilor )

depășind costul echipamentelor respective.

Tehnologia Java poate fi utilizată pentru reducere dramatică a acestor costuri.

7. Sybase PowerSite Builder v1.0

Ce este PowerSite ?

PowerSite este un mediu de dezvoltare pentru aplicații Web. PowerSite poate controla proiecte complexe care necesită lucrul în echipă. Uneltele pe care le pune la dispoziție ușurează dezvoltarea de aplicații care necesită baze de date, programare de tip client/server, servere de aplicații și componente. Modelul obiectelor PowerSite și motorul de portare oferă posibilitatea de a alege ca platformă țintă orice server Web disponibil și de a-l schimba atunci când este nevoie.

Componentele mediului de dezvoltare PowerSite :

managerul de componente PowerSite

clientul PowerSite

motorul de portare

serverul de aplicații PowerDynamo .

Managerul de componente PowerSite realizează distribuția resurselor comune între membrii echipei. Managerul de componente este o bază de date la care au acces toți membrii echipei. Ea cuprinde informații referitoare la fișiere (HTML, imagini, scripturi ), proiecte (liste de fișiere ), utilizatori, link-uri, atribute și drepturi asociate la nivel de proiect . PowerSite face parsing pe paginile utilizate și creează liste cu obiectele referite. Astfel putem știi ce efect va avea înlăturarea unui obiect.

Clientul furnizează unelte pentru lucrul cu proiecte. În client se definesc unul sau mai multe spații de lucru pentru proiectele și resursele care se folosesc. Un spațiu de lucru stabilește o conexiune la managerul de componente. În cadrul unui spațiu de lucru dezvoltatorii și managerii de proiect pot crea și deschide proiecte, pot modifica și pot citi conținutul proiectelor în funcție de permisiunile asociate.

Motorul de portare PowerSite permite plasarea informației pe orice server suportat. Acesta are grijă de aspectele specifice serverului astfel încât nu trebuie create versiuni pentru fiecare mediu de destinație.

PowerSite suportă mai multe browsere și servere Web :

browserele de la Microsoft și Netscape

serverele Web și de aplicații Microsoft și Netscape

serverele de aplicații PowerDynamo.

PowerSite include serverul Web PowerDynamo pentru utilizare în timpul dezvoltării și pentru testare la scară redusă . În timpul dezvoltării nu trebuie să se decidă ce server de aplicații se va folosi.

Dacă scripturile din partea de server folosesc modelul obiectelor PowerSite , atunci, în momentul portării , se face translatarea la modelul serverului de aplicații ales.

Unelte client :

System tree

Favorites

Editors

DataWindow design- time control

File explorer

Telnet Window

Tools customizer

InstaHelp

Unelte externe :

DataWindow Builder

PowerDynamo (parte a SQL Anywhere )

PowerX

Cine folosește PowerSite ?

Echipele de dezvoltatori folosesc PowerSite pentru a crea și modifica, organiza și reutiliza conținutul proiectelor. Managerii de proiect coordonează accesul la conținutul proiectelor prin intermediul drepturilor de acces. Webmasterii coordonează portarea proiectelor pe serverele Web folosind motorul de portare.

Dezvoltatorii de pagini Web folosesc editoarele de HTML și de scripturi integrate, putând include componente ActiveX, applet-uri și plug-in-uri. Ei pot adăuga orice resursă proiectelor, ele fiind partajate de managerul de componente .

Dezvoltatorii de conținut pot utiliza editorul HTML și uneltele externe pentru a crea pagini HTML, imagini, muzică, video și animație. Rezultatul muncii lor poate fi folosit de ceilalți membrii ai echipei.

Dezvoltatorii de componente folosesc de obicei unelte externe ca Power++ sau PowerBuilder. Pot folosi, de asemenea, și PowerX pentru a crea componente ActiveX folosind JavaScript.

Managerii de proiect definesc proiectele și drepturile de acces. PowerSite oferă o aplicație pentru administrarea securității stabilind liste de utilizatori și drepturi de acces la proiecte.

Ce scenarii de dezvoltare suportă PowerSite ?

PowerSite suportă o mare varietate de scenarii de dezvoltare astfel încât se pot construi și întreține aplicații Web în modul optim pentru fiecare proiect.

Importarea unei aplicații Web existente. Dacă se dorește folosirea ca punct de pornire un site Web existent se poate importa în proiect .

Creare unei aplicații Web noi . Se poate folosi PowerSite pentru a crea o aplicație Web cu un conținut nou . În acest caz, conducătorul echipei definește unul sau mai multe proiecte și le asociază membrilor echipei.

Editarea ad-hoc a unei aplicații Web. Dacă dezvoltarea aplicației nu necesită un control riguros, se poate edita orice fișier la care avem acces pe orice site Web. Nu este necesară importarea site-ului, nici folosirea managerului de componente .

Portarea și întreținerea aplicațiilor Web.

Ce fel de aplicații se pot construi ?

Aplicațiile Web construite pot fi pagini HTML standard sau cu design complex necesitând încărcarea de componente, scripturi la server, servere de aplicații și baze de date.

PowerSite suportă toate aromele standard de HTML , scripturi , servere Web și tehnologii pentru componente – incluzând dynamic HTML, JavaScript, orice ActiveScript (VBScript, JScript, DynaScript și altele), componente ActiveX, plug-in-uri, applet-uri Java și Java Beans.

Se pot crea site-uri Web de orice dimensiune. PowerSite suportă cu ușurință crearea de aplicații Web de mare complexitate.

Aplicații dinamice, cu transfer de date, pentru afaceri

Uneltele PowerSite ușurează crearea de aplicații Web pentru afaceri. Spre deosebire de paginile statice HTML care prezintă utilizatorului o interfață fixă, aplicațiile pentru afaceri folosesc, în general, servere de aplicații pentru a oferi informații stocate în baze de date și prezintă o interfață interactivă care permite utilizatorului să execute tranzacții în timp real.

Aplicații deschise

Spre deosebire de cele mai multe unelte pentru dezvoltarea de aplicații Web care sunt pe piață azi, PowerSite folosește o arhitectură deschisă. Se pot dezvolta aplicații pentru orice server de aplicații . Modelul obiectelor PowerSite pentru programarea la server oferă suport direct pentru majoritatea serverelor de aplicații și poate fi extins astfel încât să suporte orice server. Aplicațiile care se creează cu PowerSite pot fi create odată și folosite oricând, pe orice platformă.

Aplicații Next-Generation

Aplicațiile construite cu PowerSite pot folosi avantajele oferite de ultimele dezvoltări în tehnologia Web :

HTML, inclusiv tag-uri proprietare Microsoft Internet Explorer și Netscape

asamblare de componente

scripturi la server

integrare cu PowerBuilder și alte produse Sybase .

Extensii HTML cunoscute:

Microsoft Internet Explorer 3

Microsoft Internet Explorer 4

Netscape Navigator versiunea 3

Netscape Communicator versiunea 4 .

Componente recunoscute:

Microsoft ActiveX

plug-in-uri

applet-uri Java și Java Beans

controale din galeria de componente Powersoft .

Scripturi la server și la client:

PowerSite permite scrierea și debug-ul scripturilor la client și la server. Deoarece PowerSite suportă interfața Microsoft ActiveScript COM , se poate folosi editorul de scripturi pentru a scrie cod într-o mare varietate de limbaje, incluzând JavaScript de la Netscape, JScript și VBScript de la Microsoft.

Se poate face debugul doar pe scripturile client compatibile cu limbajul Dynamo .

Pentru scripturile la server, PowerSite oferă avantajul scrierii de cod o singură dată, urmând ca în final acesta să fie portat automat pe platforma țintă.

Platformele cunoscute sunt:

1. PowerDynamo

2. Microsoft Internet Information Server (IIS) 3.0 Active Server Pages

3. Netscape LiveWire.

Instalarea PowerSite-ului

Instalarea PowerSite-ului se face în două feluri:

Client / server

În această configurație, clientul PowerSite este instalat pe calculatorul personal și pe calculatoarele membrilor echipei, în timp ce serverul PowerSite (managerul de componente ) este instalat pe un calculator separat. Această configurație este cea standard pentru utilizarea în echipă.

De sine stătătoare

În această configurație, atât clientul, cât ți serverul PowerSite sunt instalate pe calculatorul personal. Astfel se poate folosi PowerSite fără restricții. Se poate accesa managerul de componente pe calculatorul personal și, de asemenea, pe alte calculatoare care rulează serverul PowerSite.

Integrare de baze de date:

O facilitate foarte importantă a unei aplicații Web ( care o distinge de site-urile convenționale) este abilitatea de a accesa baze de date pentru a extrage și introduce informații . În plus față de suportul pentru scripting la server, PowerSite oferă unelte pentru integrarea de baze de date în aplicațiile Web:

1. DataWindow Builder

2. SQL Anywhere.

DataWindow Builder permite crearea de obiecte și rapoarte DataWindow.

SQL Anywhere Builder realizează managementul bazelor de date într-o rețea sau pe un singur calculator. SQL Anywhere oferă o interfață grafică pentru managementul bazelor de date.

Organizarea lucrului

PowerSite oferă unelte pentru organizarea lucrului în echipă și individual. Conținutul aplicației este stocat în managerul de componente și organizat în proiecte.

Pentru fiecare membru al echipei este oferită o vedere asupra aplicației prin intermediul spațiilor de lucru.

Despre proiecte:

Un proiect este o listă de fișiere și foldere. PowerSite stochează proiectele și conținutul lor în managerul de componente. Accesul la un proiect este controlat astfel încât doar membrii cu drepturi corespunzătoare îl pot deschide.

Fiecare fișier din managerul de componente este sub control

Doar un membru al echipei poate lucra cu același fișier la un moment dat. PowerSite păstrează urma schimbărilor asupra fișierelor astfel încât ne putem întoarce la o versiune mai veche atunci când este nevoie.

Despre managerul de componente:

PowerSite păstrează urma legăturilor spre fișierele dintr-un proiect. Când se creează un fișier nou sau se modifică unul existent în managerul de componente, PowerSite examinează URL-rile din fișierul HTML și le stochează într-un format special.

Când un fișier este eliminat, PowerSite actualizează legăturile.

Despre spațiile de lucru:

Se pot crea unul sau mai multe spații de lucru. Fiecare are propriul folder Favorites, proiectele asociate și conexiunea la managerul de componente.

Când se deschide un spațiu de lucru se stabilește o conexiune cu un manager de componente specific. Odată conectat se poate deschide orice proiect la care utilizatorul are drepturi de acces.

Se pot edita pagini HTML și scripturi fără a deschide un spațiu de lucru, car nu se pot accesa proiecte.

Securitatea World Wide Web și Java

Sistemul World Wide Web a fost rezolvat inițial pentru a rezolva cererile de informații ale cercetătorilor din domeniul fizicii energiilor înalte. Astăzi, World Wide Web oferă un sistem de distribuție locală sau globală a informațiilor hipermedia. din punct de vedere tehnic, sistemul World Wide Web pune la dispoziție un sistem global de comunicare multimedia.

Informațiile sunt organizate asociativ și sunt distribuite în funcție de cererile utilizatorilor.

Istoricul și evoluția World Wide Web

În articolul “ As We My Think “ din revista The Atlantic Monthly, iulie 1945, Vannevar Bush a descris un sistem de grupare asociativă a informațiilor.

Autorul a numit acest sistem memex (memory extension) și l-a propus ca pe un instrument care să ajute mintea umană să organizeze informațiile.

În 1965, Ted Nelson a inventat termenul hipertext, ca să descrie un text care corespunde modelului lui Bush, în sensul că nu trebuia să fie secvențial. Hipertextul, așa cum l-a descris Nelson, leagă documentele astfel încât să formeze o rețea de relații care sporește posibilitățile de extindere și de înțelegere a unui text obișnuit prin legarea de alte texte. De asemenea, Nelson a inventat și termenul de hipermedia, definind prin acesta hipertextul care nu este limitat la un text simplu. Hipermedia poate include diferite forme de multimedia –imagini, grafică, sunete și secvențe video.

Ideile lui Vannevar Bush și ale lui Ted Nelson au fost reluate într-un proiect de la sfârșitul anilor ’80, astfel încât în martie 1989, Tim Berners-Lee, un cercetător de la Laboratorul European pentru Particule Fizice al Consiliului European pentru Cercetare Europeană (CERN) din Geneva, Elveția, a propus un sistem hipertext care să permită partajarea eficientă a informațiilor între membrii unui grup de cercetători care studiau fizica energiilor înalte. Propunerea lui Berners-Lee, numită “Hipertext and CERN “ a circulat pentru comentarii. Componentele principale ale propunerii erau :

Aceeași interfață cu utilizatorul pe toate platformele, care să permită acestuia accesul la informații de pe diferite tipuri de calculatoare ;

Posibilitatea de acces la diferite tipuri de documente prin intermediul acestei interfețe ;

Asigurarea “accesului universal “, adică un sistem care să permită orcărui utilizator accesul la orice fel de informații .

La sfârșitul anului 1990, un prototip al sistemului World Wide Web rula pe un calculator NeXT și a fost pusă la punct o interfață în mod linie (numită “WWW”).Componentele de bază ale sistemului Web erau gata, deși nu erau încă disponibile pentru utilizarea pe scară largă în rețea.

La începutul anilor ’90, interesul pentru sistemul Web a crescut și s-a răspândit în întreaga lume. În martie 1991, interfața WWW era folosită într-o rețea locală; în luna mai a aceluiași an era pusă la dispoziția utilizatorilor, pe calculatoarele centrale CERN.

Pe 15 ianuarie 1992, interfața WWW a devenit disponibilă în mod public pe calculatoarele CERN, iar echipa de la CERN a făcut demonstrații internaționale de folosire a sistemului.

Interesul pentru sistemul Web a crescut rapid în anul 1993. Un tânăr student al Universității din Illinois, pe nume Marc Andressen, a lucrat la un proiect pentru NCSA (National Center for Supercomputing Application) și a condus o echipă care a dezvoltat un navigator (browser) pentru Web, numit “Mosaic”. Acest program avea o interfață grafică ușor de utilizat, alimentând și mai mult interesul pentru sistemul Web și pentru informațiile on-line. Au început, apoi, să apară versiuni comerciale ale unor navigatoare.

În 1994, Marc Anderssen și câțiva colegi au plecat de la NCSA ca să formeze, împreună cu Jim Clark (fost director la Silicon Graphics ) o companie care a primit ulterior numele de Netscape Communications Corporation.

Sistemul a început să se extindă extraordinar de repede; dacă în 1994 se cunoșteau 1.500 de servere publice Web, în 1995 acestea erau peste 15.000.

La jumătatea anului 1994, Massachusets Institute of Tehnology (MIT) și CERN au anunțat crearea organizației World Wide Web Consortium sau “W³C”.

Astăzi, această organizație ghidează dezvoltarea tehnică pentru evoluția sistemului Web. W³C este o organizație formată din universități și asociații industriale particulare, condusă de Laboratory of Computer Science din cadrul MIT și care colaborează cu CERN și Institute National de Recherche en Informatique et en Automatique (INRIA), un institut francez pentru cercetări în domeniul informaticii.

La organizația W³C au aderat noi companii, printre care: AT&T, Digital Equipment Corporation, Entrprise Integration Tehnologies, FTP Software, IBM, NCSA, Netscape Communication, Novell, Sun Microsystems.

A) O definiție a sistemului Web

În ciuda creșterii rapide și a dezvoltării tehnice, sistemul Web din 1995 are aceleași componente funcționale ca și varianta din 1990. Popularitatea sistemului de afișare a informațiilor din INTERNET a îngreunat înțelegerea acestui sistem, care uneori este confundat chiar cu rețeaua INTERNET , pe când programele navigatoare sunt confundate cu însuși sistemul Web, în loc să fie văzute ca un mod de afișare a informațiilor din acesta. Web este un sistem foarte distinct de INTERNET și de programele de navigare :

În primul rând, Web nu este o rețea, ci un sistem de aplicații.

În al doilea rând, sistemul World Wide Web poate fi instalat pe diferite tipuri de rețele (care nu trebuie să facă parte din INTERNET ) și, mai mult decât atât, poate fi folosit chiar pe calculatoare neconectate la rețea sau în rețele locale independente.

Ca o definiție tehnică, World Wide Web este un sistem de comunicare a informațiilor hipertext folosit, în general, în rețeaua INTERNET și care funcționează prin comunicare de date pe baza unui model client-server. Clienții (navigatoarele Web) au acces la informațiile hipermedia și multiprotocol, aflate pe un server Web.

Fig. : Modelul client-server pentru comunicațiile de date

Modelul client-server pentru calculatoarele conectate în rețea implică trei componente : clientul, server-ul și rețeaua.

Clientul este o aplicație care, de cele mai multe ori, rulează pe calculatorul utilizatorului final.

Server-ul este o aplicație care, de obicei, rulează pe calculatorul furnizorului de informații. Programul client este adaptat sistemului hardware pe care rulează și funcționează ca o interfață între sistemul respectiv și informațiile furnizate de server. Cererea este transportată prin rețea, de la client la server. Server-ul analizează cererea și execută activitățile corespunzătoare. Aceste activități pot include căutarea într-o bază de date sau actualizarea unor informații dintr-o bază de date. Rezultatele tranzacțiilor cerute (dacă există) sunt trimise către programul client și afișate pe ecranul utilizatorului. toate comunicațiile între client și server se fac conform unui set de reguli sau protocoale definite de sistemul client-server.

În figură este ilustrată relația client-server, indicându-se care este fluxul de cereri de la client la server și cel de informații de la server la client. Clientul poate avea acces la mai multe servere, folosind protocoale pe care le înțeleg atât serverul cât și clientul.

Forma distribuită a activităților de tip “cerere” și “serviciu” din modelul client-server permite creșterea eficienței.

Deoarece comunicarea dintre client și server se face conform unui protocol predefinit, programul client poate fi adaptat în funcție de calculatorul pe care rulează (server-ul nu trebuie să știe nimic despre particularitățile programului client). Nu trebuie create versiuni separate de informații pentru fiecare platformă hardware, deoarece particularitățile fiecărei platforme sunt implementate în programele client scrise pe acesta.

B) Protocolul HTTP

HTTP (HyperText Transfer Protocol) este un protocol simplu, la nivel aplicație, în modelul TCP/IP, ce descrie cererile de la clienți și răspunsurile de la servere.

Există un model de bază pentru autentificare în protocolul HTTP, ce poate fi folosit pentru a restricționa accesul utilizatorilor prin parole. Această metodă însă, trebuie să fie folosită pentru a proteja date importante; parolele sunt trimise în clar prin rețea, aceasta reducând mult din gradul de securitate pe care îl oferă, în special în rețelele nesigure cum este INTERNET-ul.

C) Securitatea WWW

Pe lângă cele prezentate mai înainte, o altă utilizare a Web-ului cuprinde includerea de programe în paginile de Web. Programele sunt create conform unui protocol numit Common Gateway Interface (CGI) – interfață la o poartă comună.

Script-urile CGI pot fi:

simple – de exemplu, un contor ce se icrementează de fiecare dată când o persoană accesează o pagină Web sau o carte de oaspeți ;

complexe – de exemplu, serviciul de pachete-furnizor FedEx, care permite utilizatorilor să folosească serverul World Wide Web al companiei pentru a copia pachete de servicii software .

Multe alte companii explorează noi posibilități de folosire a WWW în comerțul electronic. Clienții pot răsfoi cataloagele de bunuri și servicii, pot selecta elementul dorit, iar apoi îl pot plăti prin completarea unui formular (form) oferit prin intermediul paginii de Web încărcate.

Cu toate aceste deosebite posibilități de utilizare, World Wide Web comportă anumite probleme de securitate. În ordinea importanței, acestea pot fi:

1) Un atacator poate specula bug-urile (deficiențele) existente în serverul de Web sau din script-urile CGI pentru a obține acces neautorizat la alte fișiere din sistem sau chiar pentru a obține controlul total asupra sistemului;

2) Informațiile confidențiale ce se găsesc pe server-ul de Web pot fi distribuite unor persoane neautorizate;

3) Informațiile confidențiale transmise între server-ul Web și navigator pot fi interceptate;

4) Bug-urile din navigator (sau puncte vulnerabile care nu sunt vizibile) pot permite unui server de Web rău-intenționat accesarea de informații confidențiale de pe Web-ul client.

Fiecare din aceste probleme cere un răspuns. Din nefericire, câteva din soluțiile care au început să fie folosite în mod curent sunt contradictorii. De exemplu, pentru a reduce riscurile de “ascultare”, multe organizații achiziționează servere World Wide Web sigure, care implementează o varietate de protocoale de criptare. Dar, aceste servere cer, pentru a opera, un certificat semnat digital, care trebuie actualizat periodic.

Construirea unui server Web sigur

Serverele Web sunt proiectate să recepționeze cereri anonime de la sisteme gazdă neidentificate de pe INTERNET și să furnizeze informația într-o manieră eficientă și rapidă. Ca atare, ele furnizează o poartă de intrare în calculator, care poate fi folosită atât de prieteni cât și de dușmani.

Nici un software nu este fără riscuri. Serverele Web, prin natura lor, sunt programe complexe. In plus, multe organizații folosesc servere Web al căror cod sursă este disponibil pe INTERNET. Aceasta oferă disponibilitate la inspectare de către alte organizații, existând posibilitatea ca un vizitator rău-intenționat să poată inspecta aceste surse în scopul găsirii unor vulnerabilități.

Interfața CGI

CGI este o interfață independentă de limbaj, ce permite realizatorilor de programe pentru WWW să genereze documente dinamice în aproape orice limbaj. Script-urile CGI pot fi scrise în aproape orice limbaj ce are posibilități de acces la variabilele de mediu și poate produce o ieșire.

Scopul CGI este furnizarea unui mecanism flexibil și convenabil pentru extinderea funcțiilor unui server HTTP peste limitele unor simple preluări și afișări de fișiere.

Pentru a folosi efectiv mecanismele CGI, trebuie înțelese și formularele HTML, care reprezintă modul obișnuit prin care se transmit date spre CGI.[Formularele (forms) HTML sunt descrise în specificația HTML 2.0, ce se găsește în RCF 1866 ]

Deși are avantajul de a fi o interfață flexibilă și puternică, CGI prezintă dezavantajul unor implicații asupra securității sistemului.

Datorită ușurinței de a realiza script-uri CGI, programatorii le tratează cu aceeași ușurință ca pe niște programe obișnuite, neglijând faptul că CGI este un server INTERNET, fiind astfel expus la pericolele inerente acestui tip de servere.

Programele CGI sunt scrise adeseori pentru a accepta date într-un anumit format, dar spre program pot fi transmise date arbitrare, de lungime nelimitată. Aceasta înseamnă că aceste programe trebuie scrise robust, astfel încât să fie capabile să refuze datele de intrare, atunci când acestea sunt rău-intenționate sau bizare.

Servere de uz general, cum ar fi sendmail și finger, au fost scrise în deplină cunoștință a acestor pericole. Sursele acestor programe au fost examinate ani de zile pe toate părțile, în căutarea eventualelor probleme. Chiar și în aceste condiții, problemele de securitate sunt un lucru obișnuit la astfel de programe.

În concluzie, este mai mult decât riscant să se permită utilizatorilor să creeze programe CGI, fără o evaluare detaliată a riscurilor implicate și fără luarea măsurilor corespunzătoare pentru minimizarea acestor riscuri.

Posibilitatea de a adăuga funcții la un server Web prin folosirea script-urilor CGI complică foarte mult politica de securitate ce trebuie adoptată. Atâta timp cât un script CGI poate adăuga elemente la un serevr Web, pot fi introduse și noi probleme de securitate. De exemplu, un server Web poate fi configurat astfel încât să poată fi accesate numai fișierele stocate într-un anume director, dar un utilizator poate instala neintenționat un script CGI, care permite intrușilor să citească alte fișiere de pe calculator. Mai mult, deoarece mulți utilizatori nu au o experiență în a scrie programe de securitate, este posibil (și probabil) ca script-urile CGI locale, ce pot conține bug-uri, să permită unui intrus să execute comenzi arbitrare pe sistemul în cauză.

În câteva cărți despre programarea CGI-urilor au fost prezentate câteva greșeli uzuale, dar varietatea acestora este încă foarte mare.

Platforma suport pentru un server Web sigur

Toate eforturile de a asigura securitatea script-urilor CGI sunt inutile dacă server-ul de Web însuși nu este de încredere. Din nefericire, aceasta se întâmplă de multe ori.

Deoarece are o varietate de utilitare, platforme pentru limbaje de programare și permite utilizatori ce se pot conecta de la distanță, sistemul de operare UNIX este ținta multor atacuri. Un sistem UNIX nu este deci cea mai bună soluție pentru un server de Web sigur. De asemenea, sistemele de operare de pe PC-uri prezintă unele dintre aceste caracteristici, făcând ca nici ele să nu fie o alegere dintre cele mai potrivite.

Experiența a arătat că, pentru creșterea siguranței unui server Web, acesta trebuie să ruleze un server de Web fără nimic altceva și să nu accepte conectarea de la distanță.

De exemplu, un Apple Macintosh ce rulează MacHTTP, WebStar sau un alt server de Web similar. Conform recentelor sondaje de opinie, în această categorie se înscriu cam 15% dintre serverele Web de pe INTERNET.

Există desigur multe avantaje în rularea unui serevr de Web pe o mașină UNIX în loc de a-l rula pe un Macintosh. UNIX-ul, în general, rulează mai rapid decât MacOS pe hardware comparabil și este disponibil pentru platforme hardware ce lucrează mai rapid decât calculatoarele bazate pe PowerPC. ai mult decât atât, pentru organizații este mai ușor, în general, să integreze server-ele bazate pe UNIX cu infrastructura informațională existentă. În final, sunt mai mulți cei familiarizați cu server-ele UNIX decât cu cele ce rulează MacOS. Totuși, se sugerează ca un administrator să ia în seamă modul de abordare a Web-urilor Mac.

Pentru a construi un server Web sigur pe o platformă oarecare, trebuie să se aibă în vedere câteva lucruri:

Utilizatorii din rețea nu trebuie să poată executa pe server programe arbitrare sau comenzi Shell;

Script-urile CGI care rulează pa server trebuie să realizeze funcția solicitată sau să returneze un mesaj de eroare. Script-urile trebuie să se așeze la atacuri și să poată stăpâni orice încercare de intrare rău intenționată;

În eventualitatea că server-ul a fost compromis, un intrus rău intenționat nu trebuie să fie capabil să folosească aceasta pentru un nou atac asupra organizației.

UID-ul server-ului

Cele mai multe servere Web sunt proiectate să pornească în modul superuser. Server-ul are nevoie să fie lansat ca root, astfel încât să poată “asculta” cererile pe port-ul 80 (port-ul standard pentru HTTP).

Îndată ce server-ul a pornit, el își schimbă UID-ul la cel al utilizatorului care este specificat în fișierul de configurare. În cazul server-ului de la NCSA, acest fișier de configurare se numește conf/httpd.conf. În fișier sunt 3 linii :

# User/Group: The name (or #number) of the user/group to run httpd as

User http

Group http

Acest nume utilizator (username) poate să nu fie root. În schimb, directivele user și group din fișierul de configurare pot specifica un utilizator care nu are acces special pe server. În exemplul de mai sus, utilizatorul și-a schimbat UID-ul la user http, înaintea accesării fișierelor sau a rulării script-ului CGI. Dacă există un script CGI care rulează ca superuser (și trebuie analizat bine acest lucru), aceasta trebuie să fie SUID root.

Nu trebuie să se ruleze server-ul de Web ca root! Cu toate că serverul pornește inițial ca root, fișierul http.conf nu trebuie să conțină directiva “User root”. Dacă aceasta există, fiecare script de pe server-ul Web se va executa ca superuser, putând apare probleme.

Structura de directoare a server-ului

Sever-ele sunt produse software complicate. Ele folosesc multe fișiere din mai multe directoare. Conținutul unor directoare poate fi disponibil în rețea, al altora nu. În plus, pentru siguranță, conținutul anumitor directoare poate să nu fie citit de utilizatorii sistemului.

Pentru a rula un server sigur trebuie să se înțeleagă scopul fiecărui director și ce măsuri de protecție îi sunt necesare. De exemplu, server-ul de Web de la NCSA are 6 directoare :

Multe surse recomandă să se creeze un utilizator numit www și un grup numit www pentru a fi utilizate de administrator la gestionarea server-ului Web:

drwxr-xr-x5 www www 1024 Aug 8 00:01 cgi-bin/

drwxr-x–2 www www 1024 Jun 11 17:21 conf/

-rwx––1 www www 109674 May 8 23:58 httpd/

drwxrwxr-x2 www www 1024 Aug 8 00:01 htdocs/

drwx––2 www www 1024 Jun 3 21:15 icons/

drwxr-x–2 www www 1024 May 4 22:23 logs/

Aceasta este o abordare interesantă, dar ea nu întărește prea mult politica de securitate. Deoarece programul httpd rulează ca root, oricine poate modifica acest program are posibilitatea să devină superuser. Aceasta este o vulnerabilitate deosebită, dacă fișierele server-ului sau cele de configurare sunt dispuse pe partiția NFS-export. pentru aceasta se recomandă să se seteze directorul servere-ului de Web cu proprietatea root.

drwx—-x–x8 root www 1024 Nov 8 00:01 cgi-bin/

drwx––2 root www 1024 Nov 11 17:21 conf/

drwxr-xr-x2 root www 1024 Dec 8 00:01 htdocs/

-rwx––1 root www 482168 Aug 8 23:58 httpd/

drwxrwxr-x2 root www 1024 Dec 3 21:15 icons/

drwx––2 root www 1024 Nov 4 22:23 logs/

drwxr-xr-x2 root www 1024 Aug 8 00:01 support/

De reținut că directorul cgi-bin are modul de acces 711; aceasta permite server-ului http să ruleze programele pe care le conține, dar nu permite unei persoane de pe server să vizualizeze conținutul directorului.

A) Fișierele de configurare

Server-ul de Web NCSA are următoarele fișiere în cadrul directorului conf.

Deoarece informațiile din aceste fișiere pot fi folosite pentru a submina server-ul sau întregul sistem, trebuie protejat script-urile astfel încât să nu fie citite și modificate decât de superuser.

-rw––-1 root wheel 954 Aug 6 01:00 access.conf

-rw––-1 root wheel 2840 Aug 6 01:00 httpd.conf

-rw––-1 root wheel 3290 Aug 6 01:00 mime.types

-rw––-1 root wheel 4106 Nov 8 01:00 srm.conf

B) Configurări suplimentare

În afara configurării permisiunilor, se mai pot activa sau dezactiva, după dorință, următoarele opțiuni de configurare:

a) Listarea automată a directorului

Multe server-e Web listează automat conținutul unui director, dacă în director nu există un fișier numit index.html. Această posibilitate poate cauza probleme de securitate; în orice caz, dă unui intrus posibilitatea să inspecteze fișierele și punctele vulnerabile de pe sistem.

b) Urmărirea legăturilor simbolice

Unele server-e permit să se urmărească legăturile simbolice în afara arborelui de documentare al server-ului Web. Aceasta permite oricărei persoane ce are acces la arborele de documente de pe server să facă accesibile prin Web alte documente. Pentru siguranță, nu este recomandată activarea urmăririi legăturilor simbolice. Ca alternativă, se poate seta opțiunea “If Owner Match” de pe server-ul de Web, astfel încât legăturile să fie făcute numai de către proprietarii documentelor care au creat legăturile.

c) Directivele “Server-side includes”

Server-side includes sunt directive ce pot fi încapsulate în documente HTML. Acestea sunt procesate de server-ul HTML înainte ca documentul să fie transmis unui client ce l-a cerut. Directivele server-side includes pot fi folosite pentru a include alte documente sau pentru a executa documente și a furniza rezultatul la ieșire.

Exemplele de mai jos demonstrează de ce utilizarea directivelor server-side includes nu este o idee bună:

<!–#include file=”/etc/passwd/”>

<!–#exec cmd=”rm –rf /&:cat /etc/psswd>

Primul furnizează atacatorului o copie a fișierului /etc/passwd. cel se-al doilea lansează, în fundal, un proces ce încearcă să șteargă orice fișier asupra căruia există drept de scriere.

Câteva server-e, cum ar fi cel de la NCSA, permit limitarea procesării directivelor server-side includes la câteva directoare specificate. Server-ul NCSA folosește directiva Options pentru controlul acestor includeri.

Directivele server-side includes nu vor fi niciodată activate pentru directoarele ce conțin script-uri. Aceasta, deoarece este posibil ca un script cu greșeli să poată permite unui intrus să includă fișiere arbitrare și să execute comenzi arbitrare.

Scrierea script-urilor și programelor CGI sigure

Scrierea unui script CGI sigur prezintă toată seria de probleme ce apar, la scrierea unui program SUID sigur, a unui server de rețea sigur, plus multe altele. Acestea, deoarece pot apare interacțiuni neașteptate între mediul Web, server-ul de Web și scripturile CGI, apărând probleme în combinația lor, care nu se manifestă când acestea sunt luate separat. Cele mai multe dintre “hibele“ de securitate nu sunt intenționate. Dintre toate script-urile scrise pe server-ul de Web există șansa ca cel puțin unul să aibă o deficiență serioasă de securitate. Din acest motiv, nu trebuie să se permită utilizatorilor să plaseze script-uri pe server, până când o persoană autorizată în securitate nu le-a citit și a verificat siguranța lor.

Nu trebuie să se aibă încredere deplină în navigatoarele utilizatorilor! În HTML există posibilitatea de a afișa liste de selecție, de a limita lungimea câmpurilor la un anumit număr de caractere, de a încapsula date ascunse în formulare (forms) și de specifica variabilele ce vor fi furnizate script-urilor CGI. Cu toate acestea, nu se poate face ca script-ul CGI să depindă de nici una din aceste restricții, deoarece unele script-uri CGI pot fi lansate direct prin cererea URL-ului lor; intrușii nu au voie (și nici nu doresc ) să folosească formularul impus sau interfața ce li se furnizează.

Trebuie să se acorde atenție, în special, următoarelor aspecte:

Dacă se creează o listă de selecție, valoarea care este returnată pentru câmpul de intrare poate să nu se potrivească valorii permise care a fost definită;

Dacă s-a specificat o lungime maximă pentru o variabilă, lungimea variabilei care este furnizată script-ului poate fi semnificativ mai lungă;

Variabilele care au fost furnizate script-ului pot avea nume ce nu sunt definite în script;

Utilizatorii pot vedea date ce au fost marcate ca fiind ascunse (hidden);

Valorile pentru variabilele ce sunt furnizate pot conține caractere speciale. Atacatorii sunt, prin definiție, rău intenționați și nu respectă niciodată regulile. De aceea, nu trebuie să se aibă încredere în tot ceea ce este furnizat prin rețea. Nu este de ajuns să se tasteze un script CGI! Una din cauzele pentru care este foarte ușor de creat un script nesigur se datorează faptului că este foarte dificil să se testeze script-urile cu toate variantele de clienți HTTP existente. Sunt multe programe CGI care nu realizează un control al caracterelor și nu protejează împotriva posibilității existenței caracterelor speciale (cum ar fi “ escape ” sau “ ‘ “, care sunt interpretate în mod special de Shell-ul UNIX ). Aceste caractere pot apare în șirul de caractere de intrare datorită unor deficiențe ale navigatorului Web sau, foarte probabil, pentru că un intrus rău intenționat încearcă să submineze script-ul CGI și să preia controlul asupra server-ului;

O problemă deosebit de importantă este aceea că trebuie inspectate toate valorile care sunt furnizate programului. Pentru toate valorile furnizate trebuie verificată existența caracterelor speciale și lungimea maximă pentru variabilele specificate. Prin “ toate valorile “ se înțelege: conținutul variabilelor de mediu, adresele și numele sistemelor gazdă, URL-uri, date furnizate de utilizator, valori alese din liste de selecție și date ce au fost inserate de script printr-un formular WWW. Considerând cazul unui script CGI care creează o serie de fișiere de jurnalizare pentru fiecare sistem gazdă care contactează server-ul WWW, numele fișierului de jurnalizare ar putea fi următorul: logfile/ÎnumesistemȘ. Ce va putea face acest program dacă este contactat de sistemul gazdă ../../../../etc/passwd.company.com? Execuția unui astfel de script, dacă a fost construit incorect, se poate încheia cu adăugarea unei linii la fișierul de parole (/etc/passwd) al sistemului. Astfel se pot crea conturi neautorizate pe sistem;

Trebuie avută o grijă deosebită în utilizarea apelurilor system(), popen(), a conductelor (pipe), apostrofului invers și a funcției Perl eval().

Multe limbaje de programare furnizează metode de a crea subprocese. Trebuie evitată această facilitate în scrierea scripturilor CGI. Dacă trebuie neapărat să se creeze un subproces și la acesta se vor trimite șiruri de caractere furnizate de utilizator, aceste șiruri nu trebuie să conțină metacaractere Shell (de exemplu, caracterele ` $ ‘| ; > * < & ).

A) Transmiterea poștei

Dacă se scrie un script CGI care să permită utilizatorilor să transmită poștă electronică , este indicată folosirea programului /usr/lib/sendmail pentru a transmite poșta și nu a programelor /bin/mailx sau /usr/ucb/sendmail. Aceasta, deoarece usr/lib/sendmail nu are secvențe escape (ce permit execuția unor comenzi Shell), cum au celelalte.

Există mai multe comenzi Perl care permit rularea de comenzi Shell, posibil fără ca utilizatorul să aibă cunoștință de aceasta .

Transmiterea poștei electronice într-un mod sigur este prezentată în secvența de program Shell. Este ocolit Shell-ul prin folosirea funcției exec() cu un șir fix, ce rulează direct /usr/lib/sendmail:

open (WRITE “|-“ )

|| exec ( “usr/lib/sendmail”, “-ci,” “-t” )

|| die “can’t fork$!þn”:

print WRITE “To : $addressþn”;

print WRITE “Subject: $subjectþn”;

print WRITE “From: $senderþn”;

print WRITE “þn$messagepn.þn”;

close(WRITE);

B) Plasarea script-urilor CGI

Majoritatea server-elor Web pot fi configurate astfel încât toate script-urile CGI să fie restricționate la un singur director. Se recomandă această configurație, pentru că se face mai ușor căutarea și examinarea tuturor script-urilor CGI de pe sistem. Nu este bine să se permită niciunui fișier cu extensia “.cgi” de pe server-ul Web să fie rulat ca un script CGI.

În schimb se recomandă:

Configurarea server-ului Web, astfel încât toate script-urile CGI să fie plasate într-un singur director (de obicei, directorul se numește cgi-bin);

Folosirea unui program (cum ar fi Tripwire ) care să monitorizeze schimbările neautorizate din aceste script-uri;

Permiterea unui acces limitat la acest director (cgi-bin) și la conținutul său. Utilizatorii locali nu vor avea permisiunea de a instala, de a șterge script-uri sau de a edita script-urile existente. De asemenea, dacă se dorește, se poate elimina și posibilitatea citirii, pentru a împiedica spionarea;

Să nu se țină pe server fișierele de backup, care sunt generate automat de editor. Mulți administratori de sistem folosesc editoare de texte, ca Emacs, pentru editarea script-urilor care sunt plasate pe server. Adeseori, rămân asemenea fișiere, cu nume ca start~ sau creat-acount~. Aceste fișiere backup pot fi executate de un intrus, cu rezultate nedorite.

Protejarea confidențialității script-urilor

Formularul

de intrare

Transmiterea

ieșiri CGI-ului

Intrus rău Formularul Ieșirea

intenționat de intrare CGI

Informațiile circulă pe rețea, întâi de la navigator la server, iar apoi server-ul transmite informația unui program CGI. Aceste informații pot fi interceptate în timp ce sunt transferate de la mașina client la server.

Formularul

de intrare

criptat

Transmiterea

ieșirii CGI-ului

Formularul ieșirea

de intrare CGI

criptat (în clar)

Protejarea formularelor de intrare folosind procedee de criptare

Deoarece, este foarte ușor să se facă o greșeală scriind un program CGI, trebuie ca site-ul să păstreze confidențiale programele și script-urile CGI. Aceasta, nu garantează, totuși, securitatea pentru script-urile cu bug-uri (greșeli):un intrus rău intenționat, care sondează cu perseverență, găsește deficiențele sistemului. Câteodată, munca implicată pentru această spargere este semnificativă. Dacă un intrus oarecare, după încercări repetate, renunță orientându-se către alte sisteme, cel perseverent o va lua de la capăt.

A) Combinarea HTTP cu FTP

O atenție deosebită trebuie acordată folosirii HTTP în combinație cu FTP. Multe site-uri folosesc același director pentru a stoca documentele ce sunt accesate prin anonymous FTP și WWW. De exemplu, poate exista un director numit /NetDocs pe server, care este deopotrivă directorul pentru utilizatorii FTP și directorul root al server-ului Web. Aceasta permite referirea fișierelor prin două URL-uri, cum ar fi:

http://server.com/nosmis/fișier.html sau ftp://server.com/nosmis/fișier.html

Avantajul folosiri HTTP peste FTP îl reprezintă viteza și eficiența accesului la documente. Dar combinarea HTTP și FTP într-un director poate produce o serie de probleme de securitate, incluzând:

Permiterea accesului FTP anonymous la directoarele HTTP dă utilizatorilor posibilitatea de a ocoli unele restricții de acces la documente pe care server-ul Web le poate impune. Astfel, dacă pe server-ul Web există documente confidențiale, ele nu pot fi deconspirate;

Dacă un intrus poate prelua script-urile de pe server cu FTP-ul (download), el le poate inspecta în vederea găsirii unei căi de atac. Deci, trebuie să se asigure că nu există nici o posibilitate de încărcare a unui script de către un utilizator FTP.

Fișierul /etc/passwd prezent pentru serviciul de FTP poate fi vizibil cuiva care folosește serviciul WWW, ceea ce conduce la compromiterea conținutului său. Dacă au fost incluse câteva parole reale în acest fișier, ele devin disponibile pentru clienți, putându-se sparge parolele de la distanță.

B) Alte probleme

Sunt multe alte măsuri care se pot lua pentru a face un server de Web cât mai sigur. De exemplu, se poate limita accesul la calculator, astfel încât acesta să fie doar un serevr Web dedicat. Aceasta va face foarte grea spargerea server-ului de către un intrus; dacă totuși aceasta se va petrece, se vor limita stricăciunile pe care intrusul le poate produce restului rețelei.

Dacă s-a ales soluția unui server pe un calculator stand-alone, sunt o serie de tehnici care pot izola calculatorul de rețea (de exemplu soluția firewall) și care pot reduce posibilitatea unui atac. În particular, se pot avea în vedere următoarele opțiuni pentru un astfel de sistem:

Ștergerea tuturor conturilor ce nu sunt necesare ;

Să nu se monteze NFS-ul sau să nu se exporte directoare;

Ștergerea tuturor compilatoarelor;

Ștergerea tuturor programelor utilitare care nu sunt utilizate în timpul încărcării sistemului sau de către server-ul Web;

Furnizarea a cât mai puține servicii de rețea posibile;

Să nu ruleze un server de mail;

O altă poțiune este să se plaseze server-ul WWW într-o structură de director separată. Server-ul WWW este prevăzut cu un mic program ce face un apel chroot() la director. Astfel, dacă se găsesc câteva căi de subminare a controlului server-ului, fișierul sistem corespunzător este ascuns și protejat de atac. Unele server-e pot avea această facilitate inclusă în opțiunile de instalare, așa că trebuie verificată documentația cu atenție.

Controlul accesului la fișierele de pe server

Multe site-uri sunt interesate în limitarea domeniului de informații care la distribuie server-ele lor. Aceasta deoarece un server Web este utilizat într-o organizație pentru a distribui atât date interne, cât date externe.

Multe server-e suportă două tehnici primare pentru controlul accesului la fișiere și directoare:

1) Restricționează accesul la anumite adrese IP, subrețele sau domenii DNS (Domain Name System);

2) Restricționează accesul la anumiți utilizatori. Utilizatorii sunt autentificați printr-o parolă stocată pe server.

Server-ele care sunt echipate cu software-ul necesar pentru criptografia cu chei publice au și o a trei tehnică de restricționare a accesului;

3) Restricționarea accesului doar la acei utilizatori care prezintă chei publice semnate de o autoritate de certificare.

Fișierele acces.conf și .htacces

Server-ul NCSA permite plasarea tuturor restricțiilor de acces global într-un singur fișier numit conf/acces.conf. Ca alternativă, se pot plasa restricțiile în fiecare director, folosind numele specificat de AccesFileName în fișierul de configurație conf/srm.conf. Pentru fiecare director, numele implicit al fișierului cu restricții de acces este .htacces, Dar se poate schimba acest nume după dorință.

Depinde de cel ce face configurarea dacă s-a ales folosirea mai multor fișiere de acces sau a unui singur fișier.

Desigur că este mai convenabil să existe câte un fișier în fiecare director de pe server-ul Web. De asemenea, este mai facilă mutarea de directoare pe server-ul de Web, ne mai fiind necesară actualizarea fișierului principal de control al accesului. Mai mult, nu mai este necesară reinițializarea server-ului ori de câte ori s-a făcut o schimbare în lista de control al accesului – server-ul va observa că este un nou fișier .htacces și va acționa în consecință.

Pe de altă parte, având un fișier de acces în fiecare director înseamnă că există mai multe fișiere de verificat pentru a vedea dacă directoarele sunt protejate sau nu. Există, de asemenea, o deficiență la unele server ce permite preluarea fișierelor de acces.

Accesul în fiecare director este cuprins între două tag-uri, <Directory directoryname > și </Directory>. Conținutul fișierului acces.conf :

<Directory /nsa/manual>

<Limit GET>

order deny,allow

deny from all

allow from.nsa.mail

</Limit>

</Directory>

Dacă se folosește controlul accesului per-director, nu se introduc aceste tag-uri. de exemplu:

<Limit GET>

order deny,allow

deny from all

allow from.nsa.mil

</Limit>

Există o deficiență în multe server-e Web (printre care și cel de la NCSA) care permite ca fișierul .htacces să poată fi adus ca URL. Aceasta nu este bine, deoarece un intrus poate învăța detaliile sistemului de autentificare. Din această cauză, dacă se folosesc fișiere de control per-director, este recomandat să li se dea un nume diferit de .htacces, prin specificarea acestui nume diferit în AccesFileName din fișierul srm.conf, ca mai jos:

# AccesFileName : The name of the file to look for in each directory

# for acces control information

AccesFileName.ap

A) Comenzi în interiorul blocului <Directory>

Așa cum s-a văzut, anumite comenzi sunt disponibile în cadrul blocului <Directory>. Cele utile în definirea restricțiilor de acces sunt:

Options opt1 opr2 opr3

Comanda Options se folosește pentru setare diferitelor opțiuni într-un director anume.

Opțiunile disponibile sunt:

FollowSymLinks – permite urmărirea legăturilor simbolice

SymLinksOwnerMatch – permite urmărirea legăturilor simbolice

numai de către proprietar

ExecCGI – permite executarea script-urilor CGI

Includes – permite directive server-side includes

Index – permite server-ului să răspundă la cereri prin

generarea unui fișier care conține lista

fișierelor din director

AllowOverride ce_anume

Specifică directivele care pot fi suprascrise cu fișiere de acces la nivel de director

AuthRealm domeniu

Setează numele Domeniului de autorizare pentru director. Numele domeniului este afișat de navigatorul de Web atunci când se cere numele utilizatorului (username) și parola (password).

AuthType tip

Specifică tipul autentificării folosite de server. De exemplu, NCSA httpd suportă numai un sistem de autorizare bazat pe parole.

AuthUserFile cale_absolută

Specifică calea fișierului de parole pentru httpd. Acest fișier de parole este creat și întreținut de programul NCSA htpasswd și nu este memorat în același format ca /etc/passwd.

AuthGroupFile cale_absolută

Specifică calea la fișierul de grup httpd. Acest fișier de grup este un fișier text normal, neavând formatul fișierului UNIX /etc/group. În schimb, fiecare linie începe cu un nume de grup, “;” și conține lista membrilor (separați printr-un spațiu). De exemplu:

grup1 : Ion Ana Vasile

Limit metode_ce_trebuie_limitate

Specifică începutul unei secțiuni care listează limitările în director. Secțiunea poate avea următoarele directive:

Sistemele gazdă din declarațiile allow și deny pot fi :

un nume de domeniu, cum ar fi .pub.ro;

un nume întreg de sistem gazdă, cum ar fi nc.pub.ro;

o adresă de IP (cum ar fi 204.17.195.20);

o porțiune de adresă IP(de exemplu 204.17.195) care specifică o subrețea;

cuvântul cheie “all”, care semnifică toate sistemele gazdă.

B) Exemple

De exemplu, dacă se dorește restricționarea accesului la fișierele unui director pentru toată lumea, din subrețeaua 204.17.195.*, se pot adăuga următoarele linii la fișierul acces.conf.

<Directory /usr/local/etc/httpd/htdocs/special>

<Limit GET POST>

order deny,allow

deny from 204.17.195

</Limit>

</Directory>

Dacă se dorește permiterea accesului la fișiere doar a utilizatorilor autentificați ion și vasile, și atunci când aceștia sunt subrețeaua 204.17.195, se pot adăuga liniile:

AuthType Basic

AuthName The-T-Directory

AuthUserFile /tmp/auth

<Limit GET POST>

order deny, allow

deny from all

allow from 204.17.195

require user ion vasile

</Limit>

Dacă se dorește să se permită utilizatorilor ion și vasile accesul la fișiere de oriunde din INTERNET , trebuie să fie sigur că aceștia introduc corect de la tastatură numele de utilizator (username) și parola (password) și fișierul trebuie să conțină :

AuthType Basic

AuthName The-T-Directory

AuthUserFile /tmp/auth

<Limit GET POST>

require user ion vasile

</Limit>

Definirea utilizatorilor de Web și a parolelor

Pentru a folosi utilizatori autentificați trebuie să se creeze un fișier de parole. Aceasta se poate face cu programul htpasswd, folosind operațiunea –c pentru crearea fișierului. De exemplu:

#./htpasswd –c /usr/local/etc/httpd/pw/auth ion

Audding password for ion

New password : aha1234

Re-type new password : aha1234

#

Se poate adăuga un alt utilizator și parola de rigoare folosind htpasswd. Nu se va mai folosi operațiunea -c pentru că aceasta creează un nou fișier și deci, toți utilizatorii curenți din fișierul de parole vor fi șterși:

#./htpasswd /usr/local/etc/httpd/pw/auth vasile

Audding password for vasile

New password : acoperit

Re-type new password : acoperit

#

Fișierul de parole este similar, Dar nu identic cu fișierul standard /etc/passwd:

# cat /usr/local/etc/httpd/pw/auth

ion:Zdz2f8MOeVcNY

vasile : ukJTIFYWKwta

Deoarece server-ul Web folosește funcția cript(), este important ca fișierul de parole să fie inaccesibil utilizatorilor obișnuiți de pe server, pentr a se evita un atac prin încercări de parole, folosind un program de tip Crack.

Evitarea interceptării

Riscul interceptării afectează toate protocoalele INTERNET și, în special, World Wide Web, unde pot fi transmise documente importante sau alte elemente de informație (cum ar fi numere de cărți de credit) .Există doar două căi de proiecție împotriva interceptării. Prima este să se asigure faptul că informația circulă printr-o rețea fizic sigură (ceea ce INTERNET–ul nu este ). A doua este criptarea informației astfel încât ea să poată fi decriptată numai de receptorul dorit.

O altă formă de ascultare posibilă este analiza traficului. În acest caz, un intrus observă tranzacțiile realizate la / de o destinație fără să-l intereseze conținutul. După cum se va vedea mai târziu, fișierele de login de pe server-ele Web sunt deosebit de vulnerabile la astfel de atacuri.

Interceptarea canalului fizic

Informațiile transmise pe INTERNET trebuie să fie criptate pentru a fi protejate la interceptare. Există patru modalități în care pot fi criptate informațiile :

Criptarea legăturii (Link encryption). Pentru a se asigura confidențialitatea pe liniile telefonice, se criptează pachetele IP.

Organizațiile pot folosi, de asemenea, ruter-ele pentru a cripta automat informațiile ce se transmit pe INTERNET și sunt destinate altor site-uri. Criptarea legăturii oferă confidențialitatea întregului trafic, dar aceasta poate fi realizată numai cu un aranjament preliminar. Criptarea legăturii era în general foarte scumpă, dar noua generație de ruter-e și firewall-uri au început să introducă această facilitate din fabricație;

Criptarea documentelor (Document ecriptyon). Documentele plasate pe server-ul Web pot fi criptate cu un sistem ca PGP-ul . Cu toate că această metodă oferă protecție bună, ea este greoaie deoarece cere ca documentele să fie criptate anterior plasării lor pe server și decriptate când sunt recepționate;

SSL (Secure Socket Layer). SSL este un sistem proiectat de Netscape Communication care oferă o cale TCP/IP criptată între două host-uri de pe INTERNET. SSL poate fi folosit pentru criptarea orcărui protocol TCP/IP, cum ar fi HTTP, TELNET sau FTP. SSL poate folosi o varietate de sisteme bazate pe chei publice, pentru a schimba cheia de sesiune. O dată o cheie de sesiune obținută, se pot folosi o varietate de algoritmi cu cheie secretă. O descriere completă a protocolului SSL poate fi găsită la adresa:

http:/ /home .netscape.com/newsref/std/SSL.html.

Principiul de funcționare al acestui sistem:

Se asigură

confidențialitatea

datelor în ambele

sensuri

4. SHTTP (Secure HTTP).Secure HTTP este un sistem de criptare pentru HTTP proiectat de Commerce Net. SHTTP lucrează numai cu HTTP.

Majoritatea server-elor Web comerciale caută să folosească facilitățile oferite de SSL și SHTTP. atât SSL cât și SHTTP necesită un software special pentru a fi rulate, software ce trebuie să existe atât pe server-ul de Web, cât și pe navigatorul Web.

Când se folosește un protocol criptat, securitatea datelor depinde de câteva probleme:

Puterea algoritmului de criptare;

Lungimea cheii de criptare;

Secretul cheii de criptare;

Puterea software-ului de bază care rulează pe server-ul Web;

Puterea software-lui de bază care rulează pe Web-ul client;

În vara anului 1995, au fost publicate o mulțime de articole care descriau greșeli în sistemul folosit de Netscape Navigator. În primul caz, un cercetător din Franța a putut să spargă cheia de criptare folosită pe un mesaj singular, folosind o rețea și 2 calculatoare. Mesajul a fost criptat cu versiunea internațională a lui Netscape Navigator, care a folosit o cheie RC4 de 40 de biți. În al doilea caz, un grup de studenți din Universitatea Berkley, California, au găsit o greșeală în generatorul de numere aleatoare folosit de o versiune a Netscape pentru UNIX .

Dar toate acestea nu par să aibă un impact prea puternic asupra dezvoltării comerciale a Web-ului. În cazul demonstrări existenței unor, firmele reacționează imediat și își pun la punct produsele.

Astfel, Netscape a îmbunătățit procesul de generare a numerelor aleatoare și, de asemenea, este de așteptat ca, în scurt timp, dimensiunea cheilor de criptare să crească până la 64 de biți.

Interceptare prin intermediul fișierelor de login

Majoritatea server-elor, atunci când servesc o cerere client, creează fișiere de login, ce conțin o cantitate considerabilă de informații despre fiecare cerere. Aceste fișiere cresc fără limită până când sunt curățate automat sau până când umplu hard-diskul ( provocând disfuncționalități în serviciile oferite de către server).

De exemplu, server-ul httpd al NCSA întreține următoarele fișiere de login în directorul logs/:

acces_log – conține o listă a accesului individual la server;

agent_log – conține o listă a programelor care au fost folosite pentru accesul

la server;

error_log – listă a erorilor pe care server-ul le-a înregistrat, indiferent dacă

au fost generate de server sau de script-urile CGI (ori de câte

ori un script scrie la ieșirea standard pentru erori, eroarea este

înregistrată în acest fișier);

refer_log – acest fișier conține intrări ce include URL-uri pe care

navigatorul l-a vizitat și URL-ul curent ce se vizulalizeză.

Examinând informația din aceste fișiere, se poate crea o imagine sintetică a celor care au accesat server-ul Web, a informației care a fost vizualizată și a site-urilor vizitate anterior.

În continuare, sunt descrise câmpurile care sunt stocate în fișierul acces_log :

Numele calculatorului de la distanță care a inițiat transferul;

Numele de login de la distanță, dacă a fost furnizat, sau “ – “ dacă nu;

Numele utilizatorului de la distanță, dacă a fost furnizat, sau “-“ dacă nu;

Momentul când transferul a fost inițiat (zi a lunii, luna, anul, ora, minutul, secunda și diferența de timp orar);

Comanda HTTP care a fost executată (poate fi GET pentru fișiere recepționate, POST pentru procesarea formelor sau HEAD pentru HEAD pentru vizualizarea header-ului MIME);

Starea codului care a fost returnat;

Numărul de octeți care au fost transferați;

Un atac asupra server-ului de Web poate duce la compromiterea acestui fișier. Obținerea informațiilor conținute în acest fișier de către un terț poate compromite modul confidențial de legătură între server și client.

Riscurile navigatoarelor de Web

Navigatoarele Web prezintă la rândul lor propriile probleme de securitate:

A) Executarea codului de rețea

Majoritatea Web-urilor pot fi configurate astfel încât aplicațiile ajutor (helper) să fie rulate automat atunci când sunt încărcate de pe rețea fișiere de un anume tip. Cu toate că astfel se poate furniza extensibilitate, este recomandat să se evite acest gen de configurare deoarece este un mare risc, oferind posibilitatea intrușilor să ruleze programe pe calculatorul client fără o permisiune explicită.

De asemenea,este recomandat ca un navigator Web:

Să nu se configureze /bin/csh ca un vizualizator pentru documente de tipul applications/x-csh (același lucru fiind valabil și pentru alte interpretoare de comenzi);

Să nu se configureze navigatorul de Web pentru a încărca automat foi de calcul (spreadsheets) sau procesoare de text, deoarece unele dintre ele au posibilitatea de a încapsula cod executabilîn aceste fișiere (exemplul cel mai bun îl constituie virușii care folosesc macro-urile Microsoft Word pentru atac).

O excepție la aceste reguli rigide poate fi limbajul de operare Java. Creatorii acestui limbaj au luat o serie de măsuri pentru a fi siguri că un program scris în Java nu afecează calculatorul client în timp ce lucrează. Dar, după cum vao vedea într-o secțiune următoare, și în Java există o serie de deficiențe.

B) Încrederea în furnizorii de software

În majoritatea cazurilor, licențele de software ale produselor furnizorilor de navigatoare țin să precizeze că aceștia nu-și iau nici o responsabilitate cu privire la unele accidente ce pot apare. De asemenea, documentația ce le însoțește nu lasă nici cea mai vagă idee asupra modului în care a fost construit navigatorul. De exemplu, firma Netscape Communications nu oferă spre publicare codul sursă al produselor Netscape Navigator sau Netscape Commerce Server (desigur, firma își ține secrete codurile sursă) existând posibilitatea existenței unor trape ascunse în cadrul acestor produse.

Astfel, un navigator poate scana discul sistemelor client sau server, în funcție de software-ul în cauză, în vederea găsirii unor informații de interes ce pot fi, de exemlu, trimise criptat spre furnizorul de software.

Limbajul Java în lumea Web-urilor

După ce a fost dezvoltat câțiva ani de către firma Sun Microsystems, limbajul Java a fost lansat la jumătatea lui 1995 ca parte a navigatorului Web al firmei Sun –HotJava. La puțin timp după aceasta, Netscape Communications Corp. a cumpărat licența pentru limbajul Java și l-a incorporat în versiunea 2.0 a navigatorului său Web-Netscape – liderul actual al pieței. Firma Microsoft a cumpărat și ea licență pentru Java, cu intenția vădită de a nu pierde startul. astfel, susținut de câteva dintre cele mai influente companii, Java pare a avea cea mai bună șansă de a deveni standardul pentru conținutul executabilelor de pe Web. Aceasta îl face însă o țintă atrăgătoare pentru atacuri rău intenționate și necesită o serioasă revizuire a scurității limbajului.

Apariția limbajului Java

Unul dintre principiile de bază după care a fost proiectat limbajul Java a fost simplitatea. Pentru aceasta, Din limbajul din care a derivat Java, C++ , a fost eliminat un număr de elemente. Astfel, Java diferă de C++ prin următoarele :

suportă doar un singur nivel de moștenire (s-a eliminat moștenirea multiplă);

asigură suport pentru concurență (Java a fost conceput ca un limbaj care să permită execuția concurentă a mai multor task-uri; suportul pentru aceasta este asigurat de runtime-system-ul Java care implementează mecanismul de thread-uri);

este un limbaj type-safe;

s-au eliminat pointer-ii;

Java se aseamănă, totuși, în multe puncte cu limbajul C++. Ambele limbaje furizează suport pentru programarea orientată obiect, partajează multe cuvinte cheie și alte elemente sintactice și pot fi folosite în dezvoltarea de aplicații standalone.

Compilatoarele Java produc coduri de octeți (bytecode) – implementări pentru fiecare metodă a unei clase, scrise cu setul de instrucțiuni al mașnii virtuale. Codurile de octeți sunt independente de mașină. Ele sunt transmise prin rețea, fiind apoi interpretate sau compilate în cod nativ de către runtime–system-ul Java. În vederea aducerii acestor bucăți de cod din rețea, Java fave distincție între codul local și codul adus de la distanță. Pentru a ușura operarea cu codul adus de la distanță (prin download), Java introduce conceptul de spații de nume, pentru a distinge codul local de codul adus de la distanță. Codurile de octeți provenind din surse distincte (adică mașini și/sau pagini Web diferite) sunt încărcate în spațiib de nume separate pentru a preveni coliziunea atât accidentală, cât și rău intenționată a numelor. Astfel, o clasă locală nu poate să acceseze, fie și numai accidental, o clasă sistem.

Pentru fiecare spațiu de nume se poate determina care este server-ul de pe care provin clasele respective. În afară de aceste spații de nume, în sistem există un spațiu de nume sistem (global) care următoarele proprietăți :

este partajat de toate spațiile de nume;

întotdeauna căutarea se efectuează în primul rând aici, pentru a preveni suprascrierea unei clase sistem în urma încărcării din rețea a unei alte clase.

Această ultimă proprietate nu este verificată întotdeauna.

Necesitatea securității în Java

Adăugând Java peste gama de instrumente arătată până acum se întrevăd noi probleme de securitate:

Java este un limbaj de programare ce permite aplicațiilor să folosească o serie de resurse pe mașina țintă, cum ar fi manipularea fișierelor și deschiderea soclurilor (sockets) pe sistemele de la distanță;

Codul Java se încarcă din rețea, adesea de pe mașini asupra cărora nu există nici un control. Acest cod poate conține greșeli fatale sau poate să fi fost alterat de un intrus;

Codul Java este ușor de încărcat de navigatoarele care înțeleg cod Java, cum ar fi hot Java și Netscape. Applet-urile pot fi transportate pe mașina client și executate fără a se cere nici o permisiune. Acest conținut executabil (bytecode) poate avea capacități care încalcă limitările originale ale navigatorului de Web.

Aceste caracteristici arată de ce codul Java trebuie tratat cu atenție. Fără un control al mediului, pot apare o serie de probleme ca:

O secvență de cod poate distruge fișiere și alte resurse ale calculatorului;

Cât timp își prezintă aplicația, codul silențios poate “fura” date importante de pe sistemul client, pe care le poate transfera pe mașina atacatoare;

Simpla vizitare a unei pagini Web poate duce la “încărcarea” unui virus sau a unui vierme;

Un program poate folosi sistemul client pentru atacul asupra altui sistem, ascunzând identitatea reală sau chiar mistificând, indicându-l pe acesta ca fiind adevărata sursă a atacului;

Crearea unui cao de către un programator neexperimentat poate provoca, chiar fără voia acestuia, “breșe” de securitate.

Având în vedere toate acestea, Java trebuie să ofere un mediu controlabil, în care aplicațiile să fie executate. Căile pentru abuzuri și distrugeri neintenționate trebuie anticipate și blocate.

Cadrul de securitate Java

Java încearcă să furnizeze un cadru de lucru curat, care creează un mediu de execuție sigur. Java este mai mult decât un limbaj de programare, el fiind constituit din mai multe straturi diferite, care compun mediul de execuție Java:

Limbajul de programare;

Biblioteca standard API;

Compilatorul Java;

Un cod specific (bytecode);

Un mecanism pentru încărcarea dinamică și verificarea bibliotecilor;

Un automat de colectare a deșeurilor (garbadge collection) pentru eliberarea memoriei;

O mașină virtuală universală pentru executarea bytecode-ului – Mașina Virtuală Java.

A) Siguranța oferită de un limbaj

Limbajul Java în sine oferă primul strat al securității, mai precis cele necesare pentru a proteja structurile de date și pentru a limita probabilitatea scrierii neintenționate a unor programe.

B) Java respectă programarea orientată obiect

Structurile de date private și metodele sunt încapsulate în clase Java . Accesul la aceste resurse este oferit numai printr-o interfață care este furnizată de clasă. Codul orientat obiect se dovedește a fi mai maleabil și mai clar în proiectare.

C) Fără poiter-i aritmetici

Referințele Java nu pot fi incrementate sau resetate la un punct dintr-o porțiune specificată a memoriei Mașinii Virtuale Java.

D) Verificarea limitelor tablourilor

Multe probleme de securitate apar în programele scrise greșit, în alte limbaje de programare, unde lipsește o facilitate de verificare a limitelor tablourilor.

Un program poate fi influențat să itereze dincolo de sfârșitul tabloului, referind date din afara tabloului. Java previne aceasta: o încercare de indexare a unui element, înainte de începutul sau după sfârșitul tabloului, provoacă o excepție.

E) Sistemul de conversie la Java

Java asigură câteva conversii de la un obiec la altul, dacă aceasta nu este o operație ilegală. Un obiect nu poate fi transformat în mod arbitrar la un alt tip.

F) limbajul suportă programarea firelor de execuție (threads) sigure

Programarea multi-thread este o parte intrinsecă a limbajului Java, permițându-se crearea unor programe în care au loc evenimente în același timp. Bazat pe un sistem de proceduri care permit folosirea “firelor” de evenimente multiple, Java oferă programatorilor o metodă de implementare a programelor interactive.

G) Metode și clase finale

Multe clase și metode din cadrul API Java sunt declarate finale, împiedicând posibilitatea de moștenire sau de rescriere a codului.

Verificarea

Compilatorul Java convertește codul sursă în cod de octeți (bytecode), specific pentru Mașina Virtuală Java. Compilatorul asigură toate facilitățile de securitate pe care limbajul le impune. Un compilator de încredere stabilește dacă codul este sigur și, de asemenea, folosește conversiile de tip admise. Codul de octeți Java este esența a ceea ce se transmite pe rețea fiind un cod pentru Mașina Virtuală Java. Securitatea Java ar fi ușor de subminat dacă s-ar scrie un compilator ostil, care ar genera un cod de octeți ce poate crea probleme.

În consecință, este absolut necesară o verificare suplimentară a securității în cadrul programului de navigare. Este greu să se întrețină un mediu de execuție sigur, deoarece nu se poate sti cu siguranță dacă codul de octeți a fost obținut cu un compilator “curat”, cum ar fi javac din pachetul de dezvoltare JDK . După încărcarea codului de octeți Java, prima intrare în sistem trebuie să fie precedată de o verificare. Verificarea realizează un număr de controale cu privire la toate fișierele class încărcate în mediul de execuție Java. Se execută un număr de pași înaintea aprobării vreunei încărcări de cod:

Primul pas verifică dacă fișierele class au un format general corect;

Al doilea pas verifică dacă un număr de convenții Java sunt respectate, cum ar fi verificarea dacă fiecare clasă are o superclasă (clasă de bază) – excepție făcând clasa Object – sau dacă metodele finale și clasele nu sunt suprascrise;

Al treilea pas face cea mai detaliată inspectare a fișierului class. În această etapă este examinat chiar codul de octeți pentru a asigura valabilitatea sa;

Ultimul pas realizează câteva verificări adiționale, cum ar fi verificarea existențeicâmpilor clasei.

Runtime-system-ul Java este proiectat pentru a întări semantica de acces a limbajului. Spre deosebire de C ++, programelor Java nu le este permis să acceseze datele și funcțiile prin intermediul pointer-ilor. Astfel, dacă un applet rebel încearcă să apeleze o metodă privată, runtime-system-ul semnalează o excepție, împiedicând acest acces neautorizat.

Documentația Java susșine că siguranța codurilor de octeți poate fi determinată statistic la momentul încărcării. Acest lucru nu este în întregime adevărat. În versiunea 1.0 alpha 3, sistemul de tipuri folosește o regulă covariantă pentru tablouri, așa că memorarea tablourilor necesită verificarea tipului la momentul execuției. Din păcate, aceasta înseamnă că verificatorul de coduri de octeți nu este singura componentă din runtime-system care trebuie să ruleze corect, pentru a asigura securitatea. În plus, verificările dinamice aduc după sine o penalizare asupra performanțelor.

Încărcarea claselor

Runtime-system-ul Java știe cum să încarce coduri de octeți doar din sistemul local de fișiere. În plus, codurile de octeți încărcate din sistemul local de fișiere sunt vizibile tuturor applet-urilor.

Pentru încărcarea codului din alte surse, runtime-system-ul Java apeleayă o subclasă a clasei abstracte ClassLoader, ce definește o interfașă pentru runtime-system, care cere programului Java să încarce o clasă.

Un navigator Web folosește un singur încărcător de clase (classloader), care este stabilit la început. După aceea, classloader-ul sistem nu poate fi extins,supraâncărcat, suprascris sau înlocuit. Applet-urile nu pot crea sau referi propriul lor classloader.

Clasele sunt transportate prin rețea ca șiruri de biți și sunt reconstituite în obiect Class de către subclase ale ClassLoader-ului. Fiecare clasă este etichetată cu ClassLoader-ul care o încarcă. La momentul rulării, este posibil să se determine dacă o clasă are un ClassLoader în lanțul de apel curent.

ClassLoader este un obiect care moștenește clasa abstractă java.lang.ClassLoader. Acesta încarcă applet-uri venite de pe rețea și le supune la restricțiile Managerului de Securitate a applet-urilor.

Pentru clasele care sunt încărcate în sistemul de urmărire este alocat un spațiu de nume, care se găsește și în structurile de date ale obiectului.

ClassLoader asigură că obiectele nu pot intra în alte spații de nume neautorizate. Câmpurile publice și metodele pot fi accesate; în afară de cazul în care a fost definită o interfață, nu există vizibilitate asupra variabilelor clasei.

ClassLoader oferă, de asemenea, o poartă strategică pentru controlul codului claselor ce sunt accesate. De exemplu, applet-urile sunt împiedicate să suprascrie clasele Java ca și cum ar fi furnizate de Java API.

Stabilirea unei politici de securitate

Precizările precedente asupra cadrului de securitate Java asigură că sistemul Java nu poate fi subminat de un cod incorect sau de un compilator ostil, iar codul Java rulează după reguli bine stabilite. Acestea fiind asigurate, poate fi stabilită o politică de securitate de nivel înalt. Această politică de securitate există la nivelul aplicației, permițând să se precizeze ce resurse ale programului Java pot fi accesate sau manipulate .

Biblioteca API Java furnizează clasa java.lang.SecurityManager ca posibilitate de a defini un set clar de task-uri care pot să fie sau nu realizate, cum ar fi accesul la fișiere sau în rețea. Prin implementarea unui Manager de Securitate (SecurityManager), se pot adăuga semnificative măsuri de protecție.

Mediul Java conține o clasă globală, numită SecurityManager. Metodele acestui obiect sunt utilizate pentru a realiza verificări în timpul execuției. Definind o subclasă a acestei clase se pot implementa diferite politici de protecție. Utilizarea metodelor oferite de către SecurityManager se face în implementarea metodelor publice, care accesaează resursele critice. Astfel, SecurityManager-ul este cel care posedă metode pentru a determina dacă clasa încărcată de ClassLoader se găsește în lanțul dinamic și, dacă este așa, unde anume se găsește în acest lanț. Această structură imbricată este utilizată pentru a se lua decizii în politicile de control al accesului.

Clasa SecurityManager permite deci stabilirea unei politici de securitate specifice. Această clasă abstractă oferă posibilitatea creării unui obiect care determină dacă o operație pe care programul urmează să o execute este permisă. Clasa are metode pentru atingerea următoarelor puncte în realizarea politicii de securitate:

Determină dacă o conectare pri rețea de la un sistem gazdă specificat, pe un port specificat poate fi acceptată sau nu ;

Verifică dacă un thread poate fi manipulat de un alt thread sau de un grup de thread-uri (ThreadGroup);

Împiedică crearea unei noi clase ClassLoader;

Împiedică crearea unui nou SecurityManager, care se poate suprapune peste politica existentă deja;

Verifică dacă un fișier poate fi șters;

Verifică dacă un program execută un program de pe sistemul local;

Împiedică un program să părăsească Mașina Virtuală Java fără monitorizare;

Verifică dacă o bibliotecă dinamică poate fi link-editată ;

Verifică dacă un port de rețea sigur poate fi ascultat (listen) pentru o conectare la sistemul local;

Determină dacă un program poate fi încărcat într-un pachet Java specificat;

Determină dacă un program poate crea o nouă clasă într-un pachet Java specificat;

Identifică care proprietăți sistem pot fi accesate prin metoda System.getProprety();

Verifică dacă un fișier poate fi citit;

Verifică dacă se pot scrie date într-un fișier;

Verifică dacă un program poate să creeze propria sa implementare pe socket-uri;

Navigatoarele ce înțeleg limbajul Java folosesc Managerul de Securitate pentru a stabili o politică de securitate, făcând distincție între aplicațiile Java și applet-urile Java.

Applet-urile Java sunt programe care extind clasa java.applet.Applet. Ele pot fi încărcate și executate ușor de navigatoarele ce înțeleg Java, cum ar fi Hotjava sau Netscape. Înaintea versiunii JDK1.1 nu există un mecanism pentru stabilirea unui grad de încredere asupra acestui tip de cod. În general, toate applet-urile trebuiau privite ca provenind din surse nedemne de încredere.

Un punct important în realizarea unei investigații – relativ la securitatea Java – este diferența dintre applet-uri și aplicații Java. Applet-urile pot fi executate dinamic într-un navigator, prin încărcarea unei pagini HTML care conține un element APPLET, pe când aplicațiile sunt executate direct de interpretorul Java și trebuie instalate manual pe sistemul local și executate de către utilizatorul sistemului. Navigatoarele Java nu pot executa aceste programe. Din cauza acestor deosebiri dintre applet-uri și aplicații, cele două tipuri de coduri Java se execută sub două politici de securitate diferite:

Aplicațiilor le este permis acesul la resursele sistemului. Lor li se acordă încredere pentru deschiderea și scrierea în fișiere, conectarea la diverse resurse de reșea și rularea diferitelor programe pe sistemul local;

Applet-urile, se presupune că provin din surse nesigure și au capacitatea de a produce pagube, astfel încât sunt rulate într-un cadru de execuție foarte atent controlat.

Applet-urile sunt restricționate la o seie de acțiuni:

a) Nu le este permis să citească fișiere de pe sistemul local. De exemplu, următoarele apeluri nu pot fi considerate corecte în cadrul unui applet:

File readFile = new File(“/etc/passwd”);

FileInputStream reanIn=newFileInputStream(readFile);

b)Nu le este permis să creeze, să modifice sau să șteargă fișiere de pe sistemul local . De exemplu, liniile următoare nu sunt permise într-un applet:

File writeData = new File(“write.txt”); //Nu poate crea

fișiere.

FileOutputStream out = new FileOutputSteam(writedata);

out.write(1)

File oldName = new File(“one.txt”);

File newName = newFile(“two.txt”);

oldName.renameTo(newName); //Nu poate schimba numele

fișierului.

File removeile = new File(“import.dat”); //Nu pote șterge

fișierul.

removeFile.delete();

c) Nu pot verifica existența unui fișier pe sistemul local. De exemplu,liniile următoare nu sunt permise într-un applet:

File isHere = new File(“grades.dbm”);

isHere.exists();

d) Nu pot crea un director pe sistemul local. De exemplu, liniile următoare nu sunt permise într-un applet:

File createDir = new File(“mydir”);

createDir.mkdir();

e) Nu pot să inspecteze conținutul unui director. De exemplu, liniile următoare nu sunt permise într-un applet:

String[] fileNames;

File lookAtDir = new File(“/useres/hisdir”);

fileNames = lookAtDir.list();

f) Nu pot să verifice atributele fișierelor, cum ar fi mărimea fișierelor, tipul lor sau momentul ultimei modificări. De exemplu, acestea nu sunt permise într-un applet:

File checkFile = new File(“this.dat”);

long checkSize;

boolean checkType;

long checkModTime;

checkSize = checkFile.length()

checkTipe = checkFile.isFile()

checkModTime = checkFile.lastModified();

g) Un applet nu poate crea o conexiune de rețea la o altă mașină decât la cea de pe care a fost încărcat. Această regulă este valabilă pentru conexiunile care au fist create prin una din clasele de rețea Java, incluzând java.net.Socket, java.net.URL și java.net.DatagramSocket. De exemplu, în ideea că un applet a fost încărcat de pe mașina www.deincredere.ro , liniile următoare nu sunt permise într-un applet:

// Nu poate deschide un socket TCP.

Socket mailSocket = new Socket(“mail.nesigur.ro”,25);

// Obiectele URL sunt restricționate

URL WebNesigur = new URL(http://www.nesigur.ro/);

URLConnection agent = WebNesigur.openConnection();

agent.connect();

// La fel pentru datagrame UDP.

InetAddress acestSite = new InetAddress(www.nesigur.ro);

int acestPort = 7;

byte[] data = new byte[100];

DatagramPacket sendPacket =

new DatagramPacket(data,data.length, acestSite,Port);

DatagramSocket sendSocket = new Datagramsocket();

sendSocket.send(sendPacket);

h) Applet-urile nu pot juca rolul de server, ascultând sau acceptând conexiuni socket de pe un sistem de la distanță. De exemplu, liniile următoare nu sunt permise într-un applet:

SereverSocket listener = newServerSocket(8000);

listener.accept();

i) Sunt împiedicate să execute programe ce sunt rezidente pe sistemul local. De exemplu, liniile următoare nu sunt premise într-un applet:

String command = DEL /AUTOEXEC.BAT”;

Runtime systemCommands = runtime.getRuntime();

systemCommands.exec(command);

j) Nu le este permis să încarce biblioteci dinamice sau să definească apeluri de metode native. De exemplu, liniile următoare nu sunt permise într-un applet:

Runtime systemCommands = Runtime.getRuntime();

systemCommands.loadLibrary(“local.dll”);

k) În cadrul mediului Java sunt definite câteva proprietăți standard. aceasta se face cu metoda java.lang.System.getProprety(String key). Applet-urilor le este permis să citească numai anumite proprietăți și le este interzis accesul la altele ;

l) Nu pot manipula alte thread-uri Java în afara celor din propriul grup;

m) Nu pot închide Mașina Virtuală Java. De exemplu, liniile următoare nu sunt permise într-un applet:

// Mecanismul următor este greșit.

Runtime SystemCommands = Runtime.getRuntime();

systemCommands.exit(0);

// De asemenea și acest mecanism.

System.exit(0);

n) Nu pot crea instanțe ale Managerului de Securitate (SecurityManager) sau încărcătorului de clase (ClassLoader);

o) Pachetul java.net folosește anumiți factori pentru stabilirea implementări conceptelor specifice Java: handler-e de protocol, handler-e de conținut și socket-uri. Applet-urile nu pot suprascrie specificațiile acestor clase:

java.net.URLStreamHandlerFactory, java.net.ContentHandlerFactory și java.net.SocketimpFactory.

Politica de securitate a navigatoarelor Netscape și HotJava

Netscape și HotJava reprezintă exemple a două arhitecturi distincte de construire a navigatoarelor Web:

Netscape este scris într-un limbaj nesigur și rulează applet-uri Java ca o extensie a caracteristicilor sale;

HotJava este scris chiar în Java, același runtime system suportând atât navigatorul cât și applet-urile.

Ambele arhitecturi au avantaje și dezavantaje în raport cu securiatea :

Netscape are de suferit din faptul că este implemantat într-un limbaj nesigur (depășiri de buffer, coruperi de memorie), dar furnizează o interfață cu Java bine definită. În Netscape, applet-urile Java pot numi doar acele funcții și variabile exportate explicit spre subsistemul Java;

HotJava este implementat într-un limbaj sigur și nu are de suferit din problemele de coruperi de memorie posibile, dar poate exporta, în mod accidental, prea mult din mediul său applet-urilor.

În concluzie, navigatoarele HotJava și Netscape folosesc politici de securitate specifice pentru încărcarea applet-urilor nesigure. Managerul de Securitate realizează un număr de verificări asupra acțiunilor permise unui program. ClassLoader-ul, care realizează încărcarea claselor Java din rețea, încarcă de pe sistemele externe doar acele care nu subminează această securitate. În scopul de a fi sigure, astfel de sisteme trebuie să limiteze acesul applet-urilor la resursele sistemului cum ar fi: sistemul de fișiere, unitatea centrală, rețeaua, display-ul, starea internă a navigatorului.

Sistemul de tipri de date ale limbajului trebuie să fie sigur, adică să împiedice construirea unor pointeri “frauduloși” și să verifice limitele vectorilor. În plus, sistemul trebuie să efectueze “garbage collection” pentru a preveni inconsistențele de memorie (cum ar fi omiterea eliberării unei zone de memorie odată ce ea nu mai este necesară sau eliberarea de două sau mai multe ori, în mod accidental, a unei zone de memorie), să administreze cu grijă apelurile sistem care pot accesa zone din afara programului și să nu permită applet-urilor să se influențeze unul pe celălalt.

Problemele de securitate ce apar se datorează mai multor motive cum ar fi:

erori de implementare în cadrul limbajului Java;

interacțiuni nedorite într diverse caracteristici ce s-au dorit a fi introduse în limbaj;

diferențe într limbajul Java semantica codurilor de octeți;

slăbiciuni în proiectarea limbajului și în formatul codurilor de octeți.

La baza acestor “găuri” de securitate stau slăbiciuni ale metodologiilor de proiectare folosite în dezvoltarea limbajului Java și navigatoarelor.

Mecanisme de securitate

În HotJava, controlul accesului era făcut pe un fundament destul de arbitrar și neclar. Versiunea beta a JDK (Java Developpers Kit) a introdus clasa SecurityManager ca un monitor de referință care definește și implementează o politică de securitate centralizând toate deciziile de control al acesului. Un astfel de monitor de referință trebuie să aibă trei proprietăți importante: să fie invocat întodeauna, să fie inviolabil și verificabil. Din păcate, SecurityManager-ul din Java prezintă slăbiciuni pe toate cele trei planuri:

el nu este invocat întotdeauna: înscrierea unor porțiuni de cod din runtime-system-ul Java, relevante din punvtul de vedere al securității, SecurityManager-ul trebuie apelate explicit;

nu este inviolabil: de exemplu, implementare din versiunea beta a SecurityManager-ului prezintă o variabilă protected care pute fi modificată de orice subclasă a SecurityManager; eroarea a fost corectată prin schimbarea semantici pentru protected;

nu este verifecabil: este scris într-un limbaj, Java, care nu are semantica definită cu precizie.

Clasa SecurityManager definește interfața pentru controlul accesului. Implementarea implicită pentru SecurityManager semnalează câte o SecurityException la orice verificare a accesului, obligând agentul utilizator să definească și să implementeze propria politică într-o subclasă a SecurityManager-ului. Atât în JDK cât și în Netscape, managerii de securitate folosesc în mod tipic conținutul stivei, pentru a decide dacă se permite accesul sau nu .

La momentul pornirii runtime-system-ului Java, nu există nici un Manager de Securitate instalat. Este responsabilitatea naviagtorului Web sau a altui agent utilizator să instaleze un Manager de Securitate înaintea executării codului nesigur, adus în rețea.

O metodă de asigurare a protecției pentru Managerul de Securitate în Java este folosirea sistemului de tipuri. Dacă sistemul de tipuri este fără fisuri, atunci și Managerul de Securiate este inviolabil. Prin folosirea tipurilor în locul spațiilor de adresă separate pentru protecție, Java poate fi încorporat în alte produse software cu garanția că, din punctul de vedere al securității, lucrează fără degradarea performanțelor.

Probleme de securitate apărute în Java

Au existat și există diverse clase de probleme legate de securitate în Java. O clasificare a lor poate fi următoarea:

1) atacuri de refuz al serviciului (denial of service attacs);

2) atacuri tripartite (three party attacs);

3) canale ascunse (covert channels);

4) informația disponibilă applet-urilor;

5) erori de implementare.

O astfel de clasifacare este utilă pentru înțelegerea cauzelor problemelor actuale și eventuala depistare a surselor de probleme viitoare.

Detaliem fiecare clasă.

1) Atacul de refuz al serviciului (Denial-of-Service)

O clasă importantă de atacuri reușite o reprezintă cele de refuz al serviciului. Atacurile cele mai grosolane implică așteptare ocupată (busy-waitig), consumând ciclii CPU, alocând memorie până ce sistemul clachează, blocând alte thread-uri și procese sistem. Nu există nici un mecanism în Java care să împiedice această clasă de atacuri. În plus, se pot bloca părți critice din navigatorul HotJava, blocări ce îl pot scoate din uz.

Prezentăm în continuare un exemplu cu o secvență de cod care blochează linia de stare de la baza navigatorului, împiedicând-ul pe acesta să mai încarce vreo pagină. În cazul Netscape-ului, acest atac pote bloca clasa java.net.InetAddress, blocând toate conexiunile cu alte sisteme gazdă din rețea. Atacul poate fi programat cu o întârziere de timp, astfel încât disfuncționalitatea (blocarea liniei de stare ) să se petreacă atunci când utilizatorul vizualizează o altă pagină Web, mascându-se astfel sursa atacului.

În unele situații un astfel de atac poate duce la o degradare a serviciului și nu la refuzarea acestuia. Clasa MeteredStream fiind publică, permite un astfel de atac.

Fragment de cod Java care blochează navigatorul (prin blocarea liniei sale de stare):

synchronized (Class.forName (“net.www.html.MeteredStream”))

{

while(true)

Thread.sleep (5000);

}

Atât HotJava cât și Netscape posedă câteva clase ce se pretează la acest gen de atacuri. Ele pot fi împiedicate prin înlocuirea unor clase critice cu acoperiri (wrappers), care să nu expună blocările unor persoane din exterior. Totuși atacurile la CPU și la memorie nu pot fi întotdeauna prevenite. Multe aplicații autentice necesită cantități mari de memorie și CPU, iar aceasta poate induce în eroare .

Alte forme ale acestui tip de atac pot fi următoarele:

Un atac asupra poștei electronice, când cineva trimite în mod repetat documente foarte mari pentru a umple sistemul de poștă electronică;

Folosirea unei aplicații, precum ping, pentru a “inunda” un anumit sistem;

Folosirea unui navigator automat pentru cereri repetate de resurse de la un server Web.

2) Canale ascunse și atacuri tripartite

Un atac tripartit poate porni de oriunde din INTERNET și se poate răspândi ușor, dacă este ascuns într-un applet des utilizat de către multe pagini Web. Un exemplu tipic de astfel de atac poate decurge în felul următor: Un atacator C produce un applet “cal troian”. Utilizatorului B îi place applet-ul și îi utilizează în pagina sa de Web. Un alt utilizator A vizualizează pagina de Web a lui B și astfel, applet-ul lui C stabilește un canal ascuns spre C. Acest applet permite scurgerea de informație de la a spre C, fără ca aceștia doi să fi fost în contact direct și fără ca B să fie implicat în vreun fel.

Navigatorul HotJava oferă o serie de setări de securitate pentru accesul la rețea. De obicei, cei mai mulți utilizatori folosesc modul implicit, care permite applet-ului să se conecteze la clculatorul gazdă de pe care a fost încărcat. În cazul Netscape-ului, acesta este singurul mod de securitate pe care-l au la dispoziție utilizatorii.

De fapt, HotJava și Netscape prezintă această scăpare în politica de securitate datorită unor erori de implementare, fiind astfel expuse la pericolul canalelor ascunse. Apelul sistem accept(), folosit pentru a primi o conexiune de rețea inițială de alt calculator gazdă, nu este protejat prin verificările uzuale de securitate. Acesta permite unui calculator gazdă arbitrar din INTERNET să se conecteze la navigatorul HotJava atâta timp cât locația navigatorului este cunoscută . Pentru ca acest lucru să se transforme într-un atac eficient, applet-ul trebuie să anunțe agentul extern să se conecteze la port-ul specificat. Pentru ca acest mesaj să fie transmis, sunt disponibile câteva canale ascunse. Dacă server-ul Web rulează ca “demon” de mail SMTP, applet-ul se pote conecta la el pentru a transmite un mesaj de e-mail spre orice mașină din rețea.

A încarcă pagina de Web

a lui B

cerere Web

applet produs canal

de C ascuns

Crearea unui canal ascuns

În plus, DNS-ul (Domain Name System) poate fi utilizat ca un canal bidirecționl de comunicare: un applet pote suferi un nume fictiv din domeniul atacatorului. Acesta transmite numele spre server-ul DNS al atacatorului, care pote interpreta numele ca un mesaj, iar apoi, poate transmite un număr IP pe 32 de biți, arbitrar, ca răspuns. Executănd apeluri DNS repetate, applet-ul pote stabili un canal între el și server-ul DNS al atacatorului. Acest canal pote trece și printr-un număr de firewall-uri.

Chiar dacă utilizatorul va opta pentr un mod mai restrictiv d.p.d.v. al securității, cum ar fi împiedicarea orcăror conexiuni de rețea realizate de applet-uri, DNS-ul pote totuși funcționa ca un canal ascuns de bandă îngustă, deoarece metoda InetAddress.getByName() este publică și nu efectuează verificările curente de securitate înantea realizării unei cereri DNS.

Java 1.0 alpha 3 are chiar o metodă unde applet-ul poate specifica server-ul DNS, astfel încât atacatorul nu are nevoie de propriul său nume de domeniu. Dacă server-ul Web este cooperativ, capacitatea applet-ului de a obține un URL se constituie într-un alt canal ascuns. Caracteristica de redirectare a URL reprezintă un canal tripartit: în mod normal, un applet pote instrui navigatorul să încarce orice pagină Web. Astfel, un server ostil poate înregistra URL-ul ca un mesaj, apoi poate redirecta navigatorul spre destinația originală.

Canalele ascunse obținute utilizând DNS și SMTP sunt exemple de atacuri tripartite.

Problema canalelor ascunse este cunoscută de firmele Sun și Netscape, care au declarat că vor căuta soluții de eliminare a acestui gen de atacuri în versiunile viitoare ale JDK și Netscape.

4) Informația disponibilă applet-urilor

Dacă un applet “rebel” poate stabili un canal cu orice calculator gazdă din INTERNET, întrbarea ce se naște este ce anume poate afla acel applet despre mașina utilizatorului, pentru a transmite această informație prin respectivul canal.

În HotJava, multe tentative de a citi au scrie în sistemul local de fișiere se produc prin folosirea unei cutii de dialog ce interoghează utilizatorul în privința acordării permisiunii. Liste separate de control al accesului (ACL-Access Control List) specifică unde anumite anume se pote petrece scrirea/citirea în/din fișiere/directoare, fără acordul expilcit al utilizatorului. Implicit, ACL-ul pentru scriere este vid, iar ACL-ul pentru citit conține directorul de biblioteci al HotJava, directorul public_html al utilizatorului (ce poate conține informații care compromit securitatea utilizatorului) și anume fișiere MIME mailcap. Versiunea pentru Windows a HotJava permite în plus scrierea (nu însă și citirea) în directorul TEMP. Aceasta permite unui applet să corupă fișiere utilizate de alte aplicații Windows, dacă știe sau poate afla numele pe care le pot avea anumite fișiere “importante”. Un applet poate consuma tot spațiul liber din sistemul de fișiere.

Aceste slăbiciuni pot fi înlăturate prin modificarea directă a listelor de control al accesului. Spre deosebire de HotJava, Netscape nu permite nici un fel de acces al applet-urilor asupra sistemului de fișiere.

Alte informații ce pot fi aflate de către applet-uri în HotJava sunt numele de login al utilizatorului și conținutul tuturor variabilelor de mediu. Aceasta, deoarece System.getenv() nu are verificări de securitate.

Din variable de mediu se poate afla o serie de alte lucruri: de exemplu, din variabila PATH se poate descoperi ce software este instalat pe mașina utilizatorului. În JDK și Netscape, System.getenv() a fost înlocuit cu “system properties”, dintre care multe nu sunt accesibile applet-urilor. Java permite applet-urilor să citească ceasul system, făcând posibilă evaluarea performanțelor mașinii utilizatorului.

În concluzie, există multe scurgeri de informații ce pot fi valorificate de către applet-uri ostile. În versiunile viitoare se urmărește reducerea acestora.

5) Erori de implementare

Anumite bug-uri legate de securitate provin din erori de implementare greu de localizat, ce apar în cadrul navigatorului sau subsistemului Java. Unul dintre cele mai puternice atacuri este acela că se pot server-ele FTP și HTTP ale navigatorului. Un intrus poate să-și stabilească propriul server proxy ca intrus. Cât timp clientul folosește protocoale FTP și HTTP necriptate, intrusul poate să “vadă “tot graficul spre și de la navigatorul HotJava.

Mai jos este prezentată o secvență de cod care redirecționează toate cererile HTTP și FTP:

Hotjava.props.put(“ftpProxyHost”, “proxy.intrus.org”);

Hotjava.props.put(“useFtpProxy”, “true”);

Hotjava.props.put(“proxyHost”, “proxy.intrus.org”);

Hotjava.props.put(“ftpProxyHost”, “proxy.intrus,org”);

Hotjava.props.pur(“proxyPort”, “8080”);

Hotjava.props.put(“proxySet”, “true”);

FtpClient.useFtpProxy=true;

FtpClient.ftpProxyHost=”proxy.intrus.org”

FtpClient. FtpProxyPort=8080;

HttpClient.cachingProxyHost=”proxy.intrus,org”;

HttpClient.cachingProxyPort=8080;

HttpClient.useProxyForCaching=true;

Toate acestea sunt posibile deoarece strea navigatorului este memorată în variabilele publice din clasele publice. Implementarea unui astfel de tip de atac este trivială, iar efectele sale pot fi dezastruoase asupra securități utilizatorului.

Folosind metoda put(), se poate memora proxy-ul dorit în baza de date a managerului de proprietăți dacă intrusul pote păcăli utilizatorul să tipărească o pagină Web, aceste setări vor fi salvate pe disc și vor deveni setările implicite la următoarea lansare a navigatorului HotJava. Dacă variabilele și clasele ar fi private, acest atac ar eșua. De asemenea, dacă navigatorul ar rula ăn spatele unui firewall și s-ar putea încrede în server-ele proxy pentru a accesa Web-ul atacul ar eșua.

O observație ar fi aceea că biblioteca runtime din Java trebuie să supotre toate protocoalele aflate curent în uz: HTTP, FTP, MNTP, Gopher, SMTP și Finger. Din acest motiv, applet-urile nesigure trebuie să fie capabile să utilizeze serviciile de rețea doar cu anumite restricții. Aici, FTP-ul prezintă cele mai multe dificultăți.

În aceeași categorie, a erorilor de implementare, se încadrează și depășirile de buffer(buffer overflows). HotJava și versiunea alpha a HDK prezintă multe apeluri sprintf() neverificate, care utilizează bufer-ele alocate pe stivă. Deorece sprintf() nu verifică depășirea buffer-ului, un atacator poate suprascrie stiva la execuție, transferând astfel controlul unui cod arbitrar. Aceeași slăbiciune a fost exploatată de către atacatori și în rutina de bibliotecă syslog() din UNIX (via sendmail),pentru a prelua controlul unor mașini din rețea. În Netscape și versiunea bata a JDK, aceste apeluri au fost corectate.

Biblioteca de clase Java Security API

Odată cu lansarea versiuni JDK 1.1, au apărut facilități pentru verificarea codului de pe alte surse, pentru a vedea dacă acesta nu este alterat de vreun intrus. Aceste proprietăți ale Java Security API sunt bazate pe algoritmi și concepte criptografice .

Concepte criptografice

Schemele criptografice cele mai familiare sunt cele de criptografie simetrică . Conceptual, acestea folosesc pentru criptarea unui bloc de date o cheie specifică, cum ar fi o parolă . Pentru a obține mesajul original este nevoie de aceeași cheie pentru a decripta blocul cifrat. Deoarece securitatea sistemului depinde de confidențialitatea cheilor, aceste scheme sunt numite și scheme criptografice cu chei secrete. Denumirea de sisteme simetrice provine din faptul că se folosește aceeași cheie atât pentru criptare cât și pentru decriptare. Un număr important de sisteme criptografice face parte din această familie: Data Encryption Standard (DES), IDEA sau RC2 și RC4 (algoritmi proprietari distribuiși de RSA Data Security). Una din problemele în folosirea cheilor secrete pentru a proteja comunicațiile este că ambele părți trebuie să posede aceeași cheie. Schimbul de chei trebuie și el, la rândul lui, protejat.

Astfel, înaintea transmiterii în condiții sigure a documentelor, trebuie să existe deja un mecanism de schimb de informații.

Criptografia cu chei publice- se bazează pe o pereche de chei: cheia publică și cheia privată. Cea de-a doua cheie se obșine din prima, printr-o funcție matematică greu inversabilă. Astfel, se poate obține ușor din cheia publică cheia secretă, dar procesul invers este practic imposibil deoarece funcția inversă este foarte greu de calculat. Cheia publică a receptorului este folosită de emițător pentru criptarea mesajului, ea fiind disponibilă pentru orice. Cheia privată a receptorului este folosită de acesta pentru a decripta mesajul cifrat. Acest tip de criptografie se numește și criptografie asimetrică. Acest sistem rezolvă problema distribuirii cheilor, ce introduce limitări în criptografia simetrică. Folosind cheia sa privată, emițătorul poate semna un document, prin criptarea unei secvențe “amprentă” (dependentă de document ) cu acea cheie, iar receptorul poate lua cunoștiință de aceasta prin decriptarea cu cheia publică a emițătorului. Dacă mesajul a fost alterat, semnătura nu poate fi validată. Astfel se poate verifica identitatea și integritatea datelor.

Certificatul de autentificare – este legat de una din limitările sistemului cu chei publice: verificarea faptului că o chei pubilcă aparține într-adevăr destinatarului receptorului mesajului cifrat și nu a fost falsificată de altcineva. Un intrus pote genera o pereche de chei și plasând pe server-ul de chei publice o cheie publică falsificată. Pentru aceasta, se apelează la o autoritate în care atât receptorul cât și transmițătorul au încredere, pentru a autentifica proveniența cheilor. Dacă navigatorul implementează un mecanism de securitate, cum ar fi SSL, se poate avea acces la o listă întreagă de autorități de autentificare. De exemplu, Netscape permite activarea SSL-ului prin selectarea Options => Security Preferences => Site Certificates, obținând lista agențiilor CA (Cetification Authorithes) distribuită odată cu navigatorul.

Bibliografie

1. Carmen Mușatescu – “Aspecte ale modelului client –server “

Else, Craiova, 1998

2. P. Norton – “Programarea în Java “

Editura Teora, București, 1997

3. V.Valeriu Patriciu – “Secutitatea informatică în UNIX

M.Pietroșanu-Ene și Internet”

I.Bica, C. Cristea Editura Tehnică, București,1998

Similar Posts