Sunteți pe pagina 1din 52

Programación con Sockets Secure Layer y

Pthreads
Ing. Mauricio Mena Cortés
koitoer
28 de abril de 2009

1
Índice general

1. Prefacio 5
1.1. A quien lo lea: . . . . . . . . . . . . . . . . . . . . . . . . . . 5

2. Instalación básica 7
2.1. Requerimientos del sistema . . . . . . . . . . . . . . . . . . . 7
2.2. Openssl . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8

3. Creación de certificados 9
3.1. Explicaciones . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
3.2. CA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
3.3. Certificado del servidor . . . . . . . . . . . . . . . . . . . . . 12
3.4. Certificado del cliente . . . . . . . . . . . . . . . . . . . . . . 17

4. Códigos Fuentes 23
4.1. SERVER . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
4.2. CLIENTE . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
4.3. Compilación . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
4.4. MAKE . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36

5. Servidor Multihilo 39
5.1. SERVER . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39

6. Conclusión 48
6.1. Problemas principales . . . . . . . . . . . . . . . . . . . . . . 48
6.1.1. Creación de certificados . . . . . . . . . . . . . . . . . 48
6.1.2. Firewall . . . . . . . . . . . . . . . . . . . . . . . . . . 49
6.2. Tutoriales futuros . . . . . . . . . . . . . . . . . . . . . . . . 51
6.3. Ideas Finales . . . . . . . . . . . . . . . . . . . . . . . . . . . 52

2
ÍNDICE GENERAL 3

6.4. Agradecimientos . . . . . . . . . . . . . . . . . . . . . . . . . 52
Índice de figuras

4.1. Inicio de ejecución del servidor ssl . . . . . . . . . . . . . . . 35


4.2. Conexión con socket ssl . . . . . . . . . . . . . . . . . . . . . . 36
4.3. Conexión con sockets sin ssl . . . . . . . . . . . . . . . . . . . 38

5.1. Inicio de ejecución de multihilo ssl (Comandos) . . . . . . . . 46


5.2. Inicio de ejecución de multihilo ssl (Corriendo) . . . . . . . . . 47

6.1. Iptables desbloqueando puerto . . . . . . . . . . . . . . . . . . 50


6.2. Iptables bloqueando puerto . . . . . . . . . . . . . . . . . . . 51

4
Parte 1

Prefacio

1.1. A quien lo lea:


Este tutorial pretende ser informativo y guı́a de aquellas personas que
se adentran al mundo de la programación en red utilizando el lenguaje C.
Si bien es cierto que los lenguajes orientados a objetos son más fáciles de
dominar y aprender, en un ambiente de servidores y cargas de trabajo muy
elevadas el lenguaje C sigue siendo de los más usados e importantes ya que
considerá y da una visión más detallada de los procesos que se ejecutan en
los servidores y de la red al tener que definirlos desde el protocolo a usar
Cabe mencionar que toda la documentación de las funciones, las estruc-
turas y lı́brerias se encuentran en muchas páginas de internet, además de
encontrarse en el man de cualquier sistema linux o unix, con los posibles
parámetros o definiciones de estructuras, por lo que sólo daré unos links in-
teresantes al final del manual, y no me pondré a explicar cada estructura
ni funciones del sistema. Con esto no pretendo decir que no explicaré nada,
si no que estructuras como sockaddin y demás están documentadas mucho
mejor en internet.
En lo personal he leido muchos tutoriales, donde dicen que tienen los
arhivos fuente listos para descarga y que lo ejecutes con un shell y la verdad
muchos no han funcionado, por lo que trataré de realmente plasmar código
que funcione. Todo esto para llegar a un fin, el cual será realizar un servidor
que pueda atender a varios clientes simultáneamente, además de la creación
del cliente que se conectará con el mismo. La funcionalidad del servidor que
programaré es solo el envı́o de mensajes, por lo que la implementación de un

5
PARTE 1. PREFACIO 6

uso especı́fico será responsabilidad del programador.


Tampoco pretendo explicar teorı́as de los hilos en C usando pthread, ni
la teorı́a del cifrado que se usa con un opensource llamado openssl, ya que
considero en la red hay mucha información al respecto y sale de los objetivos
de este tutorial.
Bueno esperando el tutorial sea claro, conciso y les sirva en este mundo
del Socket Programming empecemos.
Parte 2

Instalación básica

2.1. Requerimientos del sistema


Primero que nada todo este manual está orientado a sistemas linux - unix,
por lo que cabe mencionar que no funcionará en windows, aunque en esencia
es el mismo procedimiento, las librerı́as ocupadas son diferentes (winsock),
por lo que se tendrán que aplicar cambios para el funciomaniento de los
programas en entornos de Windows.
La distribución que se use no tendrá por qué importar, ya que en realidad
lo que se necesitará es tener instalado

1. GCC

2. GDB

3. OpenSSL

La instalación de Gcc es recomendable que se haga desde que se instala


el sistema linux. O con instaladores con repositorios tipo (yum,apt,etc ...).
Con respecto al GDB es el depurador de GNU, su uso es a base de una
ejecución del programa y una serie de comandos de ayudan al trace del propio
programa en ejecución, se recomienda su uso para la depuración, aunque para
este tutorial no será indispensable

7
PARTE 2. INSTALACIÓN BÁSICA 8

2.2. Openssl
Con respecto al openssl su instalación solo consta de los siguientes pasos.

1. Crear el directorio
# mkdir /usr/src/

2. Bajar de http://www.openssl.org/source/ la version estable de openssl,


que viene en tar.gz
# wget http://www.openssl.org/source/openssl-0.9.8k.tar.gz

3. Descomprimir
# tar zxvf http://www.openssl.org/source/openssl-0.9.8k.tar.gz

4. Compilamos

# cd openssl-0.9.8k
# ./config
# make
# make test
# make install

Quedando instalado en /usr/local/ssl

Comprobamos la lista de ciphers /usr/local/ssl/bin/openssl ciphers -v


’ALL:!ADH:@STRENGTH’
Si hay un problema en la instalación, que por lo general no ocurre en la
página de openssl hay documentación al respecto de la instalación, aunque
realmente es un proceso sencillo, y dependiendo de la capacidad de la máquina
será el tiempo que dure este proceso de instalación.
Mediante el uso de esta instrucción
openssl speed Podemos saber el tiempo de procesamiento del openssl en
nuestra máquina para los diferentes ciphers existentes.
Parte 3

Creación de certificados

3.1. Explicaciones
Ahora bien una vez instalado, OpenSSL nos servirá para crear los certifi-
cados que se necesitan, además de darnos la API, para trabajar con Sockets
de manera segura.
Para la creación de los certificados, en este caso necesitaremos tres, uno
que actúe como autoridad certificadora, uno que sea el del servidor y por
último el que se usará en el cliente.
client.pem Certificado del cliente. client.key Llave privada del cliente. cac-
ert.pem Certificado de Autoridad Certificadora. server.key Llave privada del
servidor. server.pem Certificado del servidor.
Para generarlos usaremos openssl, generando primero el de la autoridad
certificadora, para que firme digitalmente el del servidor y del cliente, estó de
la siguiente manera.
En este caso se crea primero la autoridad certificadora que seremos nos-
tros mismos, después de eso tendremos que hacer las peticiones para crear
dos nuevos certificados y por último firmarlos por medio de la autoridad
certificadora creada anteriormente.

3.2. CA
root@koitoersv:/home/koitoer# pwd
/home/koitoer
root@koitoersv:/home/koitoer# mkdir certs

9
PARTE 3. CREACIÓN DE CERTIFICADOS 10

root@koitoersv:/home/koitoer# cd certs/
root@koitoersv:/home/koitoer/certs# cp /usr/lib/ssl/misc/CA.sh
root@koitoersv:/home/koitoer/certs# cp /usr/lib/ssl/misc/CA.sh .
root@koitoersv:/home/koitoer/certs# ./CA.sh -newca
CA certificate filename (or enter to create)

Making CA certificate ...


Generating a 1024 bit RSA private key
................................................++++++
........++++++
writing new private key to ’./demoCA/private/./cakey.pem’
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
Verify failure
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter ’.’, the field will be left blank.
-----
Country Name (2 letter code) [MX]:
State or Province Name (full name) [Distrito Federal]:
Locality Name (eg, city) []:KoitoerCity
Organization Name (eg, company) []:Koitoercompany
Organizational Unit Name (eg, section) []:KoitoerOrg
Common Name (eg, YOUR name) []:KoitoerCorp.
Email Address []:koitoer.company@gmail.com

Please enter the following ’extra’ attributes


to be sent with your certificate request
A challenge password []:koitoerCA
An optional company name []:koitoerCAcorp
Using configuration from /usr/lib/ssl/openssl.cnf
Enter pass phrase for ./demoCA/private/./cakey.pem:
PARTE 3. CREACIÓN DE CERTIFICADOS 11

Check that the request matches the signature


Signature ok
Certificate Details:
Serial Number: 0 (0x0)
Validity
Not Before: Apr 23 14:17:14 2009 GMT
Not After : Apr 22 14:17:14 2012 GMT
Subject:
countryName = MX
stateOrProvinceName = Distrito Federal
organizationName = Koitoercompany
organizationalUnitName = KoitoerOrg
commonName = KoitoerCorp.
emailAddress = koitoer.company@gmail.com
X509v3 extensions:
X509v3 Subject Key Identifier:
EC:2A:55:C2:8C:1E:A9:CD:0E:DA:AA:8F:84:34:74:54:54
:A6:46:2A
X509v3 Authority Key Identifier:
keyid:EC:2A:55:C2:8C:1E:A9:CD:0E:DA:AA:8F:84:34:74
:54:54:A6:46:2A
DirName:/C=MX/ST=Distrito Federal/
O=Koitoercompany/OU=KoitoerOrg/
CN=KoitoerCorp./emailAddress=koitoer.company@gmail.com
serial:00

X509v3 Basic Constraints:


CA:TRUE
Certificate is to be certified until Apr 22 14:17:14 2012 GMT (1095 days)

Write out database with 1 new entries


Data Base Updated

Con esto habremos creado el certificado autorizador que se guardará en


demoCA con el nombre de cacert.pem, que actuará como nuestra autoridad
certificadora, además de crear un archivo cakey.pem que es la llave priva-
PARTE 3. CREACIÓN DE CERTIFICADOS 12

da de la autoridad certificadora creada, la cual deberemos de guardar muy


celosamente, ya que si alguien tiene acceso a esta llave y al certificado puede
firmar certificados, como si hubiesen sido emitidos por nosotros.
Ahora toca el turno de generar el certificado del servidor.

