Esempio n. 1
0
def set_password():
    """Set initial customer password. The template for this route contains
    bootstrap.css, bootstrap-theme.css and main.css.

    This is similar to the password reset option with two exceptions:
    it has a longer expiration time and does not require old password.

    :param token: Token generated by
        :meth:`app.models.User.generate_reset_token`

    :return:
    """
    token = request.json['token']
    password = request.json['password']

    s = TimedJSONWebSignatureSerializer(current_app.config['SECRET_KEY'])
    try:
        s.loads(token)
    except BadSignature:
        raise ApiException('Invalid Token', 401)
    try:
        User.set_password(token, password)
    except AttributeError as e:
        raise ApiException(str(e), 401)
    return ApiResponse({'auth': 'authenticated'})
Esempio n. 2
0
def query():
    """

    :status 501: NotImplemented
    :return:
    """
    raise ApiException('Not Implemented', status=501)
Esempio n. 3
0
def subscribe_list(list_id):
    """Subscribe email(s) to distribution list

    **Example request**:

    .. sourcecode:: http

        PUT /api/1.0/lists/certs.lists.cert.europa.eu/subscribe HTTP/1.1
        Host: do.cert.europa.eu
        Accept: application/json
        Content-Type: application/json

        {
          "emails": [
            "*****@*****.**",
            "*****@*****.**"
          ]
        }

    **Example response**:

    .. sourcecode:: http

        HTTP/1.0 200 OK
        Content-Type: application/json

        {
          "message": "List saved"
        }

    :param list_id: Distribution list ID

    :reqheader Accept: Content type(s) accepted by the client
    :resheader Content-Type: this depends on `Accept` header or request

    :<json array emails: E-mails for mass-subscription
    :>json string message: Status message

    :status 200: Group was deleted
    :status 400: Bad request
    """
    l = MailmanList.get(fqdn_listname=list_id)
    try:
        data = [request.json['email']]
    except (KeyError, TypeError) as ke:
        current_app.log.info(ke)
        data = request.json['emails']
    for email in data:
        try:
            l.subscribe(address=email.lower(),
                        pre_verified=True,
                        pre_confirmed=True)
            fetch_gpg_key(email.lower(),
                          current_app.config['GPG_KEYSERVERS'][0])
        except HTTPError as he:
            raise ApiException(email.lower() + ': ' + he.msg.decode(), he.code)
    return ApiResponse({'message': 'List saved'})
Esempio n. 4
0
def submit_gpg_key():
    """Submit GPG key to CERT-EU keyserver
    Keys are send to the first server from the GPG_KEYSERVERS configuration
    option

    **Example request**:

    .. sourcecode:: http

        POST /submit-key HTTP/1.1
        Host: do.cert.europa.eu
        Accept: application/json
        Content-Type: application/json

        {
          "ascii_key": "-----BEGIN PGP PUBLIC KEY BLOCK-----nmQENBFHn
          ...-----END PGP PUBLIC KEY BLOCK-----"

        }

    **Example response**:

    .. sourcecode:: http

        HTTP/1.0 201 CREATED
        Content-Type: application/json

        {
          "fingerprints": [
            "2D39D3A9ACCD18B1D7774A00A485C88DDA2AA2BF"
          ],
          "message": "Key saved"
        }

    :reqheader Accept: Content type(s) accepted by the client
    :resheader Content-Type: this depends on `Accept` header or request

    :<json string ascii_key: ASCII armored GPG public key
    :>json array fingerprints: List of fingerprints
    :>json string message: Status message

    :statuscode 201: GPG key successfully saved
    :statuscode 400: Bad request
    """
    result = gpg.gnupg.import_keys(request.json['ascii_key'])
    if result.fingerprints:
        send_to_ks.delay(
            current_app.config['GPG_KEYSERVERS'][0], result.fingerprints
        )
        return ApiResponse({
            'message': 'Key saved',
            'fingerprints': [f for f in result.fingerprints]},
            201)
    else:
        raise ApiException('The PGP Key could not be imported')
