Esempio n. 1
1
int main (int argc, char *argv[])
{
    ngx_pool_t *pool;
    ngx_str_t dst, src = ngx_string("cubicdaiya");
    u_char *encoded;
    size_t encoded_len;

    encoded_len = ngx_base64_encoded_length(src.len);
    pool        = ngx_create_pool(NGX_DEFAULT_POOL_SIZE, NULL);
    if (pool == NULL) {
        perror("ngx_create_pool() failed.");
        return 1;
    }
    if ((encoded = ngx_pcalloc(pool, encoded_len + 1)) == NULL) {
        perror("ngx_pcalloc() failed.");
        return 1;
    }

    dst.data = encoded;
    dst.len  = encoded_len;
    ngx_encode_base64(&dst, &src);

    printf("src:%s, dst:%s\n", src.data, dst.data);

    return 0;
}
Esempio n. 2
0
int main(int argc, char* argv[]) {
    /* str to lower */
    ngx_str_t str = ngx_string("Hello World!");
    u_char* strlow = (u_char*)malloc(str.len);
    ngx_strlow(strlow, str.data, str.len);
    fprintf(stdout, "strlow %.*s\n", str.len, strlow);
    free(strlow);

    /* base64 encode and decode */
    ngx_str_t raw_str = ngx_string("123abc"); 
    ngx_str_t base64_encoded_str = ngx_null_string; 
    ngx_str_t base64_decoded_str = ngx_null_string;

    base64_encoded_str.len = ngx_base64_encoded_length(raw_str.len);
    base64_encoded_str.data = (u_char*)malloc(base64_encoded_str.len);
    ngx_encode_base64(&base64_encoded_str, &raw_str);
    fprintf(stdout, "%.*s\n", base64_encoded_str.len, base64_encoded_str.data);

    base64_decoded_str.len = ngx_base64_decoded_length(base64_encoded_str.len);
    base64_decoded_str.data = (u_char*)malloc(base64_decoded_str.len);
    ngx_decode_base64(&base64_decoded_str, &base64_encoded_str);
    fprintf(stdout, "%.*s\n", base64_decoded_str.len, base64_decoded_str.data);
    free(base64_encoded_str.data);
    free(base64_decoded_str.data);

    return 0;
}
static int
ngx_http_lua_ngx_encode_base64(lua_State *L)
{
    ngx_str_t                p, src;

    if (lua_gettop(L) != 1) {
        return luaL_error(L, "expecting one argument");
    }

    if (lua_isnil(L, 1)) {
        src.data = (u_char *) "";
        src.len = 0;

    } else {
        src.data = (u_char *) luaL_checklstring(L, 1, &src.len);
    }

    p.len = ngx_base64_encoded_length(src.len);

    p.data = lua_newuserdata(L, p.len);

    ngx_encode_base64(&p, &src);

    lua_pushlstring(L, (char *) p.data, p.len);

    return 1;
}
ngx_int_t
ngx_mail_auth_cram_md5_salt(ngx_mail_session_t *s, ngx_connection_t *c,
    char *prefix, size_t len)
{
    u_char      *p;
    ngx_str_t    salt;
    ngx_uint_t   n;

    p = ngx_palloc(c->pool, len + ngx_base64_encoded_length(s->salt.len) + 2);
    if (p == NULL) {
        return NGX_ERROR;
    }

    salt.data = ngx_cpymem(p, prefix, len);
    s->salt.len -= 2;

    ngx_encode_base64(&salt, &s->salt);

    s->salt.len += 2;
    n = len + salt.len;
    p[n++] = CR; p[n++] = LF;

    s->out.len = n;
    s->out.data = p;

    return NGX_OK;
}
Esempio n. 5
0
static void websocket_perform_handshake(full_subscriber_t *fsub) {
  static ngx_str_t    magic = ngx_string("258EAFA5-E914-47DA-95CA-C5AB0DC85B11");
  ngx_str_t           ws_accept_key, sha1_str;
  u_char              buf_sha1[21];
  u_char              buf[255];
  ngx_str_t          *tmp, *ws_key;
  ngx_int_t           ws_version;
  ngx_http_request_t *r = fsub->sub.request;
  
  ngx_sha1_t          sha1;
  
  ws_accept_key.data = buf;
  
  r->headers_out.content_length_n = 0;
  r->header_only = 1;  
  
  if((tmp = nchan_get_header_value(r, NCHAN_HEADER_SEC_WEBSOCKET_VERSION)) == NULL) {
    r->headers_out.status = NGX_HTTP_BAD_REQUEST;
    fsub->sub.dequeue_after_response=1;
  }
  else {
    ws_version=ngx_atoi(tmp->data, tmp->len);
    if(ws_version != 13) {
      r->headers_out.status = NGX_HTTP_BAD_REQUEST;
      fsub->sub.dequeue_after_response=1;
    }
  }
  
  if((ws_key = nchan_get_header_value(r, NCHAN_HEADER_SEC_WEBSOCKET_KEY)) == NULL) {
    r->headers_out.status = NGX_HTTP_BAD_REQUEST;
    fsub->sub.dequeue_after_response=1;
  }
  
  if(r->headers_out.status != NGX_HTTP_BAD_REQUEST) {
    //generate accept key
    ngx_sha1_init(&sha1);
    ngx_sha1_update(&sha1, ws_key->data, ws_key->len);
    ngx_sha1_update(&sha1, magic.data, magic.len);
    ngx_sha1_final(buf_sha1, &sha1);
    sha1_str.len=20;
    sha1_str.data=buf_sha1;
    
    ws_accept_key.len=ngx_base64_encoded_length(sha1_str.len);
    assert(ws_accept_key.len < 255);
    ngx_encode_base64(&ws_accept_key, &sha1_str);
    
    nchan_include_access_control_if_needed(r, fsub->ctx);
    nchan_add_response_header(r, &NCHAN_HEADER_SEC_WEBSOCKET_ACCEPT, &ws_accept_key);
    nchan_add_response_header(r, &NCHAN_HEADER_UPGRADE, &NCHAN_WEBSOCKET);
#if nginx_version < 1003013
    nchan_add_response_header(r, &NCHAN_HEADER_CONNECTION, &NCHAN_UPGRADE);
#endif
    r->headers_out.status_line = NCHAN_HTTP_STATUS_101;
    r->headers_out.status = NGX_HTTP_SWITCHING_PROTOCOLS;
    
    r->keepalive=0; //apparently, websocket must not use keepalive.
  }
  
  ngx_http_send_header(r);
}
Esempio n. 6
0
/*
 * Because 'remote_user' is assumed to be provided by basic authorization
 * (see ngx_http_variable_remote_user) we are forced to create bogus
 * non-Negotiate authorization header. This may possibly clobber Negotiate
 * token too soon.
 */
    ngx_int_t