3.3. Certificado del servidor

root@koitoersv:/home/koitoer/certs# pwd
/home/koitoer/certs
root@koitoersv:/home/koitoer/certs# mkdir server_cert
root@koitoersv:/home/koitoer/certs# ls
CA.sh demoCA server_cert
root@koitoersv:/home/koitoer/certs# ./CA.sh -newreq
Generating a 1024 bit RSA private key
................++++++
...........................................................++++++
writing new private key to ’newkey.pem’
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
-----
You are about to be asked to enter information that
will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished
Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter ’.’, the field will be left blank.
-----
Country Name (2 letter code) [MX]:
State or Province Name (full name) [Distrito Federal]:
Locality Name (eg, city) []:Koitoerserverland
Organization Name (eg, company) [Telecomunicaciones de Mexico]:koitoerserver
Organizational Unit Name (eg, section) []:koitoerservers
Common Name (eg, YOUR name) []:koitoer.server
Email Address []:koitoer.server@gmail.com
PARTE 3. CREACIÓN DE CERTIFICADOS 13

Please enter the following ’extra’ attributes


to be sent with your certificate request
A challenge password []:koitoer.server
An optional company name []:koitoersslserver
Request is in newreq.pem, private key is in newkey.pem
root@koitoersv:/home/koitoer/certs# ls
CA.sh demoCA newkey.pem newreq.pem server_cert
root@koitoersv:/home/koitoer/certs# ./CA.sh -sign
Using configuration from /usr/lib/ssl/openssl.cnf
Enter pass phrase for ./demoCA/private/cakey.pem:
Check that the request matches the signature
Signature ok
Certificate Details:
Serial Number: 1 (0x1)
Validity
Not Before: Apr 23 14:27:08 2009 GMT
Not After : Apr 23 14:27:08 2011 GMT
Subject:
countryName = MX
stateOrProvinceName = Distrito Federal
localityName = Koitoerserverland
organizationName = koitoerserver
organizationalUnitName = koitoerservers
commonName = koitoer.server
emailAddress = koitoer.server@gmail.com
X509v3 extensions:
X509v3 Basic Constraints:
CA:FALSE
Netscape Comment:
OpenSSL Generated Certificate
X509v3 Subject Key Identifier:
61:4A:1E:46:8A:EA:19:39:AE:C2:5D:05:3F:2A:68
:EA:E6:69:AD:80
X509v3 Authority Key Identifier:
keyid:EC:2A:55:C2:8C:1E:A9:CD:0E:DA:AA:8F:84
:34:74:54:54:A6:46:2A
PARTE 3. CREACIÓN DE CERTIFICADOS 14

Certificate is to be certified until Apr 23 14:27:08 2011 GMT (730 days)


Sign the certificate? [y/n]:y

1 out of 1 certificate requests certified, commit? [y/n]y


Write out database with 1 new entries
Data Base Updated
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 1 (0x1)
Signature Algorithm: sha1WithRSAEncryption
Issuer: C=MX, ST=Distrito Federal, O=Koitoercompany,
OU=KoitoerOrg,
CN=KoitoerCorp./emailAddress=koitoer.company@gmail.com
Validity
Not Before: Apr 23 14:27:08 2009 GMT
Not After : Apr 23 14:27:08 2011 GMT
Subject: C=MX, ST=Distrito Federal, L=Koitoerserverland,
O=koitoerserver, OU=koitoerservers,
CN=koitoer.server/emailAddress=koitoer.server@gmail.com
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public Key: (1024 bit)
Modulus (1024 bit):
00:bb:f3:50:d8:39:32:5b:75:37:72:47:ac:e0:62:
a0:98:60:50:bc:02:3e:ec:5f:69:d5:8a:d0:54:b4:
f8:dc:f4:46:6b:4b:5b:ac:55:e7:85:f3:cf:9b:5b:
45:66:5a:7c:15:ae:e5:f6:15:11:ab:9b:51:58:1a:
f9:8f:b6:b6:14:3f:05:49:1c:a6:1d:14:67:d0:e9:
5e:e3:da:bb:26:b5:3c:0f:d6:fd:62:67:21:4c:1a:
58:cb:6f:d7:5c:a5:06:e4:cf:c4:4b:02:a2:59:d5:
d5:bf:c7:f2:1e:7a:09:22:ad:80:1b:ee:90:0a:c8:
9c:38:89:18:7f:09:65:36:c7
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Basic Constraints:
CA:FALSE
PARTE 3. CREACIÓN DE CERTIFICADOS 15

Netscape Comment:
OpenSSL Generated Certificate
X509v3 Subject Key Identifier:
61:4A:1E:46:8A:EA:19:39:AE:C2:5D:05:3F:2A:68:
E6:69:AD:80
X509v3 Authority Key Identifier:
keyid:EC:2A:55:C2:8C:1E:A9:CD:0E:DA:AA:8F:84:
34:74:54:54:A6:46:2A

Signature Algorithm: sha1WithRSAEncryption


17:b0:78:8f:0b:21:58:c8:72:f3:de:fc:fe:11:34:e9:34:4c:
6d:48:fd:03:74:1b:e7:3c:c2:50:41:0f:14:32:9a:be:ad:e3:
9a:28:92:fe:10:63:33:5e:c2:7a:d7:b1:0e:87:ba:af:06:4e:
c3:65:cd:91:5f:c8:36:27:66:b5:6b:ee:f8:5e:86:42:71:d5:
1c:27:57:ff:3f:42:f4:96:28:54:d6:1f:b7:6f:2c:15:f9:ce:
ce:04:53:ec:f5:98:b1:6d:2d:cc:ab:42:44:e2:93:47:c0:b9:
90:13:15:11:50:ef:23:05:fd:fb:a2:f5:8c:3d:cb:a1:fd:c9:
27:c3
-----BEGIN CERTIFICATE-----
MIIDQTCCAqqgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBlzELMAkGA1UEBhMCTVgx
GTAXBgNVBAgTEERpc3RyaXRvIEZlZGVyYWwxFzAVBgNVBAoTDktvaXRvZXJjb21w
YW55MRMwEQYDVQQLEwpLb2l0b2VyT3JnMRUwEwYDVQQDEwxLb2l0b2VyQ29ycC4x
KDAmBgkqhkiG9w0BCQEWGWtvaXRvZXIuY29tcGFueUBnbWFpbC5jb20wHhcNMDkw
NDIzMTQyNzA4WhcNMTEwNDIzMTQyNzA4WjCBtzELMAkGA1UEBhMCTVgxGTAXBgNV
BAgTEERpc3RyaXRvIEZlZGVyYWwxGjAYBgNVBAcTEUtvaXRvZXJzZXJ2ZXJsYW5k
MRYwFAYDVQQKEw1rb2l0b2Vyc2VydmVyMRcwFQYDVQQLEw5rb2l0b2Vyc2VydmVy
czEXMBUGA1UEAxMOa29pdG9lci5zZXJ2ZXIxJzAlBgkqhkiG9w0BCQEWGGtvaXRv
ZXIuc2VydmVyQGdtYWlsLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA
u/NQ2DkyW3U3ckes4GKgmGBQvAI+7F9p1YrQVLT43PRGa0tbrFXnhfPPm1tFZlp8
Fa7l9hURq5tRWBr5j7a2FD8FSRymHRRn0Ole49q7JrU8D9b9YmchTBpYy2/XXKUG
5M/ESwKiWdXVv8fyHnoJIq2AG+6QCsicOIkYfwllNscCAwEAAaN7MHkwCQYDVR0T
BAIwADAsBglghkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5lcmF0ZWQgQ2VydGlmaWNh
dGUwHQYDVR0OBBYEFGFKHkaK6hk5rsJdBT8qaOrmaa2AMB8GA1UdIwQYMBaAFOwq
VcKMHqnNDtqqj4Q0dFRUpkYqMA0GCSqGSIb3DQEBBQUAA4GBABeweI8LIVjIcvPe
/P4RNOk0TG1I/QN0G+c8wlBBDxQymr6t45ookv4QYzNewnrXsQ6Huq8GTsNlzZFf
yDYnZrVr7vhehkJx1RwnV/8/QvSWKFTWH7dvLBX5zs4EU+z1mLFtLcyrQkTik0fA
uZATFRFQ7yMF/fui9Yw9y6H9ySfD
-----END CERTIFICATE-----
PARTE 3. CREACIÓN DE CERTIFICADOS 16

Signed certificate is in newcert.pem


root@koitoersv:/home/koitoer/certs# ls
CA.sh demoCA newcert.pem newkey.pem newreq.pem server_cert
root@koitoersv:/home/koitoer/certs# cp newcert.pem server_cert/server.pem
root@koitoersv:/home/koitoer/certs# cp newkey.pem server_cert/server.key
root@koitoersv:/home/koitoer/certs# cp new* server_cert/
root@koitoersv:/home/koitoer/certs# ls
CA.sh demoCA newcert.pem newkey.pem newreq.pem server_cert
root@koitoersv:/home/koitoer/certs# rm new*
root@koitoersv:/home/koitoer/certs# ls
CA.sh demoCA server_cert
root@koitoersv:/home/koitoer/certs# cd server_cert/
root@koitoersv:/home/koitoer/certs/server_cert# ls
newcert.pem newkey.pem newreq.pem server.key server.pem
root@koitoersv:/home/koitoer/certs/server_cert#

Aclaro que cuando pregunta


writing new private key to ’newkey.pem’ Enter PEM pass phrase:
La clave que pongamos será la de este certificado que se está creando.
y cuando marca
Enter pass phrase for ./demoCA/private/cakey.pem:
Tenemos que introducir la passphrase de la autoridad certificadora, es decir,
el passphrase que le pusimos a cakey.pem, con lo que aseguramos que nosotros
somos los dueños del CA y firmamos el nuevo certificado generado.
Estas passphrase son de suma importancia y deben ser frase muy fuertes,
ya que en buena forma estos certificados depende de la fortaleza del passphrase.
Ya que con un ataque de fuerza bruta por diccionario se pueden clonar cer-
tificados previamente emitidos.
Ahora el certificado que creamos, es decir el del servidor, siempre que lo
usemos requerirá la intervención humana para colocar la passphrase (esto se
verá mas a detalle), por lo que ahora al crear el certificado del cliente haremos
unos cambios para evitar tener que introducir la passphrase cada que se haga
uso del certificado.
Puede ser de gran ayuda dejar el certificado del servidor con la interven-
ción humana al colocar la passphrase, ya que es el proveera el servicio y puede
que no queramos que cualquier persona pueda levantar o quitar el servicio.
PARTE 3. CREACIÓN DE CERTIFICADOS 17