Esempio n. 5
0
def toggle_2fa():
    """Toggle Two-Factor authentication

    **Example request**:

    .. sourcecode:: http

        POST /auth/toggle-2fa HTTP/1.1
        Host: do.cert.europa.eu
        Content-Type: application/json

        {
          "otp_toggle": true,
          "totp": 453007
        }

    **Example success response**:

    .. sourcecode:: http

        HTTP/1.0 200 OK
        Content-Type: application/json
        Content-Length: 31

        {
          "message": "Your options have been saved"
        }

    :reqheader Accept: Content type(s) accepted by the client
    :resheader Content-Type: this depends on `Accept` header or request

    :<json boolean otp_toggle: Enable or disable second authentication factor
    :<json integer totp: 6 digit TOTP
    :>json string message: Action status

    :statuscode 200: Password successfully changed
    """
    otp_toggle = request.json.get('otp_toggle', False)
    totp = request.json.pop('totp', False)
    user = User.query.filter_by(id=current_user.id).first_or_404()
    if not otp_toggle:
        user.otp_enabled = False
        db.session.add(user)
        db.session.commit()
        return ApiResponse({'message': 'Your options have been saved'})
    if otp_toggle and user.verify_totp(totp):
        user.otp_enabled = True
    else:
        raise ApiException('Authentication code verification failed')
    db.session.add(user)
    db.session.commit()
    return ApiResponse({'message': 'Your options have been saved'})
Esempio n. 6
0
def get_fireeye_report(sha256, envid, type):
    raise ApiException({}, 501)
    # XML, HTML, BIN and PCAP are GZipped
    Sample.query.filter_by(sha256=sha256).first_or_404()
    headers = {
        'Accept': 'text/html',
        'User-Agent': 'FireEye Sandbox API Client'
    }
    params = {'type': type, 'environmentId': envid}
    vx = fireeye.api.get('result/{}'.format(sha256),
                         params=params,
                         headers=headers)
    if type in ['xml', 'html', 'bin', 'pcap']:
        return gzip.decompress(vx)
    return vx
Esempio n. 7
0
def get_fireeye_download(sha256, eid, ftype):
    raise ApiException({}, 501)
    Sample.query.filter_by(sha256=sha256).first_or_404()
    headers = {
        'Accept': 'text/html',
        'User-Agent': 'FireEye Sandbox API Client'
    }
    params = {'type': ftype, 'environmentId': eid}
    vx = fireeye.api.get('result/{}'.format(sha256),
                         params=params,
                         headers=headers)
    if ftype in ['xml', 'html', 'bin', 'pcap']:
        ftype += '.gz'
    return send_file(BytesIO(vx),
                     attachment_filename='{}.{}'.format(sha256, ftype),
                     as_attachment=True)
Esempio n. 8
0
def do_ldap_authentication(username, password):
    """Authenticate users with CERT-EU LDAP server

    :param username: CERT-EU email or username
    :param password: Account password
    """
    if '@' in username:
        ldap_user = username.split('@')[0]
    else:
        ldap_user = username
    ldap_info, ldap_authenticated = _ldap_authenticate(ldap_user, password)
    if ldap_authenticated:
        u = User.query.filter_by(
            email=ldap_info['userPrincipalName'][0]).first()
        if not u:
            _save_ldap_user(ldap_info)
            u = User.query.filter_by(
                email=ldap_info['userPrincipalName'][0]).first()
        if login_user(u, remember=True):
            return ApiResponse({'auth': 'authenticated'}, 200)

    raise ApiException('Invalid username or password', 401)
Esempio n. 9
0
def get_fireeye_download(sha256, eid, ftype):
    raise ApiException({}, 501)
Esempio n. 10
0
def get_fireeye_report(sha256, envid, type):
    raise ApiException({}, 501)
Esempio n. 11
0
def get_fireeye_analyses():
    raise ApiException({}, 501)
