예제 #1
0
func getCredentials(a httpRequestArgs,
	hdrCreds *url.Userinfo, auths []string) (datastore.Credentials, errors.Error) {
	var creds datastore.Credentials

	if hdrCreds != nil {
		// Credentials are in the request URL:
		username := hdrCreds.Username()
		password, _ := hdrCreds.Password()
		creds = make(datastore.Credentials)
		creds[username] = password
		return creds, nil
	}
	if len(auths) > 0 {
		// Credentials are in the request header:
		// TODO: implement non-Basic auth (digest, ntlm)
		auth := auths[0]
		if strings.HasPrefix(auth, "Basic ") {
			encoded_creds := strings.Split(auth, " ")[1]
			decoded_creds, err := base64.StdEncoding.DecodeString(encoded_creds)
			if err != nil {
				return creds, errors.NewServiceErrorBadValue(err, CREDS)
			}
			// Authorization header is in format "user:pass"
			// per http://tools.ietf.org/html/rfc1945#section-10.2
			u_details := strings.Split(string(decoded_creds), ":")
			switch len(u_details) {
			case 2:
				creds = make(datastore.Credentials)
				creds[u_details[0]] = u_details[1]
			case 3:
				creds = make(datastore.Credentials)
				// Support usernames like "local:xxx" or "admin:xxx"
				creds[strings.Join(u_details[:2], ":")] = u_details[2]
			default:
				// Authorization header format is incorrect
				return creds, errors.NewServiceErrorBadValue(nil, CREDS)
			}
		}
		return creds, nil
	}
	// Credentials may be in request arguments:
	cred_data, err := a.getCredentials()
	if err == nil && len(cred_data) > 0 {
		creds = make(datastore.Credentials)
		for _, cred := range cred_data {
			user, user_ok := cred["user"]
			pass, pass_ok := cred["pass"]
			if user_ok && pass_ok {
				creds[user] = pass
			} else {
				err = errors.NewServiceErrorMissingValue("user or pass")
				break
			}
		}
	}
	return creds, err
}
예제 #2
0
// A named argument is an argument of the form: $<identifier>=json_value
func (this *urlArgs) getNamedArgs() (map[string]value.Value, errors.Error) {
	var args map[string]value.Value

	for name, _ := range this.req.Form {
		if !strings.HasPrefix(name, "$") {
			continue
		}
		arg, err := this.formValue(name)
		if err != nil {
			return args, err
		}
		if len(arg) == 0 {
			//This is an error - there _has_ to be a value for a named argument
			return args, errors.NewServiceErrorMissingValue(fmt.Sprintf("named argument %s", name))
		}
		args = addNamedArg(args, name, value.NewValue([]byte(arg)))
	}
	return args, nil
}
예제 #3
0
func getScanConfiguration(a httpRequestArgs) (*scanConfigImpl, errors.Error) {
	var sc scanConfigImpl

	scan_consistency_field, err := a.getString(SCAN_CONSISTENCY, "NOT_BOUNDED")
	if err == nil {
		sc.scan_level = newScanConsistency(scan_consistency_field)
		if sc.scan_level == server.UNDEFINED_CONSISTENCY {
			err = errors.NewServiceErrorUnrecognizedValue(SCAN_CONSISTENCY, scan_consistency_field)
		}
	}
	if err == nil {
		sc.scan_wait, err = a.getDuration(SCAN_WAIT)
	}
	if err == nil {
		sc.scan_vector, err = a.getScanVector()
	}
	if err == nil && sc.scan_level == server.AT_PLUS && sc.scan_vector == nil {
		err = errors.NewServiceErrorMissingValue(SCAN_VECTOR)
	}
	return &sc, err
}
예제 #4
0
func newHttpRequest(resp http.ResponseWriter, req *http.Request, bp BufferPool) *httpRequest {
	var httpArgs httpRequestArgs
	var err errors.Error

	e := req.ParseForm()
	if e != nil {
		err = errors.NewServiceErrorBadValue(e, "request form")
	}

	if err != nil && req.Method != "GET" && req.Method != "POST" {
		err = errors.NewServiceErrorHTTPMethod(req.Method)
	}

	if err == nil {
		httpArgs, err = getRequestParams(req)
	}

	var statement string
	if err == nil {
		statement, err = httpArgs.getStatement()
	}

	var prepared *plan.Prepared
	if err == nil {
		prepared, err = getPrepared(httpArgs)
	}

	if err == nil && statement == "" && prepared == nil {
		err = errors.NewServiceErrorMissingValue("statement or prepared")
	}

	var namedArgs map[string]value.Value
	if err == nil {
		namedArgs, err = httpArgs.getNamedArgs()
	}

	var positionalArgs value.Values
	if err == nil {
		positionalArgs, err = httpArgs.getPositionalArgs()
	}

	var namespace string
	if err == nil {
		namespace, err = httpArgs.getString(NAMESPACE, "")
	}

	var timeout time.Duration
	if err == nil {
		timeout, err = httpArgs.getDuration(TIMEOUT)
	}

	var readonly value.Tristate
	if err == nil {
		readonly, err = httpArgs.getTristate(READONLY)
	}
	if err == nil && readonly == value.FALSE && req.Method == "GET" {
		err = errors.NewServiceErrorReadonly(
			fmt.Sprintf("%s=false cannot be used with HTTP GET method.", READONLY))
	}

	var metrics value.Tristate
	if err == nil {
		metrics, err = httpArgs.getTristate(METRICS)
	}

	var format Format
	if err == nil {
		format, err = getFormat(httpArgs)
	}

	if err == nil && format != JSON {
		err = errors.NewServiceErrorNotImplemented("format", format.String())
	}

	var signature value.Tristate
	if err == nil {
		signature, err = httpArgs.getTristate(SIGNATURE)
	}

	var compression Compression
	if err == nil {
		compression, err = getCompression(httpArgs)
	}

	if err == nil && compression != NONE {
		err = errors.NewServiceErrorNotImplemented("compression", compression.String())
	}

	var encoding Encoding
	if err == nil {
		encoding, err = getEncoding(httpArgs)
	}

	if err == nil && encoding != UTF8 {
		err = errors.NewServiceErrorNotImplemented("encoding", encoding.String())
	}

	var pretty value.Tristate
	if err == nil {
		pretty, err = httpArgs.getTristate(PRETTY)
	}

	if err == nil && pretty == value.FALSE {
		err = errors.NewServiceErrorNotImplemented("pretty", "false")
	}

	var consistency *scanConfigImpl

	if err == nil {
		consistency, err = getScanConfiguration(httpArgs)
	}

	var creds datastore.Credentials
	if err == nil {
		creds, err = getCredentials(httpArgs, req.URL.User, req.Header["Authorization"])
	}

	client_id := ""
	if err == nil {
		client_id, err = httpArgs.getString(CLIENT_CONTEXT_ID, "")
	}

	base := server.NewBaseRequest(statement, prepared, namedArgs, positionalArgs,
		namespace, readonly, metrics, signature, consistency, client_id, creds)

	rv := &httpRequest{
		BaseRequest: *base,
		resp:        resp,
		req:         req,
	}

	rv.SetTimeout(rv, timeout)

	rv.writer = NewBufferedWriter(rv, bp)

	// Limit body size in case of denial-of-service attack
	req.Body = http.MaxBytesReader(resp, req.Body, MAX_REQUEST_BYTES)

	// Abort if client closes connection
	closeNotify := resp.(http.CloseNotifier).CloseNotify()
	go func() {
		<-closeNotify
		rv.Stop(server.TIMEOUT)
	}()

	if err != nil {
		rv.Fail(err)
	}

	return rv
}