Hola de nuevo. Volví a perfeccionar mi servidor, y todo marcha bien, salvo un error que no entiendo. El programa funciona correctamente, si meto los datos correctos, almacena lo que deseo, si meto datos incorrectos, intenta comprobarlos 5 veces hasta que finalmente me da el mensaje de fallo.
Sin embargo, haga lo que haga, siempre sale en la pantalla del servidor el siguiente mensaje:
Traceback (most recent call last):
File "./servidorcompleto.py", line 250, in ?
server = SocketServer.TCPServer(('khaos',port), BaseRequestHandler)
File "/usr/lib/python2.1/SocketServer.py", line 329, in __init__
self.server_bind()
File "/usr/lib/python2.1/SocketServer.py", line 340, in server_bind
self.socket.bind(self.server_address)
socket.error: (98, 'Address already in use')
Éste es mi servidor:#!/usr/bin/python
from pyPgSQL import PgSQL
import SocketServer
import sys, os, string
from syslog import *
import md5
import whrandom
import time
def conectar_db():
global cnx
try:
#syslog(LOG_DEBUG,'\nConectando a la base de datos...')
cnx = PgSQL.connect(user ='kemdb', host ='khaos', database ='smtu')
syslog(LOG_DEBUG,'\nConectado a la base de datos, comprobando datos recibidos...')
except PgSQL.Error:
sys.exit(1)
def crear_configuracion():
conf = '%c%c%c%c%c' %(3,5,0x23,0xc2,5)
return conf
def crear_challenge():
id = whrandom.randint(0,255)
syslog(LOG_INFO,'id_cliente:'+str(id))
a = whrandom.randint(0, 255)
syslog(LOG_INFO, 'challenge_value=a:'+str(a))
challenge_value = '%c%c%c%c%c%c' % (whrandom.randint(0, 255),whrandom.randint(0, 255),whrandom.randint(0, 255),whrandom.randint(0, 255),whrandom.randint(0, 255),whrandom.randint(0, 255))
len_cha = len(challenge_value)
value_size =1
name = 'mrpfd'
len_name = len(name)
length =11+len_name
lengthb = length >> 8
challenge = '%c%c%c%c%c' % (1,id,length,lengthb,len_cha)
challenge += challenge_value+name
return challenge
#print 'identidad:', challenge[1:2]
#print 'challenge_value:', challenge[5:11]
def analizar_nombre_response(cursor, response, error_com):
global nombre
nombre = response[21:]
#print 'nombre recibido de la respuesta: ', nombre
query="select * from idip where nombre='" + nombre + "'"
syslog(LOG_DEBUG,query)
try:
cursor.execute(query)
except PgSQL.Error:
error_com =1
syslog(LOG_ERR,'error al buscar usuario en base de datos')
#sys.exit()
dat = cursor.fetchall()
#syslog(LOG_DEBUG,'\nLocalizando datos...')
n = 0
for elemento in dat:
n = n+1
if n >= 2:
duplicado = 1
error_com = 0
datos = 'duplicado'
return (duplicado, datos, error_com)
elif n == 0:
duplicado = 0
error_com = 0
datos = ''
return (duplicado, datos, error_com)
else:
duplicado = 0
error_com = 0
dato= dat[0]
datos = dato[0]
return (duplicado, datos, error_com)
def localizar_nombre_db(datos):
if datos == '':
syslog(LOG_ERR,'\nNo se encuentra en la base de datos ')
encontrado = 0
return encontrado
else:
syslog(LOG_DEBUG,'\nLocalizado en la base de datos')
encontrado = 1
return encontrado
def buscar_contrasena(datos, cursor, error_com):
query = "select password from idip where nombre='" + datos + "'"
#syslog(LOG_DEBUG,query)
try:
cursor.execute(query)
except PgSQL.Error:
#sys.exit()
syslog(LOG_ERR,'\nError al buscar la contrasea')
error_comunicacion = 1
contr = cursor.fetchall()
#print contr
contras = contr[0]
return (contras[0], error_com)
def comprobar_encriptamientos(response, password):
response_value = response[5:21]
cadena = challenge[1]+password+challenge[5:11]
#print 'cadena a la que voy a aplicar yo el md5 formada por id+passw de la db+challengevalue: ', cadena
value = md5.new(challenge[1]+password+challenge[5:11]).digest()
hexvalue = md5.new()
hexvalue.update(challenge[1]+password+challenge[5:11])
imprimir = hexvalue.hexdigest()
syslog(LOG_INFO,imprimir)
if value == response_value:
exito = 1
syslog(LOG_DEBUG,'\nSuccess')
else:
exito = 0
syslog(LOG_DEBUG,'\nFailure')
return exito
def funcion_success(response):
success = '%c' % (3)+ response[1]+ '%c%c' % (0x18, 0x00)+ 'success'
#print success
return success
def funcion_failure(response):
failure = '%c' % (4)+ response[1]+ '%c%c' % (0x1b, 0x00) + 'failure'
#print failure
return failure
def almacenar_ip_date_validez(self, cursor, nombre, password, error_com):
dirip = string.split(self.client_address[0], '.')
ip = string.atoi(dirip[0])
ip <<= 8
ip |= string.atoi(dirip[1])
ip <<= 8
ip |= string.atoi(dirip[2])
ip <<= 8
ip |= string.atoi(dirip[3])
syslog(LOG_INFO, 'ip en su valor verdadero es: %x' %ip)
strip = str(ip)
strvalidez = str(1)
query ="update idip set ip ='" + strip + "'where nombre='" + nombre + "'and password='" + password + "'"
#syslog(LOG_DEBUG, query)
error = 0
try:
cursor.execute(query)
except PgSQL.Error:
syslog(LOG_ERR,'\nError al actualizar ip')
#sys.exit()
error_com = 1
query = "update idip set date ='" + time.asctime() + "'where nombre='" + nombre + "'and password='" + password + "'"
#syslog(LOG_DEBUG, query)
error = 0
try:
cursor.execute(query)
except PgSQL.Error:
syslog(LOG_ERR, '\nError al actualizar la fecha')
#sys.exit()
error_com =1
query = "update idip set validez ='" + strvalidez + "'where nombre='" + nombre + "'and password='" + password + "'"
#syslog(LOG_DEBUG, query)
try:
cursor.execute(query)
except PgSQL.Error:
syslog(LOG_ERR, '\nError al actualizar la validez')
#sys.exit()
error_com = 1
query = "select * from idip where nombre='" + nombre + "' and password ='" + password + "'"
#syslog(LOG_DEBUG, query)
error = 0
try:
cursor.execute(query)
except PgSQL.Error:
syslog(LOG_ERR, '\nError al visualizar los datos')
#sys.exit()
error_com =1
datos = cursor.fetchall()
syslog(LOG_INFO, '\nLos datos introducidos son: '+str(datos))
return error_com
def desconectar (cursor, cnx):
cursor.close()
cnx.commit()
cnx.close()
syslog(LOG_DEBUG, '\nDesconectado de la DB')
def chap_simple(self):
global cursor
global response
global challenge
global conf
conf = crear_configuracion()
self.request.send(conf)
challenge = crear_challenge()
self.request.send(challenge)
response = self.request.recv(1024)
cursor = cnx.cursor()
error_comunicacion = 0
cuenta_errores = 1
while cuenta_errores !=0 and cuenta_errores <6:
duplicado, datos, error_comunicacion = analizar_nombre_response(cursor, response, error_comunicacion)
#print 'datos, o nombre a buscar en la db:', datos
#print 'error de comunicacin antes de ver duplicado:', error_comunicacion
if error_comunicacion == 0:
if duplicado == 1:
syslog(LOG_ERR, '\nSe ha encotrado a ms de un usuario con el mismo nombre.')
#self.request.send('\nError')
error_comunicacion = 1
cuenta_errores = cuenta_errores +1
else:
encontrado = localizar_nombre_db(datos)
if encontrado ==1:
password, error_comunicacion = buscar_contrasena(datos, cursor, error_comunicacion)
if error_comunicacion == 0:
if password == []:
syslog(LOG_ERR, '\nHa habido algn error al tomar el password')
error_comunicacion = 1
cuenta_errores = cuenta_errores +1
else:
exito = comprobar_encriptamientos(response, password)
if exito ==1:
success = funcion_success(response)
self.request.send(success)
error_comunicacion = almacenar_ip_date_validez(self, cursor, nombre, password, error_comunicacion)
syslog(LOG_DEBUG, ' actualizando ip, fecha y validez...')
if error_comunicacion == 0:
cuenta_errores = 0
else:
cuenta_errores = cuenta_errores +1
else:
cuenta_errores = cuenta_errores +1
else: cuenta_errores = cuenta_errores +1
else:
cuenta_errores = cuenta_errores + 1
#self.request.send('\nError, no localizado en la base de datos')
else: cuenta_errores = cuenta_errores +1
print "cuenta_err = ",cuenta_errores,"\n"
if cuenta_errores == 6 or cuenta_errores == 0:
failure = funcion_failure(response)
self.request.send(failure)
desconectar(cursor, cnx)
else: pass
class BaseRequestHandler(SocketServer.BaseRequestHandler):
def handle(self):
conectar_db()
chap_simple (self)
#if cuenta_errores == 0: break
while 1:
puerto = sys.argv[1]
port = int(puerto)
#print "argv[1]=",puerto,"\n"
server = SocketServer.TCPServer(('',port), BaseRequestHandler)
#server.BaseRequestHandler
#server.handle_request()
server.serve_forever()
y éste es mi cliente:#!/usr/bin/python
from pyPgSQL import PgSQL
import SocketServer
import sys, os, string
import md5
import whrandom
import socket
def comprobar_nombre_contrasena(so, cuenta_errores):
while cuenta_errores !=0 and cuenta_errores <6:
nombre = raw_input('Usuario:')
contrasena = raw_input('Contrasea:')
if len(nombre)>20 or len(contrasena)>20 or nombre == '' or contrasena == '':
cuenta_errores = cuenta_errores + 1
else:
for letra in nombre:
error_nombre = 0
if letra in string.uppercase or letra in string.digits: pass
else: error_nombre = error_nombre +1
for nuevaletra in contrasena:
error_contrasena = 0
if nuevaletra in string.uppercase or nuevaletra in string.digits: pass
else: error_contrasena = error_contrasena +1
if error_nombre == 0 and error_contrasena == 0 : cuenta_errores = 0
else: cuenta_errores = cuenta_errores +1
return (cuenta_errores, nombre, contrasena)
def crear_response(so, contrasena, nombre, challenge):
response_length=21+len(nombre)
response_lengthb=response_length>>8
if response_length > 65535:
#print '\nError'
so.close()
else:
id = challenge[1]
#print 'id recibida del challenge: ', challenge[1:2]
cadena=challenge[1]+contrasena+challenge[5:11]
#print 'cadena para hacer en md5 de la respuesta formada por: id+contrasea+challengevalue: ', cadena
value=md5.new(challenge[1]+contrasena+challenge[5:11]).digest()
hexvalue=md5.new()
hexvalue.update(challenge[1]+contrasena+challenge[5:11])
imprimir = hexvalue.hexdigest()
response = '%c%c%c%c%c' %(2, id, response_length, response_lengthb, 16) + value + nombre
return response
puerto = raw_input('Puerto:')
port = int(puerto)
so = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
so.connect (('', port))
configuration = so.recv(2048)
challenge = so.recv(2048)
cuenta_errores = 1
error = 1
cuenta_errores, nombre, contrasena = comprobar_nombre_contrasena(so, cuenta_errores)
if cuenta_errores == 0:
response = crear_response(so, contrasena, nombre, challenge)
#print 'response mandada formada por: code+id+long+valuesize+value+name: ', response
so.send(response)
resultado = so.recv(1024)
code = ord(resultado[0])
if code == 3: print 'success'
elif code == 4: print 'failure'
else: print 'fallo al recibir estado'
so.close()
Si alguien me puede ayudar me sería muy útil. Gracias!!
Saludos, Edurne