Esempio n. 12
0
def add_fireeye_url_analysis():
    """Submit URLs to the FireEye Sandbox. Also accepts :http:method:`put`.

    .. warning::

        Not Implemented

    **Example request**:

    .. sourcecode:: http

        POST /api/1.0/analysis/fireeye-url HTTP/1.1
        Host: do.cert.europa.eu
        Accept: application/json
        Content-Type: application/json

        {
          "urls": ["http://cert.europa.eu"],
          "dyn_analysis": {
            "fireeye": [5, 6]
          }
        }

    **Example response**:

    .. sourcecode:: http

        HTTP/1.0 200 OK
        Content-Type: application/json

        {
          "message": "Your URLs have been submitted for dynamic analysis",
          "statuses": [
            {
              "sha256": "33a53e3b28ee41c29afe79f49ecc53b34ac125e5e15f9e7c..."
            }
          ]
        }

    :reqheader Accept: Content type(s) accepted by the client
    :resheader Content-Type: this depends on `Accept` header or request

    :<json array files: List of URLs to scan
    :<jsonarr string sha256: SHA256 of the shortcut file created
    :<json object dyn_analysis: Sandbox configuration
    :<jsonarr array fireeye: List of FireEye environments to submit to
        Get the list from :http:get:`/api/1.0/analysis/fireeye/environments`
    :>json array statuses: List of statuses returned by upstream APIs
    :>jsonarr string error: Error message from upstream API
    :>jsonarr string sha256: SHA256 calculated by upstream API
    :>json string message: Status message

    :status 202: The URLs have been accepted for scanning
    :status 400: Bad request
    """
    raise ApiException({}, 501)
    statuses = []
    samples = {}
    for env in request.json['dyn_analysis']['fireeye']:
        for url in request.json['urls']:
            sdata = {'environmentId': env, 'analyzeurl': url}
            headers = {
                'User-Agent': 'FireEye Sandbox API Client',
                'Accept': 'application/json'
            }
            resp = fireeye.submiturl(sdata, headers=headers)

            samples[resp['response']['sha256']] = url
            statuses.append(resp['response'])
            if resp['response_code'] != 0:
                current_app.log.debug(resp)

    for sha256, url in samples.items():
        surl = Sample(filename=url,
                      sha256=sha256,
                      user_id=g.user.id,
                      md5='N/A',
                      sha1='N/A',
                      sha512='N/A',
                      ctph='N/A')
        db.session.add(surl)
    db.session.commit()
    return {
        'statuses': statuses,
        'message': 'Your URLs have been submitted for dynamic analysis'
    }, 202
Esempio n. 13
0
def get_fireeye_analyses():
    """Return a paginated list of FireEye Sandbox JSON reports.

    .. warning::

        Not Implemented

    **Example request**:

    .. sourcecode:: http

        GET /api/1.0/analysis/fireeye?page=1 HTTP/1.1
        Host: do.cert.europa.eu
        Accept: application/json

    **Example response**:

    .. sourcecode:: http

        HTTP/1.0 200 OK
        Content-Type: application/json
        DO-Page-Next: null
        DO-Page-Prev: null
        DO-Page-Current: 1
        DO-Page-Item-Count: 1

        {
          "count": 3,
          "items": [
            {
              "created": "2016-03-21T16:52:52",
              "id": 4,
              "report": "...",
              "type": "Dynamic analysis"
            },
            {
              "created": "2016-03-21T16:51:49",
              "id": 3,
              "report": "...",
              "type": "Dynamic analysis"
            },
            {
              "created": "2016-03-20T17:09:03",
              "id": 2,
              "report": "...",
              "type": "Dynamic analysis"
            }
          ],
          "next": null,
          "page": 1,
          "prev": null
        }

    :reqheader Accept: Content type(s) accepted by the client
    :resheader Content-Type: this depends on `Accept` header or request
    :resheader DO-Page-Next: Next page URL
    :resheader DO-Page-Prev: Previous page URL
    :resheader DO-Page-Curent: Current page number
    :resheader DO-Page-Item-Count: Total number of items

    :>json array items: FireEye reports
    :>jsonarr integer id: AV scan unique ID
    :>jsonarr string name: File name
    :>jsonarr string sha256: SHA256 message-digest of file
    :>json integer page: Current page number
    :>json integer prev: Previous page number
    :>json integer next: Next page number
    :>json integer count: Total number of items

    :status 200: Reports found
    :status 404: Resource not found
    """
    raise ApiException({}, 501)
