示例#1
0
def tools_check_cert_chains(request):
    logger = logging.getLogger('rid_agent.views.tools_check_cert_chains')
    client_ip = handlers.GetRemoteIp(request)

    #Load the DB certs into memory for quick access
    all_certs = certificate.objects.all().values()
    cert_dict = {}
    for cert in all_certs:
        cert_dict[cert['subject']] = cert

    results_dict = {}
    for cert_subj in cert_dict:
        cert = cert_dict[cert_subj]
        cert['issuer_in_db'] = cert['issuer'] in cert_dict
        try:
            x509 = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM,
                                                   cert['pem_certificate'])
            if x509.has_expired():
                cert['expired'] = 'Yes'
            else:
                cert['expired'] = 'No'
        except:
            cert['expired'] = 'Unknown Error'
        results_dict[cert_subj] = cert

    return render_to_response('tools/check_cert_chains.html',
                              {'chain_data': results_dict},
                              context_instance=RequestContext(request))
示例#2
0
def tools_send_rid_message(request):
    logger = logging.getLogger('rid_agent.views.tools_send_rid_message')
    client_ip = handlers.GetRemoteIp(request)
    if request.method != 'POST':
        logger.info('User %s from %s rendering tools/send_rid_message',
                    request.user.username, client_ip)
        return render_to_response('tools/send_rid_message.html',
                                  {'form': forms.SendRidMessageForm()},
                                  context_instance=RequestContext(request))
    #Method is POST
    form = forms.SendRidMessageForm(request.POST)
    logger.debug('User %s from %s Attempting to validate form',
                 request.user.username, client_ip)
    try:
        if not form.is_valid():
            logger.debug('Form not valid, raising error.')
            raise Exception(None, None)

        xml_string = request.POST['rid_message']
        parsed, xml_doc = handlers.StringToXml(xml_string)
        if not parsed:
            logger.debug('RID Message not valid XML, raising error.')
            raise Exception('rid_message', str(xml_doc))

        schema_valid, message = handlers.IsValidRid(xml_doc)
        if not schema_valid:
            logger.debug('RID Message not Schema valid, raising error.')
            raise Exception('rid_message', str(message))
    except Exception as (field, error):
        if field is not None:
            logger.debug('Error was: %s; %s. Rendering form', field, error)
            form._errors[field] = ErrorList([error])
        return render_to_response('tools/send_rid_message.html',
                                  {'form': form},
                                  context_instance=RequestContext(request))
示例#3
0
def tools_build_outgoing_api_push(request):
    logger = logging.getLogger('rid_agent.views.tools_build_outgoing_api_push')
    client_ip = handlers.GetRemoteIp(request)

    post_data = ''
    form = forms.PushOutgoingMessageForm

    if len(request.POST) > 0:
        form = forms.PushOutgoingMessageForm(request.POST)
        if form.is_valid():  #Build the request
            post_data = '<api_request '
            post_data += 'destination="%s"' % form.cleaned_data[
                'ip_destination']
            if 'incoming_message_id' in form.cleaned_data:
                post_data += ' incoming_message_id="%s"' % form.cleaned_data[
                    'incoming_message_id']
            post_data += '>'
            post_data += form.cleaned_data['xml']
            post_data += '</api_request>'

    return render_to_response('tools/build_outgoing_api_push.html', {
        'form': form,
        'post_data': post_data
    },
                              context_instance=RequestContext(request))
示例#4
0
def api_10_logout(request):
    logger = logging.getLogger('rid_agent.views.api_10_logout')
    client_ip = handlers.GetRemoteIp(request)
    logger.info('User %s from %s. API 1.0 logged out.', request.user.username,
                client_ip)
    auth.logout(request)
    values_dict = {'type': 'success', 'message': 'Logout successful!'}
    return handlers.get_api_10_response(values_dict)
示例#5
0
def logout(request):
    logger = logging.getLogger('rid_agent.views.logout')
    client_ip = handlers.GetRemoteIp(request)
    logger.info('User %s has logged out from %s', request.user.username,
                client_ip)
    auth.logout(request)
    return render_to_response('core/message.html', {
        'title': 'Logged out',
        'message': 'Logout successful.'
    },
                              context_instance=RequestContext(request))
