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
}
Пример #2
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);
}
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;
}
Пример #7
0
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;
}
Пример #9
0
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);
}