]> git.immae.eu Git - github/Chocobozzz/PeerTube.git/commitdiff
Sanitize url to not end with implicit ports
authorChocobozzz <me@florianbigard.com>
Thu, 21 Dec 2017 08:56:59 +0000 (09:56 +0100)
committerChocobozzz <me@florianbigard.com>
Thu, 21 Dec 2017 08:56:59 +0000 (09:56 +0100)
server/controllers/api/server/follows.ts
server/helpers/core-utils.ts
server/helpers/custom-validators/webfinger.ts
server/initializers/constants.ts
server/initializers/migrations/0140-actor-url.ts [new file with mode: 0644]

index e7d81f7c3e97f48599373726411fb18f298f0611..ae5413b7502459535294e5abbcb8d7d1e7f72499 100644 (file)
@@ -1,19 +1,15 @@
 import * as express from 'express'
 import { UserRight } from '../../../../shared/models/users'
-import { getFormattedObjects, getServerActor, loadActorUrlOrGetFromWebfinger, logger, retryTransactionWrapper } from '../../../helpers'
-import { sequelizeTypescript, SERVER_ACTOR_NAME } from '../../../initializers'
+import {
+  getFormattedObjects, getServerActor, loadActorUrlOrGetFromWebfinger, logger, retryTransactionWrapper,
+  sanitizeHost
+} from '../../../helpers'
+import { REMOTE_SCHEME, sequelizeTypescript, SERVER_ACTOR_NAME } from '../../../initializers'
 import { getOrCreateActorAndServerAndModel } from '../../../lib/activitypub'
 import { sendFollow, sendUndoFollow } from '../../../lib/activitypub/send'
 import {
-  asyncMiddleware,
-  authenticate,
-  ensureUserHasRight,
-  paginationValidator,
-  removeFollowingValidator,
-  setBodyHostsPort,
-  setFollowersSort,
-  setFollowingSort,
-  setPagination
+  asyncMiddleware, authenticate, ensureUserHasRight, paginationValidator, removeFollowingValidator, setBodyHostsPort,
+  setFollowersSort, setFollowingSort, setPagination
 } from '../../../middlewares'
 import { followersSortValidator, followingSortValidator, followValidator } from '../../../middlewares/validators'
 import { ActorModel } from '../../../models/activitypub/actor'
