Encoding the x-ycm-hmac header value as base64.

We need to respect RFC 5987.
This commit is contained in:
Strahinja Val Markovic 2014-05-09 10:37:20 -07:00
parent ec65950a9b
commit 9691bd9236
2 changed files with 18 additions and 9 deletions

View File

@ -20,6 +20,7 @@
import vim import vim
import requests import requests
import urlparse import urlparse
from base64 import b64decode, b64encode
from retries import retries from retries import retries
from requests_futures.sessions import FuturesSession from requests_futures.sessions import FuturesSession
from ycm.unsafe_thread_pool_executor import UnsafeThreadPoolExecutor from ycm.unsafe_thread_pool_executor import UnsafeThreadPoolExecutor
@ -124,8 +125,8 @@ class BaseRequest( object ):
if not request_body: if not request_body:
request_body = '' request_body = ''
headers = dict( _HEADERS ) headers = dict( _HEADERS )
headers[ _HMAC_HEADER ] = utils.CreateHexHmac( request_body, headers[ _HMAC_HEADER ] = b64encode(
BaseRequest.hmac_secret ) utils.CreateHexHmac( request_body, BaseRequest.hmac_secret ) )
return headers return headers
session = FuturesSession( executor = _EXECUTOR ) session = FuturesSession( executor = _EXECUTOR )
@ -171,9 +172,10 @@ def JsonFromFuture( future ):
def _ValidateResponseObject( response ): def _ValidateResponseObject( response ):
if not utils.ContentHexHmacValid( response.content, if not utils.ContentHexHmacValid(
response.headers[ _HMAC_HEADER ], response.content,
BaseRequest.hmac_secret ): b64decode( response.headers[ _HMAC_HEADER ] ),
BaseRequest.hmac_secret ):
raise RuntimeError( 'Received invalid HMAC for response!' ) raise RuntimeError( 'Received invalid HMAC for response!' )
return True return True

View File

@ -19,6 +19,7 @@
import logging import logging
import httplib import httplib
from base64 import b64decode, b64encode
from bottle import request, response, abort from bottle import request, response, abort
from ycm import utils from ycm import utils
@ -30,6 +31,9 @@ _HMAC_HEADER = 'x-ycm-hmac'
# We want to ensure that every request coming in has a valid HMAC set in the # We want to ensure that every request coming in has a valid HMAC set in the
# x-ycm-hmac header and that every response coming out sets such a valid header. # x-ycm-hmac header and that every response coming out sets such a valid header.
# This is to prevent security issues with possible remote code execution. # This is to prevent security issues with possible remote code execution.
# The x-ycm-hmac value is encoded as base64 during transport instead of sent raw
# because https://tools.ietf.org/html/rfc5987 says header values must be in the
# ISO-8859-1 character set.
class HmacPlugin( object ): class HmacPlugin( object ):
name = 'hmac' name = 'hmac'
api = 2 api = 2
@ -54,9 +58,12 @@ class HmacPlugin( object ):
def RequestAuthenticated( body, hmac_secret ): def RequestAuthenticated( body, hmac_secret ):
return utils.ContentHexHmacValid( body, return utils.ContentHexHmacValid(
request.headers[ _HMAC_HEADER ], body,
hmac_secret ) b64decode( request.headers[ _HMAC_HEADER ] ),
hmac_secret )
def SetHmacHeader( body, hmac_secret ): def SetHmacHeader( body, hmac_secret ):
response.headers[ _HMAC_HEADER ] = utils.CreateHexHmac( body, hmac_secret ) response.headers[ _HMAC_HEADER ] = b64encode(
utils.CreateHexHmac( body, hmac_secret ) )