3.4. Certificado del cliente


Para el caso del cliente se realizarán las siguientes configuraciones.
Crearemos ahora el certificado del cliente, con las siguientes modifica-
ciones en el archivo
/usr/lib/ssl/misc/CA.sh
Lı́nea 56
56 REQ − new − x509 − keyoutnewkey.pem − outnewcert.pemDAYS
Cambiamos por :
56 REQ−new −nodes−x509−keyoutnewkey.pem−outnewcert.pemDAYS

También lı́nea 62
62 REQ − new − keyoutnewkey.pem − outnewreq.pemDAYS
Cambiamos por :
62 REQ − new − nodes − keyoutnewkey.pem − outnewreq.pemDAYS

Guardamos los cambios y generamos el certificado del cliente.

root@koitoersv:/home/koitoer/certs# vim /usr/lib/ssl/misc/CA.sh


root@koitoersv:/home/koitoer/certs# ls
CA.sh demoCA server_cert
root@koitoersv:/home/koitoer/certs# /usr/lib/ssl/misc/CA.sh -newreq
Generating a 1024 bit RSA private key
...++++++
....++++++
writing new private key to ’newkey.pem’
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter ’.’, the field will be left blank.
-----
Country Name (2 letter code) [MX]:
State or Province Name (full name) [Distrito Federal]:
Locality Name (eg, city) []:KoitoerClient
PARTE 3. CREACIÓN DE CERTIFICADOS 18

Organization Name (eg, company) []:KoitoerCLiente


Organizational Unit Name (eg, section) []:koitoer.sectioncliente
Common Name (eg, YOUR name) []:koitoer.cliente
Email Address []:koitoer.cliente@gmail.com

Please enter the following ’extra’ attributes


to be sent with your certificate request
A challenge password []:koitoer.ssl_cliente
An optional company name []:koitoer_ssl_cliente
Request is in newreq.pem, private key is in newkey.pem
root@koitoersv:/home/koitoer/certs# /usr/lib/ssl/misc/CA.sh -sign
Using configuration from /usr/lib/ssl/openssl.cnf
Enter pass phrase for ./demoCA/private/cakey.pem:
Check that the request matches the signature
Signature ok
Certificate Details:
Serial Number: 2 (0x2)
Validity
Not Before: Apr 23 14:38:50 2009 GMT
Not After : Apr 23 14:38:50 2011 GMT
Subject:
countryName = MX
stateOrProvinceName = Distrito Federal
localityName = KoitoerClient
organizationName = KoitoerCLiente
organizationalUnitName = koitoer.sectioncliente
commonName = koitoer.cliente
emailAddress = koitoer.cliente@gmail.com
X509v3 extensions:
X509v3 Basic Constraints:
CA:FALSE
Netscape Comment:
OpenSSL Generated Certificate
X509v3 Subject Key Identifier:
89:4C:83:EA:4B:54:C2:BB:16:80:A7:96:15:D7:42:11:
82:2E:1C:D6
X509v3 Authority Key Identifier:
keyid:EC:2A:55:C2:8C:1E:A9:CD:0E:DA:AA:8F:84:34:
PARTE 3. CREACIÓN DE CERTIFICADOS 19

74:54:54:A6:46:2A

Certificate is to be certified until Apr 23 14:38:50 2011 GMT (730 days)


Sign the certificate? [y/n]:y

1 out of 1 certificate requests certified, commit? [y/n]y


Write out database with 1 new entries
Data Base Updated
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 2 (0x2)
Signature Algorithm: sha1WithRSAEncryption
Issuer: C=MX, ST=Distrito Federal, O=Koitoercompany,
OU=KoitoerOrg, CN=KoitoerCorp./emailAddress=koitoer.company@gmail.com
Validity
Not Before: Apr 23 14:38:50 2009 GMT
Not After : Apr 23 14:38:50 2011 GMT
Subject: C=MX, ST=Distrito Federal, L=KoitoerClient,
O=KoitoerCLiente, OU=koitoer.sectioncliente,
CN=koitoer.cliente/emailAddress=koitoer.cliente@gmail.com
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public Key: (1024 bit)
Modulus (1024 bit):
00:c3:4b:60:8e:ca:88:53:c0:29:04:6f:b3:14:56:
44:3f:db:aa:48:09:c6:b5:69:0a:e8:8b:6a:17:72:
c2:f8:1a:57:f0:28:26:32:d6:03:55:f5:f4:53:62:
72:c3:27:62:bf:88:a9:26:b8:83:48:30:9a:d1:79:
1f:32:70:ca:74:ce:d6:5f:58:fd:65:70:f2:19:0a:
f2:f4:fd:48:4e:1d:8c:36:9f:6f:0b:3f:37:ab:2d:
68:dc:c9:12:7c:ce:4b:c4:1c:f8:29:44:2e:f2:20:
46:d4:fd:0a:4e:8e:af:87:23:cf:ef:7a:f8:7a:92:
61:27:6e:0b:33:5a:88:e7:2d
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Basic Constraints:
PARTE 3. CREACIÓN DE CERTIFICADOS 20

CA:FALSE
Netscape Comment:
OpenSSL Generated Certificate
X509v3 Subject Key Identifier:
89:4C:83:EA:4B:54:C2:BB:16:80:A7:96:15:D7:42
:11:82:2E:1C:D6
X509v3 Authority Key Identifier:
keyid:EC:2A:55:C2:8C:1E:A9:CD:0E:DA:AA:8F:84
:34:74:54:54:A6:46:2A

Signature Algorithm: sha1WithRSAEncryption


50:fa:50:27:ef:23:cd:bf:83:b7:21:92:23:d6:f6:ee:c2:67:
95:fe:c7:ee:7b:56:de:ad:ed:13:f0:27:91:f1:32:41:ba:62:
66:77:1f:ec:05:1b:89:6e:00:f7:c8:e4:fa:25:2a:91:4a:e3:
e7:1f:41:f2:2b:e9:00:ea:a6:43:bf:32:aa:45:53:b7:53:17:
6a:bd:9d:97:45:5e:a3:5a:2f:85:04:ee:41:4b:c4:8d:ab:ec:
1c:84:b7:a1:1a:3d:4f:e3:19:14:ed:27:08:7d:9d:6f:07:c6:
1b:e1:7b:d5:bd:90:93:15:48:fb:82:ad:3d:59:9b:bf:67:c8:
24:f9
-----BEGIN CERTIFICATE-----
MIIDSDCCArGgAwIBAgIBAjANBgkqhkiG9w0BAQUFADCBlzELMAkGA1UEBhMCTVgx
GTAXBgNVBAgTEERpc3RyaXRvIEZlZGVyYWwxFzAVBgNVBAoTDktvaXRvZXJjb21w
YW55MRMwEQYDVQQLEwpLb2l0b2VyT3JnMRUwEwYDVQQDEwxLb2l0b2VyQ29ycC4x
KDAmBgkqhkiG9w0BCQEWGWtvaXRvZXIuY29tcGFueUBnbWFpbC5jb20wHhcNMDkw
NDIzMTQzODUwWhcNMTEwNDIzMTQzODUwWjCBvjELMAkGA1UEBhMCTVgxGTAXBgNV
BAgTEERpc3RyaXRvIEZlZGVyYWwxFjAUBgNVBAcTDUtvaXRvZXJDbGllbnQxFzAV
BgNVBAoTDktvaXRvZXJDTGllbnRlMR8wHQYDVQQLExZrb2l0b2VyLnNlY3Rpb25j
bGllbnRlMRgwFgYDVQQDEw9rb2l0b2VyLmNsaWVudGUxKDAmBgkqhkiG9w0BCQEW
GWtvaXRvZXIuY2xpZW50ZUBnbWFpbC5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0A
MIGJAoGBAMNLYI7KiFPAKQRvsxRWRD/bqkgJxrVpCuiLahdywvgaV/AoJjLWA1X1
9FNicsMnYr+IqSa4g0gwmtF5HzJwynTO1l9Y/WVw8hkK8vT9SE4djDafbws/N6st
aNzJEnzOS8Qc+ClELvIgRtT9Ck6Or4cjz+96+HqSYSduCzNaiOctAgMBAAGjezB5
MAkGA1UdEwQCMAAwLAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENl
cnRpZmljYXRlMB0GA1UdDgQWBBSJTIPqS1TCuxaAp5YV10IRgi4c1jAfBgNVHSME
GDAWgBTsKlXCjB6pzQ7aqo+ENHRUVKZGKjANBgkqhkiG9w0BAQUFAAOBgQBQ+lAn
7yPNv4O3IZIj1vbuwmeV/sfue1bere0T8CeR8TJBumJmdx/sBRuJbgD3yOT6JSqR
SuPnH0HyK+kA6qZDvzKqRVO3UxdqvZ2XRV6jWi+FBO5BS8SNq+wchLehGj1P4xkU
7ScIfZ1vB8Yb4XvVvZCTFUj7gq09WZu/Z8gk+Q==
PARTE 3. CREACIÓN DE CERTIFICADOS 21

-----END CERTIFICATE-----
Signed certificate is in newcert.pem
root@koitoersv:/home/koitoer/certs# mkdir
CA.sh demoCA/ newcert.pem newkey.pem newreq.pem server_cert/
root@koitoersv:/home/koitoer/certs# mkdir cliente_cert
root@koitoersv:/home/koitoer/certs# cp newkey.pem cliente.key
root@koitoersv:/home/koitoer/certs# cp newcert.pem cliente.pem
root@koitoersv:/home/koitoer/certs# cp new* cliente
cliente_cert/ cliente.key cliente.pem
root@koitoersv:/home/koitoer/certs# cp new* cliente_cert/
root@koitoersv:/home/koitoer/certs# ls
CA.sh cliente.key demoCA newkey.pem server_cert
cliente_cert cliente.pem newcert.pem newreq.pem
root@koitoersv:/home/koitoer/certs# cp cliente.* cliente
cliente_cert/ cliente.key cliente.pem
root@koitoersv:/home/koitoer/certs# cp cliente.* cliente_cert/
root@koitoersv:/home/koitoer/certs# ls
CA.sh cliente.key demoCA newkey.pem server_cert
cliente_cert cliente.pem newcert.pem newreq.pem
root@koitoersv:/home/koitoer/certs# rm cliente.*
root@koitoersv:/home/koitoer/certs# ls
CA.sh cliente_cert demoCA newcert.pem newkey.pem newreq.pem server_cert
root@koitoersv:/home/koitoer/certs# rm new*
root@koitoersv:/home/koitoer/certs# ls
CA.sh cliente_cert demoCA server_cert
root@koitoersv:/home/koitoer/certs# cd cliente_cert/
root@koitoersv:/home/koitoer/certs/cliente_cert# ls
cliente.key cliente.pem newcert.pem newkey.pem newreq.pem
root@koitoersv:/home/koitoer/certs/cliente_cert#