ngx_http_auth_spnego_set_bogus_authorization(
        ngx_http_request_t *r)
{
    const char *bogus_passwd = "bogus_auth_gss_passwd";
    ngx_str_t plain, encoded, final;

    if (r->headers_in.user.len == 0) {
        spnego_debug0("ngx_http_auth_spnego_set_bogus_authorization: no user NGX_DECLINED");
        return NGX_DECLINED;
    }

    /* +1 because of the ":" in "user:password" */
    plain.len = r->headers_in.user.len + ngx_strlen(bogus_passwd) + 1;
    plain.data = ngx_pnalloc(r->pool, plain.len);
    if (NULL == plain.data) {
        return NGX_ERROR;
    }

    ngx_snprintf(plain.data, plain.len, "%V:%s",
            &r->headers_in.user, bogus_passwd);

    encoded.len = ngx_base64_encoded_length(plain.len);
    encoded.data = ngx_pnalloc(r->pool, encoded.len);
    if (NULL == encoded.data) {
        return NGX_ERROR;
    }

    ngx_encode_base64(&encoded, &plain);

    final.len = sizeof("Basic ") + encoded.len - 1;
static ngx_str_t *
ngx_http_push_stream_generate_websocket_accept_value(ngx_http_request_t *r, ngx_str_t *sec_key, ngx_pool_t *temp_pool)
{
#if (NGX_HAVE_SHA1)
    ngx_str_t    *sha1_signed, *accept_value;
    ngx_sha1_t   sha1;

    sha1_signed = ngx_http_push_stream_create_str(temp_pool, NGX_HTTP_PUSH_STREAM_WEBSOCKET_SHA1_SIGNED_HASH_LENGTH);
    accept_value = ngx_http_push_stream_create_str(r->pool, ngx_base64_encoded_length(NGX_HTTP_PUSH_STREAM_WEBSOCKET_SHA1_SIGNED_HASH_LENGTH));

    if ((sha1_signed == NULL) || (accept_value == NULL)) {
        return NULL;
    }

    ngx_sha1_init(&sha1);
    ngx_sha1_update(&sha1, sec_key->data, sec_key->len);
    ngx_sha1_update(&sha1, NGX_HTTP_PUSH_STREAM_WEBSOCKET_SIGN_KEY.data, NGX_HTTP_PUSH_STREAM_WEBSOCKET_SIGN_KEY.len);
    ngx_sha1_final(sha1_signed->data, &sha1);

    ngx_encode_base64(accept_value, sha1_signed);

    return accept_value;
#else
    return NULL;
#endif
}
ngx_int_t
ngx_http_set_misc_set_encode_base64url(ngx_http_request_t *r, ngx_str_t *res,
    ngx_http_variable_value_t *v)
{
    ngx_str_t        src;

    src.len = v->len;
    src.data = v->data;

    res->len = ngx_base64url_encoded_length(v->len);
    res->data = ngx_palloc(r->pool, res->len);
    if (res->data == NULL) {
        return NGX_ERROR;
    }

#if defined(nginx_version) && nginx_version >= 1005010
    ngx_encode_base64url(res, &src);
#else
    u_int i;
    ngx_encode_base64(res, &src);
    for (i=0;i<res->len;i++) {
        switch (res->data[i]) {
            case '+': res->data[i]='-'; break;
            case '/': res->data[i]='_'; break;
            case '=': res->len--; break;
        }
    }
#endif

    return NGX_OK;
}
static ngx_int_t
ngx_http_secure_cookie_set_md5_variable(ngx_http_request_t *r,
    ngx_http_variable_value_t *v, uintptr_t data)
{
    u_char                           md5_buf[16];
    ngx_str_t                        res, val;
    ngx_md5_t                        md5;
    ngx_http_secure_cookie_conf_t   *sclcf;

    sclcf = ngx_http_get_module_loc_conf(r, ngx_http_secure_cookie_module);
    if (sclcf == NULL) {
        goto not_found;
    }

    if (ngx_http_complex_value(r, sclcf->md5, &val) != NGX_OK) {
        goto not_found;
    }

    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                   "secure cookie set md5 base string: \"%V\"", &val);

    ngx_md5_init(&md5);
    ngx_md5_update(&md5, val.data, val.len);
    ngx_md5_final(md5_buf, &md5);

    res.len = 24;
    res.data = ngx_pcalloc(r->pool, res.len);
    if (res.data == NULL) {
        goto not_found;
    }

    val.len = 16;
    val.data = md5_buf;
    ngx_encode_base64(&res, &val);

    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                   "secure cookie set md5 base64: \"%V\"", &res);

    v->len = res.len;
    v->valid = 1;
    v->no_cacheable = 0;
    v->not_found = 0;
    v->data = res.data;

    return NGX_OK;

