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; }
static char *ngx_http_acme_create_jwk(ngx_conf_t *cf, void *conf, RSA *key, json_t **jwk) { ngx_str_t e, n, tmp; /* Baser64url encode e */ tmp.len = BN_num_bytes(key->e); tmp.data = ngx_alloc(tmp.len, cf->log); tmp.len = BN_bn2bin(key->e, tmp.data); e.len = ngx_base64_encoded_length(tmp.len); e.data = ngx_alloc(e.len, cf->log); ngx_encode_base64url(&e, &tmp); ngx_free(tmp.data); /* Baser64url encode n */ tmp.len = BN_num_bytes(key->n); tmp.data = ngx_alloc(tmp.len, cf->log); tmp.len = BN_bn2bin(key->n, tmp.data); n.len = ngx_base64_encoded_length(tmp.len); n.data = ngx_alloc(n.len, cf->log); ngx_encode_base64url(&n, &tmp); ngx_free(tmp.data); *jwk = json_pack("{s:s, s:s%, s:s%}", "kty", "RSA", "e", e.data, e.len, "n", n.data, n.len); if(*jwk == NULL) { ngx_log_error(NGX_LOG_ERR, cf->log, 0, "Failed to pack JWK"); return NGX_CONF_ERROR; } ngx_free(e.data); ngx_free(n.data); return NGX_CONF_OK; } /* ngx_http_acme_create_jwk */
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 }
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; }
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); }
/* * 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;
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; }
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); 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); }
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; }
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; }
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); }
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 char *ngx_http_acme_sign_json(ngx_conf_t *cf, void *conf, json_t *payload, RSA *key, ngx_str_t replay_nonce, json_t **flattened_jws) { /* * Structure according to RFC7515: * * { * "payload":"<payload contents>", * "protected":"<integrity-protected header contents>", * "header":<non-integrity-protected header contents>, * "signature":"<signature contents>" * } * * Example: * * { * "payload": * "eyJpc3MiOiJqb2UiLA0KICJleHAiOjEzMDA4MTkzODAsDQogImh0dHA6Ly9leGFtcGxlLmNvbS9pc19yb290Ijp0cnVlfQ", * "protected":"eyJhbGciOiJFUzI1NiJ9", * "header": {"kid":"e9bc097a-ce51-4036-9562-d2ade882db0d"}, * "signature": * "DtEhU3ljbEg8L38VWAfUAqOyKAM6-Xx-F4GawxaepmXFCgfTjDxw5djxLa8ISlSApmWQxfKTUJqPP3-Kg6NU1Q" * } */ /* * ACME restrictions: * The JWS MUST use the Flattened JSON Serialization * The JWS MUST be encoded using UTF-8 * The JWS Header or Protected Header MUST include “alg” and “jwk” fields * The JWS MUST NOT have the value “none” in its “alg” field */ json_t *jwk; json_t *header; ngx_str_t encoded_protected_header, serialized_payload, encoded_payload, tmp; ngx_str_t signing_input, signature, encoded_signature; u_char *tmp_char_p; /* Variables for signing */ EVP_PKEY *evp_key; EVP_MD_CTX *mdctx = NULL; int ret = 0; /* * Encode payload */ serialized_payload = (ngx_str_t)ngx_string_dynamic(json_dumps(payload, 0)); encoded_payload.len = ngx_base64_encoded_length(serialized_payload.len); encoded_payload.data = ngx_alloc(encoded_payload.len, cf->log); ngx_encode_base64url(&encoded_payload, &serialized_payload); println_debug("Signing payload: ", &serialized_payload); /* * Create header */ /* jwk header */ if(ngx_http_acme_create_jwk(cf, conf, key, &jwk) != NGX_CONF_OK) { ngx_log_error(NGX_LOG_ERR, cf->log, 0, "Failed to create the JWK from the account key"); ngx_free(serialized_payload.data); ngx_free(encoded_payload.data); return NGX_CONF_ERROR; } /* Pack header into JSON */ header = json_pack("{s:s, s:s%, s:o}", "alg", "RS256", "nonce", replay_nonce.data, replay_nonce.len, "jwk", jwk); if(header == NULL) { ngx_log_error(NGX_LOG_ERR, cf->log, 0, "Error packing JWS header"); ngx_free(serialized_payload.data); ngx_free(encoded_payload.data); return NGX_CONF_ERROR; } /* Serialize and base64url encode header */ tmp = (ngx_str_t)ngx_string_dynamic(json_dumps(header, 0)); encoded_protected_header.len = ngx_base64_encoded_length(tmp.len); encoded_protected_header.data = ngx_alloc(encoded_protected_header.len, cf->log); ngx_encode_base64url(&encoded_protected_header, &tmp); ngx_free(tmp.data); json_decref(header); /* * Create signature */ /* Create signing input */ /* = ASCII(BASE64URL(UTF8(JWS Protected Header)) || '.' || BASE64URL(JWS Payload)) */ signing_input.len = encoded_protected_header.len + strlen(".") + encoded_payload.len; signing_input.data = ngx_alloc(signing_input.len, cf->log); tmp_char_p = ngx_copy(signing_input.data, encoded_protected_header.data, encoded_protected_header.len); tmp_char_p = ngx_copy(tmp_char_p, ".", strlen(".")); tmp_char_p = ngx_copy(tmp_char_p, encoded_payload.data, encoded_payload.len); /* Convert the RSA key to the EVP_PKEY structure */ evp_key = EVP_PKEY_new(); if(evp_key == NULL) { ngx_log_error(NGX_LOG_ERR, cf->log, 0, "Error signing the message digest for the JWS signature."); return NGX_CONF_ERROR; } if(EVP_PKEY_set1_RSA(evp_key, key) == 0) { ngx_log_error(NGX_LOG_ERR, cf->log, 0, "Error signing the message digest for the JWS signature."); return NGX_CONF_ERROR; } /* Create the message digest context */ ret = 0; mdctx = EVP_MD_CTX_create(); if(mdctx == NULL) goto err; /* Initialize the DigestSign operation - SHA-256 has been selected as the message digest function */ if(EVP_DigestSignInit(mdctx, NULL, EVP_sha256(), NULL, evp_key) != 1) goto err; /* Call update with the message */ if(EVP_DigestSignUpdate(mdctx, signing_input.data, signing_input.len) != 1) goto err; /* Finalise the DigestSign operation */ /* First call EVP_DigestSignFinal with a NULL sig parameter to obtain the length of the */ /* signature. The length is returned in siglen. */ if(EVP_DigestSignFinal(mdctx, NULL, &signature.len) != 1) goto err; /* Allocate memory for the signature */ signature.data = ngx_alloc(signature.len, cf->log); /* Obtain the signature */ if(EVP_DigestSignFinal(mdctx, signature.data, &signature.len) != 1) goto err; /* Success */ ret = 1; err: if(ret != 1) { ngx_log_error(NGX_LOG_ERR, cf->log, 0, "Error signing the message digest for the JWS signature. OpenSSL error 0x%xl", ERR_get_error()); return NGX_CONF_ERROR; } /* Clean up */ EVP_MD_CTX_destroy(mdctx); EVP_PKEY_free(evp_key); /* base64url encode the signature */ encoded_signature.len = ngx_base64_encoded_length(signature.len); encoded_signature.data = ngx_alloc(encoded_signature.len, cf->log); ngx_encode_base64url(&encoded_signature, &signature); ngx_free(signature.data); /* * Create flattened JWS serialization */ *flattened_jws = json_pack("{s:s%,s:s%,s:s%}", "payload", encoded_payload.data, encoded_payload.len, "protected", encoded_protected_header.data, encoded_protected_header.len, "signature", encoded_signature.data, encoded_signature.len ); ngx_free(serialized_payload.data); // TODO (KK) Maybe this is too early for a free since the strings will be used in the flattened JWS (but when to free then?) ngx_free(encoded_payload.data); ngx_free(encoded_protected_header.data); ngx_free(encoded_signature.data); if(*flattened_jws == NULL) { ngx_log_error(NGX_LOG_ERR, cf->log, 0, "Error serializing flattened JWS"); return NGX_CONF_ERROR; } return NGX_CONF_OK; } /* ngx_http_acme_sign_json */
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; }
static ngx_int_t ngx_secure_token_cht_get_var( ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data) { ngx_secure_token_cht_token_t* token = (void*)data; ngx_str_t expires_str; ngx_str_t md5hash_str; ngx_str_t token_str; ngx_str_t acl; ngx_md5_t md5; u_char end_time_buf[NGX_INT32_LEN]; u_char md5hash_buf[MD5_DIGEST_LENGTH]; u_char token_buf[ngx_base64_encoded_length(MD5_DIGEST_LENGTH)]; time_t end_time; size_t result_size; u_char* p; ngx_int_t rc; // get the acl rc = ngx_http_secure_token_get_acl(r, token->acl, &acl); if (rc != NGX_OK) { return rc; } // get the end time end_time = token->end.val; if (token->end.type == NGX_HTTP_SECURE_TOKEN_TIME_RELATIVE) { end_time += ngx_time(); } expires_str.data = end_time_buf; expires_str.len = ngx_sprintf(end_time_buf, "%uD", (uint32_t)end_time) - end_time_buf; // calculate the signature ngx_md5_init(&md5); ngx_md5_update(&md5, acl.data, acl.len); ngx_md5_update(&md5, token->key.data, token->key.len); ngx_md5_update(&md5, expires_str.data, expires_str.len); ngx_md5_final(md5hash_buf, &md5); md5hash_str.data = md5hash_buf; md5hash_str.len = sizeof(md5hash_buf); token_str.data = token_buf; ngx_encode_base64url(&token_str, &md5hash_str); // get the result size result_size = sizeof(TOKEN_PART1) + token_str.len + sizeof(TOKEN_PART2) + expires_str.len; // allocate the result p = ngx_pnalloc(r->pool, result_size); if (p == NULL) { return NGX_ERROR; } v->data = p; // build the result p = ngx_copy(p, TOKEN_PART1, sizeof(TOKEN_PART1) - 1); p = ngx_copy(p, token_str.data, token_str.len); p = ngx_copy(p, TOKEN_PART2, sizeof(TOKEN_PART2) - 1); p = ngx_copy(p, expires_str.data, expires_str.len); *p = '\0'; v->len = p - v->data; v->valid = 1; v->no_cacheable = 0; v->not_found = 0; return NGX_OK; }