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 }
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); }
static int ngx_http_lua_ngx_sha1_bin(lua_State *L) { u_char *src; size_t slen; ngx_sha1_t sha; u_char sha_buf[SHA_DIGEST_LENGTH]; if (lua_gettop(L) != 1) { return luaL_error(L, "expecting one argument"); } if (lua_isnil(L, 1)) { src = (u_char *) ""; slen = 0; } else { src = (u_char *) luaL_checklstring(L, 1, &slen); } dd("slen: %d", (int) slen); ngx_sha1_init(&sha); ngx_sha1_update(&sha, src, slen); ngx_sha1_final(sha_buf, &sha); lua_pushlstring(L, (char *) sha_buf, sizeof(sha_buf)); return 1; }
ngx_int_t ngx_http_sticky_misc_hmac_sha1(ngx_pool_t *pool, void *in, size_t len, ngx_str_t *key, ngx_str_t *digest) { u_char hash[SHA_DIGEST_LENGTH]; u_char k[SHA_CBLOCK]; ngx_sha1_t sha1; u_int i; digest->data = ngx_pcalloc(pool, SHA_DIGEST_LENGTH * 2); if (digest->data == NULL) { return NGX_ERROR; } digest->len = SHA_DIGEST_LENGTH * 2; ngx_memzero(k, sizeof(k)); if (key->len > SHA_CBLOCK) { ngx_sha1_init(&sha1); ngx_sha1_update(&sha1, key->data, key->len); ngx_sha1_final(k, &sha1); } else { ngx_memcpy(k, key->data, key->len); } /* XOR ipad */ for (i=0; i < SHA_CBLOCK; i++) { k[i] ^= 0x36; } ngx_sha1_init(&sha1); ngx_sha1_update(&sha1, k, SHA_CBLOCK); ngx_sha1_update(&sha1, in, len); ngx_sha1_final(hash, &sha1); /* Convert k to opad -- 0x6A = 0x36 ^ 0x5C */ for (i=0; i < SHA_CBLOCK; i++) { k[i] ^= 0x6a; } ngx_sha1_init(&sha1); ngx_sha1_update(&sha1, k, SHA_CBLOCK); ngx_sha1_update(&sha1, hash, SHA_DIGEST_LENGTH); ngx_sha1_final(hash, &sha1); ngx_hex_dump(digest->data, hash, SHA_DIGEST_LENGTH); return NGX_OK; }
int ngx_http_lua_ffi_sha1_bin(const u_char *src, size_t len, u_char *dst) { #if NGX_HAVE_SHA1 ngx_sha1_t sha; ngx_sha1_init(&sha); ngx_sha1_update(&sha, src, len); ngx_sha1_final(dst, &sha); return 1; #else return 0; #endif }
ngx_int_t ngx_http_sticky_misc_sha1(ngx_pool_t *pool, void *in, size_t len, ngx_str_t *digest) { ngx_sha1_t sha1; u_char hash[SHA_DIGEST_LENGTH]; digest->data = ngx_pcalloc(pool, SHA_DIGEST_LENGTH * 2); if (digest->data == NULL) { return NGX_ERROR; } digest->len = SHA_DIGEST_LENGTH * 2; ngx_sha1_init(&sha1); ngx_sha1_update(&sha1, in, len); ngx_sha1_final(hash, &sha1); ngx_hex_dump(digest->data, hash, SHA_DIGEST_LENGTH); return NGX_OK; }
static void sample_sha1() { char key[] = "test_string"; ngx_sha1_t sha1; u_char digest[20]; int i; ngx_sha1_init(&sha1); ngx_sha1_update(&sha1, key, ngx_strlen(key)); ngx_sha1_final(digest, &sha1); puts("sample_sha1 --------"); printf("string = [%s]\n", key); for (i = 0; i < sizeof(digest); i++) { printf("%02x", digest[i]); } printf("\n"); return; }
static ngx_int_t ngx_http_weixin_auth(ngx_http_request_t *r) { u_char *p; ngx_int_t rc; ngx_str_t signature, str, array_str[3], tmp; ngx_sha1_t sha; u_char sha_buf[SHA_DIGEST_LENGTH]; u_char sha_buf_str[SHA_DIGEST_LENGTH + SHA_DIGEST_LENGTH]; ngx_http_weixin_auth_loc_conf_t *auth_conf; auth_conf = ngx_http_get_module_loc_conf(r, ngx_http_weixin_auth_module); if (ngx_http_arg(r, (u_char *) "signature", 9, &signature) != NGX_OK) { return NGX_DECLINED; } if (ngx_http_arg(r, (u_char *) "timestamp", 9, &array_str[0]) != NGX_OK) { return NGX_DECLINED; } if (ngx_http_arg(r, (u_char *) "nonce", 5, &array_str[1]) != NGX_OK) { return NGX_DECLINED; } if (signature.len != SHA_DIGEST_LENGTH * 2) { return NGX_DECLINED; } array_str[2] = auth_conf->token; // token¡¢timestamp¡¢nonce if (ngx_memn2cmp(array_str[0].data, array_str[1].data, array_str[0].len, array_str[1].len) > 0) { tmp = array_str[0]; array_str[0] = array_str[1]; array_str[1] = tmp; } if (ngx_memn2cmp(array_str[1].data, array_str[2].data, array_str[1].len, array_str[2].len) > 0) { tmp = array_str[1]; array_str[1] = array_str[2]; array_str[2] = tmp; } if (ngx_memn2cmp(array_str[0].data, array_str[1].data, array_str[0].len, array_str[1].len) > 0) { tmp = array_str[0]; array_str[0] = array_str[1]; array_str[1] = tmp; } str.len = array_str[0].len + array_str[1].len + array_str[2].len; str.data = ngx_pcalloc(r->pool, str.len + 1); if (str.data == NULL) { return NGX_ERROR; } p = str.data; p = ngx_cpymem(p, array_str[0].data, array_str[0].len); p = ngx_cpymem(p, array_str[1].data, array_str[1].len); p = ngx_cpymem(p, array_str[2].data, array_str[2].len); p = '\0'; ngx_sha1_init(&sha); ngx_sha1_update(&sha, str.data, str.len); ngx_sha1_final(sha_buf, &sha); p = ngx_hex_dump(sha_buf_str, sha_buf, SHA_DIGEST_LENGTH); p = '\0'; rc = ngx_memcmp(sha_buf_str, signature.data, SHA_DIGEST_LENGTH * 2); if (rc != 0) { return NGX_DECLINED; } return NGX_OK; }
static void ngx_mysql_read_server_greeting(ngx_event_t *rev) { size_t len; u_char *p; ssize_t n; ngx_uint_t i, capacity; ngx_mysql_t *m; ngx_connection_t *c; ngx_mysql_greeting1_pkt_t *gr1; ngx_mysql_greeting2_pkt_t *gr2; ngx_mysql_auth_pkt_t *auth; ngx_sha1_t sha; u_char hash1[20], hash2[20]; c = rev->data; m = c->data; if (rev->timedout) { ngx_log_error(NGX_LOG_ERR, rev->log, NGX_ETIMEDOUT, "mysql server %V timed out", m->peer.name); ngx_mysql_close(m, NGX_ERROR); return; } if (m->buf == NULL) { m->peer.log->action = "reading mysql server greeting"; m->buf = ngx_create_temp_buf(m->pool, /* STUB */ 1024); if (m->buf == NULL) { ngx_mysql_close(m, NGX_ERROR); return; } } n = ngx_recv(m->peer.connection, m->buf->pos, /* STUB */ 1024); if (n == NGX_AGAIN) { return; } if (n < 5) { ngx_mysql_close(m, NGX_ERROR); return; } gr1 = (ngx_mysql_greeting1_pkt_t *) m->buf->pos; if (ngx_m24toh(gr1->pktlen) > n - 4) { ngx_log_error(NGX_LOG_ERR, rev->log, 0, "mysql server %V sent incomplete greeting packet", m->peer.name); ngx_mysql_close(m, NGX_ERROR); return; } if (gr1->protocol < 10) { ngx_log_error(NGX_LOG_ERR, rev->log, 0, "mysql server %V sent unsupported protocol version %ud", m->peer.name, gr1->protocol); ngx_mysql_close(m, NGX_ERROR); return; } gr2 = (ngx_mysql_greeting2_pkt_t *) (gr1->version + ngx_strlen(gr1->version) + 1); capacity = ngx_m16toh(gr2->capacity); ngx_log_debug8(NGX_LOG_DEBUG_MYSQL, rev->log, 0, "mysql version: %ud, \"%s\", thread: %ud, salt: \"%s\", " "capacity: %Xd, charset: %ud, status: %ud, salt rest \"%s\"", gr1->protocol, gr1->version, ngx_m32toh(gr2->thread), gr2->salt1, capacity, gr2->charset, ngx_m16toh(gr2->status), &gr2->salt2); capacity = NGX_MYSQL_LONG_PASSWORD | NGX_MYSQL_CONNECT_WITH_DB | NGX_MYSQL_PROTOCOL_41 | NGX_MYSQL_SECURE_CONNECTION; len = 4 + 4 + 4 + 1 + 23 + m->login->len + 1 + 1 + m->database->len + 1; if (m->passwd->len) { len += 20; } auth = ngx_pnalloc(m->pool, len); if (auth == NULL) { ngx_mysql_close(m, NGX_ERROR); return; } ngx_htom24(auth->pktlen, len - 4); auth->pktn = (u_char)(gr1->pktn + 1); ngx_htom32(auth->capacity, capacity); ngx_htom32(auth->max_packet, 0x01000000); /* max packet size 2^24 */ ngx_memzero(auth->zero, 24); auth->charset = gr2->charset; p = ngx_copy(auth->login, m->login->data, m->login->len); *p++ = '\0'; if (m->passwd->len) { *p++ = (u_char) 20; ngx_sha1_init(&sha); ngx_sha1_update(&sha, m->passwd->data, m->passwd->len); ngx_sha1_final(hash1, &sha); ngx_sha1_init(&sha); ngx_sha1_update(&sha, hash1, 20); ngx_sha1_final(hash2, &sha); ngx_sha1_init(&sha); ngx_sha1_update(&sha, gr2->salt1, 8); ngx_sha1_update(&sha, gr2->salt2, 12); ngx_sha1_update(&sha, hash2, 20); ngx_sha1_final(hash2, &sha); for (i = 0; i < 20; i++) { *p++ = (u_char)(hash1[i] ^ hash2[i]); } } else { *p++ = '\0'; } p = ngx_copy(p, m->database->data, m->database->len); *p = '\0'; n = ngx_send(m->peer.connection, (void *) auth, len); if (n < (ssize_t) len) { ngx_log_error(NGX_LOG_ERR, rev->log, 0, "the incomplete packet was sent to mysql server %V", m->peer.name); ngx_mysql_close(m, NGX_ERROR); return; } m->peer.connection->read->handler = ngx_mysql_read_auth_result; ngx_add_timer(m->peer.connection->read, /* STUB */ 5000); }