o
    &gk.                     @   s   d dl Z d dlZd dlZd dlZd dlZd dlZe eZe	dZ
dd ZG dd dZG dd deZG d	d
 d
eZG dd deZG dd deZG dd deZG dd deZG dd deZG dd deZdS )    NzW(?<=^)"([^"]+)"(?=:|$)|(?<=:)"([^"]+)"(?=:|$)|(?<=^)([^:]*)(?=:|$)|(?<=:)([^:]*)(?=:|$)c                 C   s   t | }dd |D S )zIt works like src.split(":") but with the ability to use a colon
    if you wrap the word in quotation marks.

    a:b:c:d -> ['a', 'b', 'c', 'd'
    a:"b:c":c -> ['a', 'b:c', 'd']
    c                 S   s,   g | ]}|d  p|d p|d p|d qS )r             ).0mr   r   W/root/parts/websockify/install/lib/python3.10/site-packages/websockify/token_plugins.py
<listcomp>   s   , z%parse_source_args.<locals>.<listcomp>)_SOURCE_SPLIT_REGEXfindall)srcmatchesr   r   r   parse_source_args   s   
r   c                   @      e Zd Zdd Zdd ZdS )
BasePluginc                 C   s
   || _ d S N)sourceselfr   r   r   r   __init__   s   
zBasePlugin.__init__c                 C   s   d S r   r   r   tokenr   r   r   lookup!   s   zBasePlugin.lookupN)__name__
__module____qualname__r   r   r   r   r   r   r      s    r   c                       s,   e Zd Z fddZdd Zdd Z  ZS )ReadOnlyTokenFilec                    s   t  j|i | d | _d S r   )superr   _targetsr   argskwargs	__class__r   r   r   )   s   
zReadOnlyTokenFile.__init__c              
      s   t j jr fddt  jD }n jg}i  _d}|D ]D}dd t| D D ]6}|r_|ds_zt	
d|\}}| dd j|< W n ty^   td j|f  Y nw |d7 }q-q d S )	Nc                    s   g | ]
}t j j|qS r   )ospathjoinr   )r   fr   r   r   r	   /   s    z3ReadOnlyTokenFile._load_targets.<locals>.<listcomp>r   c                 S   s   g | ]}|  qS r   )strip)r   lr   r   r   r	   7   s    #z:\s:zSyntax error in %s on line %d)r$   r%   isdirr   listdirr   open	readlines
startswithresplitr)   rsplit
ValueErrorloggererror)r   	cfg_filesindexr'   linetoktargetr   r(   r   _load_targets-   s&   


zReadOnlyTokenFile._load_targetsc                 C   s*   | j d u r	|   || j v r| j | S d S r   )r   r=   r   r   r   r   r   @   s
   


zReadOnlyTokenFile.lookup)r   r   r   r   r=   r   __classcell__r   r   r"   r   r   %   s    r   c                       s   e Zd Z fddZ  ZS )	TokenFilec                    s   |    t |S r   )r=   r   r   r   r"   r   r   r   Q   s   zTokenFile.lookup)r   r   r   r   r>   r   r   r"   r   r?   M   s    r?   c                       $   e Zd Z fddZdd Z  ZS )TokenFileNamec                    s$   t  | tj|stdd S )Nz)TokenFileName plugin requires a directory)r   r   r$   r%   r-   	Exceptionr   r"   r   r   r   Z   s   zTokenFileName.__init__c                 C   sB   t j|}t j| j|}t j|rt|  	dS d S )Nr,   )
r$   r%   basenamer&   r   existsr/   readr)   r3   )r   r   r%   r   r   r   r   _   s
   zTokenFileName.lookupr   r   r   r   r   r>   r   r   r"   r   rA   V   s    rA   c                   @   r   )BaseTokenAPIc                 C   s$   |j d\}}|dd}||gS )Nr,   asciiignore)textr3   encode)r   resphostportr   r   r   process_resulto   s   zBaseTokenAPI.process_resultc                 C   s,   dd l }|| j| }|jr| |S d S )Nr   )requestsgetr   okrO   )r   r   rP   rL   r   r   r   r   t   s
   
zBaseTokenAPI.lookupN)r   r   r   rO   r   r   r   r   r   rG   h   s    rG   c                   @      e Zd Zdd ZdS )JSONTokenApic                 C   s   |  }|d |d fS )NrM   rN   )json)r   rL   	resp_jsonr   r   r   rO      s   zJSONTokenApi.process_resultN)r   r   r   rO   r   r   r   r   rT          rT   c                   @   rS   )JWTTokenApic              
   C   s  zddl m}m} dd l}| }zt| jd}| }W d    n1 s'w   Y  W n tyJ } zt	