Esempio n. 14
0
def login():
    """Authenticate users

    To authenticate make a JSON POST request with credentials.
    On success the API will return a ``rm`` cookie valid for 48 hours.
    Use the value of the ``rm`` cookie for all subsequent requests.
    The ``CP-TOTP-Required`` header notifies clients that they need to submit
    their 2FA token. Token will be check at :http:post:`/auth/verify-totp`

    .. note::

        2FA is used for CP requests only

    **Example request**:

    .. sourcecode:: http

        POST /auth/login HTTP/1.1
        Host: do.cert.europa.eu
        Accept: application/json
        Content-Type: application/json

        {
          "email": "*****@*****.**",
          "password":"******"
        }

    **Example response**:

    .. sourcecode:: http

        HTTP/1.0 200 OK
        Content-Type: application/json
        Set-Cookie: rm=.eGwfP...; Expires=Sun, 29-Nov-2015 09:11:45 GMT; Path=/
        Set-Cookie: session=.eJwlzrs...; Secure; HttpOnly; Path=/

        {
          "auth": "authenticated"
        }

    :reqheader Accept: Content type(s) accepted by the client
    :resheader Content-Type: this depends on `Accept` header or request
    :resheader Set-Cookie: Pass the `rm` cookie to future requests
    :resheader CP-TOTP-Required: When true client must submit TOTP at
      :http:post:`/auth/verify-totp`

    :<json string email: Email or username
    :<json string password: Password
    :>json string auth: Authentication status

    :statuscode 200: Login successful
    :statuscode 401: Invalid credentials
    """
    if current_user.is_authenticated:
        return ApiResponse({'auth': 'authenticated'})

    email = request.json.get('email') or request.json.get('username')
    password = request.json.get('password')

    if email and password:
        cp_host = request.environ.get('HTTP_HOST', None)
        if cp_host.startswith('cp.'):
            user, authenticated = User.authenticate(email, password)
            if user and authenticated:
                if user.otp_enabled:
                    session['cu'] = email
                    session['cpasswd'] = password
                    return ApiResponse({'auth': 'pre-authenticated'}, 200,
                                       {'CP-TOTP-Required': user.otp_enabled})
                else:
                    if login_user(user, remember=True):
                        return ApiResponse({'auth': 'authenticated'})

            raise ApiException('Invalid username or password', 401)

        if current_app.config['LDAP_AUTH_ENABLED']:
            return do_ldap_authentication(email, password)

        user, authenticated = User.authenticate(email, password)
        if user and authenticated:
            if login_user(user, remember=True):
                return ApiResponse({'auth': 'authenticated'})

    raise ApiException('Invalid username or password', 401)
Esempio n. 15
0
def post_message():
    """Send email to mailing list. If ``encrypted`` is set to ``True``
    the message body and all attachments will be encrypted with the public
    keys of all list members

    .. todo::

        Add icons:
        https://twitter.com/JZdziarski/status/753223642297892864

    Files in response.json.files are assumed uploaded via
    :http:post:`/api/1.0/upload`

    **Example request**:

    .. sourcecode:: http

        POST /api/1.0/lists/post HTTP/1.1
        Host: do.cert.europa.eu
        Accept: application/json

        {
          "files": [
            "targets.txt"
          ],
          "list_id": "certs.lists.cert.europa.eu",
          "subject": "zZz",
          "encrypt": false,
          "content": "ž"
        }

    **Example response**:

    .. sourcecode:: http

        HTTP/1.0 200 OK
        Content-Type: application/json

        {
          "message": "Email has been sent."
        }

    .. warning:: There is no error checking

    :reqheader Accept: Content type(s) accepted by the client
    :resheader Content-Type: this depends on `Accept` header or request

    :<json string list_id: Distribution list ID
    :<json string subject: E-mail subject
    :<json string content: E-mail content
    :<json array files: Files to attach
    :>json string message: Status message

    :status 200: Email successfully sent
    :status 400: Bad request
    :status 500: Error processing the request
    """
    msg = request.json
    files = msg.get('files', None)
    encrypted = msg.get('encrypted', None)
    list_ = MailmanList.get(fqdn_listname=msg['list_id'])
    if encrypted:
        enc = _encrypt(BytesIO(msg['content'].encode('utf-8')),
                       list_=list_,
                       always_trust=True)
        if not enc.ok:
            raise ApiException('Could not encrypt message content. '
                               'Please make sure you have all the keys.')
        content = enc.data.decode()
        attachedfiles = []
        if files:
            for file in files:
                file_path = os.path.join(current_app.config['APP_UPLOADS'],
                                         file)
                with open(file_path, 'rb') as fb:
                    outfile = file_path + '.asc'
                    cipherfile = _encrypt(fb,
                                          list_,
                                          output=outfile,
                                          always_trust=True)
                    if cipherfile.ok:
                        attachedfiles.append(file + '.asc')
    else:
        content = msg['content']
        attachedfiles = files
    send_email('*****@*****.**', [list_.fqdn_listname],
               msg['subject'],
               content,
               attach=attachedfiles)
    return ApiResponse({'message': 'Email has been sent.'})