Con lo que habremos generado el certificado del cliente. Debemos tomar


en cuenta que el nuevo certificado se nombre primero newreq.pem y newkey.pem,
donde newkey es la llave del certificado, y newreq es el certificado pero sin
firmar, después de firmar el certificado se genera un newcert.pem que es el
certificado firmado, por lo que como en el caso del cliente y del servidor,
renombró los archivos a server.key y server.pem, en el caso del cliente a
PARTE 3. CREACIÓN DE CERTIFICADOS 22

cliente.key y cliente.pem, y nunca renombró newreq.pem, ya que en realidad


no tienen ningún valor si no han sido firmados por la CA.

Ahora si tenemos el certificado cacert.pem en


/home/koitoer/certs/demoCA/cacert.pem
La llave y certificado del server en:
/home/koitoer/certs/server_cert/server.key --Llave servidor
/home/koitoer/certs/server_cert/server.pem --Certificado servidor
La llave y certificado del cliente en:
/home/koitoer/certs/cliente_cert/cliente.key --Llave cliente
/home/koitoer/certs/cliente_cert/cliente.pem --Certificado cliente

Alguna cosas que nos pueden ayudar, es la modificación del openssl.cnf,


para generar los nombres default para cada campo del certificado, además
de poner el tiempo de caducidad de los certificados y otras opciones intere-
santes. Asi que recomiendo lean un poco mas acerca de la modificación del
openssl.cnf.
Bueno una vez que se tienen los certificados, pues es hora de programar.
XD
Parte 4

Códigos fuentes del servidor y


cliente

Ahora después de unos minutos de programación tenemos listo el código


fuente del servidor SSL, veremos que la implementación consiste en crear
ciertos contextos que nos permiten darle a un socket normal previamente
hecho, la funcionalidad de seguridad que deseamos a través de la configu-
ración del mismo con contexto y mediante la elección del cipher de cifrado,
que hará uso de certificados de autenticación.

4.1. SERVER
#include <s t d i o . h>
#include <e r r n o . h>
#include <u n i s t d . h>
#include <m a l l o c . h>
#include <s t r i n g . h>
#include <s y s / s o c k e t . h>
/∗ Lı́ b r e r i a para l o s s o c k e t ∗/
#include <r e s o l v . h>
#include <netdb . h>
#include <o p e n s s l / s s l . h>
/∗ Lı́ b r e r i a de o p e n s s l para l a f u n c i o n a l i d a d y c o n t e x t o s ∗/
#include <o p e n s s l / e r r . h>
/∗ Lı́ b r e r i a de o p e n s s l para e r r o r e s ∗/
#define FAIL −1

23
PARTE 4. CÓDIGOS FUENTES 24

/∗−−− C r e a r S o c k e t −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−∗/
/∗ Crea un s o c k e t normal para i m p l e m e n t a r l e SSL −−−−−∗/

int C r e a r S o c k e t ( int p o r t ) {
int sd ;
struct s o c k a d d r i n addr ;
sd = s o c k e t ( PF INET , SOCK STREAM, 0 ) ;
b z e r o (&addr , s i z e o f ( addr ) ) ;
addr . s i n f a m i l y = AF INET ;
addr . s i n p o r t = h t o n s ( p o r t ) ;
addr . s i n a d d r . s a d d r = INADDR ANY;
i f ( bind ( sd , ( struct s o c k a d d r ∗ )&addr , s i z e o f ( addr ) ) != 0 )
{
perror ( ” Error a l l i g a r e l socket ” ) ;
abort () ;
}
i f ( l i s t e n ( sd , 1 0 ) != 0 ) {
p e r r o r ( ” E r r o r en e l l i s t e n ” ) ;
abort () ;
}
return sd ;
}

/∗−−− I n i c i a r C T X S e r v i d o r −−−−−−−−−−−−−−−−−−−−−−−−−−−∗/
/∗ I n i c i a l i z a e l s e r v i d o r y c r e a e l c o n t e x t o s e r v e r −∗/

SSL CTX∗ I n i c i a r C T X S e r v i d o r ( void ) {


SSL METHOD ∗method ;
SSL CTX ∗ c t x ;
OpenSSL add all algorithms () ;
/∗ Carga l o s c i p h e r s de c i f r a d o ∗/
SSL load error strings () ;
/∗ Carga l o s mensajes de e r r o r de SSL ∗/
method = S S L v 2 s e r v e r m e t h o d ( ) ;
/∗ Crea una i n s t a n c i a d e l método s e r v i d o r en SSLv2 ∗/
c t x = SSL CTX new ( method ) ;
/∗ Crea e l c o n t e x t o para e l método de s e r v i d o r ∗/
i f ( c t x == NULL ) {
ERR print errors fp ( stderr ) ;
abort () ;
}
/∗ Se e l i g e l a s u i t e que s e d e s e a usar , en e s t e c a s o ”DES−
CBC3−SHA” ∗/
i f ( S S L C T X s e t c i p h e r l i s t ( ctx , ”DES−CBC3−MD5” ) == 1 ) {
p r i n t f ( ” S i s e pudo e s t a b l e c e r \n” ) ;
PARTE 4. CÓDIGOS FUENTES 25

} else {
p r i n t f ( ”No s e pudo e s t a b l e c e r \n” ) ;
}
return c t x ;
}

/∗−−− C a r g a r C e r t i f i c a d o s −−−−−−−−−−−−−−−−−−−−−−−−−−−∗/
/∗ Carga l o s c e r t i f i c a d o s d e l s e r v i d o r y CA −−−−−−−∗/

void C a r g a r C e r t i f i c a d o s (SSL CTX∗ ctx , char∗ C e r t F i l e , char∗


K ey F il e ) {
/∗ Asigna e l c e r t i f i c a d o a l c o n t e x t o ∗/
i f ( S S L C T X u s e c e r t i f i c a t e f i l e ( ctx , C e r t F i l e ,
SSL FILETYPE PEM) <= 0 ) {
p r i n t f ( ”No s e pudo u s a r e l a r c h i v o de c e r t i f i c a d o \n” ) ;
ERR print errors fp ( stderr ) ;
abort () ;
} else {
p r i n t f ( ” C e r t i f i c a d o c a r g a d o \n” ) ;
}
/∗ Asigna l a l l a v e p r i m a r i a a l c o n t e x t o ∗/
i f ( S S L C T X u s e P r i v a t e K e y f i l e ( ctx , KeyFile ,
SSL FILETYPE PEM) <= 0 ) {
p r i n t f ( ”No s e pudo u s a r e l a r c h i v o de l l a v e \n” ) ;
ERR print errors fp ( stderr ) ;
abort () ;
} else {
p r i n t f ( ” L l a v e c a r g a d a . \n” ) ;
}
/∗ Se hace una v e r i f i c a c i ó n de l a l l a v e ∗/
i f ( ! SSL CTX check private key ( ctx ) ) {
p r i n t f ( ”No s e pudo u s a r e l a r c h i v o de c e r t i f i c a d o \n” ) ;
f p r i n t f ( s t d e r r , ”La l l a v e p r i m a r i a no c o r r e s p o n d e \n” ) ;
abort () ;
} else {
p r i n t f ( ” C e r t i f i c a d o y L l a v e v a l i d o s . \n” ) ;
}
}

/∗−−− M o s t r a r C e r t i f i c a d o s −−−−−−−−−−−−−−−−−−−−−−−−−−∗/
/∗ Imprime l o s c e r t i f i c a d o s −−−−−−−−−−−−−−−−−−−−−−−−−∗/

void M o s t r a r C e r t i f i c a d o s ( SSL∗ s s l )
{ X509 ∗ c e r t ;
char ∗ l i n e ;
PARTE 4. CÓDIGOS FUENTES 26

cert = SSL get peer certificate ( ssl ) ;


/∗ Mapeo de l o s c e r t i f i c a d o s a X509 ∗/
i f ( c e r t != NULL ) {
p r i n t f ( ” C e r t i f i c a d o s d e l s e r v i d o r : \ n” ) ;
l i n e = X509 NAME oneline ( X 5 0 9 g e t s u b j e c t n a m e ( c e r t ) , 0 ,
0) ;
/∗ Obtencion d e l s u b j e c t ∗/
p r i n t f ( ” S u b j e c t : %s \n” , l i n e ) ;
free ( line ) ;
l i n e = X509 NAME oneline ( X 5 0 9 g e t i s s u e r n a m e ( c e r t ) , 0 ,
0) ;
/∗ Obtencion d e l emisor ∗/
p r i n t f ( ” Emisor : %s \n” , l i n e ) ;
free ( line ) ;
X509 free ( cert ) ;
/∗ Se l i b e r a n l o s d a t o s d e l c e r t i f i c a d o ∗/
} else {
p r i n t f ( ”No hay c e r t i f i c a d o s . \ n” ) ;
}
}

/∗−−− S e r v i d o r −−−−−−−−−− −−−−−−−−−−−−−−−−−−−−−−−−−−∗/


/∗ R e a l i z a r e l p r o c e d i m i e n t o s e r v i c i o −−−−−−−−−−−−−−−∗/