dt|  W Y d }~W d S d }~ww z|| W n   z|j|ddd W n   t	
d Y Y W d S Y zS|j||d	}||j}	d
|	v r|j||jd	}||j}
d|
v rt |
d k rt	d W W d S d|
v rt |
d krt	d W W d S |
d |
d fW W S  ty } zt	
dt|  W Y d }~W d S d }~ww  ty   t	
d Y d S w )Nr   )jwtjwkrbzError loading key file: %sutf-8oct)kktyz#Failed to correctly parse key data!)keyrY   encnbfzToken can not be used yet!expzToken has expired!rM   rN   zFailed to parse token: %szGpackage jwcrypto not found, are you sure you've installed it correctly?)jwcryptorY   rZ   rU   JWKr/   r   rE   rB   r6   r7   strimport_from_pem
import_keydecodeJWTloadsheaderclaimstimewarningImportError)r   r   rY   rZ   rU   r`   key_filekey_dataeparsed_headerparsedr   r   r   r      s^   





zJWTTokenApi.lookupN)r   r   r   r   r   r   r   r   rX      rW   rX   c                   @   s    e Zd ZdZdd Zdd ZdS )
TokenRedisa  Token plugin based on the Redis in-memory data store.

    The token source is in the format:

        host[:port[:db[:password[:namespace]]]]

    where port, db, password and namespace are optional. If port or db are left empty
    they will take its default value, ie. 6379 and 0 respectively.

    If your redis server is using the default port (6379) then you can use:

        my-redis-host

    In case you need to authenticate with the redis server and you are using
    the default database and port you can use:

        my-redis-host:::verysecretpass

    You can also specify a namespace. In this case, the tokens
    will be stored in the format '{namespace}:{token}'

        my-redis-host::::my-app-namespace

    Or if your namespace is nested, you can wrap it in quotes:

        my-redis-host::::"first-ns:second-ns"

    In the more general case you will use:

        my-redis-host:6380:1:verysecretpass:my-app-namespace

    The TokenRedis plugin expects the format of the target in one of these two
    formats:

    - JSON

        {"host": "target-host:target-port"}

    - Plain text

        target-host:target-port

    Prepare data with:

        redis-cli set my-token '{"host": "127.0.0.1:5000"}'

    Verify with:

        redis-cli --raw get my-token

    Spawn a test "server" using netcat

        nc -l 5000 -v

    Note: This Token Plugin depends on the 'redis' module, so you have
    to install it before using this plugin:

          pip install redis
    c                 C   s  zdd l }W n ty   td t  Y nw d| _d| _d | _d| _	zt
|}t|dkr6|d | _n~t|dkrI|\| _| _| jsHd| _nkt|dkrd|\| _| _| _| js]d| _| jscd| _nPt|dkr|\| _| _| _| _| jszd| _| jsd| _| jsd | _n-t|d	kr|\| _| _| _| _| _	| jsd| _| jsd| _| jsd | _| j	sd| _	ntt| j| _t| j| _| j	r|  j	d
7  _	td| j| jf  W d S  ty   td|  t  Y d S w )Nr   zUnable to load redis modulei   r   r   r         r,   z&TokenRedis backend initialized (%s:%s)zpThe provided --token-source='%s' is not in the expected format <host>[:<port>[:<db>[:<password>[:<namespace>]]]])redisrp   r6   r7   sysexit_port_db	_password
_namespacer   len_serverr5   intinfo)r   r   rz   fieldsr   r   r   r      sx   

zTokenRedis.__init__c           	      C   sH  zdd l }W n ty   td t  Y nw td|  |j| j| j	| j
| jd}|| j| }|d u r;d S |d }td|  |drzt|}|d d	\}}W n8 tyo   td
|  Y d S  ty   td|  Y d S w td|r|d	\}}n	td|  d S td||f  ||gS )Nr   zFpackage redis not found, are you sure you've installed them correctly?zresolving token '%s')rM   rN   dbpasswordr\   zresponse from redis : %s{rM   r,   zUnable to decode JSON token: %sz+Unable to find 'host' key in JSON token: %sz\S+:\S+zUnable to parse token: %szhost: %s, port: %s)rz   rp   r6   r7   r{   r|   r   Redisr   r}   r~   r   rQ   r   ri   r)   debugr1   rU   rk   r3   r5   KeyErrorr2   match)	r   r   rz   clientstuffresponseStrcomborM   rN   r   r   r   r   8  sH   


zTokenRedis.lookupN)r   r   r   __doc__r   r   r   r   r   r   rv      s    ;:rv   c                       r@   )UnixDomainSocketDirectoryc                    s&   t  j|i | tj| j| _d S r   )r   r   r$   r%   abspathr   	_dir_pathr   r"   r   r   r   ^  s   z"UnixDomainSocketDirectory.__init__c              
   C   s   z=dd l }tj| jsW d S tjtj| j|}|| js$W d S tj|s-W d S |	t |j
s9W d S d|gW S  tyY } ztdt|  W Y d }~d S d }~ww )Nr   unix_socketz$Error finding unix domain socket: %s)statr$   r%   r-   r   r   r&   r1   rD   S_ISSOCKst_moderB   r6   r7   rf   )r   r   r   uds_pathrs   r   r   r   r   b  s"   
z UnixDomainSocketDirectory.lookuprF   r   r   r"   r   r   ]  s    r   )loggingr$   r{   rn   r2   rU   	getLoggerr   r6   compiler
   r   r   r   r?   rA   rG   rT   rX   rv   r   r   r   r   r   <module>   s*    
(		: 