def register(self, manager, stanza): # TODO some checking would be nice :) fields = stanza.query.x.elements(uri='jabber:x:data', name='field') var_phone = None var_code = None var_pkey = None for f in fields: if f['var'] == 'phone': var_phone = f elif f['var'] == 'code': var_code = f elif f['var'] == 'publickey': var_pkey = f # validation code request if var_phone: def _bad_phone(): e = error.StanzaError('bad-request', 'modify', 'Bad phone number.') iq = xmlstream.toResponse(stanza, 'error') iq.addChild(e.getElement()) return manager.send(iq, True) n = var_phone.value.__str__().encode('utf-8') # validate phone number syntax if not n or len(n.strip()) == 0: log.debug("number empty - %s" % n) return _bad_phone() phone = phone_num = n.strip() # exclude the initial plus to verify the digits if (phone[0] == '+'): phone_num = phone[1:] # not all digits... if not phone_num.isdigit(): log.debug("number is not all-digits - %s" % phone_num) return _bad_phone() # replace double-zero with plus if phone[0:2] == '00': phone = '+' + phone[2:] # generate userid userid = util.sha1(phone) d = self.component.validationdb.register(userid) def _continue(code, stanza, phone): status = self.send_sms(phone, code) if status: # send response with sms sender number iq = xmlstream.toResponse(stanza, 'result') query = iq.addElement((xmlstream2.NS_IQ_REGISTER, 'query')) query.addElement((None, 'instructions'), content=self.ack_instructions) form = query.addElement(('jabber:x:data', 'x')) form['type'] = 'form' hidden = form.addElement((None, 'field')) hidden['type'] = 'hidden' hidden['var'] = 'FORM_TYPE' hidden.addElement((None, 'value'), content=xmlstream2.NS_IQ_REGISTER) phone = form.addElement((None, 'field')) phone['type'] = 'text-single' phone['label'] = 'SMS sender' phone['var'] = 'from' phone.addElement((None, 'value'), content=self.config['from']) else: # send error iq = xmlstream.toResponse(stanza, 'error') e = error.StanzaError('not-acceptable', 'modify', 'Unable to send SMS.') iq.addChild(e.getElement()) return manager.send(iq, True) def _error(failure, stanza): log.debug("error: %s" % (failure, )) if isinstance(failure.value, oursql.IntegrityError): # duplicate key of userid: throttling e = error.StanzaError('service-unavailable', 'wait', 'Too many attempts.') else: e = error.StanzaError('service-unavailable', 'cancel', failure.getErrorMessage()) iq = xmlstream.toResponse(stanza, 'error') iq.addChild(e.getElement()) manager.send(iq, True) d.addCallback(_continue, stanza, phone) d.addErrback(_error, stanza) # code validation + public key elif var_code and var_pkey: # check validation code from database code = var_code.value.__str__().encode('utf-8') d = self.component.validationdb.validate(code) def _continue(userid): pkey = base64.b64decode( var_pkey.value.__str__().encode('utf-8')) signed_pkey = manager.link_public_key(pkey, userid) if signed_pkey: iq = xmlstream.toResponse(stanza, 'result') query = iq.addElement((xmlstream2.NS_IQ_REGISTER, 'query')) form = query.addElement(('jabber:x:data', 'x')) form['type'] = 'form' hidden = form.addElement((None, 'field')) hidden['type'] = 'hidden' hidden['var'] = 'FORM_TYPE' hidden.addElement( (None, 'value'), content='http://kontalk.org/protocol/register#code') signed = form.addElement((None, 'field')) signed['type'] = 'text-single' signed['label'] = 'Signed public key' signed['var'] = 'publickey' signed.addElement((None, 'value'), content=base64.b64encode(signed_pkey)) return manager.send(iq, True) else: e = error.StanzaError('bad-request', 'modify', 'Invalid public key.') iq = xmlstream.toResponse(stanza, 'error') iq.addChild(e.getElement()) manager.send(iq, True) def _error(failure): log.debug("error: %s" % (failure, )) if isinstance(failure.value, RuntimeError): e = error.StanzaError('bad-request', 'modify', failure.getErrorMessage()) else: e = error.StanzaError('service-unavailable', 'cancel', failure.getErrorMessage()) iq = xmlstream.toResponse(stanza, 'error') iq.addChild(e.getElement()) manager.send(iq, True) d.addCallback(_continue) d.addErrback(_error) else: e = error.StanzaError( 'bad-request', 'modify', 'Please provider phone number and public key or verification code.' ) iq = xmlstream.toResponse(stanza, 'error') iq.addChild(e.getElement()) manager.send(iq, True)
def test_sha1(self): text = 'test data' data = util.sha1(text) self.assertEqual(data, 'f48dd853820860816c75d54d0f584dc863327a7c')
def register(self, manager, stanza): # TODO some checking would be nice :) fields = stanza.query.x.elements(uri='jabber:x:data', name='field') var_phone = None var_code = None var_pkey = None for f in fields: if f['var'] == 'phone': var_phone = f elif f['var'] == 'code': var_code = f elif f['var'] == 'publickey': var_pkey = f # validation code request if var_phone: def _bad_phone(): e = error.StanzaError('bad-request', 'modify', 'Bad phone number.') iq = xmlstream.toResponse(stanza, 'error') iq.addChild(e.getElement()) return manager.send(iq, True) n = var_phone.value.__str__().encode('utf-8') # validate phone number syntax if not n or len(n.strip()) == 0: log.debug("number empty - %s" % n) return _bad_phone() phone = phone_num = n.strip() # exclude the initial plus to verify the digits if (phone[0] == '+'): phone_num = phone[1:] # not all digits... if not phone_num.isdigit(): log.debug("number is not all-digits - %s" % phone_num) return _bad_phone() # replace double-zero with plus if phone[0:2] == '00': phone = '+' + phone[2:] # generate userid userid = util.sha1(phone) d = self.component.validationdb.register(userid) def _continue(code, stanza, phone): status = self.send_sms(phone, code) if status: # send response with sms sender number iq = xmlstream.toResponse(stanza, 'result') query = iq.addElement((xmlstream2.NS_IQ_REGISTER, 'query')) query.addElement((None, 'instructions'), content=self.ack_instructions) form = query.addElement(('jabber:x:data', 'x')) form['type'] = 'form' hidden = form.addElement((None, 'field')) hidden['type'] = 'hidden' hidden['var'] = 'FORM_TYPE' hidden.addElement((None, 'value'), content=xmlstream2.NS_IQ_REGISTER) phone = form.addElement((None, 'field')) phone['type'] = 'text-single' phone['label'] = 'SMS sender' phone['var'] = 'from' phone.addElement((None, 'value'), content=self.config['from']) else: # send error iq = xmlstream.toResponse(stanza, 'error') e = error.StanzaError('not-acceptable', 'modify', 'Unable to send SMS.') iq.addChild(e.getElement()) return manager.send(iq, True) def _error(failure, stanza): log.debug("error: %s" % (failure, )) if isinstance(failure.value, oursql.IntegrityError): # duplicate key of userid: throttling e = error.StanzaError('service-unavailable', 'wait', 'Too many attempts.') else: e = error.StanzaError('service-unavailable', 'cancel', failure.getErrorMessage()) iq = xmlstream.toResponse(stanza, 'error') iq.addChild(e.getElement()) manager.send(iq, True) d.addCallback(_continue, stanza, phone) d.addErrback(_error, stanza) # code validation + public key elif var_code and var_pkey: # check validation code from database code = var_code.value.__str__().encode('utf-8') d = self.component.validationdb.validate(code) def _continue(userid): pkey = base64.b64decode(var_pkey.value.__str__().encode('utf-8')) signed_pkey = manager.link_public_key(pkey, userid) if signed_pkey: iq = xmlstream.toResponse(stanza, 'result') query = iq.addElement((xmlstream2.NS_IQ_REGISTER, 'query')) form = query.addElement(('jabber:x:data', 'x')) form['type'] = 'form' hidden = form.addElement((None, 'field')) hidden['type'] = 'hidden' hidden['var'] = 'FORM_TYPE' hidden.addElement((None, 'value'), content='http://kontalk.org/protocol/register#code') signed = form.addElement((None, 'field')) signed['type'] = 'text-single' signed['label'] = 'Signed public key' signed['var'] = 'publickey' signed.addElement((None, 'value'), content=base64.b64encode(signed_pkey)) return manager.send(iq, True) else: e = error.StanzaError('bad-request', 'modify', 'Invalid public key.') iq = xmlstream.toResponse(stanza, 'error') iq.addChild(e.getElement()) manager.send(iq, True) def _error(failure): log.debug("error: %s" % (failure, )) if isinstance(failure.value, RuntimeError): e = error.StanzaError('bad-request', 'modify', failure.getErrorMessage()) else: e = error.StanzaError('service-unavailable', 'cancel', failure.getErrorMessage()) iq = xmlstream.toResponse(stanza, 'error') iq.addChild(e.getElement()) manager.send(iq, True) d.addCallback(_continue) d.addErrback(_error) else: e = error.StanzaError('bad-request', 'modify', 'Please provider phone number and public key or verification code.') iq = xmlstream.toResponse(stanza, 'error') iq.addChild(e.getElement()) manager.send(iq, True)