示例#6
0
def login(request):
    logger = logging.getLogger('rid_agent.views.login')
    client_ip = handlers.GetRemoteIp(request)
    #If this is a GET request, render the login page and preserve any redirect info
    if request.method == 'GET':
        #Either redirect the user to the page they were trying to access,
        #or the default URL.
        if (request.GET is not None and 'next' in request.GET):
            next = request.GET['next']
        else:
            next = settings.LOGIN_REDIRECT_URL
        form = forms.LoginForm(initial={'next': next})
        logger.info('Login page accessed from %s with next=%s', client_ip,
                    next)
        return render_to_response('auth/login.html', {'form': form},
                                  context_instance=RequestContext(request))

    #This is a POST request, meaning a login attempt.
    if request.method == 'POST':
        form = forms.LoginForm(request.POST)
        if not form.is_valid(
        ):  #If the form isn't valid, render the login form again
            logger.debug('Login form invalid from %s', client_ip)
            return render_to_response('auth/login.html', {'form': form},
                                      context_instance=RequestContext(request))

        username = request.POST['username']
        password = request.POST['password']
        redirect_url = request.POST['next']
        user = auth.authenticate(username=username,
                                 password=password)  #attempt to auth the user
        logger.info('Login attempt for %s from %s.', username, client_ip)
        if user is not None and user.is_active:  # Correct password, and the user is marked "active"
            auth.login(request, user)  # Log in the user
            logger.info('Login successful for %s from %s. Redirecting to %s',
                        username, client_ip, redirect_url)
            return HttpResponseRedirect(
                redirect_url)  #Success, redirect to the 'next' page
        logger.info('Login failed for %s from %s', username, client_ip)
        form._errors['username'] = ErrorList(['Login Failed'])
        return render_to_response('auth/login.html', {'form': form},
                                  context_instance=RequestContext(request))
    #Shouldn't get here, but just in case render the default login page
    logger.warning(
        'Rendering a page that logically shouldn\'t be rendered. Request came from %s.',
        client_ip)
    return render_to_response('auth/login.html', {'form': forms.LoginForm},
                              context_instance=RequestContext(request))
示例#7
0
def api_10_push_outgoing_message(request):
    logger = logging.getLogger('rid_agent.views.api_10_push_outgoing_message')
    client_ip = handlers.GetRemoteIp(request)

    if len(request.POST) == 0:
        values_dict = {
            'type': 'error',
            'message': 'There was not any POST data.'
        }
        return handlers.get_api_10_response(values_dict)

    xml_string = request.POST

    parsed, xml_doc = handlers.StringToXml(xml_string)
    if not parsed:
        values_dict = {
            'type': 'error',
            'message': 'The XML was not valid: %s' % xml_doc
        }
        return handlers.get_api_10_response(values_dict)

    dest_ip = xml_doc.attrib['destination']
    incoming_message_id = None
    if 'incoming_message_id' in xml_doc.attrib:
        incoming_message_id = xml_doc.attrib['incoming_message_id']
    rid_xml_doc = xml_doc.find(
        '{urn:ietf:params:xml:ns:iodef-rid-2.0}:RIDPolicy')

    valid, message = handlers.IsValidRid(rid_xml_doc)
    if not valid:
        values_dict = {
            'type': 'error',
            'message': 'RID Message was not valid: %s' % message
        }
        return handlers.get_api_10_response(values_dict)

    rid_xml_string = etree.tostring(rid_xml_doc)
    handlers.SaveOutgoingMessage(dest_ip, incoming_message_id, rid_xml_string)

    values_dict = {
        'type': 'success',
        'message': 'The message was saved successfully.',
        'content': rid_xml_string
    }

    return handlers.get_api_10_response(values_dict)
示例#8
0
def tools_build_incoming_api_query(request):
    logger = logging.getLogger(
        'rid_agent.views.tools_build_incoming_api_query')
    client_ip = handlers.GetRemoteIp(request)

    #Default case for vars
    query_string = ''
    form = forms.PullIncomingMessageForm

    if len(request.GET) > 0:  #There are any supplied get params
        form = forms.PullIncomingMessageForm(request.GET)
        if form.is_valid():
            for k, v in form.cleaned_data.items():
                query_string += '&%s=%s' % (k, v)
    if len(query_string) > 0:
        query_string = '?' + query_string[1:]

    return render_to_response('tools/build_incoming_api_query.html', {
        'form': form,
        'title': 'Incoming Message Query Builder',
        'query_string': query_string,
        'url': '/api/1.0/pull_incoming_messages/'
    },
                              context_instance=RequestContext(request))
