#!/usr/bin/env python # # Copyright 2015-2015 breakwa11 # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. from __future__ import absolute_import, division, print_function, \ with_statement import os import sys import hashlib import logging import binascii import base64 import datetime import struct from shadowsocks.obfsplugin import plain from shadowsocks import common from shadowsocks.common import to_bytes, to_str, ord def create_verify_obfs(method): return verify_simple(method) obfs = { 'verify_simple': (create_verify_obfs,), } def match_begin(str1, str2): if len(str1) >= len(str2): if str1[:len(str2)] == str2: return True return False class verify_simple(plain.plain): def __init__(self, method): self.method = method self.recv_buf = b'' self.unit_len = 8100 def pack_data(self, buf): if len(buf) == 0: return b'' rnd_data = os.urandom(common.ord(os.urandom(1)[0]) % 16) data = common.chr(len(rnd_data) + 1) + rnd_data + buf data = struct.pack('>H', len(data) + 6) + data crc = (0xffffffff - binascii.crc32(data)) & 0xffffffff data += struct.pack(' self.unit_len: ret += self.pack_data(buf[:self.unit_len]) buf = buf[self.unit_len:] ret += self.pack_data(buf) return ret def client_encode(self, buf): return buf def client_decode(self, buf): # (buffer_to_recv, is_need_to_encode_and_send_back) return (buf, False) def client_post_decrypt(self, buf): return buf def server_pre_encrypt(self, buf): ret = b'' while len(buf) > self.unit_len: ret += self.pack_data(buf[:self.unit_len]) buf = buf[self.unit_len:] ret += self.pack_data(buf) return ret def server_encode(self, buf): return buf def server_decode(self, buf): # (buffer_to_recv, is_need_decrypt, is_need_to_encode_and_send_back) return (buf, True, False) def server_post_decrypt(self, buf): self.recv_buf += buf out_buf = b'' while len(self.recv_buf) > 2: length = struct.unpack('>H', self.recv_buf[:2])[0] if length >= 8192: raise Exception('server_post_decrype data error') if length > len(self.recv_buf): break if (binascii.crc32(self.recv_buf[:length]) & 0xffffffff) != 0xffffffff: raise Exception('server_post_decrype data uncorrect CRC32') pos = common.ord(self.recv_buf[2]) + 2 out_buf += self.recv_buf[pos:length - 4] self.recv_buf = self.recv_buf[length:] return out_buf