void S e r v i d o r ( SSL∗ s s l ) {
/∗ P rop o rci on a l a f u n c i o n a l i d a d d e l s e r v i d o r ∗/
char buf [ 1 0 2 4 ] ;
char r e p l y [ 1 0 2 4 ] ;
int sd , b y t e s ;
const char∗ HTMLecho=” Esto s o l o e s un mensaje ISO01 |EOF” ;

p r i n t f ( ” I n i c i a S e r v i d o r \n” ) ;
i f ( S S L a c c e p t ( s s l ) == FAIL ) {
/∗ Se hace e l a c c e p t − SSL ∗/
p r i n t f ( ”Hubo un e r r o r en e l S S L a c c e p t \n” ) ;
ERR print errors fp ( stderr ) ;
} else {
p r i n t f ( ” S S L a c c e p t f u e e x i t o s o \n” ) ;
MostrarCertificados ( s s l ) ;
/∗ O b t i e n e e imprime l o s c e r t i f i c a d o s ∗/
b y t e s = SSL read ( s s l , buf , s i z e o f ( buf ) ) ;
/∗ Espera una p e t i c i o n d e l c l i e n t e ∗/
i f ( bytes > 0 ) {
buf [ b y t e s ] = 0 ;
PARTE 4. CÓDIGOS FUENTES 27

p r i n t f ( ” Mensaje c l i e n t e : \” %s \”\n” , buf ) ;


s p r i n t f ( r e p l y , HTMLecho , buf ) ;
/∗ Imprime p e t i c i ó n d e l c l i e n t e ∗/
sleep (15) ;
SSL write ( s s l , reply , s t r l e n ( reply ) ) ;
/∗ Envı́a una r e s p u e s t a a l c l i e n t e ∗/
}
else
ERR print errors fp ( stderr ) ;
}
sd = S S L g e t f d ( s s l ) ;
/∗ O b t i e n e l a c o n e x i ó n d e l s o c k e t ∗/
SSL free ( s s l ) ;
/∗ L i b e r a e l e s t a d o SSL d e l c l i e n t e ∗/
c l o s e ( sd ) ;
/∗ C i e r r a l a c o n e x i ó n a l c l i e n t e ∗/
}

/∗−−− Main −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−∗/


/∗ Se e n c a r g a de c r e a r e l s e r v i d o r −−−−−−−−−−−−−−−−−−∗/

int main ( int count , char ∗ s t r i n g s [ ] ) {


SSL CTX ∗ c t x ;
/∗ Se c r e a un c o n t e x t o para i m p l e m e n t a r s e ∗/
int s e r v e r ;
/∗ Se va a u s a r para e l s o c k e t d e l s e r v i d o r ∗/
char ∗ portnum ;
/∗ Se usa como e l número de p u e r t o ∗/
SSL library init () ;
/∗ I n i c i a l i z a c i ó n de l a s lı́ b r e r i a s SSL !IMPORTANTE” ∗/
/∗ Esto s e r e q u i e r e en s i s t e m a s o p e r a t i v o s d i f e r e n t e s ∗/
/∗ de s o l a r i s ∗/

i f ( count != 2 ) {
p r i n t f ( ”Uso : %s <portnum>\n” , s t r i n g s [ 0 ] ) ;
exit (0) ;
}
portnum = s t r i n g s [ 1 ] ;
ctx = IniciarCTXServidor () ;
/∗ Se i n i c i a l i z a e l SSL para e l c o n t e x t o S e r v e r ∗/
C a r g a r C e r t i f i c a d o s ( ctx , ” s e r v . pem” , ” s e r v . key ” ) ;
/∗ Carga l o s c e r t i f i c a d o s d e l s e r v i d o r ∗/
s e r v e r = C r e a r S o c k e t ( a t o i ( portnum ) ) ;
/∗ Crea e l s o c k e t normal para e l s e r v i d o r ∗/
p r i n t f ( ” Esperando por c o n e x i o n e s [ %d ] \n” , s e r v e r ) ;
PARTE 4. CÓDIGOS FUENTES 28

p r i n t f ( ” I n i c i a a a c e p t a r c o n e x i o n e s \n” ) ;
while ( 1 ) {
struct s o c k a d d r i n addr ;
int l e n = s i z e o f ( addr ) ;
SSL ∗ s s l ;
int c l i e n t = a c c e p t ( s e r v e r , ( struct s o c k a d d r ∗ )&addr , &
len ) ;
/∗ Está en e s t a d o de a c e p t a r c o n e x i o n e s ∗/
p r i n t f ( ” Connection : %d: %d\n” ,
i n e t n t o a ( addr . s i n a d d r ) , n t o h s ( addr . s i n p o r t ) ) ;
/∗ Muestra l o s d a t o s d e l u s u a r i o que s e c o n e c t a ∗/

S S L C T X s e t v e r i f y ( ctx , SSL VERIFY PEER , NULL) ;


/∗ V e r i f i c a e l c e r t i f i c a d o d e l s e r v i d o r ∗/
i f ( ! S S L C T X l o a d v e r i f y l o c a t i o n s ( ctx , ” c a c e r t . pem” ,
NULL) ) {
f p r i n t f ( s t d e r r , ” C e r t i f i c a d o I n v a l i d o \n” ) ;
ERR print errors fp ( stderr ) ;
exit (1) ;
}
/∗ Se hace una v e r i f i c a c i ó n d e l c e r t i f i c a d o mediante l a CA ∗/

s s l = SSL new ( c t x ) ;
/∗ Se o b t i e n e e l nuevo e s t a d o SSL con su c o n t e x t o ∗/
SSL set fd ( ssl , c l i e n t ) ;
/∗ Se a s i g n a e l s o c k e t a l e s t a d o SSL para c l i e n t e ∗/
Servidor ( s s l ) ;
/∗ P ro po rci on a l a f u n c i o n a l i d a d d e l s e r v i d o r ( s e r v i c i o ) ∗/
}
close ( server ) ;
/∗ C i e r r a e l s o c k e t d e l s e r v i d o r ∗/
SSL CTX free ( c t x ) ;
/∗ L i b e r a l a c o n e x i ó n ∗/
}

Espero haya quedado claro la programación del servidor, ya que a partir


de ésta tendremos que generar el cliente tomando en cuenta el uso de los
mismos certificados, además del mismo cipher y por su puesto el mismo
handshake en el cual se comunican, cabe mencionar que en un socket normal
el envı́o de la información lo hacemos en base a write, read, send o recv
dependiendo del si son caracteres o bytes los enviados, pero en este caso
usamos dos funciones propias de la librerı́a openssl.h que son SSL write y
SSL read, con lo que aseguramos el cifrado de la información que se transmite
por la red.
PARTE 4. CÓDIGOS FUENTES 29

Ahora es hora de programar el cliente.


4.2. CLIENTE
#include <s t d i o . h>
#include <e r r n o . h>
#include <u n i s t d . h>
#include <m a l l o c . h>
#include <s t r i n g . h>
#include <s y s / s o c k e t . h>
/∗ L i b r e rı́ a para l o s s o c k e t ∗/
#include <r e s o l v . h>
#include <netdb . h>
#include <o p e n s s l / s s l . h>
/∗ L i b r e rı́ a de o p e n s s l para l a f u n c i o n a l i d a d y c o n t e x t o s ∗/
#include <o p e n s s l / e r r . h>
/∗ L i b r e rı́ a de o p e n s s l para e r r o r e s ∗/
#define FAIL −1

/∗−−− C r e a r S o c k e t −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−∗/
/∗ Crea un s o c k e t normal para i m p l e m e n t a r l e SSL −−−−−∗/

int C r e a r S o c k e t ( int p o r t ) {
int sd ;
struct s o c k a d d r i n addr ;
sd = s o c k e t ( PF INET , SOCK STREAM, 0 ) ;
b z e r o (&addr , s i z e o f ( addr ) ) ;
addr . s i n f a m i l y = AF INET ;
addr . s i n p o r t = h t o n s ( p o r t ) ;
addr . s i n a d d r . s a d d r = INADDR ANY;
i f ( bind ( sd , ( struct s o c k a d d r ∗ )&addr , s i z e o f ( addr ) ) != 0 )
{
perror ( ” Error a l l i g a r e l socket ” ) ;
abort () ;
}
i f ( l i s t e n ( sd , 1 0 ) != 0 ) {
p e r r o r ( ” E r r o r en e l l i s t e n ” ) ;
abort () ;
}
return sd ;
}

/∗−−− I n i c i a r C T X S e r v i d o r −−−−−−−−−−−−−−−−−−−−−−−−−−−∗/
/∗ I n i c i a l i z a e l s e r v i d o r y c r e a e l c o n t e x t o s e r v e r −∗/
PARTE 4. CÓDIGOS FUENTES 30

SSL CTX∗ I n i c i a r C T X S e r v i d o r ( void ) {


SSL METHOD ∗method ;
SSL CTX ∗ c t x ;
OpenSSL add all algorithms () ;
/∗ Carga l o s c i p h e r s de c i f r a d o ∗/
SSL load error strings () ;
/∗ Carga l o s mensajes de e r r o r de SSL ∗/
method = S S L v 2 s e r v e r m e t h o d ( ) ;
/∗ Crea una i n s t a n c i a d e l método s e r v i d o r en SSLv2 ∗/
c t x = SSL CTX new ( method ) ;
/∗ Crea e l c o n t e x t o para e l método de s e r v i d o r ∗/
i f ( c t x == NULL ) {
ERR print errors fp ( stderr ) ;
abort () ;
}
/∗ Se e l i g e l a s u i t e que s e d e s e a usar , en e s t e c a s o ”DES−
CBC3−SHA” ∗/
i f ( S S L C T X s e t c i p h e r l i s t ( ctx , ”DES−CBC3−MD5” ) == 1 ) {
p r i n t f ( ” S i s e pudo e s t a b l e c e r \n” ) ;
} else {
p r i n t f ( ”No s e pudo e s t a b l e c e r \n” ) ;
}
return c t x ;
}

/∗−−− C a r g a r C e r t i f i c a d o s −−−−−−−−−−−−−−−−−−−−−−−−−−−∗/
/∗ Carga l o s c e r t i f i c a d o s d e l s e r v i d o r y CA −−−−−−−∗/

void C a r g a r C e r t i f i c a d o s (SSL CTX∗ ctx , char∗ C e r t F i l e , char∗


K ey F il e ) {
/∗ Asigna e l c e r t i f i c a d o a l c o n t e x t o ∗/
i f ( S S L C T X u s e c e r t i f i c a t e f i l e ( ctx , C e r t F i l e ,
SSL FILETYPE PEM) <= 0 ) {
p r i n t f ( ”No s e pudo u s a r e l a r c h i v o de c e r t i f i c a d o \n” ) ;
ERR print errors fp ( stderr ) ;
abort () ;
} else {
p r i n t f ( ” C e r t i f i c a d o c a r g a d o \n” ) ;
}
/∗ Asigna l a l l a v e p r i m a r i a a l c o n t e x t o ∗/
i f ( S S L C T X u s e P r i v a t e K e y f i l e ( ctx , KeyFile ,
SSL FILETYPE PEM) <= 0 ) {
p r i n t f ( ”No s e pudo u s a r e l a r c h i v o de l l a v e \n” ) ;
ERR print errors fp ( stderr ) ;
PARTE 4. CÓDIGOS FUENTES 31

abort () ;
} else {
p r i n t f ( ” L l a v e c a r g a d a . \n” ) ;
}
/∗ Se hace una v e r i f i c a c i ó n de l a l l a v e ∗/
i f ( ! SSL CTX check private key ( ctx ) ) {
p r i n t f ( ”No s e pudo u s a r e l a r c h i v o de c e r t i f i c a d o \n” ) ;
f p r i n t f ( s t d e r r , ”La l l a v e p r i m a r i a no c o r r e s p o n d e \n” ) ;
abort () ;
} else {
p r i n t f ( ” C e r t i f i c a d o y L l a v e v a l i d o s . \n” ) ;
}
}