示例#9
0
def api_10_pull_incoming_messages(request):
    logger = logging.getLogger('rid_agent.views.api_10_pull_incoming_messages')
    client_ip = handlers.GetRemoteIp(request)
    logger.info('User %s from %s. Entering API pull incoming messages',
                request.user.username, client_ip)
    allowed_get_params = frozenset([
        'id', 'source_ip', 'message_type', 'created', 'created__gt', 'xml',
        'response_id', 'limit'
    ])

    if len(request.GET) == 0:  #No get parameters were supplied
        values_dict = {
            'type': 'error',
            'message': 'There were not any query parameters'
        }
        logger.info('User %s from %s. No GET parameters were supplied',
                    request.user.username, client_ip)
        return handlers.get_api_10_response(values_dict)

    form = forms.PullIncomingMessageForm(request.GET)
    if not form.is_valid():  #Error
        errors = '<error_list>'
        for field in form:
            if field.errors:
                errors += '<error>'
                errors += str(field.name) + ': ' + str(field.errors[0])
                errors += '</error>'
        errors += '</error_list>'
        values_dict = {
            'type': 'error',
            'message': 'There was an error processing the query parameters',
            'content': errors
        }
        logger.info('User %s from %s. Get parameters not valid. %s',
                    request.user.username, client_ip, errors)
        return handlers.get_api_10_response(values_dict)

    form_dict = form.cleaned_data

    #Everything looks good (I think)
    #Do the query!

    if len(form_dict) == 0:
        values_dict = {
            'type': 'error',
            'message': 'There were not any query parameters'
        }
        logger.info('User %s from %s. There were not any query parameters',
                    request.user.username, client_ip)
        return handlers.get_api_10_response(values_dict)

    limit = None
    if 'limit' in form_dict:
        limit = form_dict['limit']
        del form_dict['limit']

    if limit is not None:
        messages = incoming_message.objects.order_by('created').filter(
            **form_dict)[:limit]
    else:
        messages = incoming_message.objects.order_by('created').filter(
            **form_dict)

    values_dict = {
        'type': 'success',
        'message': 'The query was successful',
        'content': handlers.IncomingMessagesToXml(messages)
    }

    logger.info('User %s from %s. Query resulted in %s results',
                request.user.username, client_ip, len(messages))
    return handlers.get_api_10_response(values_dict)
示例#10
0
def api_10_login(request):
    #At some point 'Authorization' gets
    #re-written to 'HTTP_AUTHORIZATION'
    AUTH_HEADER = 'HTTP_AUTHORIZATION'
    logger = logging.getLogger('rid_agent.views.api_10_login')

    client_ip = handlers.GetRemoteIp(request)
    logger.info('API 1.0 login request from %s.', client_ip)

    if request.user.is_authenticated():  #User already logged in
        values_dict = {
            'type': 'success',
            'message': 'Already logged in!',
        }
        logger.info('User %s from %s was already logged in.',
                    request.user.username, client_ip)
        return handlers.get_api_10_response(values_dict)

    if AUTH_HEADER not in request.META:  #User is not logged in, no credentials to verify
        values_dict = {
            'type': 'error',
            'message':
            'No authentication parameters provided in the %s header.' %
            AUTH_HEADER,
            'status_code': '401'
        }
        logger.info(
            'Request from %s. No authentication parameters provided in the %s header.',
            AUTH_HEADER, client_ip)
        logger.debug('Request from %s header list.', client_ip)
        for header in request.META:
            logger.debug('\t%s=%s', header, request.META[header])
        logger.debug('Request from %s. End header list.', client_ip)
        resp = handlers.get_api_10_response(values_dict)
        resp['WWW-Authenticate'] = 'Basic realm="Please provide credentials"'
        return resp

    auth_info = request.META[AUTH_HEADER].split()
    if len(auth_info) != 2:  #User is not logged in, no credentials to verify
        values_dict = {
            'type': 'error',
            'message': 'There was an error with the authentication parameters'
        }
        logger.info(
            'Request from %s. There was an error with the %s header. Header value: %s',
            client_ip, AUTH_HEADER, request.META[AUTH_HEADER])
        return handlers.get_api_10_response(values_dict)

    if auth_info[0].lower(
    ) != 'basic':  #User is not logged in, no credentials to verify
        values_dict = {
            'type':
            'error',
            'message':
            'HTTP Auth Type was not basic. Only basic auth is currently supported'
        }
        logger.info(
            'Request from %s. HTTP Auth Type was not basic. Auth type was %s. Only basic auth is currently supported',
            client_ip, auth[0])
        return handlers.get_api_10_response(values_dict)
    #Attempt to log them in
    uname, passwd = base64.b64decode(auth_info[1]).split(':')
    logger.info('Request from %s. Attempting login as %s.', client_ip, uname)
    user = auth.authenticate(username=uname, password=passwd)

    if user is None:  #User could not log in
        values_dict = {
            'type': 'error',
            'message': 'The supplied credentials were invalid'
        }
        logger.info('Request from %s for user %s. User was None', client_ip,
                    uname)
        return handlers.get_api_10_response(values_dict)

    if not user.is_active:  #User is not active
        values_dict = {'type': 'error', 'message': 'The user is not active.'}
        logger.info('Request from %s for user %s. User is not active.',
                    client_ip, uname)
        return handlers.get_api_10_response(values_dict)

    auth.login(request, user)  # Log in the user

    #Authentication was successful!
    values_dict = {'type': 'success', 'message': 'Login successful!'}
    logger.info('User %s from %s. Login successful.', uname, client_ip)
    return handlers.get_api_10_response(values_dict)