Esempio n. 16
0
def search_public_ks(email=None):
    """Search GPG keys on public keyserver pool.
    The keysever pool is the second server from the GPG_KEYSERVERS
    configuration option.

    **Example request**:

    .. sourcecode:: http

        POST /api/1.0/search-keys HTTP/1.1
        Host: do.cert.europa.eu
        Accept: application/json
        Content-Type: application/json

        {
          "email": "*****@*****.**"
        }

    **Example response**:

    .. sourcecode:: http

        HTTP/1.0 200 OK
        Content-Type: application/json

        {
          "keys": [
            {
              "algo": "1",
              "date": "1379079830",
              "expires": "1479375689",
              "keyid": "8CC4185CF057F6F8690309DD28432835514AA0F6",
              "length": "4096",
              "type": "pub",
              "uids": [
                "Alexandru Ciobanu <*****@*****.**>"
              ]
            }
          ]
        }

    :reqheader Accept: Content type(s) accepted by the client
    :resheader Content-Type: this depends on `Accept` header or request

    :<json string email: E-mail address
    :>json array keys: List of found keys
    :>jsonarr string algo: `Key algorithm
      <https://tools.ietf.org/html/rfc4880#section-9.1>`_
    :>jsonarr string date: Creation date
    :>jsonarr string expires: Expiration date
    :>jsonarr string keyid: KeyID date
    :>jsonarr string length: Key size
    :>jsonarr string type: Key type. Only public keys are returned
    :>jsonarr array uids: Key type. Only public keys are returned


    :statuscode 200: GPG keys found
    :statuscode 404: No keys found for given email address

    :param email:
    """
    if email is None:
        email = request.json['email']
    keys = gpg.gnupg.search_keys(
        email, current_app.config['GPG_KEYSERVERS'][1])
    if not keys:
        raise ApiException('No keys found', 404)
    return ApiResponse({'keys': keys})
Esempio n. 17
0
def check_gpg(list_id):
    """Try to encrypt a message to all members of `list_id`.

    .. note:: The GPG client only returns errors about the last recipient

    :param list_id: List FQDN name. E.g. ``certs.lists.cert.europa.eu``

    **Example request**:

    .. sourcecode:: http

        GET /api/1.0/lists/certs.lists.cert.euroap.eu/check_gpg HTTP/1.1
        Host: do.cert.europa.eu
        Accept: application/json

    **Example response**:

    .. sourcecode:: http

        HTTP/1.0 200 OK
        Content-Type: application/json

        {
          "message": "Sample data successfuly encrypted for this list"
        }

    **Example errpr response**:

    .. sourcecode:: http

        HTTP/1.0 400 BAD REQUEST
        Content-Type: application/json

        {
          "message": "Your message can not be encrypted for all the members of
                this list",
          "stderr": "gpg: [email protected]: skipped: No public key
                    [GNUPG:] INV_RECP 1 [email protected]
                    gpg: [stdin]: encryption failed: No public key"
        }

    .. note:: stderr contains information only about the last recipient

    :reqheader Accept: Content type(s) accepted by the client
    :resheader Content-Type: this depends on `Accept` header or request

    :>json string message: Status message
    :>json string stderr: STDERR

    :status 200: Email successfully sent
    :status 400: An error has occured while trying to encrypt

    """
    l = MailmanList.get(fqdn_listname=list_id)
    emails = [m.email for m in l.members]
    if not emails:
        raise ApiException('This list has no members.')
    enc = gpg.gnupg.encrypt('test', emails, always_trust=True)
    if enc.ok:
        return ApiResponse({'message': 'Test successful.'})

    raise ApiException('Your message can not be encrypted for all '
                       'the members of this list ' + enc.stderr)