not_found:

    v->not_found = 1;

    return NGX_OK;
}
size_t
ngx_http_lua_ffi_encode_base64(const u_char *src, size_t slen, u_char *dst)
{
    ngx_str_t      in, out;

    in.data = (u_char *) src;
    in.len = slen;

    out.data = dst;

    ngx_encode_base64(&out, &in);

    return out.len;
}
static ngx_int_t
ngx_http_secure_cookie_set_expires_base64_variable(ngx_http_request_t *r,
    ngx_http_variable_value_t *v, uintptr_t data)
{
    u_char                         *last, t[32], *base64;
    time_t                          expires;
    ngx_str_t                       time, time_base64; 
    ngx_http_secure_cookie_conf_t  *sclcf;

    sclcf = ngx_http_get_module_loc_conf(r, ngx_http_secure_cookie_module);
    if (sclcf == NULL) {
        goto not_found;
    }

    base64 = ngx_palloc(r->pool, 64);
    if ( base64 == NULL) {
        goto not_found;
    }

    expires = ngx_time() + sclcf->expires;

    last = ngx_http_cookie_time(t, expires);

    time.data = t;
    time.len = last - t;

    time_base64.data = base64;
    time_base64.len = 64;

    ngx_encode_base64(&time_base64, &time);

    v->len = time_base64.len;
    v->valid = 1;
    v->no_cacheable = 0;
    v->not_found = 0;
    v->data = time_base64.data;

    return NGX_OK;

not_found:

    v->not_found = 1;

    return NGX_OK;
}
static mrb_value ngx_http_mruby_base64_encode(mrb_state *mrb, mrb_value self)
{
    mrb_value mrb_src;
    ngx_str_t src, dst;

    mrb_get_args(mrb, "o", &mrb_src);
    mrb_src = mrb_obj_as_string(mrb, mrb_src);

    src.data = (u_char *)RSTRING_PTR(mrb_src);
    src.len  = RSTRING_LEN(mrb_src);

    dst.len  = ngx_base64_encoded_length(src.len);
    dst.data = mrb_malloc(mrb, dst.len + 1);

    ngx_encode_base64(&dst, &src);

    return mrb_str_new(mrb, (char *)dst.data, dst.len);
}
Esempio n. 13
0
static int
ngx_http_lua_ngx_encode_base64(lua_State *L)
{
    ngx_http_request_t      *r;
    ngx_str_t                p, src;

    lua_pushlightuserdata(L, &ngx_http_lua_request_key);
    lua_rawget(L, LUA_GLOBALSINDEX);
    r = lua_touserdata(L, -1);
    lua_pop(L, 1);

    if (r == NULL) {
        return luaL_error(L, "no request object found");
    }

    if (lua_gettop(L) != 1) {
        return luaL_error(L, "expecting one argument");
    }

    if (strcmp(luaL_typename(L, 1), (char *) "nil") == 0) {
        src.data     = (u_char *) "";
        src.len      = 0;

    } else {
        src.data = (u_char *) luaL_checklstring(L, 1, &src.len);
    }

    p.len = ngx_base64_encoded_length(src.len);

    p.data = ngx_palloc(r->pool, p.len);
    if (p.data == NULL) {
        return NGX_ERROR;
    }

    ngx_encode_base64(&p, &src);

    lua_pushlstring(L, (char *) p.data, p.len);

    ngx_pfree(r->pool, p.data);

    return 1;
}
Esempio n. 14
0
File: sample.c Progetto: qtkmz/dojo
static void sample_base64()
{
	ngx_str_t src = ngx_string("test_string");
	ngx_str_t base64;

    base64.len = ngx_base64_encoded_length(src.len);
    base64.data = malloc(base64.len);
    if (base64.data == NULL) {
		fprintf(stderr, "Error: malloc() failed.");
        return;
    }

	ngx_encode_base64(&base64, &src);

	puts("sample_base64 --------");
	printf("string = [%.*s]\n", src.len, src.data);
	printf("base64 = [%.*s]\n", base64.len, base64.data);

	return;
}
Esempio n. 15
0
int main()
{
    u_char *p = NULL;
    ngx_uint_t size;
    ngx_str_t dst;
    ngx_str_t mystr = ngx_string("hello, world !");
    ngx_keyval_t pair = {ngx_string("url"), ngx_string("http://rainx.cn/index.php?test=1")};
    int dst_len = ngx_base64_encoded_length(mystr.len);
    printf("source length is %d, destination length is %d\n", mystr.len, dst_len);
    p = malloc(ngx_base64_encoded_length(mystr.len) + 1);
    dst.data = p;
    ngx_encode_base64(&dst, &mystr);
    printf("source str is %s\ndestination str is %s\n", mystr.data, dst.data);
    free(p);
    size = pair.value.len + 2 * ngx_escape_uri(NULL, pair.value.data, pair.value.len, NGX_ESCAPE_URI);
    p = malloc(size * sizeof(u_char));
    ngx_escape_uri(p, pair.value.data, pair.value.len, NGX_ESCAPE_URI);
    printf("escaped %s is : %s (%d)\noriginal url size is %d\n", pair.key.data, p, size, pair.value.len);
    free(p);
    return 0;
}
static mrb_value ngx_http_mruby_base64_encode(mrb_state *mrb, mrb_value self)
{
    mrb_value mrb_src;
    ngx_str_t src, dst;

    mrb_get_args(mrb, "o", &mrb_src);

    if (mrb_type(mrb_src) != MRB_TT_STRING) {
        mrb_src = mrb_funcall(mrb, mrb_src, "to_s", 0, NULL);
    }

    src.data = (u_char *)RSTRING_PTR(mrb_src);
    src.len  = RSTRING_LEN(mrb_src);

    dst.len  = ngx_base64_encoded_length(src.len);
    dst.data = mrb_malloc(mrb, dst.len + 1);

    ngx_encode_base64(&dst, &src);

    return mrb_str_new(mrb, (char *)dst.data, dst.len);
}
Esempio n. 17
0
static ngx_int_t
ngx_lua_smtp_handle_response(ngx_lua_smtp_ctx_t *ctx)
{
    u_char      *p, *last;
    ngx_str_t    dst, src, *to;
    ngx_buf_t   *b;
    ngx_uint_t   i;
    enum {
        sw_start = 0,
        sw_helo,
        sw_login,
        sw_user,
        sw_passwd,
        sw_from,
        sw_to,
        sw_data,
        sw_quit,
        sw_done
    } state;

    ngx_log_debug0(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0,
                   "lua smtp handle response");

    b = ctx->response;

    if (b->last - b->pos < 4) {
        return NGX_AGAIN;
    }

    if (*(b->last - 2) != CR || *(b->last - 1) != LF) {
        if (b->last == b->end) {
            *(b->last - 1) = '\0';
            ngx_log_error(NGX_LOG_ERR, ngx_cycle->log, 0,
                          "stmp server sent too long response line: \"%s\"",
                          b->pos);
            return NGX_ERROR;
        }

        return NGX_AGAIN;
    }

    p = b->pos;
    last = b->last;

    b = ctx->request;
    b->pos = b->start;

    state = ctx->state;

    switch (state) {

    case sw_start:
        if (p[0] != '2' || p[1] != '2' || p[2] != '0') {
            return NGX_ERROR;
        }

        b->last = ngx_slprintf(b->pos, b->end, "HELO %V" CRLF, &ctx->u.host);

        state = sw_helo;
        break;

    case sw_helo:
        if (p[0] != '2' || p[1] != '5' || p[2] != '0') {
            return NGX_ERROR;
        }

        b->last = ngx_cpymem(b->pos, "AUTH LOGIN" CRLF,
                             sizeof("AUTH LOGIN" CRLF) - 1);

        state = sw_login;
        break;

    case sw_login:
        if (p[0] != '3' || p[1] != '3' || p[2] != '4') {
            return NGX_ERROR;
        }

        src = ctx->user;

        dst.len = ngx_base64_encoded_length(src.len);
        dst.data = ngx_pnalloc(ctx->pool, dst.len);
        if (dst.data == NULL) {
            return NGX_ERROR;
        }

        ngx_encode_base64(&dst, &src);

        b->last = ngx_slprintf(b->pos, b->end, "%V" CRLF, &dst);

        state = sw_user;
        break;

    case sw_user:
        if (p[0] != '3' || p[1] != '3' || p[2] != '4') {
            return NGX_ERROR;
        }

        src = ctx->passwd;

        dst.len = ngx_base64_encoded_length(src.len);
        dst.data = ngx_pnalloc(ctx->pool, dst.len);
        if (dst.data == NULL) {
            return NGX_ERROR;
        }

        ngx_encode_base64(&dst, &src);

        b->last = ngx_slprintf(b->pos, b->end, "%V" CRLF, &dst);

        state = sw_passwd;
        break;

    case sw_passwd:
        if (p[0] != '2' || p[1] != '3' || p[2] != '5') {
            return NGX_ERROR;
        }

        b->last = ngx_slprintf(b->pos, b->end, "MAIL FROM:<%V>" CRLF,
                               &ctx->from);

        state = sw_from;
        break;

    case sw_from:
        if (p[0] != '2' || p[1] != '5' || p[2] != '0') {
            return NGX_ERROR;
        }

        to = ctx->to.elts;
        b->last = ngx_slprintf(b->pos, b->end, "RCPT TO:<%V>" CRLF,
                               &to[ctx->n++]);

        state = sw_to;
        break;

    case sw_to:
        if (p[0] != '2' || p[1] != '5' || p[2] != '0') {
            return NGX_ERROR;
        }

        if (ctx->n < ctx->to.nelts) {
            to = ctx->to.elts;
            b->last = ngx_slprintf(b->pos, b->end, "RCPT TO:<%V>" CRLF,
                                   &to[ctx->n++]);
            break;
        }

        b->last = ngx_cpymem(b->pos, "DATA" CRLF, sizeof("DATA" CRLF) - 1);

        state = sw_data;
        break;

    case sw_data:
        if (p[0] != '3' || p[1] != '5' || p[2] != '4') {
            return NGX_ERROR;
        }

        b->last = ngx_slprintf(b->pos, b->end, "Subject: %V" CRLF,
                               &ctx->subject);

        to = ctx->to.elts;
        for (i = 0; i < ctx->to.nelts; i++) {
            b->last = ngx_slprintf(b->last, b->end, "To: %V" CRLF, &to[i]);
        }

        b->last = ngx_slprintf(b->last, b->end, CRLF "%V" CRLF "." CRLF,
                               &ctx->content);

        state = sw_quit;
        break;

    case sw_quit:
        if (p[0] != '2' || p[1] != '5' || p[2] != '0') {
            return NGX_ERROR;
        }

        b->last = ngx_cpymem(b->pos, "QUIT" CRLF, sizeof("QUIT" CRLF) - 1);

        state = sw_done;
        break;

    case sw_done:
        if (p[0] != '2' || p[1] != '2' || p[2] != '1') {
            return NGX_ERROR;
        }

        return NGX_DONE;

    default:
        return NGX_ERROR;
    }

    ctx->state = state;

    ctx->peer.connection->read->handler = ngx_lua_smtp_dummy_handler;
    ctx->peer.connection->write->handler = ngx_lua_smtp_write_handler;

    ngx_lua_smtp_write_handler(ctx->peer.connection->write);

    return NGX_OK;
}
static ngx_int_t
ngx_ssl_ocsp_create_request(ngx_ssl_ocsp_ctx_t *ctx)
{
    int            len;
    u_char        *p;
    uintptr_t      escape;
    ngx_str_t      binary, base64;
    ngx_buf_t     *b;
    OCSP_CERTID   *id;
    OCSP_REQUEST  *ocsp;

    ocsp = OCSP_REQUEST_new();
    if (ocsp == NULL) {
        ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
                      "OCSP_REQUEST_new() failed");
        return NGX_ERROR;
    }

    id = OCSP_cert_to_id(NULL, ctx->cert, ctx->issuer);
    if (id == NULL) {
        ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
                      "OCSP_cert_to_id() failed");
        goto failed;
    }

    if (OCSP_request_add0_id(ocsp, id) == NULL) {
        ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
                      "OCSP_request_add0_id() failed");
        OCSP_CERTID_free(id);
        goto failed;
    }

    len = i2d_OCSP_REQUEST(ocsp, NULL);
    if (len <= 0) {
        ngx_ssl_error(NGX_LOG_CRIT, ctx->log, 0,
                      "i2d_OCSP_REQUEST() failed");
        goto failed;
    }

    binary.len = len;
    binary.data = ngx_palloc(ctx->pool, len);
    if (binary.data == NULL) {
        goto failed;
    }

    p = binary.data;
    len = i2d_OCSP_REQUEST(ocsp, &p);
    if (len <= 0) {
        ngx_ssl_error(NGX_LOG_EMERG, ctx->log, 0,
                      "i2d_OCSP_REQUEST() failed");
        goto failed;
    }

    base64.len = ngx_base64_encoded_length(binary.len);
    base64.data = ngx_palloc(ctx->pool, base64.len);
    if (base64.data == NULL) {
        goto failed;
    }

    ngx_encode_base64(&base64, &binary);

    escape = ngx_escape_uri(NULL, base64.data, base64.len,
                            NGX_ESCAPE_URI_COMPONENT);

    ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ctx->log, 0,
                   "ssl ocsp request length %z, escape %d",
                   base64.len, (int) escape);

    len = sizeof("GET ") - 1 + ctx->uri.len + sizeof("/") - 1
          + base64.len + 2 * escape + sizeof(" HTTP/1.0" CRLF) - 1
          + sizeof("Host: ") - 1 + ctx->host.len + sizeof(CRLF) - 1
          + sizeof(CRLF) - 1;

    b = ngx_create_temp_buf(ctx->pool, len);
    if (b == NULL) {
        goto failed;
    }

    p = b->last;

    p = ngx_cpymem(p, "GET ", sizeof("GET ") - 1);
    p = ngx_cpymem(p, ctx->uri.data, ctx->uri.len);

    if (ctx->uri.data[ctx->uri.len - 1] != '/') {
        *p++ = '/';
    }

    if (escape == 0) {
        p = ngx_cpymem(p, base64.data, base64.len);

    } else {
        p = (u_char *) ngx_escape_uri(p, base64.data, base64.len,
                                      NGX_ESCAPE_URI_COMPONENT);
    }

    p = ngx_cpymem(p, " HTTP/1.0" CRLF, sizeof(" HTTP/1.0" CRLF) - 1);
    p = ngx_cpymem(p, "Host: ", sizeof("Host: ") - 1);
    p = ngx_cpymem(p, ctx->host.data, ctx->host.len);
    *p++ = CR; *p++ = LF;

    /* add "\r\n" at the header end */
    *p++ = CR; *p++ = LF;

    b->last = p;
    ctx->request = b;

    OCSP_REQUEST_free(ocsp);

    return NGX_OK;

failed:

    OCSP_REQUEST_free(ocsp);

    return NGX_ERROR;
}