├── wpa-sample.pcap ├── kraken-client ├── src │ ├── utils │ │ ├── AppVersion.js │ │ ├── NotificiationService.js │ │ └── ExitHandlerService.js │ ├── assets │ │ ├── kraken-logo.png │ │ ├── screenshots │ │ │ ├── worker.png │ │ │ ├── start-worker-button.png │ │ │ ├── create-new-request-button.png │ │ │ └── create-new-request-modal.png │ │ └── icons │ │ │ └── application │ │ │ └── icon.png │ ├── index.css │ ├── components │ │ ├── SummaryTable │ │ │ ├── SummaryTable.module.css │ │ │ └── SummaryTable.js │ │ ├── SectionHeading │ │ │ ├── SectionHeading.module.css │ │ │ └── SectionHeading.js │ │ ├── Pagination │ │ │ ├── Pagination.module.css │ │ │ └── Pagination.js │ │ ├── SocialLoginWrapper │ │ │ └── SocialLoginWrapper.js │ │ ├── DetailBox │ │ │ ├── DetailBox.module.css │ │ │ └── DetailBox.js │ │ ├── Toolbar │ │ │ ├── Toolbar.module.css │ │ │ └── Toolbar.js │ │ └── StatusBox │ │ │ ├── StatusBox.module.css │ │ │ └── StatusBox.js │ ├── containers │ │ ├── Upgrade │ │ │ ├── Upgrade.module.css │ │ │ └── Upgrade.js │ │ ├── ChangePassword │ │ │ └── ChangePassword.module.css │ │ ├── Activation │ │ │ └── Activation.module.css │ │ ├── ForgotPassword │ │ │ └── ForgotPassword.module.css │ │ ├── KrakenWorker │ │ │ ├── jobcracker.browser.js │ │ │ ├── jobfetcher.js │ │ │ ├── jobreporter.js │ │ │ └── KrakenWorker.module.css │ │ ├── Register │ │ │ └── Register.module.css │ │ ├── Home │ │ │ └── Home.module.css │ │ ├── Dashboard │ │ │ └── Dashboard.module.css │ │ ├── Workers │ │ │ └── Workers.module.css │ │ ├── Login │ │ │ └── Login.module.css │ │ ├── Help │ │ │ └── Help.module.css │ │ ├── CompletedRequests │ │ │ └── CompletedRequests.module.css │ │ └── ActiveRequests │ │ │ └── ActiveRequests.module.css │ ├── App.test.js │ ├── services │ │ ├── PasswordListService.js │ │ ├── ChangeLogService.js │ │ ├── WorkerService.js │ │ ├── AxiosInstance.js │ │ ├── CompleteRequestService.js │ │ ├── ActiveRequestService.js │ │ └── AuthenticationService.js │ ├── index.js │ ├── App.js │ └── registerServiceWorker.js ├── public │ ├── robots.txt │ ├── favicon.ico │ ├── manifest.json │ ├── electron.js │ └── index.html ├── config │ ├── jest │ │ ├── cssTransform.js │ │ └── fileTransform.js │ ├── pnpTs.js │ ├── nginx.conf │ ├── modules.js │ ├── paths.js │ └── env.js ├── Dockerfile └── web-scripts │ └── test.js ├── kraken-server ├── src │ └── main │ │ ├── resources │ │ ├── executables │ │ │ ├── cap2hccapx │ │ │ └── crunch_3.6-3_amd64.deb │ │ ├── mails │ │ │ ├── assets │ │ │ │ └── kraken_logo.png │ │ │ ├── changed_password_email.html │ │ │ └── worker_offline_email.html │ │ └── liquibase │ │ │ ├── changelog-master.yaml │ │ │ └── migrations │ │ │ └── 1.1.1.yaml │ │ └── java │ │ └── com │ │ └── arcaneiceman │ │ └── kraken │ │ └── krakenserver │ │ ├── domain │ │ ├── enumerations │ │ │ ├── WorkerType.java │ │ │ ├── WorkerStatus.java │ │ │ ├── TrackingStatus.java │ │ │ └── ListType.java │ │ ├── PasswordList.java │ │ ├── BlacklistToken.java │ │ ├── TrackedPasswordList.java │ │ ├── PasswordListJobDelimiter.java │ │ ├── embeddedable │ │ │ └── CompleteTrackedList.java │ │ ├── Worker.java │ │ ├── Job.java │ │ ├── TrackedCrunchList.java │ │ ├── User.java │ │ ├── CompleteRequest.java │ │ ├── abs │ │ │ └── TrackedList.java │ │ └── ActiveRequest.java │ │ ├── repository │ │ ├── PasswordListRepository.java │ │ ├── TokenBlacklistRepository.java │ │ ├── UserRepository.java │ │ ├── PasswordListJobDelimiterRepository.java │ │ ├── CompleteRequestRepository.java │ │ ├── TrackedListRepository.java │ │ ├── WorkerRepository.java │ │ ├── ActiveRequestRepository.java │ │ └── JobRepository.java │ │ ├── config │ │ ├── Constants.java │ │ ├── ValidationConfiguration.java │ │ ├── JacksonConfiguration.java │ │ ├── HeapConfiguration.java │ │ ├── SwaggerConfiguration.java │ │ ├── DependencyConfiguration.java │ │ ├── AsyncConfiguration.java │ │ ├── OAuthUserServiceConfiguration.java │ │ ├── RecaptchaConfiguration.java │ │ ├── FileStorageConfiguration.java │ │ └── EmailConfiguration.java │ │ ├── security │ │ ├── AuthoritiesConstants.java │ │ ├── Http401UnauthorizedEntryPoint.java │ │ ├── filters │ │ │ ├── ApplicationCorsFilter.java │ │ │ ├── SwaggerFilter.java │ │ │ ├── VersionFilter.java │ │ │ ├── JWTBlacklistFilter.java │ │ │ └── JWTValidateFilter.java │ │ ├── SecurityUtils.java │ │ └── DomainUserDetailsService.java │ │ ├── KrakenServerApplication.java │ │ ├── util │ │ ├── exceptions │ │ │ ├── SystemException.java │ │ │ └── DefaultExceptionHandlerAdvice.java │ │ └── ConsoleCommandUtil.java │ │ ├── controller │ │ ├── io │ │ │ ├── CompleteRequestIO.java │ │ │ ├── WorkerIO.java │ │ │ ├── ActiveRequestIO.java │ │ │ └── AccountIO.java │ │ ├── TestController.java │ │ ├── PasswordListController.java │ │ ├── CompleteRequestController.java │ │ └── WorkerController.java │ │ └── service │ │ ├── utils │ │ ├── SwaggerService.java │ │ ├── VersionService.java │ │ ├── PasswordListJobDelimiterService.java │ │ ├── RecaptchaService.java │ │ ├── TokenBlacklistService.java │ │ ├── OAuthUserService.java │ │ ├── TokenService.java │ │ └── CrunchListService.java │ │ └── CompleteRequestService.java └── Dockerfile ├── .gitignore └── docker-compose.yml /wpa-sample.pcap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arcaneiceman/kraken/HEAD/wpa-sample.pcap -------------------------------------------------------------------------------- /kraken-client/src/utils/AppVersion.js: -------------------------------------------------------------------------------- 1 | // generated by genversion 2 | export const version = '1.2.0' 3 | -------------------------------------------------------------------------------- /kraken-client/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: /static/ -------------------------------------------------------------------------------- /kraken-client/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arcaneiceman/kraken/HEAD/kraken-client/public/favicon.ico -------------------------------------------------------------------------------- /kraken-client/src/assets/kraken-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arcaneiceman/kraken/HEAD/kraken-client/src/assets/kraken-logo.png -------------------------------------------------------------------------------- /kraken-client/src/assets/screenshots/worker.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arcaneiceman/kraken/HEAD/kraken-client/src/assets/screenshots/worker.png -------------------------------------------------------------------------------- /kraken-client/src/assets/icons/application/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arcaneiceman/kraken/HEAD/kraken-client/src/assets/icons/application/icon.png -------------------------------------------------------------------------------- /kraken-client/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | padding: 0; 4 | font-family: 'Franklin Gothic Medium', 'Arial Narrow', Arial, sans-serif; 5 | } 6 | 7 | -------------------------------------------------------------------------------- /kraken-server/src/main/resources/executables/cap2hccapx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arcaneiceman/kraken/HEAD/kraken-server/src/main/resources/executables/cap2hccapx -------------------------------------------------------------------------------- /kraken-client/src/assets/screenshots/start-worker-button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arcaneiceman/kraken/HEAD/kraken-client/src/assets/screenshots/start-worker-button.png -------------------------------------------------------------------------------- /kraken-client/src/components/SummaryTable/SummaryTable.module.css: -------------------------------------------------------------------------------- 1 | .content { 2 | margin-bottom: 0rem; 3 | } 4 | 5 | .tableHeaderRow { 6 | background: #557A95; 7 | } 8 | -------------------------------------------------------------------------------- /kraken-server/src/main/resources/mails/assets/kraken_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arcaneiceman/kraken/HEAD/kraken-server/src/main/resources/mails/assets/kraken_logo.png -------------------------------------------------------------------------------- /kraken-client/src/assets/screenshots/create-new-request-button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arcaneiceman/kraken/HEAD/kraken-client/src/assets/screenshots/create-new-request-button.png -------------------------------------------------------------------------------- /kraken-client/src/assets/screenshots/create-new-request-modal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arcaneiceman/kraken/HEAD/kraken-client/src/assets/screenshots/create-new-request-modal.png -------------------------------------------------------------------------------- /kraken-server/src/main/resources/executables/crunch_3.6-3_amd64.deb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arcaneiceman/kraken/HEAD/kraken-server/src/main/resources/executables/crunch_3.6-3_amd64.deb -------------------------------------------------------------------------------- /kraken-client/src/containers/Upgrade/Upgrade.module.css: -------------------------------------------------------------------------------- 1 | .container{ 2 | display: flex; 3 | flex-direction: column; 4 | justify-items: center; 5 | align-items: center; 6 | text-align: center; 7 | } -------------------------------------------------------------------------------- /kraken-server/src/main/java/com/arcaneiceman/kraken/krakenserver/domain/enumerations/WorkerType.java: -------------------------------------------------------------------------------- 1 | package com.arcaneiceman.kraken.krakenserver.domain.enumerations; 2 | 3 | public enum WorkerType { 4 | LOCAL, BROWSER 5 | } 6 | -------------------------------------------------------------------------------- /kraken-server/src/main/java/com/arcaneiceman/kraken/krakenserver/domain/enumerations/WorkerStatus.java: -------------------------------------------------------------------------------- 1 | package com.arcaneiceman.kraken.krakenserver.domain.enumerations; 2 | 3 | public enum WorkerStatus { 4 | ONLINE, 5 | OFFLINE 6 | } 7 | -------------------------------------------------------------------------------- /kraken-client/src/App.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './App'; 4 | 5 | it('renders without crashing', () => { 6 | const div = document.createElement('div'); 7 | ReactDOM.render(, div); 8 | }); 9 | -------------------------------------------------------------------------------- /kraken-client/src/services/PasswordListService.js: -------------------------------------------------------------------------------- 1 | import axios from './AxiosInstance' 2 | 3 | const getPasswordLists = () => { 4 | return axios.get('/password-list') 5 | } 6 | 7 | const PasswordListService = { 8 | getPasswordLists 9 | } 10 | 11 | export default PasswordListService; -------------------------------------------------------------------------------- /kraken-client/src/components/SectionHeading/SectionHeading.module.css: -------------------------------------------------------------------------------- 1 | .content { 2 | color: #959595; 3 | font-size: 10px; 4 | font-weight: 400; 5 | letter-spacing: 2px; 6 | text-transform: uppercase; 7 | margin: 30px auto 10px 5px; 8 | text-align: left; 9 | display: inline-block; 10 | } -------------------------------------------------------------------------------- /kraken-server/src/main/resources/liquibase/changelog-master.yaml: -------------------------------------------------------------------------------- 1 | databaseChangeLog: 2 | - include: 3 | file: classpath:liquibase/migrations/first-schema.yaml 4 | - include: 5 | file: classpath:liquibase/migrations/1.1.0.yaml 6 | - include: 7 | file: classpath:liquibase/migrations/1.1.1.yaml -------------------------------------------------------------------------------- /kraken-client/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import App from './App'; 4 | import 'bootstrap/dist/css/bootstrap.min.css'; 5 | //import registerServiceWorker from './registerServiceWorker'; 6 | 7 | ReactDOM.render(, document.getElementById('root')); 8 | 9 | //registerServiceWorker(); 10 | -------------------------------------------------------------------------------- /kraken-server/src/main/java/com/arcaneiceman/kraken/krakenserver/domain/enumerations/TrackingStatus.java: -------------------------------------------------------------------------------- 1 | package com.arcaneiceman.kraken.krakenserver.domain.enumerations; 2 | 3 | /** 4 | * Created by Wali on 4/21/2018. 5 | */ 6 | public enum TrackingStatus { 7 | CANCELLED, 8 | PENDING, 9 | RUNNING, 10 | COMPLETE, 11 | ERROR 12 | } 13 | -------------------------------------------------------------------------------- /kraken-client/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | } 10 | ], 11 | "start_url": ".", 12 | "display": "standalone", 13 | "theme_color": "#000000", 14 | "background_color": "#ffffff" 15 | } 16 | -------------------------------------------------------------------------------- /kraken-client/src/components/Pagination/Pagination.module.css: -------------------------------------------------------------------------------- 1 | .content { 2 | display: flex; 3 | flex-direction: row; 4 | flex-wrap: nowrap; 5 | justify-content: center; 6 | } 7 | 8 | .button{ 9 | font-family: ''; 10 | font-size: none; 11 | line-height: 0; 12 | } 13 | 14 | .pageNumbers { 15 | margin-right: 0.5rem; 16 | margin-left: 0.5rem; 17 | font-size: 0.9rem; 18 | } -------------------------------------------------------------------------------- /kraken-client/src/services/ChangeLogService.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios' 2 | 3 | const getLatestChangeLog = async () => { 4 | const readme = await axios.get('') 5 | const segments = readme.data.split("####"); 6 | segments.shift(); // Remove First Item 7 | return segments[0] 8 | } 9 | 10 | const ReadmeFileService = { 11 | getLatestChangeLog 12 | } 13 | 14 | export default ReadmeFileService; -------------------------------------------------------------------------------- /kraken-client/config/jest/cssTransform.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | // This is a custom Jest transformer turning style imports into empty objects. 4 | // http://facebook.github.io/jest/docs/en/webpack.html 5 | 6 | module.exports = { 7 | process() { 8 | return 'module.exports = {};'; 9 | }, 10 | getCacheKey() { 11 | // The output is always the same. 12 | return 'cssTransform'; 13 | }, 14 | }; 15 | -------------------------------------------------------------------------------- /kraken-client/src/components/SectionHeading/SectionHeading.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | 4 | import classes from './SectionHeading.module.css'; 5 | 6 | const SectionHeading = (props) => { 7 | const heading = props.heading; 8 | return (