/∗−−− M o s t r a r C e r t i f i c a d o s −−−−−−−−−−−−−−−−−−−−−−−−−−∗/
/∗ Imprime l o s c e r t i f i c a d o s −−−−−−−−−−−−−−−−−−−−−−−−−∗/

void M o s t r a r C e r t i f i c a d o s ( SSL∗ s s l )
{ X509 ∗ c e r t ;
char ∗ l i n e ;

cert = SSL get peer certificate ( ssl ) ;


/∗ Mapeo de l o s c e r t i f i c a d o s a X509 ∗/
i f ( c e r t != NULL ) {
p r i n t f ( ” C e r t i f i c a d o s d e l s e r v i d o r : \ n” ) ;
l i n e = X509 NAME oneline ( X 5 0 9 g e t s u b j e c t n a m e ( c e r t ) , 0 ,
0) ;
/∗ Obtención d e l s u b j e c t ∗/
p r i n t f ( ” S u b j e c t : %s \n” , l i n e ) ;
free ( line ) ;
l i n e = X509 NAME oneline ( X 5 0 9 g e t i s s u e r n a m e ( c e r t ) , 0 ,
0) ;
/∗ Obtención d e l emisor ∗/
p r i n t f ( ” Emisor : %s \n” , l i n e ) ;
free ( line ) ;
X509 free ( cert ) ;
/∗ Se l i b e r a n l o s d a t o s d e l c e r t i f i c a d o ∗/
} else {
p r i n t f ( ”No hay c e r t i f i c a d o s . \ n” ) ;
}
}

/∗−−− S e r v i d o r −−−−−−−−−− −−−−−−−−−−−−−−−−−−−−−−−−−−∗/


/∗ R e a l i z a r e l p r o c e d i m i e n t o s e r v i c i o −−−−−−−−−−−−−−−∗/
PARTE 4. CÓDIGOS FUENTES 32

void S e r v i d o r ( SSL∗ s s l ) {
/∗ P rop o rci on a l a f u n c i o n a l i d a d d e l s e r v i d o r ∗/
char buf [ 1 0 2 4 ] ;
char r e p l y [ 1 0 2 4 ] ;
int sd , b y t e s ;
const char∗ HTMLecho=” Esto s o l o e s un mensaje ISO01 |EOF” ;

p r i n t f ( ” I n i c i a S e r v i d o r \n” ) ;
i f ( S S L a c c e p t ( s s l ) == FAIL ) {
/∗ Se hace e l a c c e p t − SSL ∗/
p r i n t f ( ”Hubo un e r r o r en e l S S L a c c e p t \n” ) ;
ERR print errors fp ( stderr ) ;
} else {
p r i n t f ( ” S S L a c c e p t f u e e x i t o s o \n” ) ;
MostrarCertificados ( s s l ) ;
/∗ O b t i e n e e imprime l o s c e r t i f i c a d o s ∗/
b y t e s = SSL read ( s s l , buf , s i z e o f ( buf ) ) ;
/∗ Espera una p e t i c i ó n d e l c l i e n t e ∗/
i f ( bytes > 0 ) {
buf [ b y t e s ] = 0 ;
p r i n t f ( ” Mensaje c l i e n t e : \” %s \”\n” , buf ) ;
s p r i n t f ( r e p l y , HTMLecho , buf ) ;
/∗ Imprime p e t i c i ó n d e l c l i e n t e ∗/
sleep (15) ;
SSL write ( s s l , reply , s t r l e n ( reply ) ) ;
/∗ Envı́a una r e s p u e s t a a l c l i e n t e ∗/
}
else
ERR print errors fp ( stderr ) ;
}
sd = S S L g e t f d ( s s l ) ;
/∗ O b t i e n e l a c o n e x i ó n d e l s o c k e t ∗/
SSL free ( s s l ) ;
/∗ L i b e r a e l e s t a d o SSL d e l c l i e n t e ∗/
c l o s e ( sd ) ;
/∗ C i e r r a l a c o n e x i ó n a l c l i e n t e ∗/
}

/∗−−− Main −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−∗/


/∗ Se e n c a r g a de c r e a r e l s e r v i d o r −−−−−−−−−−−−−−−−−−∗/

int main ( int count , char ∗ s t r i n g s [ ] ) {


SSL CTX ∗ c t x ;
/∗ Se crean un c o n t e x t o para i m p l e m e n t a r s e ∗/
int s e r v e r ;
PARTE 4. CÓDIGOS FUENTES 33

/∗ Se va a u s a r para e l s o c k e t d e l s e r v i d o r ∗/
char ∗ portnum ;
/∗ Se usa como e l número de p u e r t o ∗/
SSL library init () ;
/∗ I n i c i a l i z a c i ó n de l a s l i b r e r i a s SSL !IMPORTANTE” ∗/

i f ( count != 2 ) {
p r i n t f ( ”Uso : %s <portnum>\n” , s t r i n g s [ 0 ] ) ;
exit (0) ;
}
portnum = s t r i n g s [ 1 ] ;
ctx = IniciarCTXServidor () ;
/∗ Se i n i c i a l i z a e l SSL para e l c o n t e x t o S e r v e r ∗/
C a r g a r C e r t i f i c a d o s ( ctx , ” s e r v . pem” , ” s e r v . key ” ) ;
/∗ Carga l o s c e r t i f i c a d o s d e l s e r v i d o r ∗/
s e r v e r = C r e a r S o c k e t ( a t o i ( portnum ) ) ;
/∗ Crea e l s o c k e t normal para e l s e r v i d o r ∗/
p r i n t f ( ” Esperando por c o n e x i o n e s [ %d ] \n” , s e r v e r ) ;
p r i n t f ( ” I n i c i a a a c e p t a r c o n e x i o n e s \n” ) ;
while ( 1 ) {
struct s o c k a d d r i n addr ;
int l e n = s i z e o f ( addr ) ;
SSL ∗ s s l ;
int c l i e n t = a c c e p t ( s e r v e r , ( struct s o c k a d d r ∗ )&addr , &
len ) ;
/∗ Esta en e s t a d o de a c e p t a r c o n e x i o n e s ∗/
p r i n t f ( ” Connection : %d: %d\n” ,
i n e t n t o a ( addr . s i n a d d r ) , n t o h s ( addr . s i n p o r t ) ) ;
/∗ Muestra l o s d a t o s d e l u s u a r i o que s e c o n e c t a ∗/

S S L C T X s e t v e r i f y ( ctx , SSL VERIFY PEER , NULL) ;


/∗ V e r i f i c a e l c e r t i f i c a d o d e l s e r v i d o r ∗/
i f ( ! S S L C T X l o a d v e r i f y l o c a t i o n s ( ctx , ” c a c e r t . pem” ,
NULL) ) {
f p r i n t f ( s t d e r r , ” C e r t i f i c a d o I n v a l i d o \n” ) ;
ERR print errors fp ( stderr ) ;
exit (1) ;
}
/∗ Se hace una v e r i f i c a c i ó n d e l c e r t i f i c a d o mediante l a CA ∗/

s s l = SSL new ( c t x ) ;
/∗ Se o b t i e n e e l nuevo e s t a d o SSL con su c o n t e x t o ∗/
SSL set fd ( ssl , c l i e n t ) ;
/∗ Se a s i g n a e l s o c k e t a l e s t a d o SSL para c l i e n t e ∗/
Servidor ( s s l ) ;
PARTE 4. CÓDIGOS FUENTES 34

/∗ P ro po rci on a l a f u n c i o n a l i d a d d e l s e r v i d o r ( s e r v i c i o ) ∗/
}
close ( server ) ;
/∗ C i e r r a e l s o c k e t d e l s e r v i d o r ∗/
SSL CTX free ( c t x ) ;
/∗ L i b e r a l a c o n e x i ó n ∗/
}

Como veran el código es bastante similar, solo que en esta ocasión usamos
el contexto de cliente.
4.3. Compilación
Ahora vamos a correr el servidor y el cliente, obviamente el servidor va
primero ya que si no se hace en ese orden, no tendrı́amos hacia donde conec-
tarnos para recibir el servicio, pero antes de ejecutarlos, compilemos:

root@koitoersv:/media/KINGSTON/Tutorial/Final/ServidorSSL#
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/ssl/lib
root@koitoersv:/media/KINGSTON/Tutorial/Final/ServidorSSL# pwd
/media/KINGSTON/Tutorial/Final/ServidorSSL
root@koitoersv:/media/KINGSTON/Tutorial/Final/ServidorSSL# make server
gcc -g -c server.c
gcc -o server server.o -L/usr/local/ssl/include/
-L/usr/local/ssl/lib -lssl -lcrypto -lnsl -ldl
root@koitoersv:/media/KINGSTON/Tutorial/Final/ServidorSSL# ls
cacert.pem Makefile server server.c server.key server.o server.pem
root@koitoersv:/media/KINGSTON/Tutorial/Final/ServidorSSL#

Con esto habremos compilado el servidor Ahora compilamos el cliente en


otra terminal

root@koitoersv:/media/KINGSTON/Tutorial/Final/ServidorSSL#
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/ssl/lib
koitoer@koitoersv:/media/KINGSTON/Tutorial/Final/ClienteSSL$ pwd
/media/KINGSTON/Tutorial/Final/ClienteSSL
koitoer@koitoersv:/media/KINGSTON/Tutorial/Final/ClienteSSL$ make cliente
gcc -g -c cliente.c
gcc -o cliente cliente.o -L/usr/local/ssl/include/
PARTE 4. CÓDIGOS FUENTES 35

Figura 4.1: Inicio de ejecución del servidor ssl

-L/usr/local/ssl/lib -lssl -lcrypto -lnsl -ldl


koitoer@koitoersv:/media/KINGSTON/Tutorial/Final/ClienteSSL$

Es importante resaltar el uso de la instrucción del export de la libreria, ya


que si no se hace ası́ mandara errores al no encontrar la lı́breria libcrypto.a
ni libssl.a .
Ahora lo que haremos es correr el servidor en una ventana y el cliente en
la otra.
Podemos ver que el servidor pide el passphrase de su certificado, en tanto
el cliente no, debido a las modificaciones que realizamos en CA.sh, donde
podemos crear un certificado de servidor que no requiera el passphrase.
Además de que se observa, como se muestra la información de los certifi-
cados, asi como su emisor en este caso la autoridad certificadora que somos
PARTE 4. CÓDIGOS FUENTES 36

