github.com/psiphon-labs/psiphon-tunnel-core@v2.0.28+incompatible/psiphon/upstreamproxy/auth_basic.go (about)

     1  /*
     2   * Copyright (c) 2015, Psiphon Inc.
     3   * All rights reserved.
     4   *
     5   * This program is free software: you can redistribute it and/or modify
     6   * it under the terms of the GNU General Public License as published by
     7   * the Free Software Foundation, either version 3 of the License, or
     8   * (at your option) any later version.
     9   *
    10   * This program is distributed in the hope that it will be useful,
    11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
    12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    13   * GNU General Public License for more details.
    14   *
    15   * You should have received a copy of the GNU General Public License
    16   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
    17   *
    18   */
    19  
    20  package upstreamproxy
    21  
    22  import (
    23  	"encoding/base64"
    24  	"fmt"
    25  	"net/http"
    26  )
    27  
    28  type BasicHttpAuthState int
    29  
    30  const (
    31  	BASIC_HTTP_AUTH_STATE_CHALLENGE_RECEIVED BasicHttpAuthState = iota
    32  	BASIC_HTTP_AUTH_STATE_RESPONSE_GENERATED
    33  )
    34  
    35  type BasicHttpAuthenticator struct {
    36  	state    BasicHttpAuthState
    37  	username string
    38  	password string
    39  }
    40  
    41  func newBasicAuthenticator(username, password string) *BasicHttpAuthenticator {
    42  	return &BasicHttpAuthenticator{
    43  		state:    BASIC_HTTP_AUTH_STATE_CHALLENGE_RECEIVED,
    44  		username: username,
    45  		password: password,
    46  	}
    47  }
    48  
    49  func (a *BasicHttpAuthenticator) Authenticate(req *http.Request, resp *http.Response) error {
    50  	if a.state == BASIC_HTTP_AUTH_STATE_CHALLENGE_RECEIVED {
    51  		a.state = BASIC_HTTP_AUTH_STATE_RESPONSE_GENERATED
    52  		return a.PreAuthenticate(req)
    53  	}
    54  	return proxyError(fmt.Errorf("authorization is not accepted by the proxy server"))
    55  }
    56  
    57  func (a *BasicHttpAuthenticator) IsConnectionBased() bool {
    58  	return false
    59  }
    60  
    61  func (a *BasicHttpAuthenticator) IsComplete() bool {
    62  	return a.state == BASIC_HTTP_AUTH_STATE_RESPONSE_GENERATED
    63  }
    64  
    65  func (a *BasicHttpAuthenticator) Reset() {
    66  	a.state = BASIC_HTTP_AUTH_STATE_CHALLENGE_RECEIVED
    67  }
    68  
    69  func (a *BasicHttpAuthenticator) PreAuthenticate(req *http.Request) error {
    70  	auth := a.username + ":" + a.password
    71  	req.Header.Set("Proxy-Authorization", "Basic "+base64.StdEncoding.EncodeToString([]byte(auth)))
    72  	return nil
    73  }