{heading}

); 9 | } 10 | 11 | SectionHeading.propTypes = { 12 | heading : PropTypes.string.isRequired 13 | } 14 | 15 | export default SectionHeading; -------------------------------------------------------------------------------- /kraken-client/src/components/SocialLoginWrapper/SocialLoginWrapper.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import SocialLogin from 'react-social-login' 3 | 4 | class SocialLoginWrapper extends React.Component { 5 | 6 | render() { 7 | return ( 8 |
9 | { this.props.children } 10 |
11 | ); 12 | } 13 | } 14 | 15 | export default SocialLogin(SocialLoginWrapper); -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | kraken-client/node_modules 5 | kraken-client/.pnp 6 | kraken-client/.pnp.js 7 | 8 | # testing 9 | kraken-server/s3 10 | 11 | # production 12 | kraken-client/build 13 | kraken-server/build 14 | kraken-client/dist 15 | 16 | # misc 17 | .DS_Store 18 | .env.local 19 | .env.production.local 20 | 21 | # history 22 | .history 23 | 24 | npm-debug.log* 25 | yarn-debug.log* 26 | yarn-error.log* 27 | -------------------------------------------------------------------------------- /kraken-server/src/main/java/com/arcaneiceman/kraken/krakenserver/repository/PasswordListRepository.java: -------------------------------------------------------------------------------- 1 | package com.arcaneiceman.kraken.krakenserver.repository; 2 | 3 | import com.arcaneiceman.kraken.krakenserver.domain.PasswordList; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | import org.springframework.stereotype.Repository; 6 | 7 | /** 8 | * Created by Wali on 4/22/2018. 9 | */ 10 | @Repository 11 | public interface PasswordListRepository extends JpaRepository { 12 | 13 | } 14 | -------------------------------------------------------------------------------- /kraken-server/src/main/java/com/arcaneiceman/kraken/krakenserver/config/Constants.java: -------------------------------------------------------------------------------- 1 | package com.arcaneiceman.kraken.krakenserver.config; 2 | 3 | public class Constants { 4 | 5 | /* Token Constants */ 6 | public static final String AUTHORITIES_KEY = "auth"; 7 | public static final String BLACKLIST_DIGEST_KEY = "blacklist_digest"; 8 | 9 | /* Filter Constants */ 10 | public static final String AUTHORIZATION_HEADER = "Authorization"; 11 | public static final String VERSION_HEADER = "Version"; 12 | 13 | } 14 | -------------------------------------------------------------------------------- /kraken-server/src/main/java/com/arcaneiceman/kraken/krakenserver/security/AuthoritiesConstants.java: -------------------------------------------------------------------------------- 1 | package com.arcaneiceman.kraken.krakenserver.security; 2 | 3 | /** 4 | * Constants for Spring Security authorities. 5 | */ 6 | public final class AuthoritiesConstants { 7 | 8 | public static final String SYSTEM_ADMIN = "ROLE_SYSTEM_ADMIN"; 9 | 10 | public static final String ADMIN = "ROLE_ADMIN"; 11 | 12 | public static final String CONSUMER = "ROLE_CONSUMER"; 13 | 14 | private AuthoritiesConstants() { 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /kraken-server/src/main/java/com/arcaneiceman/kraken/krakenserver/domain/enumerations/ListType.java: -------------------------------------------------------------------------------- 1 | package com.arcaneiceman.kraken.krakenserver.domain.enumerations; 2 | 3 | public enum ListType { 4 | 5 | PASSWORD_LIST(Constants.PASSWORD_LIST_VALUE), 6 | CRUNCH(Constants.CRUNCH_VALUE); 7 | 8 | ListType(String listType) { 9 | } 10 | 11 | public static class Constants { 12 | public static final String PASSWORD_LIST_VALUE = "PASSWORD_LIST"; 13 | public static final String CRUNCH_VALUE = "CRUNCH"; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /kraken-server/src/main/java/com/arcaneiceman/kraken/krakenserver/KrakenServerApplication.java: -------------------------------------------------------------------------------- 1 | package com.arcaneiceman.kraken.krakenserver; 2 | 3 | import de.codecentric.boot.admin.server.config.EnableAdminServer; 4 | import org.springframework.boot.SpringApplication; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | 7 | @EnableAdminServer 8 | @SpringBootApplication 9 | public class KrakenServerApplication { 10 | 11 | public static void main(String[] args) { 12 | SpringApplication.run(KrakenServerApplication.class, args); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /kraken-server/src/main/java/com/arcaneiceman/kraken/krakenserver/config/ValidationConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.arcaneiceman.kraken.krakenserver.config; 2 | 3 | import org.springframework.context.annotation.Bean; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.validation.beanvalidation.MethodValidationPostProcessor; 6 | 7 | @Configuration 8 | public class ValidationConfiguration { 9 | 10 | @Bean 11 | public MethodValidationPostProcessor methodValidationPostProcessor() { 12 | return new MethodValidationPostProcessor(); 13 | } 14 | 15 | } -------------------------------------------------------------------------------- /kraken-client/src/components/DetailBox/DetailBox.module.css: -------------------------------------------------------------------------------- 1 | .content { 2 | display: flex; 3 | flex-direction: column; 4 | flex-wrap: wrap; 5 | border-right: 1px solid #dbdbdb; 6 | } 7 | 8 | .boxValue { 9 | text-align: center; 10 | margin-top: 15px; 11 | color: #3a3939; 12 | font-weight: 700; 13 | font-size: 1.8rem; 14 | } 15 | 16 | .boxText { 17 | white-space: nowrap; 18 | text-align: center; 19 | color: #959595; 20 | font-size: 0.55rem; 21 | font-weight: 400; 22 | letter-spacing: 2px; 23 | text-transform: uppercase; 24 | margin: 10px; 25 | } -------------------------------------------------------------------------------- /kraken-server/src/main/java/com/arcaneiceman/kraken/krakenserver/util/exceptions/SystemException.java: -------------------------------------------------------------------------------- 1 | package com.arcaneiceman.kraken.krakenserver.util.exceptions; 2 | 3 | import lombok.Getter; 4 | import org.zalando.problem.AbstractThrowableProblem; 5 | import org.zalando.problem.Status; 6 | 7 | /** 8 | * Created by wali on 16/10/17. 9 | */ 10 | @Getter 11 | public class SystemException extends AbstractThrowableProblem { 12 | 13 | private int errorCode; 14 | 15 | public SystemException(int errorCode, String message, Status httpStatus) { 16 | super(null, message, httpStatus, null, null, null); 17 | this.errorCode = errorCode; 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /kraken-server/src/main/java/com/arcaneiceman/kraken/krakenserver/repository/TokenBlacklistRepository.java: -------------------------------------------------------------------------------- 1 | package com.arcaneiceman.kraken.krakenserver.repository; 2 | 3 | import com.arcaneiceman.kraken.krakenserver.domain.BlacklistToken; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | import org.springframework.stereotype.Repository; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * Created by wali on 30/10/17. 11 | */ 12 | @Repository 13 | public interface TokenBlacklistRepository extends JpaRepository { 14 | 15 | BlacklistToken findByTokenDigest(String token); 16 | 17 | List findByCleanUpTimeBefore(Long time); 18 | } 19 | -------------------------------------------------------------------------------- /kraken-server/src/main/java/com/arcaneiceman/kraken/krakenserver/repository/UserRepository.java: -------------------------------------------------------------------------------- 1 | package com.arcaneiceman.kraken.krakenserver.repository; 2 | 3 | import com.arcaneiceman.kraken.krakenserver.domain.User; 4 | import org.springframework.data.jpa.repository.JpaRepository; 5 | import org.springframework.data.jpa.repository.Query; 6 | import org.springframework.stereotype.Repository; 7 | 8 | import java.util.Optional; 9 | 10 | @Repository 11 | public interface UserRepository extends JpaRepository { 12 | 13 | @Query("SELECT u FROM User u WHERE u.email = ?1") 14 | Optional findByUsername(String username); 15 | 16 | Optional findUserByEmail(String email); 17 | 18 | } 19 | -------------------------------------------------------------------------------- /kraken-client/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM nginx:alpine 2 | 3 | # Add open ssl 4 | RUN apk update && apk add openssl 5 | 6 | RUN mkdir -p /etc/nginx/ssl/ \ 7 | && openssl req \ 8 | -x509 \ 9 | -subj "/C=CA/ST=Denial/L=Nowhere/O=Dis" \ 10 | -nodes \ 11 | -days 365 \ 12 | -newkey rsa:2048 \ 13 | -keyout /etc/nginx/ssl/nginx.key \ 14 | -out /etc/nginx/ssl/nginx.cert 15 | 16 | # Add nginx 17 | ADD ./config/nginx.conf /etc/nginx/nginx.conf 18 | 19 | # Set working directory to nginx asset directory 20 | WORKDIR /usr/share/nginx/html 21 | 22 | COPY ./build . 23 | 24 | # Entry point when Docker container has started 25 | ENTRYPOINT ["nginx", "-g", "daemon off;"] -------------------------------------------------------------------------------- /kraken-client/src/components/DetailBox/DetailBox.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | 4 | import classes from './DetailBox.module.css' 5 | 6 | const DetailBox = (props) => { 7 | // Extract Values 8 | const boxValue = props.boxValue; 9 | const boxText = props.boxText; 10 | 11 | // Render Components 12 | return ( 13 |
14 |
{boxValue}
15 |
{boxText}
16 |
17 | ); 18 | } 19 | 20 | DetailBox.propTypes = { 21 | boxValue : PropTypes.string.isRequired, 22 | boxText : PropTypes.string.isRequired 23 | } 24 | 25 | export default DetailBox; -------------------------------------------------------------------------------- /kraken-client/src/containers/ChangePassword/ChangePassword.module.css: -------------------------------------------------------------------------------- 1 | .header{ 2 | padding: 40px 0 100px; 3 | text-align: center; 4 | } 5 | 6 | .title{ 7 | color: #524e4e; 8 | font-weight: 100; 9 | font-size: 56px; 10 | padding: 0; 11 | margin: 0 0 20px; 12 | } 13 | 14 | .form_container{ 15 | display: flex; 16 | flex-direction: column; 17 | align-items: center; 18 | margin: -80px auto 0; 19 | } 20 | 21 | .form{ 22 | border: 2px solid #557A95; 23 | padding: 30px 40px; 24 | min-width: 400px; 25 | text-align: left; 26 | } 27 | 28 | .form_status_container{ 29 | display: flex; 30 | justify-content: center; 31 | margin-bottom : 10px; 32 | } 33 | 34 | .submit_container{ 35 | text-align: center 36 | } -------------------------------------------------------------------------------- /kraken-server/src/main/java/com/arcaneiceman/kraken/krakenserver/controller/io/CompleteRequestIO.java: -------------------------------------------------------------------------------- 1 | package com.arcaneiceman.kraken.krakenserver.controller.io; 2 | 3 | import io.swagger.annotations.ApiModel; 4 | import lombok.AllArgsConstructor; 5 | import lombok.Getter; 6 | import lombok.NoArgsConstructor; 7 | import lombok.Setter; 8 | 9 | public class CompleteRequestIO { 10 | 11 | public static class Summary { 12 | 13 | @Getter 14 | @Setter 15 | @NoArgsConstructor 16 | @AllArgsConstructor 17 | @ApiModel("CompleteRequest.Summary.Response") 18 | public static class Response { 19 | 20 | private int totalCompleteRequests; 21 | 22 | private int totalFoundRequests; 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /kraken-server/src/main/java/com/arcaneiceman/kraken/krakenserver/service/utils/SwaggerService.java: -------------------------------------------------------------------------------- 1 | package com.arcaneiceman.kraken.krakenserver.service.utils; 2 | 3 | import lombok.Getter; 4 | import org.springframework.beans.factory.annotation.Value; 5 | import org.springframework.stereotype.Service; 6 | 7 | import javax.annotation.PostConstruct; 8 | 9 | @Service 10 | public class SwaggerService { 11 | 12 | @Getter 13 | @Value("${application.swagger.context-path}") 14 | private String swaggerContextPath; 15 | 16 | @PostConstruct 17 | public void checkVariable() { 18 | if (swaggerContextPath == null || swaggerContextPath.isEmpty()) 19 | throw new IllegalStateException("Swagger Service : Swagger Documentation Context Path Not Found!"); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /kraken-client/config/pnpTs.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const { resolveModuleName } = require('ts-pnp'); 4 | 5 | exports.resolveModuleName = ( 6 | typescript, 7 | moduleName, 8 | containingFile, 9 | compilerOptions, 10 | resolutionHost 11 | ) => { 12 | return resolveModuleName( 13 | moduleName, 14 | containingFile, 15 | compilerOptions, 16 | resolutionHost, 17 | typescript.resolveModuleName 18 | ); 19 | }; 20 | 21 | exports.resolveTypeReferenceDirective = ( 22 | typescript, 23 | moduleName, 24 | containingFile, 25 | compilerOptions, 26 | resolutionHost 27 | ) => { 28 | return resolveModuleName( 29 | moduleName, 30 | containingFile, 31 | compilerOptions, 32 | resolutionHost, 33 | typescript.resolveTypeReferenceDirective 34 | ); 35 | }; 36 | -------------------------------------------------------------------------------- /kraken-client/src/containers/Activation/Activation.module.css: -------------------------------------------------------------------------------- 1 | .header { 2 | padding: 60px 0 150px; 3 | text-align: center; 4 | } 5 | 6 | .title { 7 | color: #524e4e; 8 | font-weight: 100; 9 | font-size: 56px; 10 | padding: 0; 11 | margin: 0 0 20px; 12 | } 13 | 14 | .container { 15 | display: flex; 16 | flex-direction: column; 17 | align-items: center; 18 | margin: -140px auto 0; 19 | 20 | } 21 | 22 | .form { 23 | border: 2px solid #557A95; 24 | padding: 30px 40px; 25 | min-width: 400px; 26 | text-align: left; 27 | } 28 | 29 | .form_status_container{ 30 | display: flex; 31 | justify-content: center; 32 | margin-bottom : 10px; 33 | } 34 | 35 | .resend_button { 36 | margin : 10px 37 | } 38 | 39 | .submit_container{ 40 | text-align: center 41 | } -------------------------------------------------------------------------------- /kraken-client/src/components/SummaryTable/SummaryTable.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import Table from 'react-bootstrap/Table'; 4 | 5 | import classes from './SummaryTable.module.css' 6 | 7 | const SummaryTable = (props) => { 8 | return ( 9 | 10 | 11 | 12 | {props.tableHeadings} 13 | 14 | 15 | {props.tableItems} 16 |
17 | ); 18 | } 19 | 20 | SummaryTable.propTypes = { 21 | tableHeadings: PropTypes.arrayOf(PropTypes.element), 22 | tableItems: PropTypes.arrayOf(PropTypes.element) 23 | } 24 | 25 | export default SummaryTable; -------------------------------------------------------------------------------- /kraken-client/src/containers/ForgotPassword/ForgotPassword.module.css: -------------------------------------------------------------------------------- 1 | .header{ 2 | padding: 40px 0 100px; 3 | text-align: center; 4 | } 5 | 6 | .title{ 7 | color: #524e4e; 8 | font-weight: 100; 9 | font-size: 56px; 10 | padding: 0; 11 | margin: 0 0 20px; 12 | } 13 | 14 | .form_container{ 15 | display: flex; 16 | flex-direction: column; 17 | align-items: center; 18 | margin: -80px auto 0; 19 | } 20 | 21 | .form { 22 | border: 2px solid #557A95; 23 | padding: 30px 40px; 24 | min-width: 400px; 25 | text-align: left; 26 | } 27 | 28 | .form_status_container{ 29 | display: flex; 30 | justify-content: center; 31 | margin-bottom : 10px; 32 | } 33 | 34 | .submit_container{ 35 | text-align: center; 36 | } 37 | 38 | .login_button { 39 | margin : 10px 40 | } 41 | -------------------------------------------------------------------------------- /kraken-server/src/main/java/com/arcaneiceman/kraken/krakenserver/repository/PasswordListJobDelimiterRepository.java: -------------------------------------------------------------------------------- 1 | package com.arcaneiceman.kraken.krakenserver.repository; 2 | 3 | import com.arcaneiceman.kraken.krakenserver.domain.PasswordList; 4 | import com.arcaneiceman.kraken.krakenserver.domain.PasswordListJobDelimiter; 5 | import org.springframework.data.jpa.repository.JpaRepository; 6 | import org.springframework.stereotype.Repository; 7 | 8 | import java.util.List; 9 | import java.util.Optional; 10 | 11 | @Repository 12 | public interface PasswordListJobDelimiterRepository extends JpaRepository { 13 | 14 | Optional findByIndexNumberAndOwner(Long indexNumber, PasswordList owner); 15 | 16 | List findByOwner(PasswordList owner); 17 | 18 | } 19 | -------------------------------------------------------------------------------- /kraken-client/src/utils/NotificiationService.js: -------------------------------------------------------------------------------- 1 | import { toast } from 'react-toastify'; 2 | import 'react-toastify/dist/ReactToastify.css'; 3 | 4 | toast.configure({ 5 | position: "bottom-left", 6 | autoClose: 5000, 7 | closeOnClick: true, 8 | hideProgressBar: true, 9 | pauseOnHover: false, 10 | draggable: false 11 | }) 12 | 13 | const constantToastId = "toast-id" 14 | const showNotification = (message, override) => { 15 | if (typeof message === 'undefined' || message === null) 16 | message = "Network Error" 17 | if (override) 18 | toast.error(message) 19 | else 20 | if (!toast.isActive(constantToastId)) 21 | toast.error(message, { toastId: constantToastId }) 22 | } 23 | 24 | const NotificationSerivce = { 25 | showNotification 26 | } 27 | 28 | export default NotificationSerivce; 29 | -------------------------------------------------------------------------------- /kraken-client/src/utils/ExitHandlerService.js: -------------------------------------------------------------------------------- 1 | import isElectron from 'is-electron'; 2 | let electron; 3 | if (window.require) { 4 | electron = window.require("electron"); 5 | } 6 | 7 | const handleExit = async (event) => { 8 | event.returnValue = false 9 | if (isElectron()) { 10 | let result = await electron.remote.dialog.showMessageBox( 11 | electron.remote.getCurrentWindow(), { 12 | message: 'The worker is still running. Do you still want to quit?', 13 | buttons: ['Yes', 'No'] 14 | }) 15 | if (result.response === 0) { // Yes 16 | window.removeEventListener("beforeunload", handleExit) 17 | electron.remote.getCurrentWindow().close() 18 | } 19 | } 20 | } 21 | 22 | const ExitHandlerService = { 23 | handleExit 24 | } 25 | 26 | export default ExitHandlerService; -------------------------------------------------------------------------------- /kraken-server/src/main/java/com/arcaneiceman/kraken/krakenserver/service/utils/VersionService.java: -------------------------------------------------------------------------------- 1 | package com.arcaneiceman.kraken.krakenserver.service.utils; 2 | 3 | import lombok.Getter; 4 | import org.springframework.beans.factory.annotation.Value; 5 | import org.springframework.stereotype.Service; 6 | 7 | import javax.annotation.PostConstruct; 8 | import java.util.Objects; 9 | 10 | @Service 11 | public class VersionService { 12 | 13 | @Getter 14 | @Value("${application.api-version}") 15 | private String apiVersion; 16 | 17 | @PostConstruct 18 | public void verifyVariables() { 19 | if (apiVersion == null || apiVersion.isEmpty()) 20 | throw new IllegalStateException("No Api Version specified"); 21 | } 22 | 23 | public boolean isVersionEqual(String fromRequest) { 24 | return Objects.equals(apiVersion, fromRequest); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /kraken-server/src/main/java/com/arcaneiceman/kraken/krakenserver/config/JacksonConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.arcaneiceman.kraken.krakenserver.config; 2 | 3 | import com.fasterxml.jackson.datatype.hibernate5.Hibernate5Module; 4 | import com.fasterxml.jackson.module.afterburner.AfterburnerModule; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.context.annotation.Configuration; 7 | 8 | @Configuration 9 | public class JacksonConfiguration { 10 | 11 | /* 12 | * Support for Hibernate types in Jackson. 13 | */ 14 | @Bean 15 | public Hibernate5Module hibernate5Module() { 16 | return new Hibernate5Module(); 17 | } 18 | 19 | /* 20 | * Jackson Afterburner module to speed up serialization/deserialization. 21 | */ 22 | @Bean 23 | public AfterburnerModule afterburnerModule() { 24 | return new AfterburnerModule(); 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /kraken-server/src/main/java/com/arcaneiceman/kraken/krakenserver/domain/PasswordList.java: -------------------------------------------------------------------------------- 1 | package com.arcaneiceman.kraken.krakenserver.domain; 2 | 3 | import lombok.*; 4 | import org.hibernate.annotations.Cache; 5 | import org.hibernate.annotations.CacheConcurrencyStrategy; 6 | 7 | import javax.persistence.Column; 8 | import javax.persistence.Entity; 9 | import javax.persistence.Id; 10 | import javax.persistence.Table; 11 | 12 | /** 13 | * Created by Wali on 4/21/2018. 14 | */ 15 | @NoArgsConstructor 16 | @AllArgsConstructor 17 | @Getter 18 | @Setter 19 | @EqualsAndHashCode 20 | @Entity 21 | @Table(name = "password_lists") 22 | @Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE) 23 | public class PasswordList { 24 | 25 | @Id 26 | private String name; 27 | 28 | @Column 29 | private Long jobDelimiterSetSize; 30 | 31 | @Column 32 | private String charset; 33 | 34 | @Column 35 | private String jobSize; 36 | } 37 | -------------------------------------------------------------------------------- /kraken-client/src/components/Toolbar/Toolbar.module.css: -------------------------------------------------------------------------------- 1 | .navbar { 2 | height: 2.5%; 3 | background: #557A95; 4 | } 5 | 6 | .navbarElectron { 7 | height: 2.5%; 8 | background: #557A95; 9 | line-height: 0.5 10 | } 11 | 12 | .logo { 13 | cursor: pointer; 14 | width: 2.5%; 15 | } 16 | 17 | .link { 18 | margin-right: 5px; 19 | margin-left: 5px; 20 | opacity: 0.75 !important; 21 | color: whitesmoke !important; 22 | border-radius: 5px; 23 | } 24 | 25 | .link:hover{ 26 | opacity: 1 !important; 27 | color: white !important; 28 | background: #396788 29 | } 30 | 31 | .linkPrimary{ 32 | border-radius: 5px; 33 | opacity: 0.75 !important; 34 | color: whitesmoke !important; 35 | background: #22567c; 36 | } 37 | 38 | .link:hover{ 39 | opacity: 1 !important; 40 | color: white !important; 41 | background: #0d466f ; 42 | } 43 | 44 | .collapse { 45 | justify-content: flex-end; 46 | } -------------------------------------------------------------------------------- /kraken-server/src/main/java/com/arcaneiceman/kraken/krakenserver/security/Http401UnauthorizedEntryPoint.java: -------------------------------------------------------------------------------- 1 | package com.arcaneiceman.kraken.krakenserver.security; 2 | 3 | import org.springframework.security.core.AuthenticationException; 4 | import org.springframework.security.web.AuthenticationEntryPoint; 5 | 6 | import javax.servlet.http.HttpServletRequest; 7 | import javax.servlet.http.HttpServletResponse; 8 | import java.io.IOException; 9 | 10 | /** 11 | * Returns a 401 error code (Unauthorized) to the client. 12 | */ 13 | public class Http401UnauthorizedEntryPoint implements AuthenticationEntryPoint { 14 | 15 | /** 16 | * Always returns a 401 error code to the client. 17 | */ 18 | @Override 19 | public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException arg2) 20 | throws IOException { 21 | response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Access Denied"); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /kraken-client/src/components/StatusBox/StatusBox.module.css: -------------------------------------------------------------------------------- 1 | .content { 2 | display: flex; 3 | flex-direction: row; 4 | flex-wrap: nowrap; 5 | justify-content: flex-start; 6 | margin: 4px; 7 | } 8 | 9 | .offlineStatusBullet { 10 | background: #e92424; 11 | width: 9px; 12 | height: 9px; 13 | border-radius: 5px; 14 | } 15 | 16 | .offlineStatusText{ 17 | font-size: 12px; 18 | font-weight: 700; 19 | text-transform: uppercase; 20 | color: #e92424; 21 | letter-spacing: 1px; 22 | position: relative; 23 | padding-left: 14px; 24 | line-height: 1; 25 | } 26 | 27 | .onlineStatusBullet{ 28 | background: green; 29 | width: 9px; 30 | height: 9px; 31 | border-radius: 5px; 32 | } 33 | 34 | .onlineStatusText { 35 | font-size: 12px; 36 | font-weight: 700; 37 | text-transform: uppercase; 38 | color: green; 39 | letter-spacing: 1px; 40 | position: relative; 41 | padding-left: 14px; 42 | line-height: 1; 43 | } -------------------------------------------------------------------------------- /kraken-server/src/main/java/com/arcaneiceman/kraken/krakenserver/config/HeapConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.arcaneiceman.kraken.krakenserver.config; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | import org.springframework.context.annotation.Configuration; 6 | 7 | import javax.annotation.PostConstruct; 8 | 9 | @Configuration 10 | public class HeapConfiguration { 11 | 12 | private Logger log = LoggerFactory.getLogger(HeapConfiguration.class); 13 | 14 | public static String formatSize(long v) { 15 | if (v < 1024) return v + " B"; 16 | int z = (63 - Long.numberOfLeadingZeros(v)) / 10; 17 | return String.format("%.1f %sB", (double) v / (1L << (z * 10)), " KMGTPE".charAt(z)); 18 | } 19 | 20 | @PostConstruct 21 | public void printHeapValues() { 22 | log.info("Total Memory : {}", formatSize(Runtime.getRuntime().totalMemory())); 23 | log.info("Maximum Memory : {}", formatSize(Runtime.getRuntime().maxMemory())); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /kraken-server/src/main/java/com/arcaneiceman/kraken/krakenserver/repository/CompleteRequestRepository.java: -------------------------------------------------------------------------------- 1 | package com.arcaneiceman.kraken.krakenserver.repository; 2 | 3 | import com.arcaneiceman.kraken.krakenserver.domain.CompleteRequest; 4 | import com.arcaneiceman.kraken.krakenserver.domain.User; 5 | import org.springframework.data.domain.Page; 6 | import org.springframework.data.domain.Pageable; 7 | import org.springframework.data.jpa.repository.JpaRepository; 8 | import org.springframework.stereotype.Repository; 9 | 10 | import java.util.List; 11 | import java.util.Optional; 12 | 13 | @Repository 14 | public interface CompleteRequestRepository extends JpaRepository { 15 | 16 | Page findByOwner(Pageable pageable, User owner); 17 | 18 | List findByOwner(User owner); 19 | 20 | List findByOwnerAndResultsNot(User owner, String result); 21 | 22 | Optional findByIdAndOwner(String id, User owner); 23 | } 24 | -------------------------------------------------------------------------------- /kraken-client/src/services/WorkerService.js: -------------------------------------------------------------------------------- 1 | import axios from './AxiosInstance' 2 | 3 | const createWorker = (workerName, workerType, platform) => { 4 | const data = {workerName, workerType, platform} 5 | return axios.post('/worker', data) 6 | } 7 | 8 | const getSummary = () => { 9 | return axios.get('/worker/summary') 10 | } 11 | 12 | const getWorkers = (pageNumber, pageSize) => { 13 | return axios.get('/worker?pageNumber=' + pageNumber + '&pageSize=' + pageSize +'&sort=status,desc') 14 | } 15 | 16 | const getWorker = (workerId) => { 17 | return axios.get('/worker/' + workerId) 18 | } 19 | 20 | const deleteWorker = (workerId) => { 21 | return axios.delete('/worker/' + workerId) 22 | } 23 | 24 | const sendHeartbeat = (workerId) => { 25 | return axios.post('/worker/' + workerId + '/heartbeat') 26 | } 27 | 28 | const WorkerService = { 29 | createWorker, 30 | getSummary, 31 | getWorkers, 32 | getWorker, 33 | deleteWorker, 34 | sendHeartbeat 35 | } 36 | 37 | export default WorkerService; -------------------------------------------------------------------------------- /kraken-client/src/containers/KrakenWorker/jobcracker.browser.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-restricted-globals */ 2 | import FakeHashcat from './utils/FakeHashcat' 3 | 4 | self.onmessage = async (message) => { 5 | console.debug("Cracker received job with id " + message.data.jobId + " chunkNo " + message.data.chunkNo) 6 | let returnObject = { webWorkerId: message.data.webWorkerId, jobId: message.data.jobId, chunkNo: message.data.chunkNo, result: {}, error: null } 7 | let valueToMatch = atob(message.data.valueToMatchInBase64) 8 | let mode = message.data.requestType 9 | let wordlist = message.data.candidateValues 10 | try { 11 | returnObject.result = await FakeHashcat.crack(mode, valueToMatch, wordlist) 12 | } 13 | catch (error) { 14 | returnObject.error = error; 15 | } 16 | finally { 17 | // Cleanup 18 | delete message.data.candidateValues 19 | delete message.data.valueToMatchInBase64 20 | 21 | // Return 22 | self.postMessage(returnObject) 23 | } 24 | }; -------------------------------------------------------------------------------- /kraken-server/src/main/java/com/arcaneiceman/kraken/krakenserver/domain/BlacklistToken.java: -------------------------------------------------------------------------------- 1 | package com.arcaneiceman.kraken.krakenserver.domain; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | import lombok.NoArgsConstructor; 6 | import lombok.Setter; 7 | import org.hibernate.annotations.CacheConcurrencyStrategy; 8 | 9 | import javax.persistence.Column; 10 | import javax.persistence.Entity; 11 | import javax.persistence.Id; 12 | import javax.persistence.Table; 13 | import javax.validation.constraints.NotNull; 14 | 15 | /** 16 | * Created by wali on 30/10/17. 17 | */ 18 | @Getter 19 | @Setter 20 | @AllArgsConstructor 21 | @NoArgsConstructor 22 | @Entity 23 | @Table(name = "token_blacklist") 24 | @org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE) 25 | public class BlacklistToken { 26 | 27 | private static final long serialVersionUID = 1L; 28 | 29 | @Id 30 | @NotNull 31 | private String tokenDigest; 32 | 33 | @Column 34 | private Long cleanUpTime; 35 | } 36 | 37 | -------------------------------------------------------------------------------- /kraken-client/src/containers/Register/Register.module.css: -------------------------------------------------------------------------------- 1 | .header{ 2 | padding: 40px 0 100px; 3 | text-align: center; 4 | } 5 | 6 | .title{ 7 | color: #524e4e; 8 | font-weight: 100; 9 | font-size: 56px; 10 | padding: 0; 11 | margin: 0 0 20px; 12 | } 13 | 14 | .form_container{ 15 | display: flex; 16 | flex-direction: column; 17 | align-items: center; 18 | margin: -80px auto 0; 19 | } 20 | 21 | .form{ 22 | border: 2px solid #557A95; 23 | padding: 30px 40px; 24 | min-width: 400px; 25 | max-width: 600px; 26 | text-align: left; 27 | } 28 | 29 | .form_input_postpend { 30 | max-width: 16px; 31 | color: "#557A95"; 32 | cursor: 'pointer'; 33 | } 34 | 35 | .form_status_container{ 36 | display: flex; 37 | justify-content: center; 38 | margin-bottom : 10px; 39 | } 40 | 41 | .submit_container{ 42 | margin : 10px; 43 | text-align: center 44 | } 45 | 46 | .form_footer{ 47 | display: flex; 48 | min-width: 400px; 49 | justify-content: space-between; 50 | } 51 | -------------------------------------------------------------------------------- /kraken-client/src/components/StatusBox/StatusBox.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | 4 | import classes from './StatusBox.module.css' 5 | 6 | const StatusBox = (props) => { 7 | const online = ( 8 |
9 |
10 | ONLINE 11 |
12 | ) 13 | const offline = ( 14 |
15 |
16 | OFFLINE 17 |
18 | ); 19 | 20 | switch(props.status){ 21 | case ('ONLINE'): 22 | return online; 23 | case ('OFFLINE'): 24 | return offline; 25 | default: 26 | return ( 'N/A'); 27 | } 28 | } 29 | 30 | StatusBox.propTypes = { 31 | status : PropTypes.oneOf(['ONLINE', 'OFFLINE']) 32 | } 33 | 34 | export default StatusBox; 35 | -------------------------------------------------------------------------------- /kraken-client/src/containers/KrakenWorker/jobfetcher.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-restricted-globals */ 2 | self.onmessage = (e) => { 3 | let response = {}; 4 | try { 5 | const request = { workerId: e.data.workerId, multiplier: e.data.multiplier } 6 | var xhttp = new XMLHttpRequest(); 7 | xhttp.open("POST", e.data.path, false); 8 | xhttp.setRequestHeader("Authorization", "Bearer " + e.data.token) 9 | xhttp.setRequestHeader("Content-Type", "application/json;charset=UTF-8"); 10 | xhttp.setRequestHeader("Version", '1.0.0') 11 | xhttp.send(JSON.stringify(request)); 12 | 13 | switch (xhttp.status) { 14 | case 200: 15 | response = JSON.parse(xhttp.responseText); 16 | response.status = "SUCCESS" 17 | break; 18 | default: 19 | response.status = "ERROR" 20 | console.error("Get Job Error " + xhttp.status) 21 | } 22 | } 23 | finally { 24 | self.postMessage(response) 25 | } 26 | } 27 | 28 | -------------------------------------------------------------------------------- /kraken-server/src/main/java/com/arcaneiceman/kraken/krakenserver/domain/TrackedPasswordList.java: -------------------------------------------------------------------------------- 1 | package com.arcaneiceman.kraken.krakenserver.domain; 2 | 3 | import com.arcaneiceman.kraken.krakenserver.domain.abs.TrackedList; 4 | import com.arcaneiceman.kraken.krakenserver.domain.enumerations.ListType; 5 | import com.arcaneiceman.kraken.krakenserver.domain.enumerations.TrackingStatus; 6 | import lombok.Getter; 7 | import lombok.NoArgsConstructor; 8 | import lombok.Setter; 9 | 10 | import javax.persistence.DiscriminatorValue; 11 | import javax.persistence.Entity; 12 | import java.util.ArrayList; 13 | 14 | @Getter 15 | @Setter 16 | @Entity 17 | @NoArgsConstructor 18 | @DiscriminatorValue(ListType.Constants.PASSWORD_LIST_VALUE) 19 | public class TrackedPasswordList extends TrackedList { 20 | 21 | public TrackedPasswordList(Long totalJobs, String passwordListName, ActiveRequest owner) { 22 | super(null, passwordListName, ListType.PASSWORD_LIST, TrackingStatus.PENDING, totalJobs, 23 | 0L, 0L, 0L, new ArrayList<>(), owner); 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /kraken-server/src/main/java/com/arcaneiceman/kraken/krakenserver/security/filters/ApplicationCorsFilter.java: -------------------------------------------------------------------------------- 1 | package com.arcaneiceman.kraken.krakenserver.security.filters; 2 | 3 | import org.springframework.web.cors.CorsConfiguration; 4 | import org.springframework.web.cors.UrlBasedCorsConfigurationSource; 5 | import org.springframework.web.filter.CorsFilter; 6 | 7 | public class ApplicationCorsFilter { 8 | 9 | public static CorsFilter getCorsFilter() { 10 | UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); 11 | CorsConfiguration config = new CorsConfiguration(); 12 | config.setAllowCredentials(true); 13 | config.addAllowedOrigin("*"); 14 | config.addAllowedHeader("*"); 15 | config.addAllowedMethod("OPTIONS"); 16 | config.addAllowedMethod("GET"); 17 | config.addAllowedMethod("PUT"); 18 | config.addAllowedMethod("POST"); 19 | config.addAllowedMethod("DELETE"); 20 | config.addAllowedOrigin("http://localhost:3000/"); 21 | source.registerCorsConfiguration("/**", config); 22 | return new CorsFilter(source); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /kraken-server/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM openjdk:8-jre 2 | 3 | # Update Apt 4 | RUN apt-get update 5 | 6 | # Add Crunch 7 | COPY src/main/resources/executables/crunch_3.6-3_amd64.deb crunch.deb 8 | RUN apt-get install ./crunch.deb 9 | # OR Get it through apt 10 | #RUN apt-get update && apt-get --yes install crunch && rm -rf /var/lib/apt/lists/* 11 | 12 | # Add cap2hccapx 13 | COPY src/main/resources/executables/cap2hccapx cap2hccapx 14 | # OR Get it through wget 15 | # https://raw.githubusercontent.com/hashcat/hashcat-utils/master/src/cap2hccapx 16 | RUN mv cap2hccapx /bin 17 | 18 | # Add a kraken user to run our application so that it doesn't need to run as root 19 | RUN useradd -ms /bin/bash kraken 20 | WORKDIR /home/kraken 21 | 22 | # Copy Password Lists 23 | ADD src/main/resources/lists lists 24 | 25 | # Copy the config file explicitly 26 | COPY src/main/resources/application.yaml application.yaml 27 | 28 | # Copy the jar file from build into the container 29 | COPY ./build/libs/kraken-server.jar kraken-server.jar 30 | 31 | CMD ["echo", "Trying to run Kraken? Override required configurations values and try again, eg java [args] -jar kraken-server.jar See https://github.com/arcaneiceman for help"] 32 | -------------------------------------------------------------------------------- /kraken-client/src/containers/Home/Home.module.css: -------------------------------------------------------------------------------- 1 | .container{ 2 | display: flex; 3 | flex-direction: column; 4 | justify-content: center; 5 | } 6 | 7 | .logo{ 8 | width: 50vw; 9 | height: 40vh; 10 | align-self: center; 11 | object-fit: contain; 12 | } 13 | 14 | .title{ 15 | max-height: 15vh; 16 | width: auto; 17 | font-size: 6em; 18 | text-align: center; 19 | } 20 | 21 | .subTitle{ 22 | max-height: 10vh; 23 | font-size: 2.5em; 24 | text-align: center 25 | } 26 | 27 | .disclaimer{ 28 | margin-top: 1em; 29 | text-align: center 30 | } 31 | 32 | .buttonContainer{ 33 | display: flex; 34 | justify-content: center; 35 | } 36 | 37 | .button{ 38 | font-size: 1.25em; 39 | min-width: 5%; 40 | min-height: 2.5%; 41 | margin: 2.5%; 42 | padding:1%; 43 | background-color: #557A95; 44 | border-color: #557A95; 45 | } 46 | 47 | .formContainer { 48 | margin-top: 2em; 49 | display: flex; 50 | justify-content: center; 51 | } 52 | 53 | .form{ 54 | max-width: 40vw; 55 | min-width: 24vw; 56 | } 57 | 58 | .donationContainer { 59 | display: flex; 60 | flex-direction: column; 61 | align-items: center; 62 | margin: 10px; 63 | } -------------------------------------------------------------------------------- /kraken-server/src/main/java/com/arcaneiceman/kraken/krakenserver/repository/TrackedListRepository.java: -------------------------------------------------------------------------------- 1 | package com.arcaneiceman.kraken.krakenserver.repository; 2 | 3 | import com.arcaneiceman.kraken.krakenserver.domain.ActiveRequest; 4 | import com.arcaneiceman.kraken.krakenserver.domain.abs.TrackedList; 5 | import com.arcaneiceman.kraken.krakenserver.domain.enumerations.TrackingStatus; 6 | import org.springframework.data.jpa.repository.JpaRepository; 7 | import org.springframework.data.jpa.repository.Lock; 8 | import org.springframework.stereotype.Repository; 9 | 10 | import javax.persistence.LockModeType; 11 | import java.util.Optional; 12 | 13 | @Repository 14 | public interface TrackedListRepository extends JpaRepository { 15 | 16 | //@QueryHints({@QueryHint(name = "javax.persistence.lock.timeout", value ="5000")}) 17 | @Lock(LockModeType.PESSIMISTIC_WRITE) 18 | TrackedList findFirstByTrackingStatusAndOwner(TrackingStatus trackingStatus, ActiveRequest owner); 19 | 20 | //@QueryHints({@QueryHint(name = "javax.persistence.lock.timeout", value ="5000")}) 21 | @Lock(LockModeType.PESSIMISTIC_WRITE) 22 | Optional findByIdAndOwner(String id, ActiveRequest owner); 23 | 24 | } 25 | -------------------------------------------------------------------------------- /kraken-client/src/components/Pagination/Pagination.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import Octicon, { ChevronLeft, ChevronRight } from '@githubprimer/octicons-react' 4 | 5 | import classes from './Pagination.module.css'; 6 | 7 | const Pagination = (props) => { 8 | const nextOnClick = props.nextOnClick; 9 | const prevOnClick = props.prevOnClick; 10 | const currentPage = props.currentPage; 11 | const totalPages = props.totalPages; 12 | 13 | return ( 14 |
15 | 18 | {currentPage} {' / '} {totalPages} 19 | 22 |
23 | ); 24 | } 25 | 26 | Pagination.propTypes = { 27 | nextOnClick: PropTypes.func.isRequired, 28 | prevOnClick: PropTypes.func.isRequired, 29 | currentPage: PropTypes.number.isRequired, 30 | totalPages: PropTypes.number.isRequired 31 | } 32 | 33 | export default Pagination; -------------------------------------------------------------------------------- /kraken-server/src/main/java/com/arcaneiceman/kraken/krakenserver/domain/PasswordListJobDelimiter.java: -------------------------------------------------------------------------------- 1 | package com.arcaneiceman.kraken.krakenserver.domain; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnore; 4 | import lombok.*; 5 | import org.hibernate.annotations.CacheConcurrencyStrategy; 6 | import org.hibernate.annotations.GenericGenerator; 7 | 8 | import javax.persistence.*; 9 | import java.io.Serializable; 10 | 11 | @EqualsAndHashCode(callSuper = false, of = "indexNumber") 12 | @Getter 13 | @Setter 14 | @NoArgsConstructor 15 | @AllArgsConstructor 16 | @Embeddable 17 | @Table(name = "password_lists_job_delimiter") 18 | @Entity 19 | @org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE) 20 | public class PasswordListJobDelimiter implements Serializable { 21 | 22 | /** 23 | * Using synthetic key to avoid repeating data 24 | */ 25 | @Id 26 | @GeneratedValue(generator = "uuid2") 27 | @GenericGenerator(name = "uuid2", strategy = "uuid2") 28 | private String id; 29 | 30 | @Column 31 | private Long indexNumber; 32 | 33 | @Column 34 | private Long startByte; 35 | 36 | @Column 37 | private Long endByte; 38 | 39 | @JsonIgnore 40 | @ManyToOne 41 | private PasswordList owner; 42 | } 43 | -------------------------------------------------------------------------------- /kraken-client/src/services/AxiosInstance.js: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | 3 | const instance = axios.create({ 4 | baseURL: localStorage.getItem("url") == null ? "http://localhost:5000/api" : localStorage.getItem("url") 5 | }); 6 | 7 | instance.interceptors.request.use( 8 | function (config) { 9 | const token = localStorage.getItem("currentToken"); 10 | if (token !== null) 11 | config.headers.Authorization = "Bearer " + token; 12 | return config; 13 | }); 14 | 15 | instance.interceptors.response.use( 16 | function (response) { 17 | return response; 18 | }, 19 | function (error) { 20 | if (error.response != null && error.response.status != null) { 21 | if (error.response.status === 401 && !error.response.config.url.includes("/authenticate")) 22 | window.location = '/login' 23 | if (error.response.status === 412) 24 | window.location = '/upgrade' 25 | } 26 | else { 27 | error.response = { data: { message: error.message } } 28 | } 29 | return Promise.reject(error); 30 | }); 31 | 32 | instance.defaults.headers.post['Content-Type'] = 'application/json' 33 | instance.defaults.headers.common['Version'] = '1.0.0' 34 | 35 | export default instance; -------------------------------------------------------------------------------- /kraken-server/src/main/java/com/arcaneiceman/kraken/krakenserver/repository/WorkerRepository.java: -------------------------------------------------------------------------------- 1 | package com.arcaneiceman.kraken.krakenserver.repository; 2 | 3 | import com.arcaneiceman.kraken.krakenserver.domain.User; 4 | import com.arcaneiceman.kraken.krakenserver.domain.Worker; 5 | import com.arcaneiceman.kraken.krakenserver.domain.enumerations.WorkerStatus; 6 | import org.springframework.data.domain.Page; 7 | import org.springframework.data.domain.Pageable; 8 | import org.springframework.data.jpa.repository.JpaRepository; 9 | import org.springframework.data.jpa.repository.Lock; 10 | import org.springframework.stereotype.Repository; 11 | 12 | import javax.persistence.LockModeType; 13 | import java.util.Date; 14 | import java.util.List; 15 | import java.util.Optional; 16 | import java.util.stream.Stream; 17 | 18 | @Repository 19 | public interface WorkerRepository extends JpaRepository { 20 | 21 | @Lock(LockModeType.PESSIMISTIC_WRITE) 22 | Stream getByStatusAndLastCheckInBefore(WorkerStatus status, Date currentTimeMinusExpiry); 23 | 24 | @Lock(LockModeType.PESSIMISTIC_WRITE) 25 | Optional findByIdAndOwner(String id, User owner); 26 | 27 | Page findByOwner(User owner, Pageable pageable); 28 | 29 | List findByOwner(User owner); 30 | 31 | } 32 | -------------------------------------------------------------------------------- /kraken-client/src/containers/KrakenWorker/jobreporter.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-restricted-globals */ 2 | self.onmessage = (e) => { 3 | let response = {}; 4 | try { 5 | const request = { 6 | workerId: e.data.workerId, 7 | requestId: e.data.requestId, 8 | listId: e.data.listId, 9 | jobId: e.data.jobId, 10 | trackingStatus: e.data.trackingStatus, 11 | results: e.data.results, 12 | } 13 | var xhttp = new XMLHttpRequest(); 14 | xhttp.open("POST", e.data.path, false); 15 | xhttp.setRequestHeader("Authorization", "Bearer " + e.data.token) 16 | xhttp.setRequestHeader("Content-Type", "application/json;charset=UTF-8"); 17 | xhttp.setRequestHeader("Version", '1.0.0') 18 | xhttp.send(JSON.stringify(request)); 19 | 20 | switch (xhttp.status) { 21 | case 200: 22 | response.jobId = e.data.jobId; 23 | response.status = "SUCCESS" 24 | break; 25 | default: 26 | response.jobId = e.data.jobId; 27 | response.status = "ERROR" 28 | console.error("Report Job Error " + xhttp.status) 29 | } 30 | } 31 | finally{ 32 | self.postMessage(response) 33 | } 34 | 35 | } -------------------------------------------------------------------------------- /kraken-server/src/main/java/com/arcaneiceman/kraken/krakenserver/security/filters/SwaggerFilter.java: -------------------------------------------------------------------------------- 1 | package com.arcaneiceman.kraken.krakenserver.security.filters; 2 | 3 | import com.arcaneiceman.kraken.krakenserver.service.utils.SwaggerService; 4 | import org.springframework.web.filter.GenericFilterBean; 5 | 6 | import javax.servlet.FilterChain; 7 | import javax.servlet.ServletException; 8 | import javax.servlet.ServletRequest; 9 | import javax.servlet.ServletResponse; 10 | import javax.servlet.http.HttpServletRequest; 11 | import javax.servlet.http.HttpServletResponse; 12 | import java.io.IOException; 13 | 14 | public class SwaggerFilter extends GenericFilterBean { 15 | 16 | private final SwaggerService swaggerService; 17 | 18 | public SwaggerFilter(SwaggerService swaggerService) { 19 | this.swaggerService = swaggerService; 20 | } 21 | 22 | public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException { 23 | String path = ((HttpServletRequest) request).getServletPath(); 24 | if (path.endsWith(swaggerService.getSwaggerContextPath())) 25 | ((HttpServletResponse) response).sendRedirect("/swagger-ui.html"); 26 | else 27 | filterChain.doFilter(request, response); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /kraken-server/src/main/java/com/arcaneiceman/kraken/krakenserver/repository/ActiveRequestRepository.java: -------------------------------------------------------------------------------- 1 | package com.arcaneiceman.kraken.krakenserver.repository; 2 | 3 | import com.arcaneiceman.kraken.krakenserver.domain.ActiveRequest; 4 | import com.arcaneiceman.kraken.krakenserver.domain.User; 5 | import org.springframework.data.domain.Page; 6 | import org.springframework.data.domain.Pageable; 7 | import org.springframework.data.jpa.repository.JpaRepository; 8 | import org.springframework.data.jpa.repository.Lock; 9 | import org.springframework.stereotype.Repository; 10 | 11 | import javax.persistence.LockModeType; 12 | import java.util.List; 13 | import java.util.Optional; 14 | 15 | @Repository 16 | public interface ActiveRequestRepository extends JpaRepository { 17 | 18 | Page findByOwner(Pageable pageable, User owner); 19 | 20 | List findByOwner(User owner); 21 | 22 | //@QueryHints({@QueryHint(name = "javax.persistence.lock.timeout", value ="5000")}) 23 | @Lock(LockModeType.PESSIMISTIC_WRITE) 24 | ActiveRequest findFirstByOwner(User owner); 25 | 26 | //@QueryHints({@QueryHint(name = "javax.persistence.lock.timeout", value ="5000")}) 27 | @Lock(LockModeType.PESSIMISTIC_WRITE) 28 | Optional findByIdAndOwner(String id, User owner); 29 | 30 | } 31 | -------------------------------------------------------------------------------- /kraken-client/src/containers/Upgrade/Upgrade.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import isElectron from 'is-electron'; 3 | import Toolbar from '../../components/Toolbar/Toolbar'; 4 | 5 | import classes from './Upgrade.module.css' 6 | 7 | class Upgrade extends Component { 8 | 9 | render() { 10 | // NavLinks for Toolbar 11 | let navLinks = []; 12 | navLinks.push({ text: 'Login', onClick: () => { this.props.history.push('/login'); }, isPrimary: true }); 13 | navLinks.push({ text: 'Help', onClick: () => { this.props.history.push('/help') } }) 14 | navLinks.push({ text: 'Forgot Password', onClick: () => { this.props.history.push('/forgot-password'); } }) 15 | const toolbar = isElectron() ? : 16 | 17 | return ( 18 |
19 | {toolbar} 20 |
21 |

Please upgrade your client! This version is no longer supported!

22 |
23 |

For Browser : Empty cache and reload

24 |

For Desktop : Download the new client

25 |
26 |
27 | ); 28 | } 29 | 30 | } 31 | 32 | export default Upgrade; -------------------------------------------------------------------------------- /kraken-server/src/main/java/com/arcaneiceman/kraken/krakenserver/repository/JobRepository.java: -------------------------------------------------------------------------------- 1 | package com.arcaneiceman.kraken.krakenserver.repository; 2 | 3 | import com.arcaneiceman.kraken.krakenserver.domain.Job; 4 | import com.arcaneiceman.kraken.krakenserver.domain.abs.TrackedList; 5 | import com.arcaneiceman.kraken.krakenserver.domain.enumerations.TrackingStatus; 6 | import org.springframework.data.jpa.repository.JpaRepository; 7 | import org.springframework.data.jpa.repository.Lock; 8 | import org.springframework.stereotype.Repository; 9 | 10 | import javax.persistence.LockModeType; 11 | import java.util.Date; 12 | import java.util.Optional; 13 | import java.util.stream.Stream; 14 | 15 | @Repository 16 | public interface JobRepository extends JpaRepository { 17 | 18 | //@QueryHints({@QueryHint(name = "javax.persistence.lock.timeout", value ="5000")}) 19 | @Lock(LockModeType.PESSIMISTIC_WRITE) 20 | Stream findByTrackingStatusAndWillExpireAtBefore(TrackingStatus trackingStatus, Date currentTime); 21 | 22 | //@QueryHints({@QueryHint(name = "javax.persistence.lock.timeout", value ="5000")}) 23 | @Lock(LockModeType.PESSIMISTIC_WRITE) 24 | Optional findByIdAndOwner(String id, TrackedList owner); 25 | 26 | @Lock(LockModeType.PESSIMISTIC_WRITE) 27 | Job findFirstByOwnerAndTrackingStatus(TrackedList owner, TrackingStatus trackingStatus); 28 | } 29 | -------------------------------------------------------------------------------- /kraken-server/src/main/java/com/arcaneiceman/kraken/krakenserver/util/exceptions/DefaultExceptionHandlerAdvice.java: -------------------------------------------------------------------------------- 1 | package com.arcaneiceman.kraken.krakenserver.util.exceptions; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | import lombok.NoArgsConstructor; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | import org.springframework.http.HttpStatus; 9 | import org.springframework.http.ResponseEntity; 10 | import org.springframework.web.bind.annotation.ControllerAdvice; 11 | import org.springframework.web.bind.annotation.ExceptionHandler; 12 | 13 | import java.util.Objects; 14 | 15 | @ControllerAdvice 16 | public class DefaultExceptionHandlerAdvice { 17 | 18 | private static final Logger log = LoggerFactory.getLogger(DefaultExceptionHandlerAdvice.class); 19 | 20 | @ExceptionHandler(SystemException.class) 21 | public ResponseEntity handleException(SystemException e) { 22 | log.error("Error Code {}, Error Message : {}", e.getErrorCode(), e.getMessage()); 23 | return new ResponseEntity<>(new ExceptionDTO(e.getErrorCode(), e.getMessage()), 24 | HttpStatus.valueOf(Objects.requireNonNull(e.getStatus()).getStatusCode())); 25 | } 26 | 27 | @Data 28 | @AllArgsConstructor 29 | @NoArgsConstructor 30 | private class ExceptionDTO { 31 | private int code; 32 | private String message; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /kraken-server/src/main/java/com/arcaneiceman/kraken/krakenserver/controller/TestController.java: -------------------------------------------------------------------------------- 1 | package com.arcaneiceman.kraken.krakenserver.controller; 2 | 3 | import com.arcaneiceman.kraken.krakenserver.service.ActiveRequestService; 4 | import org.springframework.context.annotation.Profile; 5 | import org.springframework.http.HttpStatus; 6 | import org.springframework.validation.annotation.Validated; 7 | import org.springframework.web.bind.annotation.PostMapping; 8 | import org.springframework.web.bind.annotation.RequestMapping; 9 | import org.springframework.web.bind.annotation.ResponseStatus; 10 | import org.springframework.web.bind.annotation.RestController; 11 | 12 | @Profile("test") 13 | @RestController 14 | @RequestMapping("${application.context-path}") 15 | public class TestController { 16 | 17 | private final ActiveRequestService activeRequestService; 18 | 19 | public TestController(ActiveRequestService activeRequestService) { 20 | this.activeRequestService = activeRequestService; 21 | } 22 | 23 | @Validated 24 | @PostMapping("/expire-workers") 25 | @ResponseStatus(HttpStatus.OK) 26 | public void expireWorker() { 27 | activeRequestService.performWorkerTimeout(); 28 | } 29 | 30 | @Validated 31 | @PostMapping("/expire-jobs") 32 | @ResponseStatus(HttpStatus.OK) 33 | public void expireJob() { 34 | activeRequestService.performJobTimeout(); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /kraken-client/config/nginx.conf: -------------------------------------------------------------------------------- 1 | 2 | user nginx; 3 | worker_processes auto; 4 | 5 | error_log /var/log/nginx/error.log notice; 6 | pid /var/run/nginx.pid; 7 | 8 | 9 | events { 10 | worker_connections 1024; 11 | } 12 | 13 | 14 | http { 15 | include /etc/nginx/mime.types; 16 | default_type application/octet-stream; 17 | 18 | log_format main '$remote_addr - $remote_user [$time_local] "$request" ' 19 | '$status $body_bytes_sent "$http_referer" ' 20 | '"$http_user_agent" "$http_x_forwarded_for"'; 21 | 22 | access_log /var/log/nginx/access.log main; 23 | 24 | sendfile on; 25 | #tcp_nopush on; 26 | 27 | keepalive_timeout 65; 28 | 29 | #gzip on; 30 | 31 | include /etc/nginx/conf.d/*.conf; 32 | 33 | server { 34 | listen 443 ssl; 35 | server_name localhost; 36 | ssl_certificate /etc/nginx/ssl/nginx.cert; 37 | ssl_certificate_key /etc/nginx/ssl/nginx.key; 38 | root /usr/share/nginx/html; 39 | 40 | location /api { 41 | proxy_pass http://kraken-server:5000/api; 42 | } 43 | } 44 | 45 | server { 46 | listen 80; 47 | server_name localhost; 48 | root /usr/share/nginx/html; 49 | 50 | location /api { 51 | proxy_pass http://kraken-server:5000/api; 52 | } 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /kraken-client/config/jest/fileTransform.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const path = require('path'); 4 | const camelcase = require('camelcase'); 5 | 6 | // This is a custom Jest transformer turning file imports into filenames. 7 | // http://facebook.github.io/jest/docs/en/webpack.html 8 | 9 | module.exports = { 10 | process(src, filename) { 11 | const assetFilename = JSON.stringify(path.basename(filename)); 12 | 13 | if (filename.match(/\.svg$/)) { 14 | // Based on how SVGR generates a component name: 15 | // https://github.com/smooth-code/svgr/blob/01b194cf967347d43d4cbe6b434404731b87cf27/packages/core/src/state.js#L6 16 | const pascalCaseFileName = camelcase(path.parse(filename).name, { 17 | pascalCase: true, 18 | }); 19 | const componentName = `Svg${pascalCaseFileName}`; 20 | return `const React = require('react'); 21 | module.exports = { 22 | __esModule: true, 23 | default: ${assetFilename}, 24 | ReactComponent: React.forwardRef(function ${componentName}(props, ref) { 25 | return { 26 | $$typeof: Symbol.for('react.element'), 27 | type: 'svg', 28 | ref: ref, 29 | key: null, 30 | props: Object.assign({}, props, { 31 | children: ${assetFilename} 32 | }) 33 | }; 34 | }), 35 | };`; 36 | } 37 | 38 | return `module.exports = ${assetFilename};`; 39 | }, 40 | }; 41 | -------------------------------------------------------------------------------- /kraken-server/src/main/java/com/arcaneiceman/kraken/krakenserver/controller/PasswordListController.java: -------------------------------------------------------------------------------- 1 | package com.arcaneiceman.kraken.krakenserver.controller; 2 | 3 | import com.arcaneiceman.kraken.krakenserver.domain.PasswordList; 4 | import com.arcaneiceman.kraken.krakenserver.security.AuthoritiesConstants; 5 | import com.arcaneiceman.kraken.krakenserver.service.utils.PasswordListService; 6 | import org.springframework.data.domain.Page; 7 | import org.springframework.data.domain.Pageable; 8 | import org.springframework.http.HttpStatus; 9 | import org.springframework.security.access.annotation.Secured; 10 | import org.springframework.validation.annotation.Validated; 11 | import org.springframework.web.bind.annotation.*; 12 | 13 | @RestController 14 | @RequestMapping("${application.context-path}") 15 | public class PasswordListController { 16 | 17 | private PasswordListService passwordListService; 18 | 19 | public PasswordListController(PasswordListService passwordListService) { 20 | this.passwordListService = passwordListService; 21 | } 22 | 23 | @Validated 24 | @GetMapping("/password-list") 25 | @Secured(AuthoritiesConstants.CONSUMER) 26 | @ResponseStatus(HttpStatus.OK) 27 | Page list(Pageable pageable, 28 | @RequestHeader(value = "Authorization") String bearerToken, 29 | @RequestHeader(value = "Version") String apiVersion) { 30 | return passwordListService.list(pageable); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /kraken-server/src/main/java/com/arcaneiceman/kraken/krakenserver/security/SecurityUtils.java: -------------------------------------------------------------------------------- 1 | package com.arcaneiceman.kraken.krakenserver.security; 2 | 3 | import com.arcaneiceman.kraken.krakenserver.util.exceptions.SystemException; 4 | import org.springframework.security.core.Authentication; 5 | import org.springframework.security.core.context.SecurityContext; 6 | import org.springframework.security.core.context.SecurityContextHolder; 7 | import org.springframework.security.core.userdetails.UserDetails; 8 | import org.zalando.problem.Status; 9 | 10 | /** 11 | * Created by Wali on 13/03/18. 12 | */ 13 | public class SecurityUtils { 14 | 15 | public static String getCurrentUsernameFromContext() { 16 | try { 17 | SecurityContext securityContext = SecurityContextHolder.getContext(); 18 | Authentication authentication = securityContext.getAuthentication(); 19 | if (authentication.getPrincipal() instanceof UserDetails) { 20 | UserDetails springSecurityUser = (UserDetails) authentication.getPrincipal(); 21 | return springSecurityUser.getUsername(); 22 | } else if (authentication.getPrincipal() instanceof String) 23 | return (String) authentication.getPrincipal(); 24 | else 25 | throw new Exception(); 26 | } catch (Exception e) { 27 | throw new SystemException(1, "Failed to retrieve security context", Status.INTERNAL_SERVER_ERROR); 28 | } 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /kraken-client/src/containers/Dashboard/Dashboard.module.css: -------------------------------------------------------------------------------- 1 | .container { 2 | display: flex; 3 | flex-direction: column; 4 | padding-left: 5%; 5 | padding-right: 5%; 6 | padding-bottom: 2%; 7 | } 8 | 9 | .dashboardAlertContainer { 10 | display: flex; 11 | justify-content: center; 12 | min-width: 50%; 13 | max-width: 50%; 14 | align-self: center; 15 | } 16 | 17 | .responsiveLayout { 18 | display: flex; 19 | flex-direction: row; 20 | flex-wrap: nowrap; 21 | } 22 | 23 | .main { 24 | display: flex; 25 | flex-direction: column; 26 | min-width: 60%; 27 | margin-right: 2.5%; 28 | } 29 | 30 | .side { 31 | display: flex; 32 | flex-direction: column; 33 | min-width: 35%; 34 | margin-left: 2.5% 35 | } 36 | 37 | .newRequestTrackedListBox { 38 | display: flex; 39 | flex-direction: row; 40 | flex-wrap: wrap; 41 | margin-bottom: 8px; 42 | min-height: 50px; 43 | border-radius: 5px; 44 | border: 0.5px solid grey; 45 | } 46 | 47 | .newRequestTrackedListPill { 48 | background-color: #ddd; 49 | border: none; 50 | color: black; 51 | padding: 5px 5px; 52 | text-align: center; 53 | text-decoration: none; 54 | display: inline-block; 55 | margin: 4px 4px; 56 | cursor: pointer; 57 | border-radius: 16px; 58 | } 59 | 60 | .modal_form_label{ 61 | font-size: 12px; 62 | font-weight: 400; 63 | color: #524e4e; 64 | } 65 | 66 | .errorMessage { 67 | flex-grow: 1; 68 | color: red; 69 | } 70 | 71 | .formGroup { 72 | margin-bottom: auto 73 | } -------------------------------------------------------------------------------- /kraken-client/public/electron.js: -------------------------------------------------------------------------------- 1 | const electron = require("electron"); 2 | const path = require("path"); 3 | const isDev = require("electron-is-dev"); 4 | let mainWindow; 5 | 6 | function createWindow() { 7 | mainWindow = new electron.BrowserWindow({ 8 | width: 1200, height: 800, minWidth: 1200, minHeight: 800, 9 | webPreferences: { nodeIntegration: true, devTools: true } 10 | }); 11 | if (isDev) { 12 | mainWindow.loadURL("http://localhost:3000") 13 | mainWindow.webContents.openDevTools(); 14 | } 15 | else { 16 | mainWindow.loadURL(`file://${path.join(__dirname, "../build/index.html")}`) 17 | } 18 | 19 | // Hide Menu Bar 20 | mainWindow.setMenuBarVisibility(false) 21 | 22 | // Handle External Links 23 | mainWindow.webContents.on('new-window', function (e, url) { 24 | e.preventDefault(); 25 | electron.shell.openExternal(url); 26 | }); 27 | 28 | // Handle Close 29 | mainWindow.on("closed", () => (mainWindow = null)); 30 | 31 | // Set Content Security Policy 32 | electron.session.defaultSession.webRequest.onHeadersReceived((details, callback) => { 33 | callback({ 34 | responseHeaders: { 35 | ...details.responseHeaders, 36 | 'Content-Security-Policy': ['script-src \'self\' \'unsafe-eval\' \'unsafe-inline\''] 37 | } 38 | }) 39 | }) 40 | } 41 | 42 | electron.app.on("ready", createWindow); 43 | 44 | electron.app.on("window-all-closed", () => { 45 | if (process.platform !== "darwin") { 46 | electron.app.quit(); 47 | } 48 | }); 49 | 50 | electron.app.on("activate", () => { 51 | if (mainWindow === null) { 52 | createWindow(); 53 | } 54 | }); 55 | -------------------------------------------------------------------------------- /kraken-client/web-scripts/test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | // Do this as the first thing so that any code reading it knows the right env. 4 | process.env.BABEL_ENV = 'test'; 5 | process.env.NODE_ENV = 'test'; 6 | process.env.PUBLIC_URL = ''; 7 | 8 | // Makes the script crash on unhandled rejections instead of silently 9 | // ignoring them. In the future, promise rejections that are not handled will 10 | // terminate the Node.js process with a non-zero exit code. 11 | process.on('unhandledRejection', err => { 12 | throw err; 13 | }); 14 | 15 | // Ensure environment variables are read. 16 | require('../config/env'); 17 | 18 | 19 | const jest = require('jest'); 20 | const execSync = require('child_process').execSync; 21 | let argv = process.argv.slice(2); 22 | 23 | function isInGitRepository() { 24 | try { 25 | execSync('git rev-parse --is-inside-work-tree', { stdio: 'ignore' }); 26 | return true; 27 | } catch (e) { 28 | return false; 29 | } 30 | } 31 | 32 | function isInMercurialRepository() { 33 | try { 34 | execSync('hg --cwd . root', { stdio: 'ignore' }); 35 | return true; 36 | } catch (e) { 37 | return false; 38 | } 39 | } 40 | 41 | // Watch unless on CI or explicitly running all tests 42 | if ( 43 | !process.env.CI && 44 | argv.indexOf('--watchAll') === -1 && 45 | argv.indexOf('--watchAll=false') === -1 46 | ) { 47 | // https://github.com/facebook/create-react-app/issues/5210 48 | const hasSourceControl = isInGitRepository() || isInMercurialRepository(); 49 | argv.push(hasSourceControl ? '--watch' : '--watchAll'); 50 | } 51 | 52 | 53 | jest.run(argv); 54 | -------------------------------------------------------------------------------- /kraken-server/src/main/java/com/arcaneiceman/kraken/krakenserver/domain/embeddedable/CompleteTrackedList.java: -------------------------------------------------------------------------------- 1 | package com.arcaneiceman.kraken.krakenserver.domain.embeddedable; 2 | 3 | import com.arcaneiceman.kraken.krakenserver.domain.abs.TrackedList; 4 | import com.arcaneiceman.kraken.krakenserver.domain.enumerations.ListType; 5 | import com.arcaneiceman.kraken.krakenserver.domain.enumerations.TrackingStatus; 6 | import lombok.Data; 7 | import lombok.NoArgsConstructor; 8 | 9 | import javax.persistence.Column; 10 | import javax.persistence.Embeddable; 11 | import javax.persistence.EnumType; 12 | import javax.persistence.Enumerated; 13 | 14 | @Data 15 | @NoArgsConstructor 16 | @Embeddable 17 | public class CompleteTrackedList { 18 | 19 | @Column 20 | private String listName; 21 | @Column 22 | @Enumerated(EnumType.STRING) 23 | private ListType listType; 24 | @Column 25 | @Enumerated(EnumType.STRING) 26 | private TrackingStatus trackingStatus; 27 | @Column 28 | private Long totalJobCount; 29 | @Column 30 | private Long completedJobCount; 31 | @Column 32 | private Long errorJobCount; 33 | 34 | public CompleteTrackedList(TrackedList trackedList) { 35 | this.listName = trackedList.getListName(); 36 | this.listType = trackedList.getListType(); 37 | this.trackingStatus = trackedList.getTrackingStatus(); 38 | this.totalJobCount = trackedList.getTotalJobCount(); 39 | this.completedJobCount = trackedList.getCompletedJobCount(); 40 | this.errorJobCount = trackedList.getErrorJobCount(); 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /kraken-client/src/containers/Workers/Workers.module.css: -------------------------------------------------------------------------------- 1 | .main { 2 | background: #fff; 3 | border: 1px solid #dbdbdb; 4 | border-radius: 4px; 5 | box-shadow: 2px 2px 3px rgba(0,0,0,.05); 6 | margin: 0 5px 10px 0; 7 | position: relative; 8 | text-align: left; 9 | } 10 | 11 | .loadingBackground{ 12 | width: 100%; 13 | height: 100%; 14 | position: absolute; 15 | background: black; 16 | opacity: 0.2; 17 | } 18 | 19 | .loadingSpinner{ 20 | position: absolute; 21 | top: 50%; 22 | left: 50%; 23 | opacity: 1; 24 | } 25 | 26 | .detailContainer { 27 | display: flex; 28 | flex-direction: row; 29 | justify-content: flex-start; 30 | } 31 | 32 | .detailModalDetailContainer{ 33 | display: flex; 34 | justify-content: space-between; 35 | margin: 5px; 36 | } 37 | 38 | .detailModalHeading{ 39 | white-space: nowrap; 40 | color: #959595; 41 | font-size: 0.55rem; 42 | font-weight: 400; 43 | letter-spacing: 2px; 44 | text-transform: uppercase; 45 | margin: 10px; 46 | } 47 | 48 | .detailModalValue{ 49 | margin: 10px; 50 | } 51 | 52 | .lastDetailItem { 53 | flex-grow: 1; 54 | } 55 | 56 | .tableRowWithValue { 57 | cursor: copy; 58 | } 59 | 60 | .tableItem { 61 | padding: 15px 10px; 62 | text-align: left; 63 | font-size: 14px; 64 | vertical-align: middle; 65 | border-bottom: 1px solid #dbdbdb; 66 | line-height: 1.3; 67 | } 68 | 69 | .tableHeaderColumnText { 70 | color: #fff; 71 | font-weight: 700; 72 | padding: 15px 10px; 73 | font-size: 14px; 74 | text-align: left; 75 | } -------------------------------------------------------------------------------- /kraken-server/src/main/java/com/arcaneiceman/kraken/krakenserver/config/SwaggerConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.arcaneiceman.kraken.krakenserver.config; 2 | 3 | import org.springframework.beans.factory.annotation.Value; 4 | import org.springframework.context.annotation.Bean; 5 | import org.springframework.context.annotation.Configuration; 6 | import springfox.documentation.builders.ApiInfoBuilder; 7 | import springfox.documentation.builders.PathSelectors; 8 | import springfox.documentation.builders.RequestHandlerSelectors; 9 | import springfox.documentation.service.Contact; 10 | import springfox.documentation.spi.DocumentationType; 11 | import springfox.documentation.spring.web.plugins.Docket; 12 | import springfox.documentation.swagger2.annotations.EnableSwagger2; 13 | 14 | @Configuration 15 | @EnableSwagger2 16 | public class SwaggerConfiguration { 17 | 18 | @Value("${application.api-version}") 19 | private String apiVersion; 20 | 21 | @Bean 22 | public Docket api() { 23 | return new Docket(DocumentationType.SWAGGER_2) 24 | .select() 25 | .apis(RequestHandlerSelectors.basePackage("com.arcaneiceman.kraken.krakenserver.controller")) 26 | .paths(PathSelectors.any()) 27 | .build() 28 | .apiInfo(new ApiInfoBuilder() 29 | .title("Kraken Server API") 30 | .description("Swagger Documentation for Kraken Server") 31 | .version(apiVersion) 32 | .contact(new Contact("Wali Usmani", "https://github.com/arcaneiceman", "-")).build()); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /kraken-server/src/main/java/com/arcaneiceman/kraken/krakenserver/config/DependencyConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.arcaneiceman.kraken.krakenserver.config; 2 | 3 | import com.arcaneiceman.kraken.krakenserver.util.ConsoleCommandUtil; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.context.annotation.Configuration; 8 | 9 | import java.io.IOException; 10 | import java.util.concurrent.ExecutionException; 11 | import java.util.concurrent.TimeUnit; 12 | 13 | @Configuration 14 | public class DependencyConfiguration { 15 | 16 | private static Logger log = LoggerFactory.getLogger(DependencyConfiguration.class); 17 | 18 | @Autowired 19 | public DependencyConfiguration() throws IOException, InterruptedException, ExecutionException { 20 | String testCap2Hccapx = ConsoleCommandUtil.executeCommandInConsole( 21 | 1, TimeUnit.SECONDS, ConsoleCommandUtil.OutputStream.ERROR, "cap2hccapx"); 22 | if (testCap2Hccapx != null && testCap2Hccapx.contains("usage")) 23 | log.info("Cap2Hccapx Found"); 24 | else 25 | throw new RuntimeException("Cap2Hccapx was not found on this machine!"); 26 | String testCrunch = ConsoleCommandUtil.executeCommandInConsole( 27 | 1, TimeUnit.SECONDS, ConsoleCommandUtil.OutputStream.ERROR, "crunch"); 28 | if (testCrunch != null && testCrunch.contains("Crunch")) 29 | log.info("Crunch Found"); 30 | else 31 | throw new RuntimeException("Crunch was not found on this machine!"); 32 | } 33 | 34 | 35 | } 36 | -------------------------------------------------------------------------------- /kraken-server/src/main/java/com/arcaneiceman/kraken/krakenserver/security/filters/VersionFilter.java: -------------------------------------------------------------------------------- 1 | package com.arcaneiceman.kraken.krakenserver.security.filters; 2 | 3 | import com.arcaneiceman.kraken.krakenserver.service.utils.VersionService; 4 | import org.springframework.web.filter.GenericFilterBean; 5 | 6 | import javax.servlet.FilterChain; 7 | import javax.servlet.ServletException; 8 | import javax.servlet.ServletRequest; 9 | import javax.servlet.ServletResponse; 10 | import javax.servlet.http.HttpServletRequest; 11 | import javax.servlet.http.HttpServletResponse; 12 | import java.io.IOException; 13 | 14 | import static com.arcaneiceman.kraken.krakenserver.config.Constants.VERSION_HEADER; 15 | 16 | public class VersionFilter extends GenericFilterBean { 17 | 18 | private VersionService versionService; 19 | 20 | public VersionFilter(VersionService versionService) { 21 | this.versionService = versionService; 22 | } 23 | 24 | @Override 25 | public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException { 26 | HttpServletRequest httpServletRequest = (HttpServletRequest) request; 27 | if (((HttpServletRequest) request).getRequestURI().contains("/api/")) 28 | if (versionService.isVersionEqual(httpServletRequest.getHeader(VERSION_HEADER))) 29 | filterChain.doFilter(request, response); 30 | else 31 | ((HttpServletResponse) response).sendError(HttpServletResponse.SC_PRECONDITION_FAILED, 32 | VERSION_HEADER + " header does not match " + versionService.getApiVersion()); 33 | else 34 | filterChain.doFilter(request, response); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /kraken-server/src/main/java/com/arcaneiceman/kraken/krakenserver/util/ConsoleCommandUtil.java: -------------------------------------------------------------------------------- 1 | package com.arcaneiceman.kraken.krakenserver.util; 2 | 3 | import com.amazonaws.util.IOUtils; 4 | 5 | import java.io.IOException; 6 | import java.util.concurrent.*; 7 | 8 | public class ConsoleCommandUtil { 9 | 10 | public static String executeCommandInConsole(long timeout, 11 | TimeUnit timeUnit, 12 | OutputStream outputStream, 13 | String... commands) throws IOException, InterruptedException, ExecutionException { 14 | // Create Two Spawned Threads for Handling output and error 15 | ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(2); 16 | 17 | ProcessBuilder pb = new ProcessBuilder(commands); 18 | Process process = pb.start(); 19 | Future output = newFixedThreadPool.submit(() -> IOUtils.toString(process.getInputStream())); 20 | Future error = newFixedThreadPool.submit(() -> IOUtils.toString(process.getErrorStream())); 21 | 22 | newFixedThreadPool.shutdown(); 23 | 24 | if (timeout != 0 && timeUnit != null) 25 | if (!process.waitFor(timeout, timeUnit)) 26 | process.destroy(); 27 | else 28 | process.waitFor(); 29 | 30 | switch (outputStream) { 31 | case ERROR: 32 | return error.get(); 33 | case OUT: 34 | return output.get(); 35 | default: 36 | return null; 37 | } 38 | } 39 | 40 | public enum OutputStream { 41 | ERROR, OUT 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /kraken-server/src/main/java/com/arcaneiceman/kraken/krakenserver/controller/io/WorkerIO.java: -------------------------------------------------------------------------------- 1 | package com.arcaneiceman.kraken.krakenserver.controller.io; 2 | 3 | import com.arcaneiceman.kraken.krakenserver.domain.enumerations.WorkerType; 4 | import io.swagger.annotations.ApiModel; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Getter; 7 | import lombok.NoArgsConstructor; 8 | import lombok.Setter; 9 | 10 | import javax.validation.constraints.NotBlank; 11 | import javax.validation.constraints.NotNull; 12 | 13 | public class WorkerIO { 14 | 15 | public static class Heartbeat { 16 | 17 | @Getter 18 | @NoArgsConstructor 19 | @AllArgsConstructor 20 | @ApiModel("Worker.Heartbeat.Request") 21 | public static class Request { 22 | 23 | @NotNull 24 | String id; 25 | } 26 | } 27 | 28 | public static class Create { 29 | 30 | @Getter 31 | @NoArgsConstructor 32 | @AllArgsConstructor 33 | @ApiModel("Worker.Create.Request") 34 | public static class Request { 35 | 36 | @NotNull 37 | @NotBlank 38 | private String workerName; 39 | 40 | @NotNull 41 | private WorkerType workerType; 42 | 43 | private String platform; 44 | } 45 | } 46 | 47 | public static class Summary { 48 | 49 | @Getter 50 | @Setter 51 | @NoArgsConstructor 52 | @AllArgsConstructor 53 | @ApiModel("Worker.Summary.Response") 54 | public static class Response { 55 | 56 | private int totalActiveWorkers; 57 | 58 | private int totalOnlineWorkers; 59 | 60 | private int totalOfflineWorkers; 61 | 62 | private long jobsInQueue; 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /kraken-client/src/containers/Login/Login.module.css: -------------------------------------------------------------------------------- 1 | .header{ 2 | padding: 40px 0 100px; 3 | text-align: center; 4 | } 5 | 6 | .title{ 7 | color: #524e4e; 8 | font-weight: 100; 9 | font-size: 56px; 10 | padding: 0; 11 | margin: 0 0 20px; 12 | } 13 | 14 | .loginContainer{ 15 | display: flex; 16 | flex-direction: column; 17 | margin: -80px auto 0; 18 | border: 2px solid #557A95; 19 | padding: 30px 40px; 20 | /*max-width: 50vw;*/ 21 | max-width: 25vw; 22 | } 23 | 24 | .loginSocial{ 25 | display: flex; 26 | flex-direction: column; 27 | min-width: 15vw; 28 | justify-content: space-around 29 | } 30 | 31 | .loginSeperator{ 32 | left: 50%; 33 | transform: translate(-50%); 34 | border: 2px solid #ddd; 35 | height: inherit; 36 | } 37 | 38 | .loginSeperatorText{ 39 | position: absolute; 40 | top: 50%; 41 | transform: translate(-50%, -50%); 42 | background-color: #f1f1f1; 43 | border: 2px solid #ccc; 44 | border-radius: 50%; 45 | padding: 5.5px 10px; 46 | } 47 | 48 | .loginForm{ 49 | display: flex; 50 | flex-direction: column; 51 | text-align: left; 52 | min-width: 15vw; 53 | } 54 | 55 | .form_status_container{ 56 | display: flex; 57 | justify-content: center; 58 | margin-bottom : 10px; 59 | } 60 | 61 | .form_input_postpend { 62 | max-width: 16px; 63 | color: "#557A95"; 64 | cursor: 'pointer'; 65 | } 66 | 67 | .submit_container{ 68 | display: flex; 69 | justify-content: center; 70 | margin: 20px; 71 | text-align: center 72 | } 73 | 74 | .loginContainerFooter{ 75 | text-decoration: #524e4e; 76 | display: flex; 77 | /*justify-content: space-between;*/ 78 | justify-content: center; 79 | } 80 | 81 | .bitcoinAddress{ 82 | margin-top: -10px; 83 | font-weight: bold; 84 | } -------------------------------------------------------------------------------- /kraken-server/src/main/java/com/arcaneiceman/kraken/krakenserver/domain/Worker.java: -------------------------------------------------------------------------------- 1 | package com.arcaneiceman.kraken.krakenserver.domain; 2 | 3 | import com.arcaneiceman.kraken.krakenserver.domain.enumerations.WorkerStatus; 4 | import com.arcaneiceman.kraken.krakenserver.domain.enumerations.WorkerType; 5 | import com.fasterxml.jackson.annotation.JsonIgnore; 6 | import lombok.AllArgsConstructor; 7 | import lombok.Getter; 8 | import lombok.NoArgsConstructor; 9 | import lombok.Setter; 10 | import org.hibernate.annotations.CacheConcurrencyStrategy; 11 | import org.hibernate.annotations.GenericGenerator; 12 | 13 | import javax.persistence.*; 14 | import java.util.Date; 15 | import java.util.List; 16 | 17 | @NoArgsConstructor 18 | @AllArgsConstructor 19 | @Getter 20 | @Setter 21 | @Table(name = "workers") 22 | @Entity 23 | @org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE) 24 | public class Worker { 25 | 26 | private static final long serialVersionUID = 1L; 27 | 28 | @Id 29 | @GeneratedValue(generator = "uuid2") 30 | @GenericGenerator(name = "uuid2", strategy = "uuid2") 31 | private String id; 32 | 33 | @Column 34 | private String name; 35 | 36 | @Column 37 | @Enumerated(EnumType.STRING) 38 | private WorkerType type; 39 | 40 | @Column(columnDefinition = "TEXT") 41 | private String platform; 42 | 43 | @Column 44 | private Long totalJobCount; 45 | 46 | @Column 47 | private Long completedJobCount; 48 | 49 | @Column 50 | private Long errorJobCount; 51 | 52 | @Column 53 | @Enumerated(EnumType.STRING) 54 | private WorkerStatus status; 55 | 56 | @Column 57 | private Date lastCheckIn; 58 | 59 | @OneToMany(mappedBy = "worker", fetch = FetchType.LAZY) 60 | private List jobList; 61 | 62 | @JsonIgnore 63 | @ManyToOne 64 | private User owner; 65 | 66 | } 67 | -------------------------------------------------------------------------------- /kraken-client/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 15 | 16 | 25 | React App 26 | 27 | 28 | 29 |
30 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /kraken-server/src/main/java/com/arcaneiceman/kraken/krakenserver/security/filters/JWTBlacklistFilter.java: -------------------------------------------------------------------------------- 1 | package com.arcaneiceman.kraken.krakenserver.security.filters; 2 | 3 | import com.arcaneiceman.kraken.krakenserver.config.Constants; 4 | import com.arcaneiceman.kraken.krakenserver.service.utils.TokenBlacklistService; 5 | import org.springframework.web.filter.GenericFilterBean; 6 | 7 | import javax.servlet.FilterChain; 8 | import javax.servlet.ServletException; 9 | import javax.servlet.ServletRequest; 10 | import javax.servlet.ServletResponse; 11 | import javax.servlet.http.HttpServletResponse; 12 | import java.io.IOException; 13 | 14 | /** 15 | * Security Filter : {@link JWTBlacklistFilter} 16 | *

17 | * Filter Order : Second 18 | *

19 | * Checks if the blacklist cache contains the token (token's digest to be more specific) 20 | *

21 | * If it exists: 22 | * Throw {@link HttpServletResponse}.SC_UNAUTHORIZED error 23 | * Else: 24 | * Allow pass through 25 | */ 26 | public class JWTBlacklistFilter extends GenericFilterBean { 27 | 28 | private TokenBlacklistService tokenBlacklistService; 29 | 30 | public JWTBlacklistFilter(TokenBlacklistService tokenBlacklistService) { 31 | this.tokenBlacklistService = tokenBlacklistService; 32 | } 33 | 34 | @Override 35 | public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) 36 | throws IOException, ServletException { 37 | String blacklist_digest = (String) servletRequest.getAttribute(Constants.BLACKLIST_DIGEST_KEY); 38 | if (blacklist_digest != null && tokenBlacklistService.isInBlacklist(blacklist_digest)) 39 | ((HttpServletResponse) servletResponse).sendError(HttpServletResponse.SC_UNAUTHORIZED, "The token is blocked"); 40 | else 41 | filterChain.doFilter(servletRequest, servletResponse); 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /kraken-server/src/main/java/com/arcaneiceman/kraken/krakenserver/config/AsyncConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.arcaneiceman.kraken.krakenserver.config; 2 | 3 | import org.springframework.beans.factory.annotation.Value; 4 | import org.springframework.context.annotation.Configuration; 5 | import org.springframework.context.annotation.PropertySource; 6 | import org.springframework.scheduling.annotation.AsyncConfigurer; 7 | import org.springframework.scheduling.annotation.EnableAsync; 8 | import org.springframework.scheduling.annotation.EnableScheduling; 9 | import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; 10 | 11 | import java.util.concurrent.Executor; 12 | 13 | @Configuration 14 | @EnableAsync 15 | @EnableScheduling 16 | @PropertySource("application.yaml") 17 | public class AsyncConfiguration implements AsyncConfigurer { 18 | 19 | @Value("${application.async.core-pool-size}") 20 | private int corePoolSize; 21 | 22 | @Value("${application.async.max-pool-size}") 23 | private int maxPoolSize; 24 | 25 | @Value("${application.async.queue-capacity}") 26 | private int queueCapacity; 27 | 28 | @Value("${application.async.thread-name}") 29 | private String threadName; 30 | 31 | @Override 32 | public Executor getAsyncExecutor() { 33 | corePoolSize = corePoolSize == 0 ? 5 : corePoolSize; 34 | maxPoolSize = maxPoolSize == 0 ? 5 : maxPoolSize; 35 | queueCapacity = queueCapacity == 0 ? 100 : queueCapacity; 36 | threadName = threadName == null ? "Async Executor Thread" : threadName; 37 | ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); 38 | executor.setCorePoolSize(corePoolSize); 39 | executor.setMaxPoolSize(maxPoolSize); 40 | executor.setQueueCapacity(queueCapacity); 41 | executor.setThreadNamePrefix(threadName); 42 | executor.initialize(); 43 | return executor; 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /kraken-client/src/App.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { BrowserRouter, Route, Switch } from 'react-router-dom' 3 | import Home from './containers/Home/Home' 4 | import Dashboard from './containers/Dashboard/Dashboard' 5 | import Login from './containers/Login/Login' 6 | import Register from './containers/Register/Register' 7 | import Activation from './containers/Activation/Activation' 8 | import ChangePassword from './containers/ChangePassword/ChangePassword' 9 | import ForgotPassword from './containers/ForgotPassword/ForgotPassword' 10 | import Upgrade from './containers/Upgrade/Upgrade'; 11 | import Help from './containers/Help/Help' 12 | import { version } from './utils/AppVersion' 13 | 14 | import krakenLogo from './assets/kraken-logo.png'; 15 | 16 | class App extends Component { 17 | 18 | componentDidMount(){ 19 | document.title = "Kraken Client v" + version 20 | } 21 | 22 | render() { 23 | return ( 24 | 25 |

26 |
27 | 28 |
29 | 30 | {/* Secure Routes */} 31 | 32 | 33 | {/* Insecure Routes */} 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 |
43 | 44 | ); 45 | } 46 | 47 | } 48 | 49 | export default App; 50 | -------------------------------------------------------------------------------- /kraken-server/src/main/java/com/arcaneiceman/kraken/krakenserver/domain/Job.java: -------------------------------------------------------------------------------- 1 | package com.arcaneiceman.kraken.krakenserver.domain; 2 | 3 | import com.arcaneiceman.kraken.krakenserver.domain.abs.TrackedList; 4 | import com.arcaneiceman.kraken.krakenserver.domain.enumerations.TrackingStatus; 5 | import com.fasterxml.jackson.annotation.JsonIgnore; 6 | import lombok.*; 7 | import org.hibernate.annotations.CacheConcurrencyStrategy; 8 | import org.hibernate.annotations.GenericGenerator; 9 | 10 | import javax.persistence.*; 11 | import java.util.Date; 12 | import java.util.List; 13 | 14 | /** 15 | * Created by Wali on 4/21/2018. 16 | */ 17 | @EqualsAndHashCode(callSuper = false, of = {"startIndex", "startMarker"}) 18 | @Getter 19 | @Setter 20 | @NoArgsConstructor 21 | @AllArgsConstructor 22 | @Embeddable 23 | @Table(name = "jobs") 24 | @Entity 25 | @org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE) 26 | public class Job { 27 | 28 | private static final long serialVersionUID = 1L; 29 | 30 | /** 31 | * Using synthetic key to avoid repeating data 32 | */ 33 | @JsonIgnore 34 | @Id 35 | @GeneratedValue(generator = "uuid2") 36 | @GenericGenerator(name = "uuid2", strategy = "uuid2") 37 | private String id; 38 | 39 | // Used by Password Lists and Crunch Lists 40 | @Column 41 | private Long startIndex; 42 | 43 | // Used by Crunch List 44 | @Column 45 | private String startMarker; 46 | 47 | @Column 48 | private Long multiplier; 49 | 50 | @Column 51 | @Enumerated(EnumType.STRING) 52 | private TrackingStatus trackingStatus; 53 | 54 | @Column 55 | private Integer errorCount; 56 | 57 | @Column 58 | private Date willExpireAt; 59 | 60 | @JsonIgnore 61 | @ManyToOne(fetch = FetchType.LAZY) 62 | private Worker worker; 63 | 64 | @JsonIgnore 65 | @ManyToOne(fetch = FetchType.LAZY) 66 | private TrackedList owner; 67 | 68 | @Transient 69 | private List values; 70 | 71 | } 72 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '3' 2 | 3 | services: 4 | 5 | db: 6 | container_name: postgres 7 | image: postgres 8 | restart: always 9 | environment: 10 | POSTGRES_DB: kraken 11 | POSTGRES_USER: root 12 | POSTGRES_PASSWORD: root 13 | ports: 14 | - "5432:5432" 15 | 16 | s3: 17 | container_name: minio 18 | image: minio/minio 19 | environment: 20 | - MINIO_ROOT_USER=admin 21 | - MINIO_ROOT_PASSWORD=password 22 | ports: 23 | - "9000:9000" 24 | - "9001:9001" 25 | volumes: 26 | - ./kraken-server/s3:/data 27 | command: server /data --console-address ":9001" 28 | 29 | kraken-server: 30 | container_name: server 31 | image: krakendbpc/kraken-server 32 | ports: 33 | - "5000:5000" 34 | command: java 35 | -Dapplication.security.jwt-token-signing-key=password 36 | -Dspring.datasource.url=jdbc:postgresql://db:5432/kraken 37 | -Dspring.datasource.username=root -Dspring.datasource.password=root 38 | -Dfile-storage.url=http://s3:9000 39 | -Dfile-storage.access-key=admin -Dfile-storage.secret-key=password 40 | -Dspring.security.user.password=password 41 | -Dspring.mail.host=url -Dspring.mail.port=0 42 | -Dspring.mail.username=username -Dspring.mail.password=password 43 | -Dapplication.mail.from-address=email -Dapplication.mail.web-url=http://localhost:3000 44 | -Dapplication.recaptcha.secret=secret 45 | -jar kraken-server.jar 46 | depends_on: 47 | - "db" 48 | - "s3" 49 | 50 | kraken-client: 51 | container_name: client 52 | image: krakendbpc/kraken-client 53 | ports: 54 | - "8443:443" 55 | - "8080:80" 56 | depends_on: 57 | - "kraken-server" 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /kraken-server/src/main/java/com/arcaneiceman/kraken/krakenserver/security/DomainUserDetailsService.java: -------------------------------------------------------------------------------- 1 | package com.arcaneiceman.kraken.krakenserver.security; 2 | 3 | import com.arcaneiceman.kraken.krakenserver.domain.User; 4 | import com.arcaneiceman.kraken.krakenserver.repository.UserRepository; 5 | import org.springframework.security.core.GrantedAuthority; 6 | import org.springframework.security.core.authority.SimpleGrantedAuthority; 7 | import org.springframework.security.core.userdetails.UserDetails; 8 | import org.springframework.security.core.userdetails.UserDetailsService; 9 | import org.springframework.security.core.userdetails.UsernameNotFoundException; 10 | import org.springframework.stereotype.Component; 11 | import org.springframework.transaction.annotation.Transactional; 12 | 13 | import java.util.ArrayList; 14 | import java.util.List; 15 | import java.util.Locale; 16 | 17 | /** 18 | * Authenticate a user from the database. 19 | */ 20 | @Component("userDetailsService") 21 | public class DomainUserDetailsService implements UserDetailsService { 22 | 23 | private final UserRepository userRepository; 24 | 25 | public DomainUserDetailsService(UserRepository userRepository) { 26 | this.userRepository = userRepository; 27 | } 28 | 29 | @Override 30 | @Transactional 31 | public UserDetails loadUserByUsername(final String username) { 32 | User userFromRepository = userRepository.findByUsername(username.toLowerCase(Locale.ENGLISH)) 33 | .orElseThrow(() -> new UsernameNotFoundException("")); 34 | return createSpringSecurityUser(userFromRepository); 35 | } 36 | 37 | private org.springframework.security.core.userdetails.User createSpringSecurityUser(User user) { 38 | List grantedAuthorities = new ArrayList<>(); 39 | grantedAuthorities.add(new SimpleGrantedAuthority(user.getAuthority())); 40 | return new org.springframework.security.core.userdetails.User( 41 | user.getUsername(), user.getPassword(), grantedAuthorities); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /kraken-server/src/main/java/com/arcaneiceman/kraken/krakenserver/domain/TrackedCrunchList.java: -------------------------------------------------------------------------------- 1 | package com.arcaneiceman.kraken.krakenserver.domain; 2 | 3 | import com.arcaneiceman.kraken.krakenserver.domain.abs.TrackedList; 4 | import com.arcaneiceman.kraken.krakenserver.domain.enumerations.ListType; 5 | import com.arcaneiceman.kraken.krakenserver.domain.enumerations.TrackingStatus; 6 | import io.swagger.annotations.ApiModelProperty; 7 | import lombok.Getter; 8 | import lombok.NoArgsConstructor; 9 | import lombok.Setter; 10 | 11 | import javax.persistence.Column; 12 | import javax.persistence.DiscriminatorValue; 13 | import javax.persistence.Entity; 14 | import java.util.ArrayList; 15 | 16 | @Getter 17 | @Setter 18 | @Entity 19 | @NoArgsConstructor 20 | @DiscriminatorValue(ListType.Constants.CRUNCH_VALUE) 21 | public class TrackedCrunchList extends TrackedList { 22 | 23 | @Column 24 | @ApiModelProperty(hidden = true) 25 | private Integer min; 26 | 27 | @Column 28 | @ApiModelProperty(hidden = true) 29 | private Integer max; 30 | 31 | @Column 32 | @ApiModelProperty(hidden = true) 33 | private String characters; 34 | 35 | @Column 36 | @ApiModelProperty(hidden = true) 37 | private String nextJobString; 38 | 39 | @Column 40 | @ApiModelProperty(hidden = true) 41 | private String pattern; 42 | 43 | public TrackedCrunchList(String listName, 44 | Long totalJobs, 45 | Integer min, 46 | Integer max, 47 | String characters, 48 | String nextJobString, 49 | String pattern, 50 | ActiveRequest owner) { 51 | super(null, listName, ListType.CRUNCH, TrackingStatus.PENDING, totalJobs, 52 | 0L, 0L, 0L, new ArrayList<>(), owner); 53 | this.min = min; 54 | this.max = max; 55 | this.characters = characters; 56 | this.nextJobString = nextJobString; 57 | this.pattern = pattern; 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /kraken-server/src/main/java/com/arcaneiceman/kraken/krakenserver/service/utils/PasswordListJobDelimiterService.java: -------------------------------------------------------------------------------- 1 | package com.arcaneiceman.kraken.krakenserver.service.utils; 2 | 3 | import com.arcaneiceman.kraken.krakenserver.domain.PasswordList; 4 | import com.arcaneiceman.kraken.krakenserver.domain.PasswordListJobDelimiter; 5 | import com.arcaneiceman.kraken.krakenserver.repository.PasswordListJobDelimiterRepository; 6 | import com.arcaneiceman.kraken.krakenserver.util.exceptions.SystemException; 7 | import org.springframework.stereotype.Service; 8 | import org.springframework.transaction.annotation.Transactional; 9 | import org.zalando.problem.Status; 10 | 11 | @Service 12 | @Transactional 13 | class PasswordListJobDelimiterService { 14 | 15 | private final PasswordListJobDelimiterRepository passwordListJobDelimiterRepository; 16 | 17 | 18 | public PasswordListJobDelimiterService(PasswordListJobDelimiterRepository passwordListJobDelimiterRepository) { 19 | this.passwordListJobDelimiterRepository = passwordListJobDelimiterRepository; 20 | } 21 | 22 | public PasswordListJobDelimiter create(long jobDelimiterIndex, 23 | Long jobStartMarker, 24 | Long jobOffsetMarker, 25 | PasswordList owner) { 26 | PasswordListJobDelimiter passwordListJobDelimiter = 27 | new PasswordListJobDelimiter(null, jobDelimiterIndex, jobStartMarker, jobOffsetMarker, owner); 28 | return passwordListJobDelimiterRepository.save(passwordListJobDelimiter); 29 | } 30 | 31 | public PasswordListJobDelimiter get(Long indexNumber, PasswordList owner) { 32 | return passwordListJobDelimiterRepository.findByIndexNumberAndOwner(indexNumber, owner) 33 | .orElseThrow(() -> new SystemException(2342, "Could not find Job Delimiter", Status.NOT_FOUND)); 34 | } 35 | 36 | public void delete(PasswordList owner) { 37 | passwordListJobDelimiterRepository.deleteAll(passwordListJobDelimiterRepository.findByOwner(owner)); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /kraken-client/src/components/Toolbar/Toolbar.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import PropTypes from 'prop-types'; 3 | import Navbar from 'react-bootstrap/Navbar'; 4 | import Nav from 'react-bootstrap/Nav' 5 | import Octicon, { LogoGithub, MarkGithub } from '@githubprimer/octicons-react'; 6 | import krakenLogo from './../../assets/kraken-logo.png'; 7 | import { useHistory } from "react-router-dom"; 8 | 9 | import classes from './Toolbar.module.css' 10 | 11 | const Toolbar = (props) => { 12 | // Nav Links 13 | const navLinks = props.navLinks.map(navLink => { 14 | if (navLink.isPrimary) 15 | return ( {navLink.text} ) 16 | else 17 | return ( {navLink.text} ) 18 | }); 19 | 20 | const history = useHistory(); 21 | return ( 22 | 23 | { history.push("/dashboard") }} /> 24 | 25 | { history.push("/") }}>Kraken beta 26 | 27 | 29 | 30 | 31 | 32 | 35 | 36 | 37 | ); 38 | }; 39 | 40 | Toolbar.propTypes = { 41 | navLinks: PropTypes.arrayOf(PropTypes.shape({ 42 | text: PropTypes.string.isRequired, 43 | onClick: PropTypes.func.isRequired, 44 | }).isRequired), 45 | type: PropTypes.oneOf(['electron', 'web']) 46 | } 47 | 48 | export default Toolbar; -------------------------------------------------------------------------------- /kraken-server/src/main/java/com/arcaneiceman/kraken/krakenserver/service/utils/RecaptchaService.java: -------------------------------------------------------------------------------- 1 | package com.arcaneiceman.kraken.krakenserver.service.utils; 2 | 3 | import com.arcaneiceman.kraken.krakenserver.config.RecaptchaConfiguration; 4 | import com.arcaneiceman.kraken.krakenserver.util.exceptions.SystemException; 5 | import org.springframework.beans.factory.annotation.Autowired; 6 | import org.springframework.beans.factory.annotation.Value; 7 | import org.springframework.http.ResponseEntity; 8 | import org.springframework.stereotype.Service; 9 | import org.zalando.problem.Status; 10 | 11 | import javax.annotation.PostConstruct; 12 | import java.util.HashMap; 13 | import java.util.Map; 14 | 15 | @Service 16 | public class RecaptchaService { 17 | 18 | @Autowired 19 | RecaptchaConfiguration recaptchaConfiguration; 20 | 21 | @PostConstruct 22 | public void verifyVariables() { 23 | if (recaptchaConfiguration == null) 24 | throw new IllegalStateException("Recaptcha Configuration could not be found"); 25 | } 26 | 27 | // TODO : Add retry template to this 28 | public void verifyRecaptcha(String recaptchaResponse) { 29 | if (recaptchaConfiguration.getIsInDebug() || !recaptchaConfiguration.isConfigured()) 30 | return; 31 | if (recaptchaResponse.isEmpty()) 32 | throw new SystemException(231, "Please fill the captcha", Status.BAD_REQUEST); 33 | Map body = new HashMap<>(); 34 | body.put("secret", recaptchaConfiguration.getRecaptchaSecret()); 35 | body.put("response", recaptchaResponse); 36 | ResponseEntity recaptchaResponseEntity = recaptchaConfiguration.getRestTemplate() 37 | .postForEntity(recaptchaConfiguration.getRecaptchaSecret() + "?secret={secret}&response={response}", body, Map.class, body); 38 | Map responseBody = recaptchaResponseEntity.getBody(); 39 | if (responseBody != null && responseBody.get("success") != null && (Boolean) responseBody.get("success")) 40 | return; 41 | else 42 | throw new SystemException(232, "Could not validate captcha", Status.UNAUTHORIZED); 43 | } 44 | 45 | 46 | } 47 | -------------------------------------------------------------------------------- /kraken-server/src/main/java/com/arcaneiceman/kraken/krakenserver/domain/User.java: -------------------------------------------------------------------------------- 1 | package com.arcaneiceman.kraken.krakenserver.domain; 2 | 3 | import com.fasterxml.jackson.annotation.JsonIgnore; 4 | import lombok.*; 5 | import org.hibernate.annotations.CacheConcurrencyStrategy; 6 | import org.hibernate.annotations.GenericGenerator; 7 | 8 | import javax.persistence.*; 9 | import javax.validation.constraints.Email; 10 | import javax.validation.constraints.NotNull; 11 | import javax.validation.constraints.Size; 12 | import java.io.Serializable; 13 | import java.util.Date; 14 | 15 | /** 16 | * A user. 17 | */ 18 | @Entity 19 | @Getter 20 | @Setter 21 | @NoArgsConstructor 22 | @AllArgsConstructor 23 | @ToString(of = {"id", "email", "name", "authority"}) 24 | @EqualsAndHashCode(of = "id") 25 | @Table(name = "users") 26 | @org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE) 27 | public class User implements Serializable { 28 | 29 | private static final long serialVersionUID = 1L; 30 | 31 | @Id 32 | @GeneratedValue(generator = "uuid2") 33 | @GenericGenerator(name = "uuid2", strategy = "uuid2") 34 | private String id; 35 | 36 | @NotNull 37 | @Email 38 | @Size(min = 1, max = 50) 39 | @Column(length = 50, unique = true, nullable = false) 40 | private String email; 41 | 42 | @NotNull 43 | @Column 44 | private String name; 45 | 46 | @JsonIgnore 47 | @Size(min = 60, max = 60) 48 | @Column(length = 60) 49 | private String password; 50 | 51 | @NotNull 52 | @JsonIgnore 53 | @Column 54 | private String authority; 55 | 56 | @NotNull 57 | @JsonIgnore 58 | @Column 59 | private Boolean isActive; 60 | 61 | @Size(max = 20) 62 | @Column(length = 20) 63 | @JsonIgnore 64 | private String activationKey; 65 | 66 | @Column 67 | private Long createdAt; 68 | 69 | public User(String name, String email, String authority) { 70 | this.name = name; 71 | this.email = email; 72 | this.authority = authority; 73 | this.createdAt = new Date().getTime(); 74 | } 75 | 76 | public String getUsername() { 77 | return email; 78 | } 79 | 80 | public void setUsername(String username) { 81 | this.email = username; 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /kraken-client/src/services/CompleteRequestService.js: -------------------------------------------------------------------------------- 1 | import axios from './AxiosInstance' 2 | 3 | const getSummary = () => { 4 | return axios.get('/complete-request/summary') 5 | } 6 | 7 | const listCompleteRequests = (pageNumber, pageSize) => { 8 | return axios.get('/complete-request?pageNumber=' + pageNumber + '&pageSize=' + pageSize) 9 | .then(response => { 10 | response.data.content.forEach(completeRequest => { 11 | completeRequest.totalJobCount = completeRequest.trackedLists.map(trackedList => trackedList.totalJobCount).reduce((acc, value) => acc + value, 0); 12 | completeRequest.completedJobCount = completeRequest.trackedLists.map(trackedList => trackedList.completedJobCount).reduce((acc, value) => acc + value, 0); 13 | completeRequest.errorJobCount = completeRequest.trackedLists.map(trackedList => trackedList.errorJobCount).reduce((acc, value) => acc + value, 0); 14 | if (Object.keys(completeRequest.results).length === 0) 15 | completeRequest.result = "Not Found" 16 | else if (Object.keys(completeRequest.results).length < completeRequest.targetCount) 17 | completeRequest.result = "Partial" 18 | else 19 | completeRequest.result = "Found" 20 | 21 | switch(completeRequest.requestType){ 22 | case "2500": 23 | completeRequest.requestType = "WPA"; 24 | break; 25 | case "1000": 26 | completeRequest.requestType = "NTLM"; 27 | break; 28 | case "0": 29 | completeRequest.requestType = "MD5"; 30 | break; 31 | default: 32 | completeRequest.requestType = "Unknown" 33 | } 34 | }) 35 | return response; 36 | }) 37 | } 38 | 39 | const deleteCompleteRequest = (completeRequestId) => { 40 | return axios.delete('/complete-request/' + completeRequestId) 41 | } 42 | 43 | const CompleteRequestService = { 44 | getSummary, 45 | listCompleteRequests, 46 | deleteCompleteRequest, 47 | } 48 | 49 | export default CompleteRequestService; -------------------------------------------------------------------------------- /kraken-client/src/services/ActiveRequestService.js: -------------------------------------------------------------------------------- 1 | import axios from './AxiosInstance' 2 | 3 | const createActiveRequest = (requestType, requestName, requestMetadata, valueToMatchInBase64, trackedLists) => { 4 | const data = { requestType, requestName, requestMetadata, valueToMatchInBase64, trackedLists } 5 | return axios.post('/active-request', data) 6 | } 7 | 8 | const getSummary = () => { 9 | return axios.get('/active-request/summary') 10 | } 11 | 12 | const listActiveRequests = (pageNumber, pageSize) => { 13 | return axios.get('/active-request?pageNumber=' + pageNumber + '&pageSize=' + pageSize) 14 | .then(response => { 15 | response.data.content.forEach(activeRequest => { 16 | activeRequest.totalJobCount = activeRequest.trackedLists.map(trackedList => trackedList.totalJobCount).reduce((acc, value) => acc + value, 0); 17 | activeRequest.completedJobCount = activeRequest.trackedLists.map(trackedList => trackedList.completedJobCount).reduce((acc, value) => acc + value, 0); 18 | activeRequest.errorJobCount = activeRequest.trackedLists.map(trackedList => trackedList.errorJobCount).reduce((acc, value) => acc + value, 0); 19 | switch(activeRequest.requestType){ 20 | case "2500": 21 | activeRequest.requestType = "WPA"; 22 | break; 23 | case "1000": 24 | activeRequest.requestType = "NTLM"; 25 | break; 26 | case "0": 27 | activeRequest.requestType = "MD5"; 28 | break; 29 | default: 30 | activeRequest.requestType = "Unknown" 31 | } 32 | }) 33 | return response; 34 | }) 35 | } 36 | 37 | const deleteActiveRequest = (activeRequestId) => { 38 | return axios.delete('/active-request/' + activeRequestId) 39 | } 40 | 41 | const getJobPath = () => { 42 | return '/active-request/get-job'; 43 | } 44 | 45 | const reportJobPath = () => { 46 | return '/active-request/report-job' 47 | } 48 | 49 | const ActiveRequestService = { 50 | createActiveRequest, 51 | getSummary, 52 | listActiveRequests, 53 | deleteActiveRequest, 54 | getJobPath, 55 | reportJobPath, 56 | } 57 | 58 | export default ActiveRequestService; 59 | -------------------------------------------------------------------------------- /kraken-server/src/main/java/com/arcaneiceman/kraken/krakenserver/domain/CompleteRequest.java: -------------------------------------------------------------------------------- 1 | package com.arcaneiceman.kraken.krakenserver.domain; 2 | 3 | import com.arcaneiceman.kraken.krakenserver.domain.embeddedable.CompleteTrackedList; 4 | import com.arcaneiceman.kraken.krakenserver.domain.enumerations.TrackingStatus; 5 | import com.fasterxml.jackson.annotation.JsonGetter; 6 | import com.fasterxml.jackson.annotation.JsonIgnore; 7 | import com.fasterxml.jackson.core.type.TypeReference; 8 | import com.fasterxml.jackson.databind.ObjectMapper; 9 | import lombok.*; 10 | import org.hibernate.annotations.CacheConcurrencyStrategy; 11 | import org.hibernate.annotations.GenericGenerator; 12 | 13 | import javax.persistence.*; 14 | import javax.validation.constraints.NotNull; 15 | import java.io.IOException; 16 | import java.util.HashMap; 17 | import java.util.List; 18 | import java.util.Map; 19 | 20 | @EqualsAndHashCode(callSuper = false, of = "id") 21 | @Setter 22 | @Getter 23 | @NoArgsConstructor 24 | @AllArgsConstructor 25 | @Table(name = "completed_requests") 26 | @Entity 27 | @org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE) 28 | public class CompleteRequest { 29 | 30 | @Id 31 | @GeneratedValue(generator = "uuid2") 32 | @GenericGenerator(name = "uuid2", strategy = "uuid2") 33 | private String id; 34 | 35 | @NotNull 36 | @Column 37 | private String requestType; 38 | 39 | @NotNull 40 | @Column 41 | private String requestName; 42 | 43 | @Column(columnDefinition = "TEXT") 44 | private String requestMetadata; 45 | 46 | @JsonGetter 47 | public Map getRequestMetadata() throws IOException { 48 | return new ObjectMapper().readValue(requestMetadata, new TypeReference>() { 49 | }); 50 | } 51 | 52 | @NotNull 53 | @Column(nullable = false) 54 | private Integer targetCount; 55 | 56 | @ElementCollection(fetch = FetchType.EAGER) 57 | private List trackedLists; 58 | 59 | @Column(columnDefinition = "TEXT") 60 | private String results; 61 | 62 | @JsonGetter 63 | public Map getResults() throws IOException { 64 | return new ObjectMapper().readValue(results, new TypeReference>() { 65 | }); 66 | } 67 | 68 | @NotNull 69 | @Column 70 | private TrackingStatus status; 71 | 72 | @JsonIgnore 73 | @ManyToOne 74 | private User owner; 75 | } 76 | -------------------------------------------------------------------------------- /kraken-client/src/containers/Help/Help.module.css: -------------------------------------------------------------------------------- 1 | .sun { 2 | background: linear-gradient(0deg,#22567c,#557A95); 3 | padding: 80px 100px 60px; 4 | margin: 0 -100px; 5 | height: 15%; 6 | border-bottom-left-radius: 100% 25%; 7 | border-bottom-right-radius: 100% 25%; 8 | position: relative; 9 | color: #fff; 10 | display: flex; 11 | justify-content: center 12 | } 13 | 14 | .panelContainer { 15 | margin: auto; 16 | position: relative; 17 | margin-top: 50px; 18 | margin-bottom: 10px; 19 | margin-right: 15%; 20 | margin-left: 15%; 21 | display: flex; 22 | justify-content: space-between; 23 | min-height: 100px; 24 | flex-wrap: wrap; 25 | } 26 | 27 | .panel{ 28 | margin: 25px; 29 | border-radius: 5px; 30 | background-color: #fff; 31 | box-shadow: 0 5px 10px 0 rgba(35,35,35,.1); 32 | text-align: center; 33 | overflow: hidden; 34 | height: 225px; 35 | width: 225px; 36 | position: relative; 37 | display: block; 38 | color: #3a3939; 39 | } 40 | 41 | .panel:hover{ 42 | color: #557A95 43 | } 44 | 45 | .panelImageContainer { 46 | display: flex; 47 | justify-content: center; 48 | align-items: center; 49 | width: 50px; 50 | height: 50px; 51 | line-height: 50px; 52 | border-radius: 50px; 53 | background: #f5f5f5; 54 | margin: 30px auto; 55 | color: #3a3939; 56 | font-size: 40px; 57 | } 58 | 59 | .panelLink:hover, .panelLink:visited, .panelLink:link, .panelLink:active 60 | { 61 | color: inherit; 62 | text-decoration: none; 63 | } 64 | 65 | .panelTitle{ 66 | font-size: 18px; 67 | font-weight: 700; 68 | line-height: 1.5; 69 | padding: 0 16px; 70 | margin: 20px; 71 | } 72 | 73 | .panelText{ 74 | font-size: 16px; 75 | line-height: 1.5; 76 | color: #959595; 77 | padding: 0 15px; 78 | } 79 | 80 | .panelFooter{ 81 | height: 5px; 82 | border-radius: 0 0 5px 5px; 83 | background-image: linear-gradient(270deg,#22567c,#557A95); 84 | position: absolute; 85 | bottom: 0; 86 | width: 100%; 87 | } 88 | 89 | .logoContainer{ 90 | display: flex; 91 | justify-content: center; 92 | align-items: center; 93 | } 94 | 95 | .content { 96 | padding-left: 15%; 97 | padding-right: 15%; 98 | } 99 | 100 | .donationContainer { 101 | display: flex; 102 | flex-direction: column; 103 | align-items: center; 104 | } 105 | 106 | .bitcoinAddress{ 107 | margin-top: -10px; 108 | font-weight: bold; 109 | } -------------------------------------------------------------------------------- /kraken-server/src/main/java/com/arcaneiceman/kraken/krakenserver/domain/abs/TrackedList.java: -------------------------------------------------------------------------------- 1 | package com.arcaneiceman.kraken.krakenserver.domain.abs; 2 | 3 | import com.arcaneiceman.kraken.krakenserver.domain.ActiveRequest; 4 | import com.arcaneiceman.kraken.krakenserver.domain.Job; 5 | import com.arcaneiceman.kraken.krakenserver.domain.TrackedCrunchList; 6 | import com.arcaneiceman.kraken.krakenserver.domain.TrackedPasswordList; 7 | import com.arcaneiceman.kraken.krakenserver.domain.enumerations.ListType; 8 | import com.arcaneiceman.kraken.krakenserver.domain.enumerations.TrackingStatus; 9 | import com.fasterxml.jackson.annotation.JsonIgnore; 10 | import com.fasterxml.jackson.annotation.JsonSubTypes; 11 | import com.fasterxml.jackson.annotation.JsonTypeInfo; 12 | import lombok.*; 13 | import org.hibernate.annotations.GenericGenerator; 14 | 15 | import javax.persistence.*; 16 | import java.util.List; 17 | 18 | @Getter 19 | @Setter 20 | @EqualsAndHashCode(callSuper = false, of = "id") 21 | @Entity 22 | @Table(name = "tracked_lists") 23 | @AllArgsConstructor 24 | @NoArgsConstructor 25 | @Inheritance(strategy = InheritanceType.SINGLE_TABLE) 26 | @JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "listType") 27 | @JsonSubTypes({ 28 | @JsonSubTypes.Type(value = TrackedPasswordList.class, name = ListType.Constants.PASSWORD_LIST_VALUE), 29 | @JsonSubTypes.Type(value = TrackedCrunchList.class, name = ListType.Constants.CRUNCH_VALUE)}) 30 | @DiscriminatorColumn(name = "list_type", discriminatorType = DiscriminatorType.STRING) 31 | public abstract class TrackedList { 32 | 33 | private static final long serialVersionUID = 1L; 34 | 35 | @JsonIgnore 36 | @Id 37 | @GeneratedValue(generator = "uuid2") 38 | @GenericGenerator(name = "uuid2", strategy = "uuid2") 39 | private String id; 40 | 41 | @Column 42 | private String listName; 43 | 44 | @Column(name = "list_type", insertable = false, updatable = false) 45 | @Enumerated(EnumType.STRING) 46 | private ListType listType; 47 | 48 | @Column 49 | @Enumerated(EnumType.STRING) 50 | private TrackingStatus trackingStatus; 51 | 52 | @Column 53 | private Long totalJobCount; 54 | 55 | @Column 56 | private Long nextJobIndex; 57 | 58 | @Column 59 | private Long completedJobCount; 60 | 61 | @Column 62 | private Long errorJobCount; 63 | 64 | @JsonIgnore 65 | @OneToMany(mappedBy = "owner", fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true) 66 | private List jobQueue; 67 | 68 | @JsonIgnore 69 | @ManyToOne 70 | private ActiveRequest owner; 71 | 72 | } 73 | -------------------------------------------------------------------------------- /kraken-client/src/containers/CompletedRequests/CompletedRequests.module.css: -------------------------------------------------------------------------------- 1 | .mainContainer { 2 | background: #fff; 3 | border: 1px solid #dbdbdb; 4 | border-radius: 4px; 5 | box-shadow: 2px 2px 3px rgba(0,0,0,.05); 6 | margin: 0 5px 10px 0; 7 | position: relative; 8 | text-align: left; 9 | } 10 | 11 | .loadingBackground{ 12 | width: 100%; 13 | height: 100%; 14 | position: absolute; 15 | background: black; 16 | opacity: 0.2; 17 | } 18 | 19 | .loadingSpinner{ 20 | position: absolute; 21 | top: 50%; 22 | left: 50%; 23 | opacity: 1; 24 | } 25 | 26 | .summarySectionContainer { 27 | display: flex; 28 | flex-direction: row; 29 | justify-content: flex-start; 30 | } 31 | 32 | .summaryLastItem { 33 | flex-grow: 1; 34 | } 35 | 36 | .tableHeaderColumnText { 37 | color: #fff; 38 | font-weight: 700; 39 | padding: 15px 10px; 40 | font-size: 14px; 41 | text-align: left; 42 | } 43 | 44 | .tableRowWithValue { 45 | cursor: copy; 46 | } 47 | 48 | .tableItem { 49 | cursor: copy; 50 | padding: 15px 10px; 51 | text-align: left; 52 | font-size: 14px; 53 | vertical-align: middle; 54 | border-bottom: 1px solid #dbdbdb; 55 | line-height: 1.3; 56 | } 57 | .detailModalContainer{ 58 | display: flex; 59 | flex-direction: column; 60 | } 61 | 62 | .detailModalProgressBarContainer{ 63 | display: flex; 64 | } 65 | 66 | .detailModalDetailContainer{ 67 | display: flex; 68 | justify-content: space-between; 69 | margin: 5px; 70 | } 71 | 72 | .detailModalHeading{ 73 | white-space: nowrap; 74 | color: #959595; 75 | font-size: 0.55rem; 76 | font-weight: 400; 77 | letter-spacing: 2px; 78 | text-transform: uppercase; 79 | margin: 10px; 80 | } 81 | 82 | .detailModalValue{ 83 | margin: 10px; 84 | } 85 | 86 | .detailModalRequestMetadataContainer{ 87 | margin: 5px; 88 | } 89 | 90 | .detailModalRequestMetadataTable { 91 | margin: 10px; 92 | } 93 | 94 | .detailModalListContainer{ 95 | margin: 5px; 96 | } 97 | 98 | .detailModalListPillContainer { 99 | align-self: stretch; 100 | display: flex; 101 | flex-direction: row; 102 | flex-wrap: wrap; 103 | min-height: 50px; 104 | border-radius: 5px; 105 | border: 0.5px solid grey; 106 | } 107 | 108 | .detailModalTrackedListPill { 109 | border: none; 110 | padding: 5px 5px; 111 | text-align: center; 112 | text-decoration: none; 113 | display: inline-block; 114 | margin: 4px 4px; 115 | cursor: pointer; 116 | border-radius: 16px; 117 | } 118 | 119 | 120 | -------------------------------------------------------------------------------- /kraken-server/src/main/java/com/arcaneiceman/kraken/krakenserver/config/OAuthUserServiceConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.arcaneiceman.kraken.krakenserver.config; 2 | 3 | import lombok.Getter; 4 | import lombok.Setter; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | import org.springframework.beans.factory.annotation.Value; 8 | import org.springframework.boot.context.properties.ConfigurationProperties; 9 | import org.springframework.boot.context.properties.EnableConfigurationProperties; 10 | import org.springframework.boot.web.client.RestTemplateBuilder; 11 | import org.springframework.context.annotation.Configuration; 12 | import org.springframework.retry.backoff.ExponentialBackOffPolicy; 13 | import org.springframework.retry.policy.SimpleRetryPolicy; 14 | import org.springframework.retry.support.RetryTemplate; 15 | import org.springframework.web.client.RestTemplate; 16 | 17 | import javax.annotation.PostConstruct; 18 | import java.util.Map; 19 | 20 | @Configuration 21 | @EnableConfigurationProperties 22 | @ConfigurationProperties(prefix = "application.oauth-user-service") 23 | public class OAuthUserServiceConfiguration { 24 | 25 | @Getter 26 | private Logger log = LoggerFactory.getLogger(RecaptchaConfiguration.class); 27 | 28 | @Getter 29 | @Value("${application.oauth-user-service.is-in-debug}") 30 | private Boolean isInDebug; 31 | 32 | @Getter 33 | @Value("${application.oauth-user-service.retry-attempts}") 34 | private Integer retryAttempts; 35 | 36 | @Getter 37 | @Value("${application.oauth-user-service.retry-interval}") 38 | private Long retryInterval; 39 | 40 | @Getter 41 | @Setter 42 | private Map providers; 43 | 44 | @Getter 45 | private RetryTemplate retryTemplate; 46 | 47 | @Getter 48 | private RestTemplate restTemplate; 49 | 50 | public void generateClients() { 51 | restTemplate = new RestTemplateBuilder().build(); 52 | retryTemplate = new RetryTemplate(); 53 | retryTemplate.setRetryPolicy(new SimpleRetryPolicy(getRetryAttempts())); 54 | ExponentialBackOffPolicy backOffPolicy = new ExponentialBackOffPolicy(); 55 | backOffPolicy.setInitialInterval(getRetryInterval()); 56 | retryTemplate.setBackOffPolicy(backOffPolicy); 57 | } 58 | 59 | @PostConstruct 60 | public void postConstruct() { 61 | // Generate Client(s) 62 | generateClients(); 63 | 64 | // TODO: Test Client 65 | // providers.forEach( (provider, urlAndFields) -> { 66 | // restTemplate.getFo(url); 67 | // }); 68 | 69 | log.info("Successfully configured Oauth User Service Configuration"); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /kraken-server/src/main/java/com/arcaneiceman/kraken/krakenserver/service/utils/TokenBlacklistService.java: -------------------------------------------------------------------------------- 1 | package com.arcaneiceman.kraken.krakenserver.service.utils; 2 | 3 | import com.arcaneiceman.kraken.krakenserver.domain.BlacklistToken; 4 | import com.arcaneiceman.kraken.krakenserver.repository.TokenBlacklistRepository; 5 | import lombok.Getter; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | import org.springframework.beans.factory.annotation.Value; 9 | import org.springframework.scheduling.annotation.Scheduled; 10 | import org.springframework.stereotype.Service; 11 | 12 | import javax.annotation.PostConstruct; 13 | import java.util.Date; 14 | import java.util.List; 15 | 16 | /** 17 | * Created by wali on 26/09/17. 18 | *

19 | * Token Blacklist Cache temporarily holds blacklisted token digest. 20 | *

21 | * All tokens expire after being added to cache in their validity period 22 | *

23 | * If validity period = t and token was created at t1 then token expires in t1 + t. 24 | *

25 | * Thus, if the token is blacklisted as soon as it is created, it will stay in cache as long as it is valid. 26 | */ 27 | @Service 28 | public class TokenBlacklistService { 29 | 30 | private Logger log = LoggerFactory.getLogger(TokenBlacklistService.class); 31 | 32 | @Getter 33 | @Value("${application.security.jwt-token-validity-in-milliseconds}") 34 | private long tokenValidityInMilliseconds; 35 | 36 | private TokenBlacklistRepository tokenBlacklistRepository; 37 | 38 | public TokenBlacklistService(TokenBlacklistRepository tokenBlacklistRepository) { 39 | this.tokenBlacklistRepository = tokenBlacklistRepository; 40 | } 41 | 42 | @PostConstruct 43 | public void verifyVariables() { 44 | if (tokenValidityInMilliseconds == 0) 45 | throw new IllegalStateException("No Token Validity Period Defined"); 46 | } 47 | 48 | public void addToBlackList(String tokenDigest) { 49 | tokenBlacklistRepository.save(new BlacklistToken(tokenDigest, new Date().getTime() + tokenValidityInMilliseconds)); 50 | } 51 | 52 | public boolean isInBlacklist(String tokenDigest) { 53 | return tokenBlacklistRepository.findByTokenDigest(tokenDigest) != null; 54 | } 55 | 56 | @Scheduled(initialDelay = 60000L, fixedDelay = 3600000L) 57 | public void cleanupTokens() { 58 | log.info("Running: Token Cleanup Task"); 59 | List tokensToClean = tokenBlacklistRepository.findByCleanUpTimeBefore(new Date().getTime()); 60 | tokensToClean.forEach(blacklistToken -> tokenBlacklistRepository.delete(blacklistToken)); 61 | log.info("Complete: Token Cleanup Task"); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /kraken-client/config/modules.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const fs = require('fs'); 4 | const path = require('path'); 5 | const paths = require('./paths'); 6 | const chalk = require('react-dev-utils/chalk'); 7 | const resolve = require('resolve'); 8 | 9 | /** 10 | * Get the baseUrl of a compilerOptions object. 11 | * 12 | * @param {Object} options 13 | */ 14 | function getAdditionalModulePaths(options = {}) { 15 | const baseUrl = options.baseUrl; 16 | 17 | // We need to explicitly check for null and undefined (and not a falsy value) because 18 | // TypeScript treats an empty string as `.`. 19 | if (baseUrl == null) { 20 | // If there's no baseUrl set we respect NODE_PATH 21 | // Note that NODE_PATH is deprecated and will be removed 22 | // in the next major release of create-react-app. 23 | 24 | const nodePath = process.env.NODE_PATH || ''; 25 | return nodePath.split(path.delimiter).filter(Boolean); 26 | } 27 | 28 | const baseUrlResolved = path.resolve(paths.appPath, baseUrl); 29 | 30 | // We don't need to do anything if `baseUrl` is set to `node_modules`. This is 31 | // the default behavior. 32 | if (path.relative(paths.appNodeModules, baseUrlResolved) === '') { 33 | return null; 34 | } 35 | 36 | // Allow the user set the `baseUrl` to `appSrc`. 37 | if (path.relative(paths.appSrc, baseUrlResolved) === '') { 38 | return [paths.appSrc]; 39 | } 40 | 41 | // Otherwise, throw an error. 42 | throw new Error( 43 | chalk.red.bold( 44 | "Your project's `baseUrl` can only be set to `src` or `node_modules`." + 45 | ' Create React App does not support other values at this time.' 46 | ) 47 | ); 48 | } 49 | 50 | function getModules() { 51 | // Check if TypeScript is setup 52 | const hasTsConfig = fs.existsSync(paths.appTsConfig); 53 | const hasJsConfig = fs.existsSync(paths.appJsConfig); 54 | 55 | if (hasTsConfig && hasJsConfig) { 56 | throw new Error( 57 | 'You have both a tsconfig.json and a jsconfig.json. If you are using TypeScript please remove your jsconfig.json file.' 58 | ); 59 | } 60 | 61 | let config; 62 | 63 | // If there's a tsconfig.json we assume it's a 64 | // TypeScript project and set up the config 65 | // based on tsconfig.json 66 | if (hasTsConfig) { 67 | const ts = require(resolve.sync('typescript', { 68 | basedir: paths.appNodeModules, 69 | })); 70 | config = ts.readConfigFile(paths.appTsConfig, ts.sys.readFile).config; 71 | // Otherwise we'll check if there is jsconfig.json 72 | // for non TS projects. 73 | } else if (hasJsConfig) { 74 | config = require(paths.appJsConfig); 75 | } 76 | 77 | config = config || {}; 78 | const options = config.compilerOptions || {}; 79 | 80 | const additionalModulePaths = getAdditionalModulePaths(options); 81 | 82 | return { 83 | additionalModulePaths: additionalModulePaths, 84 | hasTsConfig, 85 | }; 86 | } 87 | 88 | module.exports = getModules(); 89 | -------------------------------------------------------------------------------- /kraken-server/src/main/java/com/arcaneiceman/kraken/krakenserver/service/utils/OAuthUserService.java: -------------------------------------------------------------------------------- 1 | package com.arcaneiceman.kraken.krakenserver.service.utils; 2 | 3 | import com.arcaneiceman.kraken.krakenserver.config.OAuthUserServiceConfiguration; 4 | import com.arcaneiceman.kraken.krakenserver.domain.User; 5 | import com.arcaneiceman.kraken.krakenserver.security.AuthoritiesConstants; 6 | import com.arcaneiceman.kraken.krakenserver.util.exceptions.SystemException; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.http.HttpEntity; 9 | import org.springframework.http.HttpHeaders; 10 | import org.springframework.http.HttpMethod; 11 | import org.springframework.http.ResponseEntity; 12 | import org.springframework.stereotype.Service; 13 | import org.zalando.problem.Status; 14 | 15 | import javax.annotation.PostConstruct; 16 | import java.util.Map; 17 | 18 | @Service 19 | public class OAuthUserService { 20 | 21 | @Autowired 22 | OAuthUserServiceConfiguration oAuthUserServiceConfiguration; 23 | 24 | @PostConstruct 25 | public void verifyVariables() { 26 | if (oAuthUserServiceConfiguration == null) 27 | throw new IllegalStateException("Recaptcha Configuration could not be found"); 28 | } 29 | 30 | // TODO Integrate Retry Template 31 | public User findUser(String provider, String accessToken) { 32 | if (oAuthUserServiceConfiguration.getIsInDebug()) 33 | return new User(null, "test@test.com", "test", "password", 34 | AuthoritiesConstants.CONSUMER, true, null, null); 35 | String url = oAuthUserServiceConfiguration.getProviders().get(provider.toLowerCase()); 36 | if (url == null || url.isEmpty()) 37 | throw new SystemException(6565, "No Authorized URL for provider " + provider, Status.BAD_REQUEST); 38 | 39 | HttpHeaders headers = new HttpHeaders(); 40 | headers.add("Authorization", "Bearer " + accessToken); 41 | HttpEntity request = new HttpEntity<>(headers); 42 | ResponseEntity recaptchaResponseEntity = 43 | oAuthUserServiceConfiguration.getRestTemplate().exchange(url, HttpMethod.GET, request, Map.class); 44 | Map responseBody = recaptchaResponseEntity.getBody(); 45 | if (responseBody == null) 46 | throw new SystemException(3434, "Could not fetch response from " + provider, Status.BAD_REQUEST); 47 | 48 | String email = responseBody.get("email"); 49 | if (email == null || email.isEmpty()) 50 | throw new SystemException(2324, "Could not fetch email from " + provider + " (Is it accessible?)", Status.BAD_REQUEST); 51 | String name = responseBody.get("name"); 52 | if (name == null || name.isEmpty()) 53 | throw new SystemException(4343, "Could not fetch name from " + provider + " (Is it accessible?)", Status.BAD_REQUEST); 54 | return new User(null, email, name, null, AuthoritiesConstants.CONSUMER, true, null, null); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /kraken-server/src/main/java/com/arcaneiceman/kraken/krakenserver/domain/ActiveRequest.java: -------------------------------------------------------------------------------- 1 | package com.arcaneiceman.kraken.krakenserver.domain; 2 | 3 | import com.arcaneiceman.kraken.krakenserver.domain.abs.TrackedList; 4 | import com.fasterxml.jackson.annotation.JsonGetter; 5 | import com.fasterxml.jackson.annotation.JsonIgnore; 6 | import com.fasterxml.jackson.core.JsonProcessingException; 7 | import com.fasterxml.jackson.core.type.TypeReference; 8 | import com.fasterxml.jackson.databind.ObjectMapper; 9 | import lombok.*; 10 | import org.hibernate.annotations.CacheConcurrencyStrategy; 11 | import org.hibernate.annotations.GenericGenerator; 12 | 13 | import javax.persistence.*; 14 | import javax.validation.constraints.NotNull; 15 | import java.io.IOException; 16 | import java.util.HashMap; 17 | import java.util.List; 18 | import java.util.Map; 19 | 20 | @EqualsAndHashCode(callSuper = false, of = "id") 21 | @Setter 22 | @Getter 23 | @NoArgsConstructor 24 | @AllArgsConstructor 25 | @Table(name = "active_requests") 26 | @Entity 27 | @org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE) 28 | public class ActiveRequest { 29 | 30 | private static final long serialVersionUID = 1L; 31 | 32 | @Id 33 | @GeneratedValue(generator = "uuid2") 34 | @GenericGenerator(name = "uuid2", strategy = "uuid2") 35 | private String id; 36 | 37 | @NotNull 38 | @Column 39 | private String requestName; 40 | 41 | @NotNull 42 | @Column 43 | private String requestType; 44 | 45 | @Column(columnDefinition = "TEXT") 46 | private String requestMetadata; 47 | 48 | @NotNull 49 | @Column(nullable = false) 50 | private Integer targetCount; 51 | 52 | @NotNull 53 | @JsonIgnore 54 | @Lob 55 | private String valueToMatchInBase64; 56 | 57 | @JsonGetter(value = "requestMetadata") 58 | public Map getRequestMetadataOverride() throws IOException { 59 | return new ObjectMapper().readValue(requestMetadata, new TypeReference>() { 60 | }); 61 | } 62 | 63 | public void setRequestMetadataOverride(Map requestMetadata) throws JsonProcessingException { 64 | this.requestMetadata = new ObjectMapper().writeValueAsString(requestMetadata); 65 | } 66 | 67 | @Column(columnDefinition = "TEXT") 68 | private String results; 69 | 70 | @JsonGetter(value = "results") 71 | public Map getResultsOverride() throws IOException { 72 | return new ObjectMapper().readValue(results, new TypeReference>() { 73 | }); 74 | } 75 | 76 | public void setResultsOverride(Map results) throws JsonProcessingException { 77 | this.results = new ObjectMapper().writeValueAsString(results); 78 | } 79 | 80 | @OneToMany(mappedBy = "owner", fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval = true) 81 | private List trackedLists; 82 | 83 | @JsonIgnore 84 | @ManyToOne 85 | private User owner; 86 | } 87 | -------------------------------------------------------------------------------- /kraken-server/src/main/java/com/arcaneiceman/kraken/krakenserver/controller/CompleteRequestController.java: -------------------------------------------------------------------------------- 1 | package com.arcaneiceman.kraken.krakenserver.controller; 2 | 3 | import com.arcaneiceman.kraken.krakenserver.controller.io.CompleteRequestIO; 4 | import com.arcaneiceman.kraken.krakenserver.domain.CompleteRequest; 5 | import com.arcaneiceman.kraken.krakenserver.security.AuthoritiesConstants; 6 | import com.arcaneiceman.kraken.krakenserver.service.CompleteRequestService; 7 | import org.springframework.data.domain.Page; 8 | import org.springframework.data.domain.Pageable; 9 | import org.springframework.http.HttpStatus; 10 | import org.springframework.security.access.annotation.Secured; 11 | import org.springframework.validation.annotation.Validated; 12 | import org.springframework.web.bind.annotation.*; 13 | 14 | import javax.validation.Valid; 15 | 16 | @RestController 17 | @RequestMapping("${application.context-path}") 18 | public class CompleteRequestController { 19 | 20 | private CompleteRequestService completeRequestService; 21 | 22 | public CompleteRequestController(CompleteRequestService completeRequestService) { 23 | this.completeRequestService = completeRequestService; 24 | } 25 | 26 | @Validated 27 | @GetMapping("/complete-request") 28 | @Secured(AuthoritiesConstants.CONSUMER) 29 | @ResponseStatus(HttpStatus.OK) 30 | public Page list(Pageable pageable, 31 | @RequestHeader(value = "Authorization") String bearerToken, 32 | @RequestHeader(value = "Version") String apiVersion) { 33 | return completeRequestService.list(pageable); 34 | } 35 | 36 | @Validated 37 | @GetMapping(value = "/complete-request/{id}") 38 | @Secured(AuthoritiesConstants.CONSUMER) 39 | @ResponseStatus(HttpStatus.OK) 40 | public CompleteRequest get(@Valid @PathVariable String id, 41 | @RequestHeader(value = "Authorization") String bearerToken, 42 | @RequestHeader(value = "Version") String apiVersion) { 43 | return completeRequestService.get(id); 44 | } 45 | 46 | @Validated 47 | @Secured(AuthoritiesConstants.CONSUMER) 48 | @GetMapping(value = "/complete-request/summary") 49 | @ResponseStatus(HttpStatus.OK) 50 | public CompleteRequestIO.Summary.Response summary(@RequestHeader(value = "Authorization") String bearerToken, 51 | @RequestHeader(value = "Version") String apiVersion) { 52 | return completeRequestService.summary(); 53 | } 54 | 55 | @Validated 56 | @DeleteMapping(value = "/complete-request/{id}") 57 | @Secured(AuthoritiesConstants.CONSUMER) 58 | @ResponseStatus(HttpStatus.NO_CONTENT) 59 | public void delete(@Valid @PathVariable String id, 60 | @RequestHeader(value = "Authorization") String bearerToken, 61 | @RequestHeader(value = "Version") String apiVersion) { 62 | completeRequestService.delete(id); 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /kraken-server/src/main/java/com/arcaneiceman/kraken/krakenserver/config/RecaptchaConfiguration.java: -------------------------------------------------------------------------------- 1 | package com.arcaneiceman.kraken.krakenserver.config; 2 | 3 | import lombok.Getter; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | import org.springframework.beans.factory.annotation.Value; 7 | import org.springframework.boot.context.properties.ConfigurationProperties; 8 | import org.springframework.boot.context.properties.EnableConfigurationProperties; 9 | import org.springframework.boot.web.client.RestTemplateBuilder; 10 | import org.springframework.context.annotation.Configuration; 11 | import org.springframework.http.ResponseEntity; 12 | import org.springframework.retry.backoff.ExponentialBackOffPolicy; 13 | import org.springframework.retry.policy.SimpleRetryPolicy; 14 | import org.springframework.retry.support.RetryTemplate; 15 | import org.springframework.web.client.RestTemplate; 16 | 17 | import javax.annotation.PostConstruct; 18 | import java.net.MalformedURLException; 19 | import java.net.URL; 20 | import java.util.Locale; 21 | 22 | @Configuration 23 | @EnableConfigurationProperties 24 | @ConfigurationProperties(prefix = "application.recaptcha") 25 | public class RecaptchaConfiguration { 26 | 27 | private Logger log = LoggerFactory.getLogger(RecaptchaConfiguration.class); 28 | 29 | @Getter 30 | private boolean isConfigured = false; 31 | 32 | @Getter 33 | @Value("${application.recaptcha.is-in-debug}") 34 | private Boolean isInDebug; 35 | 36 | @Getter 37 | @Value("${application.recaptcha.url}") 38 | private String recaptchaUrl; 39 | 40 | @Getter 41 | @Value("${application.recaptcha.secret}") 42 | private String recaptchaSecret; 43 | 44 | @Getter 45 | @Value("${application.recaptcha.retry-attempts}") 46 | private Integer retryAttempts; 47 | 48 | @Getter 49 | @Value("${application.recaptcha.retry-interval}") 50 | private Long retryInterval; 51 | 52 | @Getter 53 | private RetryTemplate retryTemplate; 54 | 55 | @Getter 56 | private RestTemplate restTemplate; 57 | 58 | public void generateClients() { 59 | try{ 60 | new URL(recaptchaUrl); 61 | 62 | restTemplate = new RestTemplateBuilder().build(); 63 | retryTemplate = new RetryTemplate(); 64 | retryTemplate.setRetryPolicy(new SimpleRetryPolicy(getRetryAttempts())); 65 | ExponentialBackOffPolicy backOffPolicy = new ExponentialBackOffPolicy(); 66 | backOffPolicy.setInitialInterval(getRetryInterval()); 67 | retryTemplate.setBackOffPolicy(backOffPolicy); 68 | 69 | restTemplate.getForEntity(recaptchaUrl, String.class); 70 | 71 | isConfigured = true; 72 | log.info("Successfully configured Recaptcha Configuration"); 73 | } 74 | catch (Exception e){ 75 | log.error("Recaptcha Configuration was not configured properly : " + e.getMessage()); 76 | } 77 | } 78 | 79 | @PostConstruct 80 | public void postConstruct() { 81 | // Generate Client(s) 82 | generateClients(); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /kraken-client/config/paths.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const path = require('path'); 4 | const fs = require('fs'); 5 | const url = require('url'); 6 | 7 | // Make sure any symlinks in the project folder are resolved: 8 | // https://github.com/facebook/create-react-app/issues/637 9 | const appDirectory = fs.realpathSync(process.cwd()); 10 | const resolveApp = relativePath => path.resolve(appDirectory, relativePath); 11 | 12 | const envPublicUrl = process.env.PUBLIC_URL; 13 | 14 | function ensureSlash(inputPath, needsSlash) { 15 | const hasSlash = inputPath.endsWith('/'); 16 | if (hasSlash && !needsSlash) { 17 | return inputPath.substr(0, inputPath.length - 1); 18 | } else if (!hasSlash && needsSlash) { 19 | return `${inputPath}/`; 20 | } else { 21 | return inputPath; 22 | } 23 | } 24 | 25 | const getPublicUrl = appPackageJson => 26 | envPublicUrl || require(appPackageJson).homepage; 27 | 28 | // We use `PUBLIC_URL` environment variable or "homepage" field to infer 29 | // "public path" at which the app is served. 30 | // Webpack needs to know it to put the right