示例#11
0
def tools_index(request):
    logger = logging.getLogger('rid_agent.views.tools.index')
    client_ip = handlers.GetRemoteIp(request)
    logger.debug('Entering tools/index; request from %s', client_ip)
    return render_to_response('tools/index.html',
                              context_instance=RequestContext(request))
示例#12
0
def rid(request):
    client_ip = handlers.GetRemoteIp(request)
    logger = logging.getLogger('rid_agent.views.rid')
    logger.debug('Entering views.rid, request from %s; User not auth yet.',
                 client_ip)

    #At this point, Apache should have authenticated the user using the SSLVerifyClient directive.
    #Now the app needs to read the client DN and use that to perform application authorization.
    if 'SSL_CLIENT_S_DN' not in request.META:
        logger.warn(
            'Client Subject DN is not in the HTTP Headers; Returning Http 500 error'
        )
        logger.info(
            'Did you remember to add \'SSLOptions StdEnvVars\' to your SSL configuration file?'
        )
        return HttpResponse(
            status=500
        )  #500 - Internal Server Error; The Client DN. This is more than likely a server error

    if 'SSL_CLIENT_S_DN_CN' not in request.META:
        logger.warn(
            'Client Subject CN is not in the HTTP Headers; Returning Http 500 error'
        )
        logger.info(
            'Did you remember to add \'SSLOptions StdEnvVars\' to your SSL configuration file?'
        )
        return HttpResponse(
            status=500
        )  #500 - Internal server error; The Client CN. This is more than likely a server error

    #The "username" is the CN of the SSL cert plus an underscore plus the MD5 of the
    #DN. The "Password" is always 'Password123'. This method will create the user and
    #Set the appropriate role if the user does not already exist
    client_dn = request.META['SSL_CLIENT_S_DN']
    logger.debug('Got a DN of %s from %s', client_dn, client_ip)
    client_cn = request.META['SSL_CLIENT_S_DN_CN']
    logger.debug('Got a CN of %s from %s', client_cn, client_ip)
    username = client_cn
    username = username[:
                        30]  #TODO: This is not the best 'algorithm', and needs to be changed for a production system
    #			#The database table should be updated to allow long CNs (CNs over 30 chars), but that's
    #			#a bigger change than this
    logger.debug('Username is %s from %s', username, client_ip)
    password = '******'

    user = auth.authenticate(
        username=username,
        password=password)  #attempt to authenticate the user
    logger.info('Login attempt for %s from %s', username, client_ip)
    if user is None:  # The user doesn't exist, need to create the user and associated profile with the appropriate permissions.
        user = User.objects.create_user(username, '*****@*****.**', password)
        user.save()  #Create the user, which also creates the user profile.
        user = auth.authenticate(username=username,
                                 password=password)  #This shouldn't fail.
        if user is None or not user.is_active:  #This _really_ shouldn't fail
            logger.error(
                'The user (%s) that was just created from (%s) could not be logged in',
                username, client_ip)
            return HttpResponse(status=500)  #500 - Internal Server Error
        #Modify the profile so that the user has the appropriate role
        profile = user.get_profile()
        profile.rid_peer = True
        profile.save()
    #After this point, any non-existing users should be authenticated
    auth.login(request, user)

    #Now we can check permissions
    user_profile = request.user.get_profile()
    allowed = getattr(user_profile, 'rid_peer')
    if not allowed:
        logger.info(
            'The user %s from %s does not have the rid_peer permission; returning 403 forbidden',
            request.user.username, client_ip)
        return HttpResponse(status=403)  #403 - Forbidden
    #Uncomment to log the headers for debugging purposes.
    #This is commented out because it is verbose
    #for header in request.META:
    #	logger.debug('%s: %s', header, request.META[header])

    #These IF statements implement the logical checks for HTTP headers.
    #The order is important per the wording in RFC 6546 section 3
    #The 'Request-URI' requirement is filled by urls.py
    if request.method == 'GET' or request.method == 'HEAD':
        logger.info('%s request method was %s. Responded with 204 No Content',
                    client_ip, request.method)
        return HttpResponse(status=204)  #204 - No Content

    if request.method != 'POST':
        logger.info('%s request method was %s. Responded with 405 Not Allowed',
                    client_ip, request.method)
        return HttpResponseNotAllowed(
            ['POST'])  #405 - Not allowed, with allowed methods supplied

    if request.META['CONTENT_TYPE'] != 'text/xml':
        logger.info(
            '%s request content type was %s, not text/xml. Responded with 415 Unsupported Media Type',
            client_ip, request.META['CONTENT_TYPE'])
        return HttpResponse(status=415)  #415 - Unsupported Media Type

    #At this point, header and authentication preconditions are have been met.
    #We must now parse the POST data. It should be a valid RID/IODEF XML blob. At this layer
    #We simply check to see if it's schema-valid and push it into a message store.

    #TODO: Check encoding type
    #TODO: Use validators.RidMessageValidator, rather than this code
    xml_byte_string = request.body
    xml_string = xml_byte_string.decode("utf-8")
    #TODO: This should probably be done by the webserver
    xml_size = len(xml_string)
    if xml_size > settings.MAX_RID_MESSAGE_SIZE:
        logger.info(
            '%s request had a size of %s, larger than the mas size of %s.' +
            ' Responding with 413 Request Entity Too Large', client_ip,
            xml_size, settings.MAX_RID_MESSAGE_SIZE)
        return HttpResponse(status=413)  #413 - Request Entity Too Large

    #Determine if the XML is well formed. If not, respond w/ HTTP 400
    parsed, xml_doc = handlers.StringToXml(xml_string)
    if not parsed:
        logger.info('User %s sent XML document from %s. Parse error: %s ',
                    request.user.username, client_ip, xml_doc)
        return SimpleTemplateResponse('core/message.html', {
            'title': 'XML Parse Error',
            'message': str(xml_doc)
        },
                                      status=400)  #400 - Bad Request

    #Determine whether or not the XML is schema valid.
    #If it's not, responde with an HTTP 400.
    schema_valid, message = handlers.IsValidRid(xml_doc)
    if not schema_valid:
        logger.info(
            'User %s sent XML document from %s. Schema validation error: %s ',
            request.user.username, client_ip, xml_doc)
        return SimpleTemplateResponse('core/message.html', {
            'title': 'XML Parse or Schema Validation Error',
            'message': str(message)
        },
                                      status=400)  #400 - Bad Request

    #At this point, the XML document is well formed and is schema valid
    logger.debug('User %s sent valid XML document from %s',
                 request.user.username, client_ip)
    type = handlers.GetRidMessageType(xml_doc)

    #Do some checking on the RID message type.
    if type not in rid_message_types:
        logger.info(
            '%s RID Message type was %s. Responding with HTTP 400 Bad Request',
            client_ip, type)
        return HttpResponse("The supplied RID type was not valid",
                            status=400)  #400 - Bad Request

    if type not in supported_rid_message_types:
        logger.info(
            '%s RID Message type was %s. Responding with HTTP 501 Not Implemented',
            client_ip, type)
        return HttpResponse(
            "The supplied RID type is not currently supported.",
            status=501)  #501 - Not Implemented

    #Save the message and return HTTP 202
    logger.info('%s RID message, attempting to save', client_ip)
    success, return_code = handlers.SaveIncomingMessage(
        client_ip, type, xml_string)
    logger.info('%s RID message save status=%s; Return code (ID?) %s',
                client_ip, success, return_code)

    if type == 'Query':
        return HttpResponse(status=202)
    return HttpResponse(status=200)