Figura 4.2: Conexión con socket ssl

nostros mismos. Cuando lo corremos parece que es tardado pero recordemos


que en el código existe un sleep de 5 segundos .
Gracias a wireshark que es un analizador de protocolos de red (sniffer)
podemos ver que nuestra información no va en texto claro y que la comuni-
cación es lograda correctamente.

4.4. MAKE
Para compilar más fácilmente podemos hacer uso de un Makefile, recor-
dando su sintaxis.

CC = gcc
PARTE 4. CÓDIGOS FUENTES 37

Aplicacion: server cliente

server: server.o
$(CC) -o server server.o -L/usr/local/ssl/include/
-L/usr/local/ssl/lib -lssl -lcrypto -lnsl -ldl

server.o: server.c
$(CC) -g -c server.c

cliente: cliente.o
$(CC) -o cliente cliente.o -L/usr/local/ssl/include/
-L/usr/local/ssl/lib -lssl -lcrypto -lnsl -ldl

cliente.o: cliente.c
$(CC) -g -c cliente.c

cipher:
/usr/local/ssl/bin/openssl ciphers -v ’ALL:!ADH:@STRENGTH’

clean:
rm *.o

Bien con esto tenemos un cliente SSL y un servidor SSL, que sólo se
mandan mensaje entre sı́. Si ejecutamos varios clientes a la vez, veremos que
el servidor sólo podrá responder a uno por uno, aunque los otros los tenga
en una cola tipo FIFO. Por lo que ahora programaremos un servidor que
acepte varios clientes a la vez, esto lo haremos usando el mismo certificado
del servidor, ya previamente hecho.
PARTE 4. CÓDIGOS FUENTES 38

Figura 4.3: Conexión con sockets sin ssl


Parte 5

Servidor Multihilo

5.1. SERVER
Hasta este punto hemos logrado un server que acepta conexiones pero solo
una a la vez, es cierto que tiene una cola de espera, pero no les puede dar
servicio a más de un cliente a la vez, como lo pueden corroborar si ejecutan
en dos consolas a dos clientes, ya que en el código del servidor puse un sleep
5 que ponen en espera al cliente 5 segundos, entonces en este caso nuestro
servidor sólo atiende a uno a la vez, pero vamos que es un servidor si no puede
dar servicio a más de un cliente a la vez. Para lograr lo antes mencionado
haremos uso de la implementación de pthread, que es conocido como POSIX
Thread.
Para esto no deseo modificar los codigos anteriores, ni decirles que parte se
modifica, ni que lı́neas, ya que puede resultar confuso y tal vez no funcione al
final, por lo que hacer un nuevo servidor en otro fichero, en el caso del cliente
no tendremos que hacerle ninguna modificación debido a que la funcionalidad
de multihilos la da el servidor no el cliente. Otra cosa que se tendrá que
modificar es el makefile, ya que al usar pthread deberemos de usar -lpthread
al compilar nuestros programas, ademas de incluir lı́brerias extras.
En el código del serverthread.c he quitado todos los comentarios anteriores
del SSL, y sólo deje los que explican la parte de los hilos y concurrencia.

#include <s t d i o . h>


#include <e r r n o . h>
#include <u n i s t d . h>
#include <m a l l o c . h>

39
PARTE 5. SERVIDOR MULTIHILO 40

#include <s t r i n g . h>


#include <s y s / s o c k e t . h>
#include <r e s o l v . h>
#include <netdb . h>
#include <o p e n s s l / s s l . h>
#include <o p e n s s l / e r r . h>
#include <p t h r e a d . h>
/∗ L i b r e rı́ a de POXIS t h r e a d ∗/
#define FAIL −1
#define NUM THREADS 5

/∗ E s t r u c t u r a que s e u s a r á como argumento ∗/


struct t h r e a d d a t a {
int t h r e a d i d ;
/∗ I d e n t i d i f i c a d o r de h i l o ∗/
SSL ∗ message ;
/∗ Estado s s l de l a c o n e x i ó n ∗/
};

/∗−−− C r e a r S o c k e t −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−∗/
/∗ Crea un s o c k e t normal para i m p l e m e n t a r l e SSL −−−−−∗/