Esempio n. 18
0
def change_password():
    """Change password

    **Example request**:

    .. sourcecode:: http

        POST /auth/change-password HTTP/1.1
        Host: do.cert.europa.eu
        Content-Type: application/json

        {
          "current_password": "******",
          "new_password": "******",
          "confirm_password": "******"
        }

    **Example success response**:

    .. sourcecode:: http

        HTTP/1.0 200 OK
        Content-Type: application/json
        Content-Length: 31

        {
          "message": "Password updated"
        }

    **Example error response**:

    .. sourcecode:: http

        HTTP/1.0 422 UNPROCESSABLE ENTITY
        Content-Type: application/json
        Content-Length: 87

        {
          "message": "'current_password' is a required property",
          "validator": "required"
        }

    :reqheader Accept: Content type(s) accepted by the client
    :resheader Content-Type: this depends on `Accept` header or request

    :<json string current_password: Current password
    :<json string new_password: New password
    :<json string confirm_password: Password confirmation
    :>json string message: Action status

    :statuscode 200: Password successfully changed
    :statuscode 422: Unprocessable Entity.
    """
    if not current_user.check_password(request.json.get('current_password')):
        raise ApiException('Invalid current password')
    # it makes no sense to check the current password
    # if not current_user.check_password(request.json.get('current_password')):
    #    return {'message': 'Invalid current password'}, 400
    new_pass = request.json.get('new_password', None)
    confirm_pass = request.json.get('confirm_password', None)
    if new_pass != confirm_pass:
        raise ApiException('Confirmation password does not match')
    try:
        current_user.password = request.json.get('new_password')
        db.session.add(current_user)
        db.session.commit()
        return ApiResponse({'message': 'Your password has been updated'})
    except AssertionError as ae:
        raise ApiException(ae)
Esempio n. 19
0
def get_fireeye_analysis(sha256, envid):
    raise ApiException({}, 501)
Esempio n. 20
0
def get_fireeye_analysis(sha256, envid):
    """Return FireEye Sandbox dynamic analysis for sample identified by
        :attr:`~app.models.Sample.sha256`, running in :param: envid.

    ..  note::

        FireEye Sandbox REST API returns mixed responses.
        Most errors will return :http:statuscode:`200`.

    **Example request**:

    .. sourcecode:: http

        GET api/1.0/analysis/fireeye/54abd4674f61029d9ae3f8f805b9b7/1 HTTP/1.1
        Host: do.cert.europa.eu
        Accept: application/json

    **Example success response**:

    .. sourcecode:: http

        HTTP/1.0 200 OK
        Content-Type: application/json

        {
          "response": {
            "analysis_start_time": "2016-04-28 17:03:52",
            "domains": [],
            "environmentDescription": "Windows 7 64 bit (KERNELMODE)",
            "environmentId": "6",
            "hosts": [
              "40.118.103.7"
            ],
            "isinteresting": false,
            "isurlanalysis": false,
            "md5": "864cc77a27d4618149ec0bba060bbca0",
            "multiscan_detectrate_pcnt": 0,
            "sha1": "31fced6d00e58147bff56902b986fd0cc6295aeb",
            "sha256": "54abd4674f61029d9ae3f8f8f5a484d396d10b87c9dc77765d87c2",
            "size": 336384,
            "submitname": "54abd4674f61029d9ae3f8f8f5a484d396d10b87c9dc777657",
            "targeturl": "",
            "threatlevel": 1,
            "threatscore": 41,
            "type": "PE32 executable (GUI) Intel 80386 Mono/.Net assembly"
          },
          "response_code": 0
        }

    **Example error response**:

    .. sourcecode:: http

        HTTP/1.0 200 OK
        Content-Type: application/json

        {
          "response": {
            "error": "Failed to save report to webservice",
            "state": "ERROR"
          },
          "response_code": 0
        }

    :param sha256: SHA256 of file
    :param envid: Environment ID. For the list of available environments see:
        :http:get:`/api/1.0/analysis/fireeye/environments`.

    :reqheader Accept: Content type(s) accepted by the client
    :resheader Content-Type: this depends on `Accept` header or request

    :>json integer response_code: Response code.
      ``0`` for success, ``-1`` for errors
    :>json object response: Analysis summary or error details
    :>jsonobj string analysis_start_time: Analysis start time
    :>jsonobj array domains: Domains contacted during analysis
    :>jsonobj string environmentDescription: Environment details
    :>jsonobj string environmentId: Environment unique ID
    :>jsonobj array hosts: Hosts contacted during analysis
    :>jsonobj boolean isinteresting:
    :>jsonobj boolean isurlanalysis: Marker for URL analyzer
    :>jsonobj integer multiscan_detectrate_pcnt:
    :>jsonobj string md5: MD5 digest calculated upstream
    :>jsonobj string sha1: SHA1 digest calculated upstream
    :>jsonobj string sha256: SHA256 digest calculated upstream
    :>jsonobj integer size: Size of sample in bytes
    :>jsonobj string submitname: Submission file name
    :>jsonobj string targeturl:
    :>jsonobj integer threatlevel: Threatlevel
    :>jsonobj integer threatscore: Threat score
    :>jsonobj string type: Type of sample
    :>jsonobj string state: State of analysis
    :>jsonobj string error: Error message reported by upstream

    :status 200: Request successful. ``response_code`` check required to
      determine if action was successful.
    :status 404: Resource not found
    """
    raise ApiException({}, 501)
    sample = Sample.query.filter_by(sha256=sha256).first_or_404()
    state = fireeye.api.get('state/{}'.format(sha256),
                            params={'environmentId': envid})
    status = state['response_code'] == 0
    if status and state['response']['state'] == 0:
        #: FIXME: return the fireeye.api.get('result/sha256')
        #: and create a summary from that
        #: offer HTML & JSON downloads
        params = {'type': 'json', 'environmentId': envid}
        if sample.filename.startswith('http'):
            vx = {
                'response': {
                    'analysis_start_time': '1',
                    'environmentId': envid
                },
                'response_code': 0
            }
        else:
            vx = fireeye.api.get('summary/{}'.format(sha256), params=params)
        return ApiResponse(vx)
    else:
        state['response']['environmentId'] = envid
        return ApiResponse(state)