@@ -82,10 +78,12 @@ async function followRetry (req: express.Request, res: express.Response, next: e
   const actorName = SERVER_ACTOR_NAME
 
   for (const host of hosts) {
+    const sanitizedHost = sanitizeHost(host, REMOTE_SCHEME.HTTP)
+
     // We process each host in a specific transaction
     // First, we add the follow request in the database
     // Then we send the follow request to other actor
-    const p = loadActorUrlOrGetFromWebfinger(actorName, host)
+    const p = loadActorUrlOrGetFromWebfinger(actorName, sanitizedHost)
       .then(actorUrl => getOrCreateActorAndServerAndModel(actorUrl))
       .then(targetActor => {
         const options = {
@@ -95,7 +93,7 @@ async function followRetry (req: express.Request, res: express.Response, next: e
 
         return retryTransactionWrapper(follow, options)
       })
-      .catch(err => logger.warn('Cannot follow server %s.', host, err))
+      .catch(err => logger.warn('Cannot follow server %s.', sanitizedHost, err))
 
     tasks.push(p)
   }
index 443115336946150ae9363508fa3ed5ac3def52af..0c6c36d11741e0d58fcf7c00fbb5d63751a21d27 100644 (file)
@@ -11,6 +11,26 @@ import * as mkdirp from 'mkdirp'
 import { join } from 'path'
 import * as pem from 'pem'
 import * as rimraf from 'rimraf'
+import { URL } from 'url'
+
+function sanitizeUrl (url: string) {
+  const urlObject = new URL(url)
+
+  if (urlObject.protocol === 'https:' && urlObject.port === '443') {
+    urlObject.port = ''
+  } else if (urlObject.protocol === 'http:' && urlObject.port === '80') {
+    urlObject.port = ''
+  }
+
+  return urlObject.href.replace(/\/$/, '')
+}
+
+// Don't import remote scheme from constants because we are in core utils
+function sanitizeHost (host: string, remoteScheme: string) {
+  let toRemove = remoteScheme === 'https' ? 443 : 80
+
+  return host.replace(new RegExp(`:${toRemove}$`), '')
+}
 
 function isTestInstance () {
   return process.env.NODE_ENV === 'test'
@@ -114,6 +134,8 @@ export {
   root,
   escapeHTML,
   pageToStartAndCount,
+  sanitizeUrl,
+  sanitizeHost,
 
   promisify0,
   promisify1,
index 1b9aad444f0ac835d91e0d3b3d2a37816ff59b00..46f1ac210c79bf491a591621df27e77a4b9bdb7f 100644 (file)
@@ -1,4 +1,5 @@
-import { CONFIG } from '../../initializers'
+import { CONFIG, REMOTE_SCHEME } from '../../initializers'
+import { sanitizeHost } from '../core-utils'
 import { exists } from './misc'
 
 function isWebfingerResourceValid (value: string) {
@@ -11,7 +12,7 @@ function isWebfingerResourceValid (value: string) {
 
   const host = actorParts[1]
 
-  return host === CONFIG.WEBSERVER.HOSTNAME || host === CONFIG.WEBSERVER.HOST
+  return sanitizeHost(host, REMOTE_SCHEME.HTTP) === CONFIG.WEBSERVER.HOSTNAME
 }
 
 // ---------------------------------------------------------------------------
index 2ea2aa6b9bde20dbba58abb8d82ebf995944f982..100a77622f5ce2f214da8703d2111a0f23eee84b 100644 (file)
@@ -1,15 +1,15 @@
 import * as config from 'config'
 import { join } from 'path'
 import { JobCategory, JobState, VideoRateType } from '../../shared/models'
-import { FollowState } from '../../shared/models/actors'
 import { ActivityPubActorType } from '../../shared/models/activitypub'
+import { FollowState } from '../../shared/models/actors'
 import { VideoPrivacy } from '../../shared/models/videos'
 // Do not use barrels, remain constants as independent as possible
-import { isTestInstance, root } from '../helpers/core-utils'
+import { isTestInstance, root, sanitizeHost, sanitizeUrl } from '../helpers/core-utils'
 
 // ---------------------------------------------------------------------------
 
-const LAST_MIGRATION_VERSION = 135
+const LAST_MIGRATION_VERSION = 140
 
 // ---------------------------------------------------------------------------
 
@@ -38,6 +38,44 @@ const OAUTH_LIFETIME = {
 
 // ---------------------------------------------------------------------------
 
+// Number of points we add/remove from a friend after a successful/bad request
+const SERVERS_SCORE = {
+  PENALTY: -10,
+  BONUS: 10,
+  BASE: 100,
+  MAX: 1000
+}
+
+const FOLLOW_STATES: { [ id: string ]: FollowState } = {
+  PENDING: 'pending',
+  ACCEPTED: 'accepted'
+}
+
+const REMOTE_SCHEME = {
+  HTTP: 'https',
+  WS: 'wss'
+}
+
+const JOB_STATES: { [ id: string ]: JobState } = {
+  PENDING: 'pending',
+  PROCESSING: 'processing',
+  ERROR: 'error',
+  SUCCESS: 'success'
+}
+const JOB_CATEGORIES: { [ id: string ]: JobCategory } = {
+  TRANSCODING: 'transcoding',
+  ACTIVITYPUB_HTTP: 'activitypub-http'
+}
+// How many maximum jobs we fetch from the database per cycle
+const JOBS_FETCH_LIMIT_PER_CYCLE = {
+  transcoding: 10,
+  httpRequest: 20
+}
+// 1 minutes
+let JOBS_FETCHING_INTERVAL = 60000
+
+// ---------------------------------------------------------------------------
+
 const CONFIG = {
   LISTEN: {
     PORT: config.get<number>('listen.port')
@@ -93,8 +131,6 @@ const CONFIG = {
     }
   }
 }
-CONFIG.WEBSERVER.URL = CONFIG.WEBSERVER.SCHEME + '://' + CONFIG.WEBSERVER.HOSTNAME + ':' + CONFIG.WEBSERVER.PORT
-CONFIG.WEBSERVER.HOST = CONFIG.WEBSERVER.HOSTNAME + ':' + CONFIG.WEBSERVER.PORT
 
 const AVATARS_DIR = {
   ACCOUNT: join(CONFIG.STORAGE.AVATARS_DIR, 'account')
@@ -238,44 +274,6 @@ const ACTIVITY_PUB_ACTOR_TYPES: { [ id: string ]: ActivityPubActorType } = {
 
 // ---------------------------------------------------------------------------
 
-// Number of points we add/remove from a friend after a successful/bad request
-const SERVERS_SCORE = {
-  PENALTY: -10,
-  BONUS: 10,
-  BASE: 100,
-  MAX: 1000
-}
-
-const FOLLOW_STATES: { [ id: string ]: FollowState } = {
-  PENDING: 'pending',
-  ACCEPTED: 'accepted'
-}
-
-const REMOTE_SCHEME = {
-  HTTP: 'https',
-  WS: 'wss'
-}
-
-const JOB_STATES: { [ id: string ]: JobState } = {
-  PENDING: 'pending',
-  PROCESSING: 'processing',
-  ERROR: 'error',
-  SUCCESS: 'success'
-}
-const JOB_CATEGORIES: { [ id: string ]: JobCategory } = {
-  TRANSCODING: 'transcoding',
-  ACTIVITYPUB_HTTP: 'activitypub-http'
-}
-// How many maximum jobs we fetch from the database per cycle
-const JOBS_FETCH_LIMIT_PER_CYCLE = {
-  transcoding: 10,
-  httpRequest: 20
-}
-// 1 minutes
-let JOBS_FETCHING_INTERVAL = 60000
-
-// ---------------------------------------------------------------------------
-
 const PRIVATE_RSA_KEY_SIZE = 2048
 
 // Password encryption
@@ -334,6 +332,9 @@ if (isTestInstance() === true) {
   ACTIVITY_PUB.COLLECTION_ITEMS_PER_PAGE = 2
 }
 
+CONFIG.WEBSERVER.URL = sanitizeUrl(CONFIG.WEBSERVER.SCHEME + '://' + CONFIG.WEBSERVER.HOSTNAME + ':' + CONFIG.WEBSERVER.PORT)
+CONFIG.WEBSERVER.HOST = sanitizeHost(CONFIG.WEBSERVER.HOSTNAME + ':' + CONFIG.WEBSERVER.PORT, REMOTE_SCHEME.HTTP)
+
 // ---------------------------------------------------------------------------
 
 export {
diff --git a/server/initializers/migrations/0140-actor-url.ts b/server/initializers/migrations/0140-actor-url.ts
new file mode 100644 (file)
index 0000000..626f3c4
--- /dev/null
@@ -0,0 +1,42 @@
+import * as Sequelize from 'sequelize'
+import { DataType } from 'sequelize-typescript'
+import { createPrivateAndPublicKeys } from '../../helpers'
+import { CONFIG } from '../constants'
+
+async function up (utils: {
+  transaction: Sequelize.Transaction,
+  queryInterface: Sequelize.QueryInterface,
+  sequelize: Sequelize.Sequelize
+}): Promise<void> {
+  const toReplace = CONFIG.WEBSERVER.HOSTNAME + ':443'
+  const by = CONFIG.WEBSERVER.HOST
+  const replacer = column => `replace("${column}", '${toReplace}', '${by}')`
+
+  {
+    const query = `UPDATE video SET url = ${replacer('url')}`
+    await utils.sequelize.query(query)
+  }
+
+  {
+    const query = `
+      UPDATE actor SET url = ${replacer('url')}, "inboxUrl" = ${replacer('inboxUrl')}, "outboxUrl" = ${replacer('outboxUrl')},
+      "sharedInboxUrl" = ${replacer('sharedInboxUrl')}, "followersUrl" = ${replacer('followersUrl')},
+      "followingUrl" = ${replacer('followingUrl')}
+    `
+    await utils.sequelize.query(query)
+  }
+
+  {
+    const query = `UPDATE server SET host = replace(host, ':443', '')`
+    await utils.sequelize.query(query)
+  }
+}
+
+function down (options) {
+  throw new Error('Not implemented.')
+}
+
+export {
+  up,
+  down
+}