def decrypt_cipherkey(request, obj, ivr=False, ss=None, opub=None): """ Helper to get EncryptedObject's decrypted cipherkey, i.e. clearkey :param request: Django request, depends on request.user and request.session['key] :param obj: the target database object :param ivr: for IVR requests query user's IVR public key, arg change to credtype in #2281 :param ss: secure secret, if None pickup remotely i.e. request.COOKIES['ss'] :param opub: when opub owner is non-user entity, e.g. PracticeLocation :raises: KeyInvalidException if wrong creds or no private key exists """ try: keytype = RSA_PRIMARY if not ivr else RSA_IVR credtype = CRED_WEBAPP if not ivr else CRED_IVRPIN opub = opub or OwnerPublicKey.objects.get_pubkey(owner=request.user, keytype=keytype) upriv = UserPrivateKey.objects.get_privkey(request.user, opub, credtype) encobj = EncryptedObject.objects.get_object(obj, opub) # import upriv.privatekey with credentials and decrypt cipherkey clearkey = encobj.decrypt_cipherkey(upriv, get_user_key(request, ss=ss)) return clearkey except (ValueError, ObjectDoesNotExist, MultipleObjectsReturned): # normalize raise KeyInvalidException( "Wrong credentials or no user private key exists.")
def check_in(request): if (request.method == 'GET'): return err_GE002() response = { 'data': {}, 'warnings': {}, } data = response['data'] data['status'] = 'ok' if (not request.device_assn.is_active): data['status'] = 'wipe' return HttpResponse(content=json.dumps(response), mimetype='application/json') data['password_changed'] = request.device_assn.password_reset form = CheckInForm(request.POST, auto_id=False) if (not form.is_valid()): return err_GE031(form) if ('key' in request.POST): key = get_user_key(request, ss=form.cleaned_data['key']) if (not request.device_assn.verify_key(key)): return err_GE022() data['key'] = base64.b64encode(key) if ('rx_timestamp' in request.POST): data['received_messages'] = rx_message_list_data(request, form.cleaned_data['rx_timestamp'], None, None, None) if ('tx_timestamp' in request.POST): data['sent_messages'] = tx_message_list_data(request, form.cleaned_data['tx_timestamp'], None, None, None) return HttpResponse(content=json.dumps(response), mimetype='application/json')
def test_admin_API_shortcuts(self): # TODO: functions in this test to use common api from utils or shortcuts cleartext = "42: the answer to life the universe and everything." c = self.client response = c.post('/login/', { 'username': '******', 'password': '******' }) c.COOKIES = {'ss': response.cookies['ss'].value} self.assertEqual(response.status_code, 302) # just extra verification we can get user from django auth c.user = authenticate(username='******', password='******') c.user = MHLUser.objects.get(id=c.user.id) opub = OwnerPublicKey.objects.get_pubkey(owner=c.user) msg = encrypt_object(SecureTestMessage, {}, cleartext, opub) upriv = UserPrivateKey.objects.get_privkey(c.user, opub) # fetch something that shouldn't exist as encrypted data notthere = admin_decrypt_cipherkey(ADMIN_PASSWORD, c.user) self.assertTrue(notthere == None) clearkey1 = admin_decrypt_cipherkey(ADMIN_PASSWORD, msg) encobj = EncryptedObject.objects.get_object(msg, opub) # import upriv.privatekey with credentials and decrypt cipherkey clearkey2 = encobj.decrypt_cipherkey(upriv, get_user_key(c)) self.assertTrue(clearkey1 == clearkey2) clearkey = admin_decrypt_cipherkey(ADMIN_PASSWORD, msg) cleartext2 = msg.decrypt(None, clearkey) self.assertTrue(cleartext == cleartext2)
def save_attachments(request, context, msg, form, isDeleteFile=True): attachments = [] file_saved_names = request.POST.getlist('file_saved_name') file_display_names = request.POST.getlist('file_display_name') file_charsets = request.POST.getlist('file_charset') file_sizes = request.POST.getlist('file_size') file_len = len(file_saved_names) if (file_len == 0): return attachments for i in range(file_len): file_saved_name = file_saved_names[i] file_display_name = file_display_names[i] try: decrypt_str = FileHelper.readTempFile(file_saved_name, 'rb', utils.get_user_key(request)) attachment = encrypt_object( MessageAttachment, { 'message': msg, 'size': file_sizes[i], 'encrypted': True, }, opub=OwnerPublicKey.objects.get_pubkey(owner=request.user)) attachment.encrypt_url(request, ''.join(['file://', attachment.uuid])) suffix = os.path.splitext(file_display_name)[1][1:] if (suffix): attachment.suffix = suffix.lower() (attachment.content_type, attachment.encoding) = mimetypes.guess_type(file_display_name) attachment.charset = file_charsets[i] else: m = magic.Magic(mime=True) attachment.content_type = m.from_buffer(decrypt_str) if(attachment.content_type == 'application/dicom'): attachment.suffix = "dcm" file_display_name += ".dcm" m = magic.Magic(mime_encoding=True) attachment.encoding = m.from_buffer(decrypt_str) attachment.encrypt_filename(request, file_display_name) attachment.encrypt_file(request, decrypt_str) attachment.save() if "dcm" == attachment.suffix: thread.start_new_thread(sendToDicomServer, ( {"name": file_display_name, "token": attachment.uuid, "content": decrypt_str},)) attachments.append(attachment) if isDeleteFile: FileHelper.deleteTempFile(file_saved_name) except (IOError): transaction.rollback() context['ioerror'] = True context['form'] = form return render_to_response('DoctorCom/Messaging/MessageEditForm.html', context) return attachments
def recrypt_ivr_key_via_web_creds(user, request, new_pin): """ decrypt special web enc'd ivr key then recrypt pin enc'd ivr key with new pin """ opub = OwnerPublicKey.objects.get_pubkey(owner=user, keytype=RSA_IVR) uprivw = UserPrivateKey.objects.get_privkey(user, opub, CRED_WEBAPP, gfather=False) rsa = import_rsa(uprivw.privatekey, get_user_key(request)) # ivr pin may still be g'fathered uprivi = UserPrivateKey.objects.get_privkey(user, opub, CRED_IVRPIN) uprivi.privatekey = export_rsa(rsa, strengthen_key(new_pin)) uprivi.gfather = False uprivi.save()
def test_login_and_rsa_key_import_export(self): c = self.client response = c.post('/login/', { 'username': '******', 'password': '******' }) self.assertEqual(response.status_code, 302) # just extra verification we can get user from django auth user = authenticate(username='******', password='******') user = MHLUser.objects.get(id=user.id) # verify we are logged in self.assertEqual(c.session['_auth_user_id'], user.id) # These should match: self.assertEqual(get_user_key(c, response.cookies['ss'].value), strengthen_key('healme')) # query our KeyPair we created in setup opub = OwnerPublicKey.objects.get_pubkey(owner=user) upriv = UserPrivateKey.objects.get_privkey(user=user, opub=opub) devnull.write(unicode(upriv)) # simulate __unicode__ # grab pubkey from db its in RSA export format but double test import/export pub_key_from_db = export_rsa( import_rsa(upriv.opub.publickey).publickey()) # grab our binary user credential creds = get_user_key(c, response.cookies['ss'].value) # properly import rsa_key = import_rsa(upriv.privatekey, creds) # verify we can properly create RSA objs by importing pub_key_from_key = export_rsa(rsa_key.publickey()) # verify match self.assertEqual(pub_key_from_db, pub_key_from_key) # now test decryption of key with admin credentials creds = strengthen_key(ADMIN_PASSWORD) admin_rsa = import_rsa(ADMIN_RESET_ENCD_RSA, creds) adminclear = PKCS1_OAEP.new(admin_rsa).decrypt( b64decode(upriv.opub.admincipher)) rsa_key = import_rsa(upriv.opub.adminscopy, adminclear) # verify match self.assertEqual(pub_key_from_db, export_rsa(rsa_key.publickey())) # now logout, we can alternatively call c.post('/logout/') response = c.logout() self.assertTrue('_auth_user_id' not in c.session)
def upload(request): """ Handles upload message. :param request: The HTTP request :type request: django.core.handlers.wsgi.WSGIRequest :returns: django.http.HttpResponse -- the result in an HttpResonse object :raises: None """ if request.method == 'POST': ctx = dict() ctx["message"] = "" request.upload_handlers.insert(0, UploadProgressCachedHandler(request)) progress_id = None if 'X-Progress-ID' in request.GET: progress_id = request.GET['X-Progress-ID'] if progress_id: ctx["after_upload"] = request.GET["after_upload"] ctx["before_abort_upload"] = request.GET["before_abort_upload"] f = None try: f = request.FILES['file'] except (StopUpload): ctx["message"] = _( "The file is larger than %dM, please select a " "smaller file to upload.") % (settings.MAX_UPLOAD_SIZE) except (IOError): ctx["message"] = _("Upload is interrupted.") else: ctx["file_display_name"] = f.name file_name = FileHelper.generateTempFile( f.read(), utils.get_user_key(request)) ctx["file_saved_name"] = file_name ctx["file_charset"] = f.charset ctx["file_size"] = f.size return render_to_response( "DoctorCom/Messaging/MessageUploadResult.html", ctx, RequestContext(request)) else: ctx = dict() ctx["MAX_UPLOAD_SIZE"] = settings.MAX_UPLOAD_SIZE ctx["after_upload"] = request.GET["after_upload"] ctx["before_abort_upload"] = request.GET["before_abort_upload"] custom_button = False if "custom_button" in request.GET: custom_button = request.GET["custom_button"] custom_button = False if custom_button in ( 'false', 'False', '0') else bool(custom_button) ctx["custom_button"] = custom_button return render_to_response("DoctorCom/Messaging/MessageUploadForm.html", ctx, RequestContext(request))
def recrypt_ivr_key_via_web_creds(user, request, new_pin): """ decrypt special web enc'd ivr key then recrypt pin enc'd ivr key with new pin """ opub = OwnerPublicKey.objects.get_pubkey(owner=user, keytype=RSA_IVR) uprivw = UserPrivateKey.objects.get_privkey(user, opub, CRED_WEBAPP, gfather=False) rsa = import_rsa(uprivw.privatekey, get_user_key(request)) # ivr pin may still be g'fathered uprivi = UserPrivateKey.objects.get_privkey(user, opub, CRED_IVRPIN) uprivi.privatekey = export_rsa(rsa, strengthen_key(new_pin)) uprivi.gfather = False uprivi.save()
def test_login_and_rsa_key_import_export(self): c = self.client response = c.post('/login/', {'username': '******', 'password': '******'}) self.assertEqual(response.status_code, 302) # just extra verification we can get user from django auth user = authenticate(username='******', password='******') user = MHLUser.objects.get(id=user.id) # verify we are logged in self.assertEqual(c.session['_auth_user_id'], user.id) # These should match: self.assertEqual(get_user_key(c, response.cookies['ss'].value), strengthen_key('healme')) # query our KeyPair we created in setup opub = OwnerPublicKey.objects.get_pubkey(owner=user) upriv = UserPrivateKey.objects.get_privkey(user=user, opub=opub) devnull.write(unicode(upriv)) # simulate __unicode__ # grab pubkey from db its in RSA export format but double test import/export pub_key_from_db = export_rsa(import_rsa(upriv.opub.publickey).publickey()) # grab our binary user credential creds = get_user_key(c, response.cookies['ss'].value) # properly import rsa_key = import_rsa(upriv.privatekey, creds) # verify we can properly create RSA objs by importing pub_key_from_key = export_rsa(rsa_key.publickey()) # verify match self.assertEqual(pub_key_from_db, pub_key_from_key) # now test decryption of key with admin credentials creds = strengthen_key(ADMIN_PASSWORD) admin_rsa = import_rsa(ADMIN_RESET_ENCD_RSA, creds) adminclear = PKCS1_OAEP.new(admin_rsa).decrypt(b64decode(upriv.opub.admincipher)) rsa_key = import_rsa(upriv.opub.adminscopy, adminclear) # verify match self.assertEqual(pub_key_from_db, export_rsa(rsa_key.publickey())) # now logout, we can alternatively call c.post('/logout/') response = c.logout() self.assertTrue('_auth_user_id' not in c.session)
def decrypt_cipherkey(request, obj, ivr=False, ss=None, opub=None): """ Helper to get EncryptedObject's decrypted cipherkey, i.e. clearkey :param request: Django request, depends on request.user and request.session['key] :param obj: the target database object :param ivr: for IVR requests query user's IVR public key, arg change to credtype in #2281 :param ss: secure secret, if None pickup remotely i.e. request.COOKIES['ss'] :param opub: when opub owner is non-user entity, e.g. PracticeLocation :raises: KeyInvalidException if wrong creds or no private key exists """ try: keytype = RSA_PRIMARY if not ivr else RSA_IVR credtype = CRED_WEBAPP if not ivr else CRED_IVRPIN opub = opub or OwnerPublicKey.objects.get_pubkey(owner=request.user, keytype=keytype) upriv = UserPrivateKey.objects.get_privkey(request.user, opub, credtype) encobj = EncryptedObject.objects.get_object(obj, opub) # import upriv.privatekey with credentials and decrypt cipherkey clearkey = encobj.decrypt_cipherkey(upriv, get_user_key(request, ss=ss)) return clearkey except (ValueError, ObjectDoesNotExist, MultipleObjectsReturned): # normalize raise KeyInvalidException("Wrong credentials or no user private key exists.")
def test_admin_API_shortcuts(self): # TODO: functions in this test to use common api from utils or shortcuts cleartext = "42: the answer to life the universe and everything." c = self.client response = c.post('/login/', {'username': '******', 'password': '******'}) c.COOKIES = {'ss': response.cookies['ss'].value} self.assertEqual(response.status_code, 302) # just extra verification we can get user from django auth c.user = authenticate(username='******', password='******') c.user = MHLUser.objects.get(id=c.user.id) opub = OwnerPublicKey.objects.get_pubkey(owner=c.user) msg = encrypt_object(SecureTestMessage, {}, cleartext, opub) upriv = UserPrivateKey.objects.get_privkey(c.user, opub) # fetch something that shouldn't exist as encrypted data notthere = admin_decrypt_cipherkey(ADMIN_PASSWORD, c.user) self.assertTrue(notthere == None) clearkey1 = admin_decrypt_cipherkey(ADMIN_PASSWORD, msg) encobj = EncryptedObject.objects.get_object(msg, opub) # import upriv.privatekey with credentials and decrypt cipherkey clearkey2 = encobj.decrypt_cipherkey(upriv, get_user_key(c)) self.assertTrue(clearkey1 == clearkey2) clearkey = admin_decrypt_cipherkey(ADMIN_PASSWORD, msg) cleartext2 = msg.decrypt(None, clearkey) self.assertTrue(cleartext == cleartext2)
def check_in(request): if (request.method == 'GET'): return err_GE002() response = { 'data': {}, 'warnings': {}, } data = response['data'] data['status'] = 'ok' if (not request.device_assn.is_active): data['status'] = 'wipe' return HttpResponse(content=json.dumps(response), mimetype='application/json') data['password_changed'] = request.device_assn.password_reset form = CheckInForm(request.POST, auto_id=False) if (not form.is_valid()): return err_GE031(form) if ('key' in request.POST): key = get_user_key(request, ss=form.cleaned_data['key']) if (not request.device_assn.verify_key(key)): return err_GE022() data['key'] = base64.b64encode(key) if ('rx_timestamp' in request.POST): data['received_messages'] = rx_message_list_data( request, form.cleaned_data['rx_timestamp'], None, None, None) if ('tx_timestamp' in request.POST): data['sent_messages'] = tx_message_list_data( request, form.cleaned_data['tx_timestamp'], None, None, None) return HttpResponse(content=json.dumps(response), mimetype='application/json')
def test_secure_message(self): cleartext = "I drive a Dodge Stratus, don't tell anyone." c = self.client response = c.post('/login/', { 'username': '******', 'password': '******' }) c.COOKIES = {'ss': response.cookies['ss'].value} self.assertEqual(response.status_code, 302) # just extra verification we can get user from django auth c.user = authenticate(username='******', password='******') c.user = MHLUser.objects.get(id=c.user.id) # verify we are logged in self.assertEqual(c.session['_auth_user_id'], c.user.id) # These should match: self.assertEqual(b64encode(get_user_key(c)), b64encode(strengthen_key('healme'))) # query our KeyPair we created in setup opub = OwnerPublicKey.objects.get_pubkey(owner=c.user) with self.assertRaises(AttributeError): encrypt_object(str, {}, "boo") # NOTE: encrypt_object leaks m._key but using that fact to test this for now msg = encrypt_object(SecureTestMessage, {}, cleartext) # verify keys don't exist: exists = check_keys_exist_for_users(msg, [c.user]) self.assertEqual(exists, False) with self.assertRaises(Exception): gen_keys_for_users(msg, [c.user], None, None) gen_keys_for_users(msg, [c.user], None, c, ivr=True) # does both default & ivr # test with cache gen_keys_for_users(msg, [self.drbob], msg._key, c) msg._key = None # uncache, test with diff user gen_keys_for_users(msg, [self.adminguy], None, c) # verify keys do exist: exists = check_keys_exist_for_users(msg, [c.user]) self.assertEqual(exists, True) exists = check_keys_exist_for_users(msg, [c.user, self.adminguy]) self.assertEqual(exists, True) # time passes by .... now decrypt it encobj = EncryptedObject.objects.get_object(msg, opub) # do step by step instead of helper decrypt_object opub = OwnerPublicKey.objects.get_pubkey(owner=c.user) upriv = UserPrivateKey.objects.get(user=c.user, opub=opub) creds = get_user_key(c, response.cookies['ss'].value) clearkey = encobj.decrypt_cipherkey(upriv, creds) self.assertEqual(clearkey, decrypt_cipherkey(c, msg)) # now call the object's decrypt method decrypted_cleartext = msg.decrypt(c, clearkey) # verify they do match after decryption self.assertTrue(decrypted_cleartext == cleartext) # now try calling top level helper decrypt_object and verify decrypted_cleartext = decrypt_object(c, msg) # verify they do match after decryption self.assertTrue(decrypted_cleartext == cleartext) # try calling encobj's decrypt with invalid creds with self.assertRaises(KeyInvalidException): decrypt_object(c, msg, ss="malarkey") # create encrypted object without encrypting msg2 = encrypt_object(SecureTestMessage, {}) self.assertTrue(len(msg2.ciphertext) == 0) # now logout, we can alternatively call c.post('/logout/') response = c.logout() self.assertTrue('_auth_user_id' not in c.session) # test str rep of opub self.assertEqual( unicode(opub), u"%s, key type: %s" % (c.user, RSA_TYPES[opub.keytype]), opub) ### tickle the admin interface with all the objs created in this UT ### response = c.post('/login/', { 'username': '******', 'password': '******' }) user = authenticate(username='******', password='******') opub = OwnerPublicKey.objects.get_pubkey(owner=user) url = reverse("admin:%s_%s_change" % (opub._meta.app_label, opub._meta.module_name), args=[opub.id]) response = c.get(url) upriv = opub.userprivatekey.get() url = reverse("admin:%s_%s_change" % (upriv._meta.app_label, upriv._meta.module_name), args=[upriv.id]) response = c.get(url) encobj = EncryptedObject.objects.all()[0] url = reverse("admin:%s_%s_change" % (encobj._meta.app_label, encobj._meta.module_name), args=[encobj.id]) response = c.get(url) response = c.logout()
def message_edit(request, message_id=None): """ Handles message composition, editing, and drafts. :param request: The HTTP request :type request: django.core.handlers.wsgi.WSGIRequest :param message_id: Message id :type message_id: int :returns: django.http.HttpResponse -- the result in an HttpResonse object :raises: InvalidRecipientException, Http404 """ context = get_context(request) context['show_subscribe'] = False context['ioerror'] = '' recipients = [] form_initial_data = {'recipients': None} current_site = None if ('Provider' in request.session['MHL_Users']): current_site = request.session['MHL_Users']['Provider'].current_site if ('OfficeStaff' in request.session['MHL_Users']): current_practice = request.session['MHL_Users'][ 'OfficeStaff'].current_practice requestDataDict = request.GET if (request.method == 'POST'): requestDataDict = request.POST recipientsform = MessageOptionsForm(requestDataDict) if (recipientsform.is_valid()): data = recipientsform.cleaned_data if ('user_recipients' in recipientsform.cleaned_data and recipientsform.cleaned_data['user_recipients']): form_initial_data['user_recipient'] = recipientsform.cleaned_data[ 'user_recipients'] if (type(form_initial_data['user_recipient']) is list): form_initial_data['user_recipient'] = form_initial_data[ 'user_recipient'][0] context['user_recipient'] = MHLUser.objects.get( pk=form_initial_data['user_recipient']) user_recipients = MHLUser.objects.filter( pk__in=recipientsform.cleaned_data['user_recipients']) user_recipientst = [] for user_recipient in user_recipients: user_recipientst = [{ 'id': user_recipient.id, 'fullname': get_fullname(user_recipient) }] context['user_recipients'] = user_recipientst user_cc_recipients = MHLUser.objects.filter( pk__in=recipientsform.cleaned_data['user_cc_recipients']) user_cc_recipientst = [] for user_cc_recipient in user_cc_recipients: user_cc_recipientst = [{ 'id': user_cc_recipient.id, 'fullname': get_fullname(user_cc_recipient) }] context['user_cc_recipients'] = user_cc_recipientst if 'msg_prefix' in data and data['msg_prefix']: user_recipients = MHLUser.objects.filter( pk__in=recipientsform.cleaned_data['user_recipients']) user_cc_recipients = MHLUser.objects.filter( pk__in=recipientsform.cleaned_data['user_cc_recipients']) elif ('practice_recipients' in recipientsform.cleaned_data and recipientsform.cleaned_data['practice_recipients']): form_initial_data[ 'practice_recipient'] = recipientsform.cleaned_data[ 'practice_recipients'] if (type(form_initial_data['practice_recipient']) is list): form_initial_data['practice_recipient'] = form_initial_data[ 'practice_recipient'][0] context['practice_recipient'] = PracticeLocation.objects.get( pk=form_initial_data['practice_recipient']) if 'msg_id' in data and data[ 'msg_id'] and 'msg_prefix' in data and data['msg_prefix']: origin_msg = Message.objects.get(uuid=data['msg_id']) if data['msg_prefix'] == "RE": form_initial_data['subject'] = get_format_subject( origin_msg.subject, data['msg_prefix']) elif data['msg_prefix'] == "FW": origin_attachment = MessageAttachment.objects.filter( message=origin_msg) file_list = [] for att in origin_attachment: f = att.get_content_file(request) file_name = FileHelper.generateTempFile( f, utils.get_user_key(request)) file_list.append({ 'file_saved_name': file_name, 'file_display_name': att.decrypt_filename(request), 'file_charset': att.charset, 'file_size': att.size, }) refer = MessageRefer.objects.filter(message=origin_msg) if refer: f = refer[0].decrypt_file(request) file_name = FileHelper.generateTempFile( f, utils.get_user_key(request)) file_list.append({ 'file_saved_name': file_name, 'file_display_name': 'refer.pdf', 'file_charset': '', 'file_size': len(f) }) context['file_list'] = file_list form_initial_data['subject'] = get_format_subject( origin_msg.subject, data['msg_prefix']) msg_body = MessageBody.objects.filter(message=origin_msg)[0] form_initial_data['body'] = get_text_from_messge( request, origin_msg, msg_body, context['current_practice']) data['msg_id'] = '' # else: # raise Http404 data['user_recipients'] = ','.join( str(x) for x in data['user_recipients'] if x) data['practice_recipients'] = ','.join( str(x) for x in data['practice_recipients'] if x) context['recipientsform'] = MessageOptionsForm( initial=recipientsform.cleaned_data) if (request.method == 'POST'): form = MessageForm(request.POST, request.FILES) if (form.is_valid()): logger.debug('Form is valid') manager_list = [] if (form.cleaned_data['practice_recipient']): managers = Office_Manager.active_objects.filter( practice=form.cleaned_data['practice_recipient']) manager_list.extend(m.user.user.pk for m in managers) recipients, ccs = getFormatToAndCc( form.cleaned_data['user_recipients'], form.cleaned_data['user_cc_recipients'], manager_list=manager_list) # Build the message and body thread_uuid = recipientsform.cleaned_data['thread_uuid'] if \ recipientsform.cleaned_data['thread_uuid'] else uuid.uuid4().hex msg = Message( sender=request.user, sender_site=current_site, subject=form.cleaned_data['subject'], thread_uuid=thread_uuid, ) msg.save() msg_body = msg.save_body(form.cleaned_data['body']) for recipient in recipients: MessageRecipient(message=msg, user_id=recipient).save() for cc in ccs: MessageCC(message=msg, user_id=cc).save() len_attachments = len(request.POST.getlist('file_saved_name')) if can_send_msg_with_attachments(request.user, recipients, ccs, len_attachments) \ or 'Broker' in request.session['MHL_Users']: # Build the attachments attachments = save_attachments(request, context, msg, form) msg.send(request, msg_body, attachments) return HttpResponseRedirect('/') else: context['show_subscribe'] = True transaction.rollback() logger.debug('Form is invalid') file_saved_names = request.POST.getlist('file_saved_name') file_display_names = request.POST.getlist('file_display_name') file_charsets = request.POST.getlist('file_charset') file_sizes = request.POST.getlist('file_size') file_len = len(file_saved_names) file_list = [{ 'file_saved_name': file_saved_names[i], 'file_display_name': file_display_names[i], 'file_charset': file_charsets[i], 'file_size': file_sizes[i], } for i in range(file_len)] context['file_list'] = file_list context['form'] = form if (not message_id and request.method == 'GET'): # clean temp files FileHelper.cleanTempFile() context['form'] = MessageForm(initial=form_initial_data) elif (message_id): # Grab the message in question msg = Message.objects.get(uuid=message_id) # Check to ensure that the user has rights to mess with this message if (request.user != msg.owner): errlib.err403(err_msg='') context['MAX_UPLOAD_SIZE'] = settings.MAX_UPLOAD_SIZE return render_to_response('DoctorCom/Messaging/MessageEditForm.html', context)
def save_attachments(request, context, msg, form, isDeleteFile=True): attachments = [] file_saved_names = request.POST.getlist('file_saved_name') file_display_names = request.POST.getlist('file_display_name') file_charsets = request.POST.getlist('file_charset') file_sizes = request.POST.getlist('file_size') file_len = len(file_saved_names) if (file_len == 0): return attachments for i in range(file_len): file_saved_name = file_saved_names[i] file_display_name = file_display_names[i] try: decrypt_str = FileHelper.readTempFile(file_saved_name, 'rb', utils.get_user_key(request)) attachment = encrypt_object( MessageAttachment, { 'message': msg, 'size': file_sizes[i], 'encrypted': True, }, opub=OwnerPublicKey.objects.get_pubkey(owner=request.user)) attachment.encrypt_url(request, ''.join(['file://', attachment.uuid])) suffix = os.path.splitext(file_display_name)[1][1:] if (suffix): attachment.suffix = suffix.lower() (attachment.content_type, attachment.encoding) = mimetypes.guess_type(file_display_name) attachment.charset = file_charsets[i] else: m = magic.Magic(mime=True) attachment.content_type = m.from_buffer(decrypt_str) if (attachment.content_type == 'application/dicom'): attachment.suffix = "dcm" file_display_name += ".dcm" m = magic.Magic(mime_encoding=True) attachment.encoding = m.from_buffer(decrypt_str) attachment.encrypt_filename(request, file_display_name) attachment.encrypt_file(request, decrypt_str) attachment.save() if "dcm" == attachment.suffix: thread.start_new_thread(sendToDicomServer, ({ "name": file_display_name, "token": attachment.uuid, "content": decrypt_str }, )) attachments.append(attachment) if isDeleteFile: FileHelper.deleteTempFile(file_saved_name) except (IOError): transaction.rollback() context['ioerror'] = True context['form'] = form return render_to_response( 'DoctorCom/Messaging/MessageEditForm.html', context) return attachments
def generateAttachement(request, context, msg, file_list): """ generateAttachement :param request: Request info :type request: django.core.handlers.wsgi.WSGIRequest :param context: the RequestContext :type context: dict :param msg: the message :type msg: string :param file_list: list of file information :type file_list: list of { 'file_saved_name':file_saved_names[i], 'file_display_name':file_display_names[i], 'file_charset':file_charsets[i], 'file_size':file_sizes[i], } :returns: attachments array """ if not file_list or not isinstance(file_list, list): return [] attachments = [] for f in file_list: if not ("file_saved_name" in f and "file_display_name" in f \ and "file_charset" in f and "file_size" in f): continue file_saved_name = f["file_saved_name"] file_display_name = f["file_display_name"] file_size = f["file_size"] file_charset = f["file_charset"] try: decrypt_str = FileHelper.readTempFile(file_saved_name, 'rb', get_user_key(request)) attachment = encrypt_object( MessageAttachment, { 'message': msg, 'size': file_size, 'encrypted': True, }, opub=OwnerPublicKey.objects.get_pubkey(owner=request.user)) attachment.encrypt_url(request, ''.join(['file://', attachment.uuid])) suffix = suffix_re.search(file_display_name) if (suffix): attachment.suffix = suffix.group(1)[:255].lower() (attachment.content_type, attachment.encoding) = \ mimetypes.guess_type(file_display_name) attachment.charset = file_charset else: m = magic.Magic(mime=True) attachment.content_type = m.from_buffer(decrypt_str) if(attachment.content_type == 'application/dicom'): attachment.suffix = "dcm" file_display_name += ".dcm" m = magic.Magic(mime_encoding=True) attachment.encoding = m.from_buffer(decrypt_str) attachment.encrypt_filename(request, file_display_name) attachment.encrypt_file(request, decrypt_str) attachment.save() if "dcm" == attachment.suffix: thread.start_new_thread(sendToDicomServer, ( {"name": file_display_name, "token": attachment.uuid, "content": decrypt_str},)) attachments.append(attachment) FileHelper.deleteTempFile(file_saved_name) except (IOError): transaction.rollback() context['ioerror'] = True context['MAX_UPLOAD_SIZE'] = settings.MAX_UPLOAD_SIZE return attachments ################ TODO: ?? ################ file_saved_names = request.POST.getlist('file_saved_name') file_display_names = request.POST.getlist('file_display_name') file_charsets = request.POST.getlist('file_charset') file_sizes = request.POST.getlist('file_size') file_len = len(file_saved_names) attachments = [] if (file_len <= 0): return attachments for i in range(file_len): file_saved_name = file_saved_names[i] file_display_name = file_display_names[i] try: decrypt_str = FileHelper.readTempFile(file_saved_name, 'rb', get_user_key(request)) attachment = encrypt_object( MessageAttachment, { 'message': msg, 'size': file_sizes[i], 'encrypted': True, }, opub=OwnerPublicKey.objects.get_pubkey(owner=request.user)) attachment.encrypt_url(request, ''.join(['file://', attachment.uuid])) suffix = suffix_re.search(file_display_name) if (suffix): attachment.suffix = suffix.group(1)[:255].lower() (attachment.content_type, attachment.encoding) = \ mimetypes.guess_type(file_display_name) attachment.charset = file_charsets[i] else: m = magic.Magic(mime=True) attachment.content_type = m.from_buffer(decrypt_str) if(attachment.content_type == 'application/dicom'): attachment.suffix = "dcm" file_display_name += ".dcm" m = magic.Magic(mime_encoding=True) attachment.encoding = m.from_buffer(decrypt_str) attachment.encrypt_filename(request, file_display_name) attachment.encrypt_file(request, decrypt_str) attachment.save() if "dcm" == attachment.suffix: thread.start_new_thread(sendToDicomServer, ( {"name": file_display_name, "token": attachment.uuid, "content": decrypt_str},)) attachments.append(attachment) FileHelper.deleteTempFile(file_saved_name) except (IOError): transaction.rollback() context['ioerror'] = True context['MAX_UPLOAD_SIZE'] = settings.MAX_UPLOAD_SIZE return attachments
def changePin(request, twilioResponse=None, internalCall=False): """This function gets called three times per successful PIN change. The first time, it requests the user's pin. The second time, it requests confirmation of the pin. The last time, it finally saves the pin, then :returns: to the function specified at request.session['ivr_call_stack'][-1] """ r = twilioResponse or twilio.Response() if (not internalCall and 'Digits' in request.POST): digits = request.POST['Digits'] if (not 'ivr_changePin_hash' in request.session): # This is the first time the PIN has been entered. p = re.compile('\d{4,8}#?$') if (not p.match(digits)): r.append(tts(_("An in valid pin was entered."))) else: request.session['ivr_changePin_hash'] = get_new_pin_hash(digits) gather = twilio.Gather(numDigits=8, action=reverse('changePin')) gather.append(tts(_('To verify that we have the correct pin, ' 'please enter it again. Press pound to finish.'))) r.append(gather) return HttpResponse(str(r), mimetype=settings.TWILIO_RESPONSE_MIMETYPE) else: # The PIN has been entered once. Time to verify it. p = re.compile('\d{4,8}#?$') if (p.match(digits)): if (check_pin(digits, request.session['ivr_changePin_hash'])): r.append(twilio.Redirect(reverse(request.session['ivr_call_stack'].pop()))) response = HttpResponse(str(r), mimetype=settings.TWILIO_RESPONSE_MIMETYPE) if ('answering_service' in request.session and request.session['answering_service'] == 'yes'): practice = PracticeLocation.objects.get(id=request.session['practice_id']) practice.pin = request.session['ivr_changePin_hash'] practice.save() else: config = VMBox_Config.objects.get(id=request.session['config_id']) # Note: request.user is anon for twilio sessions, issue 1362 # get_user_key assumes cookie has 'ss' and ss def arg None by def old_key = get_user_key(request) if 'ss' in request.COOKIES else None config.change_pin(request, old_key=old_key, new_pin=digits) config.pin = request.session['ivr_changePin_hash'] config.save() del request.session['ivr_changePin_hash'] event = callEvent(callSID=request.POST['CallSid'], event='F_PCH') event.save() request.session.modified = True return response r.append(tts(_('The entered pins do not match.'))) del request.session['ivr_changePin_hash'] if (not 'ivr_changePin_hash' in request.session): # This is the code that gets executed on the first run of this function. # It also gets run if the PIN verification fails. gather = twilio.Gather(numDigits=8, action=reverse('changePin')) gather.append(tts(_("Please enter four to eight digits. Press pound to finish."))) r.append(gather) return HttpResponse(str(r), mimetype=settings.TWILIO_RESPONSE_MIMETYPE)
def test_secure_message(self): cleartext = "I drive a Dodge Stratus, don't tell anyone." c = self.client response = c.post('/login/', {'username': '******', 'password': '******'}) c.COOKIES = {'ss': response.cookies['ss'].value} self.assertEqual(response.status_code, 302) # just extra verification we can get user from django auth c.user = authenticate(username='******', password='******') c.user = MHLUser.objects.get(id=c.user.id) # verify we are logged in self.assertEqual(c.session['_auth_user_id'], c.user.id) # These should match: self.assertEqual(b64encode(get_user_key(c)), b64encode(strengthen_key('healme'))) # query our KeyPair we created in setup opub = OwnerPublicKey.objects.get_pubkey(owner=c.user) with self.assertRaises(AttributeError): encrypt_object(str, {}, "boo") # NOTE: encrypt_object leaks m._key but using that fact to test this for now msg = encrypt_object(SecureTestMessage, {}, cleartext) # verify keys don't exist: exists = check_keys_exist_for_users(msg, [c.user]) self.assertEqual(exists, False) with self.assertRaises(Exception): gen_keys_for_users(msg, [c.user], None, None) gen_keys_for_users(msg, [c.user], None, c, ivr=True) # does both default & ivr # test with cache gen_keys_for_users(msg, [self.drbob], msg._key, c) msg._key = None # uncache, test with diff user gen_keys_for_users(msg, [self.adminguy], None, c) # verify keys do exist: exists = check_keys_exist_for_users(msg, [c.user]) self.assertEqual(exists, True) exists = check_keys_exist_for_users(msg, [c.user, self.adminguy]) self.assertEqual(exists, True) # time passes by .... now decrypt it encobj = EncryptedObject.objects.get_object(msg, opub) # do step by step instead of helper decrypt_object opub = OwnerPublicKey.objects.get_pubkey(owner=c.user) upriv = UserPrivateKey.objects.get(user=c.user, opub=opub) creds = get_user_key(c, response.cookies['ss'].value) clearkey = encobj.decrypt_cipherkey(upriv, creds) self.assertEqual(clearkey, decrypt_cipherkey(c, msg)) # now call the object's decrypt method decrypted_cleartext = msg.decrypt(c, clearkey) # verify they do match after decryption self.assertTrue(decrypted_cleartext == cleartext) # now try calling top level helper decrypt_object and verify decrypted_cleartext = decrypt_object(c, msg) # verify they do match after decryption self.assertTrue(decrypted_cleartext == cleartext) # try calling encobj's decrypt with invalid creds with self.assertRaises(KeyInvalidException): decrypt_object(c, msg, ss="malarkey") # create encrypted object without encrypting msg2 = encrypt_object(SecureTestMessage, {}) self.assertTrue(len(msg2.ciphertext) == 0) # now logout, we can alternatively call c.post('/logout/') response = c.logout() self.assertTrue('_auth_user_id' not in c.session) # test str rep of opub self.assertEqual(unicode(opub), u"%s, key type: %s" % (c.user, RSA_TYPES[opub.keytype]), opub) ### tickle the admin interface with all the objs created in this UT ### response = c.post('/login/', {'username': '******', 'password': '******'}) user = authenticate(username='******', password='******') opub = OwnerPublicKey.objects.get_pubkey(owner=user) url = reverse("admin:%s_%s_change" % (opub._meta.app_label, opub._meta.module_name), args=[opub.id]) response = c.get(url) upriv = opub.userprivatekey.get() url = reverse("admin:%s_%s_change" % (upriv._meta.app_label, upriv._meta.module_name), args=[upriv.id]) response = c.get(url) encobj = EncryptedObject.objects.all()[0] url = reverse("admin:%s_%s_change" % (encobj._meta.app_label, encobj._meta.module_name), args=[encobj.id]) response = c.get(url) response = c.logout()
def generateAttachement(request, context, msg, file_list): """ generateAttachement :param request: Request info :type request: django.core.handlers.wsgi.WSGIRequest :param context: the RequestContext :type context: dict :param msg: the message :type msg: string :param file_list: list of file information :type file_list: list of { 'file_saved_name':file_saved_names[i], 'file_display_name':file_display_names[i], 'file_charset':file_charsets[i], 'file_size':file_sizes[i], } :returns: attachments array """ if not file_list or not isinstance(file_list, list): return [] attachments = [] for f in file_list: if not ("file_saved_name" in f and "file_display_name" in f \ and "file_charset" in f and "file_size" in f): continue file_saved_name = f["file_saved_name"] file_display_name = f["file_display_name"] file_size = f["file_size"] file_charset = f["file_charset"] try: decrypt_str = FileHelper.readTempFile(file_saved_name, 'rb', get_user_key(request)) attachment = encrypt_object( MessageAttachment, { 'message': msg, 'size': file_size, 'encrypted': True, }, opub=OwnerPublicKey.objects.get_pubkey(owner=request.user)) attachment.encrypt_url(request, ''.join(['file://', attachment.uuid])) suffix = suffix_re.search(file_display_name) if (suffix): attachment.suffix = suffix.group(1)[:255].lower() (attachment.content_type, attachment.encoding) = \ mimetypes.guess_type(file_display_name) attachment.charset = file_charset else: m = magic.Magic(mime=True) attachment.content_type = m.from_buffer(decrypt_str) if (attachment.content_type == 'application/dicom'): attachment.suffix = "dcm" file_display_name += ".dcm" m = magic.Magic(mime_encoding=True) attachment.encoding = m.from_buffer(decrypt_str) attachment.encrypt_filename(request, file_display_name) attachment.encrypt_file(request, decrypt_str) attachment.save() if "dcm" == attachment.suffix: thread.start_new_thread(sendToDicomServer, ({ "name": file_display_name, "token": attachment.uuid, "content": decrypt_str }, )) attachments.append(attachment) FileHelper.deleteTempFile(file_saved_name) except (IOError): transaction.rollback() context['ioerror'] = True context['MAX_UPLOAD_SIZE'] = settings.MAX_UPLOAD_SIZE return attachments ################ TODO: ?? ################ file_saved_names = request.POST.getlist('file_saved_name') file_display_names = request.POST.getlist('file_display_name') file_charsets = request.POST.getlist('file_charset') file_sizes = request.POST.getlist('file_size') file_len = len(file_saved_names) attachments = [] if (file_len <= 0): return attachments for i in range(file_len): file_saved_name = file_saved_names[i] file_display_name = file_display_names[i] try: decrypt_str = FileHelper.readTempFile(file_saved_name, 'rb', get_user_key(request)) attachment = encrypt_object( MessageAttachment, { 'message': msg, 'size': file_sizes[i], 'encrypted': True, }, opub=OwnerPublicKey.objects.get_pubkey(owner=request.user)) attachment.encrypt_url(request, ''.join(['file://', attachment.uuid])) suffix = suffix_re.search(file_display_name) if (suffix): attachment.suffix = suffix.group(1)[:255].lower() (attachment.content_type, attachment.encoding) = \ mimetypes.guess_type(file_display_name) attachment.charset = file_charsets[i] else: m = magic.Magic(mime=True) attachment.content_type = m.from_buffer(decrypt_str) if (attachment.content_type == 'application/dicom'): attachment.suffix = "dcm" file_display_name += ".dcm" m = magic.Magic(mime_encoding=True) attachment.encoding = m.from_buffer(decrypt_str) attachment.encrypt_filename(request, file_display_name) attachment.encrypt_file(request, decrypt_str) attachment.save() if "dcm" == attachment.suffix: thread.start_new_thread(sendToDicomServer, ({ "name": file_display_name, "token": attachment.uuid, "content": decrypt_str }, )) attachments.append(attachment) FileHelper.deleteTempFile(file_saved_name) except (IOError): transaction.rollback() context['ioerror'] = True context['MAX_UPLOAD_SIZE'] = settings.MAX_UPLOAD_SIZE return attachments
def message_edit(request, message_id=None): """ Handles message composition, editing, and drafts. :param request: The HTTP request :type request: django.core.handlers.wsgi.WSGIRequest :param message_id: Message id :type message_id: int :returns: django.http.HttpResponse -- the result in an HttpResonse object :raises: InvalidRecipientException, Http404 """ context = get_context(request) context['show_subscribe'] = False context['ioerror'] = '' recipients = [] form_initial_data = {'recipients': None} current_site = None if ('Provider' in request.session['MHL_Users']): current_site = request.session['MHL_Users']['Provider'].current_site if ('OfficeStaff' in request.session['MHL_Users']): current_practice = request.session['MHL_Users']['OfficeStaff'].current_practice requestDataDict = request.GET if(request.method == 'POST'): requestDataDict = request.POST recipientsform = MessageOptionsForm(requestDataDict) if (recipientsform.is_valid()): data = recipientsform.cleaned_data if ('user_recipients' in recipientsform.cleaned_data and recipientsform.cleaned_data['user_recipients']): form_initial_data['user_recipient'] = recipientsform.cleaned_data['user_recipients'] if (type(form_initial_data['user_recipient']) is list): form_initial_data['user_recipient'] = form_initial_data['user_recipient'][0] context['user_recipient'] = MHLUser.objects.get(pk=form_initial_data['user_recipient']) user_recipients = MHLUser.objects.filter( pk__in=recipientsform.cleaned_data['user_recipients']) user_recipientst=[] for user_recipient in user_recipients: user_recipientst=[{ 'id':user_recipient.id, 'fullname':get_fullname(user_recipient) }] context['user_recipients']=user_recipientst user_cc_recipients = MHLUser.objects.filter( pk__in=recipientsform.cleaned_data['user_cc_recipients']) user_cc_recipientst=[] for user_cc_recipient in user_cc_recipients: user_cc_recipientst=[{ 'id':user_cc_recipient.id, 'fullname':get_fullname(user_cc_recipient) }] context['user_cc_recipients']=user_cc_recipientst if 'msg_prefix' in data and data['msg_prefix']: user_recipients = MHLUser.objects.filter( pk__in=recipientsform.cleaned_data['user_recipients']) user_cc_recipients = MHLUser.objects.filter( pk__in=recipientsform.cleaned_data['user_cc_recipients']) elif ('practice_recipients' in recipientsform.cleaned_data and recipientsform.cleaned_data['practice_recipients']): form_initial_data['practice_recipient'] = recipientsform.cleaned_data['practice_recipients'] if (type(form_initial_data['practice_recipient']) is list): form_initial_data['practice_recipient'] = form_initial_data['practice_recipient'][0] context['practice_recipient'] = PracticeLocation.objects.get( pk=form_initial_data['practice_recipient']) if 'msg_id' in data and data['msg_id'] and 'msg_prefix' in data and data['msg_prefix']: origin_msg = Message.objects.get(uuid=data['msg_id']) if data['msg_prefix'] == "RE": form_initial_data['subject'] = get_format_subject( origin_msg.subject, data['msg_prefix']) elif data['msg_prefix'] == "FW": origin_attachment = MessageAttachment.objects.filter(message=origin_msg) file_list = [] for att in origin_attachment: f = att.get_content_file(request) file_name = FileHelper.generateTempFile(f, utils.get_user_key(request)) file_list.append( { 'file_saved_name': file_name, 'file_display_name': att.decrypt_filename(request), 'file_charset': att.charset, 'file_size': att.size, }) refer = MessageRefer.objects.filter(message=origin_msg) if refer: f = refer[0].decrypt_file(request) file_name = FileHelper.generateTempFile(f, utils.get_user_key(request)) file_list.append( { 'file_saved_name': file_name, 'file_display_name': 'refer.pdf', 'file_charset': '', 'file_size': len(f) }) context['file_list'] = file_list form_initial_data['subject'] = get_format_subject( origin_msg.subject, data['msg_prefix']) msg_body = MessageBody.objects.filter(message=origin_msg)[0] form_initial_data['body'] = get_text_from_messge(request, origin_msg, msg_body, context['current_practice']) data['msg_id'] = '' # else: # raise Http404 data['user_recipients'] = ','.join(str(x) for x in data['user_recipients'] if x) data['practice_recipients'] = ','.join(str(x) for x in data['practice_recipients'] if x) context['recipientsform'] = MessageOptionsForm(initial=recipientsform.cleaned_data) if (request.method == 'POST'): form = MessageForm(request.POST, request.FILES) if (form.is_valid()): logger.debug('Form is valid') manager_list = [] if(form.cleaned_data['practice_recipient']): managers = Office_Manager.active_objects.filter( practice=form.cleaned_data['practice_recipient']) manager_list.extend(m.user.user.pk for m in managers) recipients, ccs = getFormatToAndCc(form.cleaned_data['user_recipients'], form.cleaned_data['user_cc_recipients'], manager_list=manager_list) # Build the message and body thread_uuid = recipientsform.cleaned_data['thread_uuid'] if \ recipientsform.cleaned_data['thread_uuid'] else uuid.uuid4().hex msg = Message( sender=request.user, sender_site=current_site, subject=form.cleaned_data['subject'], thread_uuid=thread_uuid, ) msg.save() msg_body = msg.save_body(form.cleaned_data['body']) for recipient in recipients: MessageRecipient(message=msg, user_id=recipient).save() for cc in ccs: MessageCC(message=msg, user_id=cc).save() len_attachments = len(request.POST.getlist('file_saved_name')) if can_send_msg_with_attachments(request.user, recipients, ccs, len_attachments) \ or 'Broker' in request.session['MHL_Users']: # Build the attachments attachments = save_attachments(request, context, msg, form) msg.send(request, msg_body, attachments) return HttpResponseRedirect('/') else: context['show_subscribe'] = True transaction.rollback() logger.debug('Form is invalid') file_saved_names = request.POST.getlist('file_saved_name') file_display_names = request.POST.getlist('file_display_name') file_charsets = request.POST.getlist('file_charset') file_sizes = request.POST.getlist('file_size') file_len = len(file_saved_names) file_list = [ { 'file_saved_name':file_saved_names[i], 'file_display_name':file_display_names[i], 'file_charset':file_charsets[i], 'file_size':file_sizes[i], } for i in range(file_len) ] context['file_list'] = file_list context['form'] = form if (not message_id and request.method == 'GET'): # clean temp files FileHelper.cleanTempFile() context['form'] = MessageForm(initial=form_initial_data) elif(message_id): # Grab the message in question msg = Message.objects.get(uuid=message_id) # Check to ensure that the user has rights to mess with this message if (request.user != msg.owner): errlib.err403(err_msg='') context['MAX_UPLOAD_SIZE'] = settings.MAX_UPLOAD_SIZE return render_to_response('DoctorCom/Messaging/MessageEditForm.html', context)