Esempio n. 21
0
def add_fireeye_url_analysis():
    raise ApiException({}, 501)
Esempio n. 22
0
def verify_totp():
    """Check the `TOTP
    <https://en.wikipedia.org/wiki/Time-based_One-time_Password_Algorithm>`_
    submitted by the client.

    **Example request**:

    .. sourcecode:: http

        POST /auth/verify-totp HTTP/1.1
        Host: do.cert.europa.eu
        Accept: application/json
        Content-Type: application/json

        {
          "totp": "123456"
        }

    **Example response**:

    .. sourcecode:: http

        HTTP/1.0 200 OK
        Content-Type: application/json
        Set-Cookie: session=40e418c37cb4cc68_5776d7a0; Secure; HttpOnly; Path=/
        Set-Cookie: rm=.eJwNzrEKAjEMANB_OW4USZqkTW_SwcnFQUQQhzZtUPQ44f4fvPVN7z
          Gsy9wPc3l_97bMw2741U_zMK2vIhgmBMAx8f10vh5vchmLdLS;
          Expires=Sun, 03-Jul-2016 20:52:58 GMT; Secure; HttpOnly; Path=/

        {
          "auth": "authenticated"
        }

    :reqheader Accept: Content type(s) accepted by the client
    :resheader Content-Type: this depends on `Accept` header or request
    :resheader Set-Cookie: Pass the `rm` cookie to future requests

    :<json integer totp: 6 digit authentication code generated by one of these
      TOTP applications: `Google Authenticator
      <https://support.google.com/accounts/answer/1066447?hl=en>`_,
      `Duo Mobile <https://guide.duo.com/third-party-accounts>`_,
      `Authenticator <https://www.microsoft.com/en-US/store/apps/
      Authenticator/9WZDNCRFJ3RJ>`_
    :>json string auth: Authentication status

    :status 200: Login successful
    :status 404: User doesn't have 2FA enabled
    :status 401: User did not provide the first authentication factor
    :status 400: Invalid TOTP
    """
    email = session.pop('cu', None)
    password = session.pop('cpasswd', None)
    user, authenticated = User.authenticate(email, password)
    if not authenticated:
        raise ApiException('Please login first', 401)

    token = request.json['totp']
    user = User.query.filter_by(id=user.id).first_or_404()
    if not user.otp_enabled:
        raise ApiException('Verification failed', 400)

    if user.verify_totp(token):
        if login_user(user, remember=True):
            return ApiResponse({'auth': 'authenticated'})

    raise ApiException('Authentication code verification failed', 400)