int C r e a r S o c k e t ( int p o r t ) {
int sd ;
struct s o c k a d d r i n addr ;

sd = s o c k e t ( PF INET , SOCK STREAM, 0 ) ;


b z e r o (&addr , s i z e o f ( addr ) ) ;
addr . s i n f a m i l y = AF INET ;
addr . s i n p o r t = h t o n s ( p o r t ) ;
addr . s i n a d d r . s a d d r = INADDR ANY;
i f ( bind ( sd , ( struct s o c k a d d r ∗ )&addr , s i z e o f ( addr ) ) != 0 )
{
perror ( ” Error a l l i g a r e l socket ” ) ;
abort () ;
}
i f ( l i s t e n ( sd , 1 0 ) != 0 ) {
p e r r o r ( ” E r r o r en e l l i s t e n ” ) ;
abort () ;
}
return sd ;
PARTE 5. SERVIDOR MULTIHILO 41

/∗−−− I n i c i a r C T X S e r v i d o r −−−−−−−−−−−−−−−−−−−−−−−−−−−∗/
/∗ I n i c i a l i z a e l s e r v i d o r y c r e a e l c o n t e x t o s e r v e r −∗/

SSL CTX∗ I n i c i a r C T X S e r v i d o r ( void ) {


SSL METHOD ∗method ;
SSL CTX ∗ c t x ;
OpenSSL add all algorithms () ;
SSL load error strings () ;
method = S S L v 2 s e r v e r m e t h o d ( ) ;
c t x = SSL CTX new ( method ) ;
i f ( c t x == NULL ) {
ERR print errors fp ( stderr ) ;
abort () ;
}

i f ( S S L C T X s e t c i p h e r l i s t ( ctx , ”DES−CBC3−MD5” ) == 1 ) {
p r i n t f ( ” S i s e pudo e s t a b l e c e r \n” ) ;
} else {
p r i n t f ( ”No s e pudo e s t a b l e c e r \n” ) ;
}
return c t x ;
}

/∗−−− C a r g a r C e r t i f i c a d o s −−−−−−−−−−−−−−−−−−−−−−−−−−−∗/
/∗ Carga l o s c e r t i f i c a d o s d e l s e r v i d o r y CA −−−−−−−∗/

void C a r g a r C e r t i f i c a d o s (SSL CTX∗ ctx , char∗ C e r t F i l e , char∗


K ey F il e ) {

i f ( S S L C T X u s e c e r t i f i c a t e f i l e ( ctx , C e r t F i l e ,
SSL FILETYPE PEM) <= 0 ) {
p r i n t f ( ”No s e pudo u s a r e l a r c h i v o de c e r t i f i c a d o \n” ) ;
ERR print errors fp ( stderr ) ;
abort () ;
} else {
p r i n t f ( ” C e r t i f i c a d o c a r g a d o \n” ) ;
}

i f ( S S L C T X u s e P r i v a t e K e y f i l e ( ctx , KeyFile ,
SSL FILETYPE PEM) <= 0 ) {
p r i n t f ( ”No s e pudo u s a r e l a r c h i v o de l l a v e \n” ) ;
ERR print errors fp ( stderr ) ;
abort () ;
PARTE 5. SERVIDOR MULTIHILO 42

} else {
p r i n t f ( ” L l a v e c a r g a d a . \n” ) ;
}

i f ( ! SSL CTX check private key ( ctx ) ) {


p r i n t f ( ”No s e pudo u s a r e l a r c h i v o de c e r t i f i c a d o \n” ) ;
f p r i n t f ( s t d e r r , ”La l l a v e p r i m a r i a no c o r r e s p o n d e a l
c e r t i f i c a d o p u b l i c o \n” ) ;
abort () ;
} e l s e { struct t h r e a d d a t a {
int t h r e a d i d ;
int sum ;
char ∗ s s l s o c k e t ;
};

p r i n t f ( ” C e r t i f i c a d o y L l a v e v a l i d o s . \n” ) ;
}
}

/∗−−− M o s t r a r C e r t i f i c a d o s −−−−−−−−−−−−−−−−−−−−−−−−−−∗/
/∗ Imprime l o s c e r t i f i c a d o s −−−−−−−−−−−−−−−−−−−−−−−−−∗/

void M o s t r a r C e r t i f i c a d o s ( SSL∗ s s l )
{ X509 ∗ c e r t ;
char ∗ l i n e ;

cert = SSL get peer certificate ( ssl ) ;


i f ( c e r t != NULL ) {
p r i n t f ( ” C e r t i f i c a d o s d e l s e r v i d o r : \ n” ) ;
l i n e = X509 NAME oneline ( X 5 0 9 g e t s u b j e c t n a m e ( c e r t ) , 0 ,
0) ;
p r i n t f ( ” S u b j e c t : %s \n” , l i n e ) ;
free ( line ) ;
l i n e = X509 NAME oneline ( X 5 0 9 g e t i s s u e r n a m e ( c e r t ) , 0 ,
0) ;
p r i n t f ( ” Emisor : %s \n” , l i n e ) ;
free ( line ) ;
X509 free ( cert ) ;
} else {
p r i n t f ( ”No hay c e r t i f i c a d o s . \ n” ) ;
}
}
PARTE 5. SERVIDOR MULTIHILO 43

/∗−−− S e r v i d o r −−−−−−−−−− −−−−−−−−−−−−−−−−−−−−−−−−−−∗/


/∗ R e a l i z a r e l p r o c e d i m i e n t o s e r v i c i o −−−−−−−−−−−−−−−∗/

void ∗ S e r v i d o r ( void ∗ t h r e a d a r g ) {
char buf [ 1 0 2 4 ] ;
char r e p l y [ 1 0 2 4 ] ;
int sd , b y t e s ;
const char∗ HTMLecho=” Esto s o l o e s e l mensaje de mi s e r v i d o r
SSL m u l t i h i l o ” ;

/∗ E s t r u c t u r a donde s e guardan l o s par áme tr os de l o s t h r e a d s


∗/
struct t h r e a d d a t a ∗ my data ;
int t a s k i d ;

/∗ P a rs e r de l o s d a t o s de l a e s t r u c t u r a a v a r i a b l e s ∗/
my data = ( struct t h r e a d d a t a ∗ ) t h r e a d a r g ;
t a s k i d = my data−>t h r e a d i d ;
SSL ∗ s s l = my data−>s s l s o c k e t ;

p r i n t f ( ” I n i c i a S e r v i d o r \n” ) ;
i f ( S S L a c c e p t ( s s l ) == FAIL ) {
p r i n t f ( ”Hubo un e r r o r en e l S S L a c c e p t \n” ) ;
ERR print errors fp ( stderr ) ;
} else {
p r i n t f ( ” S S L a c c e p t f u e e x i t o s o \n” ) ;
MostrarCertificados ( s s l ) ;
b y t e s = SSL read ( s s l , buf , s i z e o f ( buf ) ) ;
i f ( bytes > 0 ) {
buf [ b y t e s ] = 0 ;
p r i n t f ( ” Mensaje c l i e n t e : \” %s \”\n” , buf ) ;
s p r i n t f ( r e p l y , HTMLecho , buf ) ;
sleep (5) ;
SSL write ( s s l , reply , s t r l e n ( reply ) ) ;
}
else
ERR print errors fp ( stderr ) ;
}
sd = S S L g e t f d ( s s l ) ;
SSL free ( s s l ) ;
c l o s e ( sd ) ;
}
PARTE 5. SERVIDOR MULTIHILO 44

/∗−−− Main −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−∗/


/∗ Se e n c a r g a de c r e a r e l s e r v i d o r −−−−−−−−−−−−−−−−−−∗/

int main ( int count , char ∗ s t r i n g s [ ] ) {


p t h r e a d t t h r e a d s [NUM THREADS ] ; /∗ A r r e g l o de h i l o s ∗/
struct t h r e a d d a t a t h r e a d d a t a a r r a y [NUM THREADS ] ;
int t =0;
int r c ;
SSL CTX ∗ c t x ;
int s e r v e r ;
char ∗ portnum ;
SSL library init () ;

i f ( count != 2 ) {
p r i n t f ( ”Uso : %s <portnum>\n” , s t r i n g s [ 0 ] ) ;
exit (0) ;
}
portnum = s t r i n g s [ 1 ] ;
ctx = IniciarCTXServidor () ;
C a r g a r C e r t i f i c a d o s ( ctx , ” s e r v . pem” , ” s e r v . key ” ) ;
s e r v e r = C r e a r S o c k e t ( a t o i ( portnum ) ) ;
p r i n t f ( ” Esperando por c o n e x i o n e s [ %d ] \n” , s e r v e r ) ;
p r i n t f ( ” I n i c i a a a c e p t a r c o n e x i o n e s \n” ) ;
while ( 1 ) {
struct s o c k a d d r i n addr ;
SSL ∗ s s l ;
int l e n = s i z e o f ( addr ) ;
int c l i e n t = a c c e p t ( s e r v e r , ( struct s o c k a d d r ∗ )&addr , &
len ) ;
p r i n t f ( ” Connection : %d: %d\n” ,
i n e t n t o a ( addr . s i n a d d r ) , n t o h s ( addr . s i n p o r t ) ) ;

S S L C T X s e t v e r i f y ( ctx , SSL VERIFY PEER , NULL) ;


i f ( ! S S L C T X l o a d v e r i f y l o c a t i o n s ( ctx , ” c a c e r t . pem” ,
NULL) ) {
f p r i n t f ( s t d e r r , ” C e r t i f i c a d o I n v a l i d o \n” ) ;
ERR print errors fp ( stderr ) ;
exit (1) ;
}

s s l = SSL new ( c t x ) ;
PARTE 5. SERVIDOR MULTIHILO 45

/∗ Se c r e a c o n t e x t o ∗/
SSL set fd ( ssl , c l i e n t ) ;
t++;
/∗ Se da número de p t h r e a d ∗/
thread data array [ t ] . thread id = t ;
/∗ Se l e da e l i d d e l t h r e a d a l t h r e a d ∗/
t h r e a d d a t a a r r a y [ t ] . message = s s l ;
/∗ Se l e da e l a s i g n a e l c o n t e x t o de l a c o n e x i ó n a l t h r e a d ∗/
r c = p t h r e a d c r e a t e (& t h r e a d s [ t ] , NULL, S e r v l e t , ( void ∗ )
&t h r e a d d a t a a r r a y [ t ] ) ;
/∗ Se c r e a e l h i l o y s e l e manda l a e s t r u c t u r a l l e n a d a
p r e v i a m e n t e ∗/
}
close ( server ) ;
SSL CTX free ( c t x ) ;
}

Con lo que tenemos el servidor de hilos, y lo ejecutamos de la misma


forma que el servidor sin hilos.

root@koitoersv:/media/KINGSTON/Tutorial/Final/ServidorSSLMultihilo#
make serverthread
gcc -c -o serverthread.o serverthread.c
gcc -o serverthread serverthread.o -L/usr/local/ssl/include/
-L/usr/local/ssl/lib -lssl -lcrypto -lnsl -ldl -lpthread
root@koitoersv:/media/KINGSTON/Tutorial/Final/ServidorSSLMultihilo#

Ahora vemos en la siguiente pantalla como es la ejecución en 3 pantallas


del servidor ssl multithread.
Como vemos si ejecutamos todos al mismo tiempo, todos terminan al
mismo tiempo debido a que se tiene un servidor que puede procesar varias
peticiones aparentemente al mismo tiempo, como vemos al cliente se le pasa
la dirección IP o dirección local o nombre de dominio y el puerto en el cual
levantamos el servidor. Obviamente el mensaje del cliente y el servidor son
estáticos, podriamos hacer la modificación para que los mensajes los leyera
desde lı́nea de comandos, pero eso es ya otra historia y sale del contexto de
este tutorial.
PARTE 5. SERVIDOR MULTIHILO 46

Figura 5.1: Inicio de ejecución de multihilo ssl (Comandos)


PARTE 5. SERVIDOR MULTIHILO 47

Figura 5.2: Inicio de ejecución de multihilo ssl (Corriendo)


Parte 6

Conclusión e ideas finales

6.1. Problemas principales


Esta sección es la última que escribo con los posibles problemas que
pueden llegar a tener y algunos con los que yo me enfrente.

6.1.1. Creación de certificados


Un problema que llega a ocurrir, es que después de colocar la información
para generar al certificado de CA, cliente o de server, el programa CA.sh
mande este mensaje:

Enter pass phrase for ./demoCA/private/./cakey.pem:


unable to load CA private key
13881:error:06065064:digital envelope routines:EVP_DecryptFinal_ex
:bad decrypt:evp_enc.c:461:
13881:error:0906A065:PEM routines:PEM_do_header
:bad decrypt:pem_lib.c:425:

Con lo que hace referencia que la passhprase del CA es incorrecta.


Otro error común es que salgan las siguientes lineas:

koitoer@koitoersv:~ /usr/lib/ssl/misc/CA.sh -newca


mkdir: cannot create directory ‘./demoCA’: File exists

48
PARTE 6. CONCLUSIÓN 49

mkdir: cannot create directory ‘./demoCA/certs’: File exists


mkdir: cannot create directory ‘./demoCA/crl’: File exists
mkdir: cannot create directory ‘./demoCA/newcerts’: File exists
mkdir: cannot create directory ‘./demoCA/private’: File exists

Lo único que tendremos que hacer es un rm -rf ./demoCA para borrar


los directorios.

Por último a veces sucede que sale un error parecido a este

Enter pass phrase for ./demoCA/private/./cakey.pem:


/*Marca que algo no existe y no lo puede crear */

Lo que se tiene que revisar es el openssl.cnf para saber a dónde está apuntando
la creación de los certificados.

6.1.2. Firewall
Otro punto importante es que al usar sockets, ocupamos una o varias
direcciones IP’s y puertos, por lo que si elegimos un puerto por debajo del
1024 tendremos que usar permisos de root, además de que dependiendo de
la configuración los puertos pueden estar bloqueados por un firewall, por lo
que tendremos que configurarlo para permitir el acceso a éstos. En este caso
haremos uso de iptables.

#netstat -a
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 *:1025 *:* LISTEN
tcp 0 0 localhost:50246 localhost:1025 ESTABLISHED
tcp 0 0 localhost:1025 localhost:50246 ESTABLISHED
tcp 0 0 localhost:50245 localhost:1025 TIME_WAIT

Ahora realizamos las configuraciones para abrir el puerto por si estuviese


bloqueado.

iptables -A INPUT -p tcp -s 0/0 -d 127.0.0.1/24


--destination-port 1025 -j ACCEPT
PARTE 6. CONCLUSIÓN 50

Figura 6.1: Iptables desbloqueando puerto


PARTE 6. CONCLUSIÓN 51

Figura 6.2: Iptables bloqueando puerto

O por si lo queremos bloquear XD

iptables -A INPUT -p tcp -s 0/0 -d 127.0.0.1/24


--destination-port 1025 -j DROP
Con lo que vemos que cuando se bloquea se produce un timeout en el
cliente.

6.2. Tutoriales futuros


El siguiente tutorial que he empezado es la implementación de un socket
crudo que permita la creación de un pequeño sniffer, ademas de unos ejemplos
de uso de los sockets crudos, que como tal nos permiten la implementación
PARTE 6. CONCLUSIÓN 52

de nuevos protocolos o la posibilidad de alterar información en protocolos


existentes.

6.3. Ideas Finales


Espero que este tutorial les haya servido como guı́a para adentrarse en
el mundo del socket programming, en este caso es cierto java y c++, van
ganando adeptos y terreno dı́a con dı́a, pero vamos siempre es bueno empezar
en los origenes con C. Y aunque muchas personas creen que el lenguaje C
es obsoleto en estos dı́as, les puedo decir sin temor a equivocarme que tiene
muchas aplicaciones, y una que personalmente llegué a manejar es en la parte
de envı́o de la tramas bancarias a través de la red y al ser información sensible
se ocupa cifrado.
Espero también disculpen mis faltas de ortografı́a y mi redacción, si en
algún momento consideran que está mal. Cualquier aclaración, duda o co-
mentario me pueden contactar a este correo. ((koitoer.server@gmail.com))
Este tutorial es dedicado a cada una de las personas que conocı́ en mi
paso por la Facultad de Ingenierı́a, UNAM.

Los códigos del tutorial están en esta página:


http://www.koitoer.com/tutoriales/opensslthread.tar.gz

Este tutorial fue creado en LATEX.

6.4. Agradecimientos
Un agradecimiento muy especial Martha Velasco Jiménez, por la valiosa
corrección que hizo a este documento, GRACIAS.

S-ar putea să vă placă și