36 Commits

Author SHA1 Message Date
dependabot[bot]
c97eac958b Bump libsqlite3-sys from 0.22.2 to 0.25.1
Bumps [libsqlite3-sys](https://github.com/rusqlite/rusqlite) from 0.22.2 to 0.25.1.
- [Release notes](https://github.com/rusqlite/rusqlite/releases)
- [Changelog](https://github.com/rusqlite/rusqlite/blob/master/Changelog.md)
- [Commits](https://github.com/rusqlite/rusqlite/commits/v0.25.1)

---
updated-dependencies:
- dependency-name: libsqlite3-sys
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-02-15 15:45:10 +00:00
kpcyrd
844a40e929 Release v0.25.0 2023-01-28 19:51:02 +01:00
kpcyrd
2238285c16 Merge pull request #239 from kpcyrd/update
Update dependencies, fix #238
2023-01-28 18:42:38 +00:00
kpcyrd
e397edb4f4 Refactor MQTT client integration, integrate automatic keep-alive 2023-01-28 17:58:11 +01:00
kpcyrd
70b5039d50 Fix some clippy warnings, remove base64 crate 2023-01-27 19:31:48 +01:00
kpcyrd
326c868699 Update dependencies 2023-01-27 19:15:24 +01:00
kpcyrd
1be1967d6f Release v0.24.3 2022-11-13 03:22:10 +01:00
kpcyrd
5364328e2a Merge pull request #236 from kpcyrd/bump
Fix clone3 sandbox crash, improve sandbox crash error message
2022-11-13 02:19:54 +00:00
kpcyrd
01bcb10833 Fix chrono deprecation warnings 2022-11-13 03:01:07 +01:00
kpcyrd
56f7b1c646 Fix winkekatze-sub.lua example module 2022-11-12 21:47:15 +01:00
kpcyrd
dc26c14da4 Allow clone3 syscall in sandbox (#235) 2022-11-12 21:46:47 +01:00
kpcyrd
a2c70e43de Replace EOF while parsing a value at line 1 column 0 error with Sandbox child has crashed 2022-11-12 21:37:05 +01:00
kpcyrd
b28276c42e Update dependencies 2022-11-12 21:24:19 +01:00
kpcyrd
aa3311bfab Merge pull request #234 from SpriteOvO/riscv64
Support compiling for RISC-V 64-bit
2022-09-29 16:43:42 +00:00
Sprite
edb5b4bf25 Support compiling for RISC-V 64-bit 2022-09-28 21:18:02 +08:00
kpcyrd
231d3293fe Merge pull request #229 from kpcyrd/bump
Update dependencies
2022-07-17 17:02:38 +00:00
kpcyrd
febb39ab03 Update dependencies 2022-07-17 18:49:21 +02:00
kpcyrd
ebc1fa791d Fix clippy warnings, reduce heap allocations 2022-07-14 00:04:38 +02:00
kpcyrd
3ea88d9bd5 Merge pull request #227 from stoeckmann/paths
Fix error messages in paths.rs
2022-04-13 22:49:41 +00:00
Tobias Stoeckmann
006e3618fb Unify function bodies 2022-04-13 22:29:38 +02:00
Tobias Stoeckmann
c4b74aa6fc Adjust error messages to show target directory 2022-04-13 22:29:36 +02:00
kpcyrd
6cd97d980d Release v0.24.2 2022-03-29 02:38:09 +02:00
kpcyrd
b4f2591378 Merge pull request #225 from kpcyrd/bump
Update dependencies
2022-03-29 00:27:34 +00:00
kpcyrd
3a204a92a5 Add docker release github action 2022-03-29 01:16:52 +02:00
kpcyrd
b65c72d090 Update Dockerfile to alpine 3.15 and buildkit 2022-03-28 20:40:15 +02:00
kpcyrd
035ef9aa76 Add missing seccomp syscall (rseq) 2022-03-28 19:25:22 +02:00
kpcyrd
35c6501623 Update dependencies 2022-03-28 18:44:32 +02:00
kpcyrd
c0cb5840cc Merge pull request #224 from ysf/patch-1
Fixed typo
2022-03-21 17:57:30 +00:00
ysf
bba152d560 Fixed typo 2022-03-21 09:18:52 +01:00
kpcyrd
53a39d54bc Merge pull request #223 from definitepotato/issue-222
Adding syscall to seccomp sandbox.
2022-01-19 11:19:33 +00:00
definitepotato
455403baaf Adding syscall to seccomp sandbox. 2022-01-15 13:14:16 -05:00
kpcyrd
ec07344a0b Merge pull request #221 from kpcyrd/clippy
Fix clippy warnings
2022-01-14 15:56:14 +00:00
kpcyrd
c2d95659dc Fix clippy warnings 2022-01-13 20:05:34 +01:00
kpcyrd
cd99ac3911 Release v0.24.1 2021-12-05 16:17:51 +01:00
kpcyrd
f2a5dbc60c Merge pull request #219 from kpcyrd/seccomp
seccomp: Allow fstat call
2021-12-05 12:05:12 +00:00
kpcyrd
6425483c2b seccomp: Allow fstat call 2021-12-05 12:37:20 +01:00
55 changed files with 1630 additions and 1083 deletions

58
.github/workflows/docker-release.yml vendored Normal file
View File

@@ -0,0 +1,58 @@
name: Publish Docker image
on:
release:
types: [ published ]
jobs:
push_to_registry:
name: Push Docker image to GitHub Registry
runs-on: ubuntu-latest
steps:
-
name: Checkout
uses: actions/checkout@v2
-
name: Docker meta
id: meta
uses: docker/metadata-action@v3
with:
images: |
ghcr.io/kpcyrd/sn0int
tags: |
type=semver,pattern={{raw}}
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
-
name: Cache Docker layers
uses: actions/cache@v2
with:
path: /tmp/.buildx-cache
key: ${{ runner.os }}-buildx-${{ github.sha }}
restore-keys: |
${{ runner.os }}-buildx-
-
name: Login to Registry
uses: docker/login-action@v1
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
-
name: Build and push Docker images
uses: docker/build-push-action@v2
with:
push: true
tags: ${{ steps.meta.outputs.tags }}
file: Dockerfile
cache-from: type=local,src=/tmp/.buildx-cache
cache-to: type=local,dest=/tmp/.buildx-cache-new
-
# Temp fix
# https://github.com/docker/build-push-action/issues/252
# https://github.com/moby/buildkit/issues/1896
name: Move cache
run: |
rm -rf /tmp/.buildx-cache
mv /tmp/.buildx-cache-new /tmp/.buildx-cache

View File

@@ -22,7 +22,7 @@ jobs:
- uses: actions/checkout@v2
- name: Build the Docker image
run: docker build -t ${{ matrix.build.name }} -f ${{ matrix.build.file }} .
run: DOCKER_BUILDKIT=1 docker build -t ${{ matrix.build.name }} -f ${{ matrix.build.file }} .
- name: Test the Docker image
run: docker run --rm ${{ matrix.build.name }} --help

2071
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,13 +1,13 @@
[package]
name = "sn0int"
version = "0.24.0"
version = "0.25.0"
description = "Semi-automatic OSINT framework and package manager"
authors = ["kpcyrd <git@rxv.cc>"]
license = "GPL-3.0"
repository = "https://github.com/kpcyrd/sn0int"
categories = ["command-line-utilities"]
readme = "README.md"
edition = "2018"
edition = "2021"
[workspace]
members = ["sn0int-common",
@@ -33,8 +33,8 @@ sqlite-bundled = ["libsqlite3-sys/bundled"]
[dependencies]
sn0int-common = { version="0.13.0", path="sn0int-common" }
sn0int-std = { version="=0.24.0", path="sn0int-std" }
rustyline = "9.0"
sn0int-std = { version="=0.25.0", path="sn0int-std" }
rustyline = "10.0"
log = "0.4"
env_logger = "0.9"
hlua-badtouch = "0.4"
@@ -46,15 +46,14 @@ lazy_static = "1.0"
shellwords = "1.0"
diesel = { version = "1.0.0", features = ["sqlite", "chrono"] }
diesel_migrations = { version = "1.3.0", features = ["sqlite"] }
libsqlite3-sys = { version = "0.22.0", features = ["bundled-windows"] }
libsqlite3-sys = { version = "0.25.1", features = ["bundled-windows"] }
chrono = { version = "0.4", features = ["serde"] }
dirs-next = "2.0"
url = "2.0"
percent-encoding = "2.1"
#chrootable-https = { path = "../chrootable-https" }
chrootable-https = "0.16"
base64 = "0.13"
data-encoding = "2.1.2"
data-encoding = "2.3.3"
serde = { version = "1.0", features = ["derive"] }
serde_urlencoded = "0.7"
serde_json = "1.0"
@@ -72,17 +71,17 @@ semver = "1"
bytes = "0.4"
bytesize = "1.0"
ipnetwork = "0.18"
strum = "0.23"
strum_macros = "0.23"
strum = "0.24"
strum_macros = "0.24"
embedded-triple = "0.1.0"
humansize = "1.1.0"
digest = "0.9"
md-5 = "0.9"
sha-1 = "0.9"
sha2 = "0.9"
sha3 = "0.9"
hmac = "0.11"
digest = "0.10"
md-5 = "0.10"
sha-1 = "0.10"
sha2 = "0.10"
sha3 = "0.10"
hmac = "0.12"
walkdir = "2.2"
nude = "0.3"
@@ -93,7 +92,7 @@ os-version = "0.2"
caps = "0.5"
#syscallz = { path="../syscallz-rs" }
syscallz = "0.16"
nix = "0.23"
nix = "0.24"
[target.'cfg(target_os="openbsd")'.dependencies]
pledge = "0.4"
@@ -101,5 +100,5 @@ unveil = "0.3"
[dev-dependencies]
#boxxy = { path = "../boxxy-rs" }
boxxy = "0.12"
boxxy = "0.13"
tempfile = "3.0"

View File

@@ -1,14 +1,18 @@
FROM rust:alpine3.13
FROM rust:alpine3.15
ENV RUSTFLAGS="-C target-feature=-crt-static"
RUN apk add --no-cache musl-dev sqlite-dev libseccomp-dev libsodium-dev
WORKDIR /usr/src/sn0int
COPY . .
RUN cargo build --release --verbose
RUN strip target/release/sn0int
RUN --mount=type=cache,target=/var/cache/buildkit \
CARGO_HOME=/var/cache/buildkit/cargo \
CARGO_TARGET_DIR=/var/cache/buildkit/target \
cargo build --release --locked --verbose && \
cp -v /var/cache/buildkit/target/release/sn0int /
RUN strip /sn0int
FROM alpine:3.13
FROM alpine:3.15
RUN apk add --no-cache libgcc sqlite-libs libseccomp libsodium
COPY --from=0 /usr/src/sn0int/target/release/sn0int /usr/local/bin/sn0int
COPY --from=0 /sn0int /usr/local/bin/sn0int
VOLUME ["/data", "/cache"]
ENV XDG_DATA_HOME=/data \
XDG_CACHE_HOME=/cache

View File

@@ -44,6 +44,13 @@ Alpine
$ apk add sqlite-dev libseccomp-dev libsodium-dev
Docker
~~~~~~
.. code-block:: bash
$ DOCKER_BUILDKIT=1 docker build -t kpcyrd/sn0int .
OpenBSD
~~~~~~~

View File

@@ -119,7 +119,7 @@ You might experience a sandbox failure, especially on architectures that are
less popular. This usually looks like this::
[sn0int][example][kpcyrd/ctlogs] > run
[-] Failed "example.com": EOF while parsing a value at line 1 column 0
[-] Failed "example.com": Sandbox child has crashed
[+] Finished kpcyrd/ctlogs (1 errors)
A module that never finishes could also mean an IO thread inside the worker got

View File

@@ -3,7 +3,7 @@
-- License: GPL-3.0
function run()
-- echo 'www.example.com' | sn0int run -vvf --stdin modules/harness/import-subdomains.lu
-- echo 'www.example.com' | sn0int run -vvf --stdin modules/harness/import-subdomains.lua
while true do
local line = stdin_readline()

View File

@@ -10,8 +10,17 @@ function run()
mqtt_subscribe(sock, '#', 0)
while true do
local pkt = mqtt_recv_text(sock)
-- read the next mqtt packet
local pkt = mqtt_recv(sock)
if last_err() then return end
info(pkt)
local text
if pkt then
-- attempt to utf8 decode the body if there was a pkt
text = utf8_decode(pkt['body'])
if last_err() then clear_err() end
end
info({pkt=pkt, text=text})
end
end

View File

@@ -1,5 +1,5 @@
use crate::id::ModuleID;
use serde::{Serialize, Deserialize};
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize)]
pub struct WhoamiResponse {

View File

@@ -1,2 +1,2 @@
pub use anyhow::{Error, Context, anyhow, format_err, bail};
pub use anyhow::{anyhow, bail, format_err, Context, Error};
pub type Result<T> = ::std::result::Result<T, Error>;

View File

@@ -1,10 +1,9 @@
use crate::errors::*;
use serde::{de, Serialize, Serializer, Deserialize, Deserializer};
use serde::{de, Deserialize, Deserializer, Serialize, Serializer};
use std::fmt;
use std::result;
use std::str::FromStr;
#[inline(always)]
fn valid_char(c: char) -> bool {
nom::character::is_alphanumeric(c as u8) || c == '-'
@@ -71,7 +70,8 @@ impl Serialize for ModuleID {
impl<'de> Deserialize<'de> for ModuleID {
fn deserialize<D>(deserializer: D) -> result::Result<Self, D::Error>
where D: Deserializer<'de>
where
D: Deserializer<'de>,
{
let s = String::deserialize(deserializer)?;
FromStr::from_str(&s).map_err(de::Error::custom)

View File

@@ -1,8 +1,8 @@
pub mod api;
pub mod errors;
pub use crate::errors::*;
pub mod metadata;
pub mod id;
pub mod metadata;
pub use crate::id::*;
pub use rocket_failure_errors::StrictApiResponse as ApiResponse;

View File

@@ -1,9 +1,9 @@
use crate::errors::*;
use nom::IResult;
use nom::bytes::complete::{tag, take_until};
use nom::combinator::map_res;
use nom::multi::fold_many0;
use serde::{Serialize, Deserialize};
use nom::IResult;
use serde::{Deserialize, Serialize};
use std::str::FromStr;
mod stealth;

View File

@@ -1,5 +1,5 @@
use crate::errors::*;
use serde::{Serialize, Deserialize};
use serde::{Deserialize, Serialize};
use std::str::FromStr;
#[derive(Debug, Eq, PartialEq, PartialOrd, Clone, Serialize, Deserialize)]

View File

@@ -1,11 +1,11 @@
[package]
name = "sn0int-std"
version = "0.24.0"
version = "0.25.0"
description = "sn0int - stdlib"
authors = ["kpcyrd <git@rxv.cc>"]
repository = "https://github.com/kpcyrd/sn0int"
license = "GPL-3.0"
edition = "2018"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@@ -31,25 +31,26 @@ pem = "1"
url = "2.0"
tungstenite = { version = "0.13", default-features = false }
kuchiki = "0.8.0"
maxminddb = "0.21"
x509-parser = "0.12"
der-parser = "6"
maxminddb = "0.23"
x509-parser = "0.13"
der-parser = "8"
publicsuffix = { version="2", default-features=false }
xml-rs = "0.8"
geo = "0.18"
geo = "0.23"
bytes = "0.4"
base64 = "0.13"
chrono = { version = "0.4", features = ["serde"] }
mqtt-protocol = "0.11"
sodiumoxide = { version="0.2.5", features=["use-pkg-config"] }
image = "0.23.0"
image = "0.23"
kamadak-exif = "0.5.1"
img_hash_median = "4.0.0"
bs58 = "0.4"
digest = "0.9"
blake2 = "0.9"
digest = "0.10"
blake2 = "0.10"
data-encoding = "2.3.3"
thiserror = "1.0.38"
[dev-dependencies]
env_logger = "0.9"

View File

@@ -1,8 +1,9 @@
use blake2::Blake2bVar;
use bytes::Bytes;
use blake2::VarBlake2b;
use data_encoding::BASE64;
use digest::{Update, VariableOutput};
use serde::ser::{Serialize, Serializer};
use serde::de::{self, Deserialize, Deserializer};
use serde::ser::{Serialize, Serializer};
use std::result;
#[derive(Debug, Clone, PartialEq)]
@@ -21,7 +22,7 @@ impl Blob {
}
pub fn hash(bytes: &[u8]) -> String {
let mut h = VarBlake2b::new(32).unwrap();
let mut h = Blake2bVar::new(32).unwrap();
h.update(bytes);
let output = h.finalize_boxed();
Self::encode_hash(&output)
@@ -40,7 +41,7 @@ impl Serialize for Blob {
where
S: Serializer,
{
let s = base64::encode(&self.bytes);
let s = BASE64.encode(&self.bytes);
serializer.serialize_str(&s)
}
}
@@ -52,7 +53,7 @@ impl<'de> Deserialize<'de> for Blob {
D: Deserializer<'de>,
{
let s = String::deserialize(deserializer)?;
let bytes = base64::decode(&s)
let bytes = BASE64.decode(s.as_bytes())
.map_err(de::Error::custom)?;
Ok(Blob::create(Bytes::from(bytes)))
}

View File

@@ -1,3 +1,3 @@
pub use log::{trace, debug, info, warn, error};
pub use failure::{Error, ResultExt, format_err, bail};
pub use failure::{bail, format_err, Error, ResultExt};
pub use log::{debug, error, info, trace, warn};
pub type Result<T> = ::std::result::Result<T, Error>;

View File

@@ -1,7 +1,7 @@
use crate::errors::*;
use crate::hlua::AnyLuaValue;
use crate::json::LuaJsonValue;
use geo::{LineString, Polygon, Coordinate};
use geo::{LineString, Polygon, Coord};
use geo::prelude::*;
use serde::Deserialize;
@@ -21,7 +21,7 @@ impl Point {
pub fn polygon_contains(ring: &[Point], p: &Point) -> bool {
let ring = ring.iter()
.map(|p| Coordinate { x: p.lon, y: p.lat })
.map(|p| Coord { x: p.lon, y: p.lat })
.collect::<Vec<_>>();
let polygon = Polygon::new(LineString::from(ring), vec![]);

View File

@@ -72,7 +72,7 @@ pub struct Continent {
}
impl Continent {
fn from_maxmind(continent: geoip2::model::Continent) -> Option<Self> {
fn from_maxmind(continent: geoip2::city::Continent) -> Option<Self> {
let code = continent.code?;
let name = from_geoip_model_names(continent.names)?;
@@ -90,7 +90,7 @@ pub struct Country {
}
impl Country {
fn from_maxmind(country: geoip2::model::Country) -> Option<Self> {
fn from_maxmind(country: geoip2::city::Country) -> Option<Self> {
let code = country.iso_code?;
let name = from_geoip_model_names(country.names)?;
@@ -108,7 +108,7 @@ pub struct Location {
}
impl Location {
fn from_maxmind(location: &geoip2::model::Location) -> Option<Self> {
fn from_maxmind(location: &geoip2::city::Location) -> Option<Self> {
let latitude = match location.latitude {
Some(latitude) => latitude,
_ => return None,

View File

@@ -93,7 +93,7 @@ pub fn cardinal_direction_modifier(value: &exif::Value) -> Result<f64> {
let s = s.get(0)
.ok_or_else(|| format_err!("Cardinal direction value is empty"))?;
match s.get(0) {
match s.first() {
Some(b'N') => Ok(1.0),
Some(b'S') => Ok(-1.0),
Some(b'E') => Ok(1.0),

View File

@@ -3,8 +3,8 @@ use hlua_badtouch as hlua;
pub mod blobs;
pub mod crt;
pub mod crypto;
mod errors;
pub mod engine;
mod errors;
pub mod geo;
pub mod geoip;
pub mod gfx;

View File

@@ -1,20 +1,26 @@
use chrootable_https::DnsResolver;
use crate::errors::*;
use crate::hlua::AnyLuaValue;
use mqtt::packet::VariablePacketError;
use crate::json::LuaJsonValue;
use crate::sockets::{Stream, SocketOptions};
use mqtt::{TopicFilter, QualityOfService};
use mqtt::control::ConnectReturnCode;
use crate::sockets::{SocketOptions, Stream};
use chrootable_https::DnsResolver;
use mqtt::control::fixed_header::FixedHeaderError;
use mqtt::encodable::{Encodable, Decodable};
use mqtt::packet::{VariablePacket, ConnectPacket, SubscribePacket, PingreqPacket};
use serde::{Serialize, Deserialize};
use mqtt::control::ConnectReturnCode;
use mqtt::encodable::{Decodable, Encodable};
use mqtt::packet::VariablePacketError;
use mqtt::packet::{ConnectPacket, PingreqPacket, SubscribePacket, VariablePacket};
use mqtt::{QualityOfService, TopicFilter};
use serde::{Deserialize, Serialize};
use std::convert::TryFrom;
use std::io;
use std::net::SocketAddr;
use std::time::{Duration, Instant};
use url::Url;
// a reasonable default for keep-alive
// some servers reject 0 as invalid with a very confusing error message
const DEFAULT_PING_INTERVAL: u64 = 90;
const DEFAULT_KEEP_ALIVE: u16 = 120;
#[derive(Debug, Default, Deserialize)]
pub struct MqttOptions {
pub username: Option<String>,
@@ -23,10 +29,12 @@ pub struct MqttOptions {
pub proxy: Option<SocketAddr>,
#[serde(default)]
pub connect_timeout: u64,
#[serde(default)]
pub read_timeout: u64,
pub read_timeout: Option<u64>,
#[serde(default)]
pub write_timeout: u64,
pub ping_interval: Option<u64>,
pub keep_alive: Option<u16>,
}
impl MqttOptions {
@@ -37,25 +45,44 @@ impl MqttOptions {
}
}
#[derive(Debug, thiserror::Error)]
pub enum MqttRecvError {
#[error("Failed to read mqtt packet: {0:#}")]
Recv(#[from] VariablePacketError),
#[error("Failed to read mqtt packet: connection disconnected")]
RecvDisconnect,
#[error("Failed to interact with mqtt: {0:#}")]
Error(Error),
}
impl From<Error> for MqttRecvError {
fn from(err: Error) -> Self {
MqttRecvError::Error(err)
}
}
pub struct MqttClient {
stream: Stream,
last_ping: Instant,
ping_interval: Option<u64>,
}
impl MqttClient {
pub fn negotiate(stream: Stream, options: &MqttOptions) -> Result<MqttClient> {
// default to DEFAULT_PING_INTERVAL, if an explicit value of 0 was set, disable auto-ping
let ping_interval = Some(options.ping_interval.unwrap_or(DEFAULT_PING_INTERVAL));
ping_interval.filter(|s| *s != 0);
let mut client = MqttClient {
stream,
last_ping: Instant::now(),
ping_interval,
};
let mut pkt = ConnectPacket::new("sn0int");
pkt.set_user_name(options.username.clone());
pkt.set_password(options.password.clone());
/*
if let Some(keep_alive) = msg.keep_alive {
packet.set_keep_alive(keep_alive);
}
*/
pkt.set_keep_alive(options.keep_alive.unwrap_or(DEFAULT_KEEP_ALIVE));
client.send(pkt.into())?;
let pkt = client.recv()?;
@@ -72,14 +99,19 @@ impl MqttClient {
}
}
pub fn connect<R: DnsResolver>(resolver: &R, url: Url, options: &MqttOptions) -> Result<MqttClient> {
pub fn connect<R: DnsResolver>(
resolver: &R,
url: Url,
options: &MqttOptions,
) -> Result<MqttClient> {
let tls = match url.scheme() {
"mqtt" => false,
"mqtts" => true,
_ => bail!("Invalid mqtt protocol"),
};
let host = url.host_str()
let host = url
.host_str()
.ok_or_else(|| format_err!("Missing host in url"))?;
let port = match (url.port(), tls) {
@@ -88,29 +120,57 @@ impl MqttClient {
(None, false) => 1883,
};
// if no read timeout is configured then keep alive won't work
let read_timeout = options.read_timeout.unwrap_or(DEFAULT_PING_INTERVAL);
let stream = Stream::connect_stream(resolver, host, port, &SocketOptions {
tls,
sni_value: None,
disable_tls_verify: false,
proxy: options.proxy,
let stream = Stream::connect_stream(
resolver,
host,
port,
&SocketOptions {
tls,
sni_value: None,
disable_tls_verify: false,
proxy: options.proxy,
connect_timeout: options.connect_timeout,
read_timeout: options.read_timeout,
write_timeout: options.write_timeout,
})?;
connect_timeout: options.connect_timeout,
read_timeout,
write_timeout: options.write_timeout,
},
)?;
Self::negotiate(stream, options)
}
fn maintain_ping(&mut self) -> Result<()> {
if let Some(ping_interval) = self.ping_interval {
if self.last_ping.elapsed() >= Duration::from_secs(ping_interval) {
self.ping().context("Failed to ping")?;
self.last_ping = Instant::now();
}
}
Ok(())
}
fn send(&mut self, pkt: VariablePacket) -> Result<()> {
self.maintain_ping()?;
debug!("Sending mqtt packet: {:?}", pkt);
pkt.encode(&mut self.stream)?;
Ok(())
}
fn recv(&mut self) -> std::result::Result<VariablePacket, VariablePacketError> {
let pkt = VariablePacket::decode(&mut self.stream)?;
fn recv(&mut self) -> std::result::Result<VariablePacket, MqttRecvError> {
self.maintain_ping()?;
let pkt = VariablePacket::decode(&mut self.stream).map_err(|err| match err {
// search for any io error and check if it's ErrorKind::UnexpectedEof
VariablePacketError::IoError(err)
| VariablePacketError::FixedHeaderError(FixedHeaderError::IoError(err))
if err.kind() == io::ErrorKind::UnexpectedEof =>
{
MqttRecvError::RecvDisconnect
}
_ => MqttRecvError::Recv(err),
})?;
debug!("Received mqtt packet: {:?}", pkt);
Ok(pkt)
}
@@ -139,30 +199,35 @@ impl MqttClient {
pub fn recv_pkt(&mut self) -> Result<Option<Pkt>> {
match self.recv() {
Ok(pkt) => Ok(Some(Pkt::try_from(pkt)?)),
Err(VariablePacketError::IoError(err)) if err.kind() == io::ErrorKind::WouldBlock => Ok(None),
Err(VariablePacketError::FixedHeaderError(FixedHeaderError::IoError(err))) if err.kind() == io::ErrorKind::WouldBlock => Ok(None),
Err(err) => Err(Error::from(err))
// search for any io error and check if it's ErrorKind::WouldBlock
Err(MqttRecvError::Recv(
VariablePacketError::IoError(err)
| VariablePacketError::FixedHeaderError(FixedHeaderError::IoError(err)),
)) if err.kind() == io::ErrorKind::WouldBlock => Ok(None),
Err(err) => Err(err.into()),
}
}
pub fn ping(&mut self) -> Result<()> {
let pkt = PingreqPacket::new();
self.send(pkt.into())
let pkt = VariablePacket::PingreqPacket(pkt);
pkt.encode(&mut self.stream)?;
Ok(())
}
}
#[derive(Serialize, Deserialize)]
#[serde(tag = "type")]
pub enum Pkt {
#[serde(rename="publish")]
#[serde(rename = "publish")]
Publish(Publish),
#[serde(rename="pong")]
#[serde(rename = "pong")]
Pong,
}
impl Pkt {
pub fn to_lua(&self) -> Result<AnyLuaValue> {
let v = serde_json::to_value(&self)?;
let v = serde_json::to_value(self)?;
let v = LuaJsonValue::from(v).into();
Ok(v)
}

View File

@@ -129,7 +129,7 @@ impl Stream {
let socket = if connect_timeout > 0 {
TcpStream::connect_timeout(&addr, Duration::from_secs(connect_timeout))?
} else {
TcpStream::connect(&addr)?
TcpStream::connect(addr)?
};
debug!("successfully connected to {:?}", addr);
@@ -138,7 +138,7 @@ impl Stream {
tls::wrap_if_enabled(socket, host, options)
}
pub fn connect_socks5_stream(proxy: &SocketAddr, host: &str, port: u16, options: &SocketOptions) -> Result<Stream> {
pub fn connect_socks5_stream(proxy: SocketAddr, host: &str, port: u16, options: &SocketOptions) -> Result<Stream> {
debug!("connecting to {:?}:{:?} with socks5 on {:?}", host, port, proxy);
let addr = match host.parse::<Ipv4Addr>() {
@@ -146,7 +146,7 @@ impl Stream {
_ => ProxyDest::Domain(host.to_string()),
};
let fut = socks5::connect(proxy, addr, port);
let fut = socks5::connect(&proxy, addr, port);
let mut rt = Runtime::new()?;
let socket = rt.block_on(fut)?;
@@ -211,7 +211,7 @@ impl Socket {
Ok(Socket::new(stream))
}
pub fn connect_socks5(proxy: &SocketAddr, host: &str, port: u16, options: &SocketOptions) -> Result<Socket> {
pub fn connect_socks5(proxy: SocketAddr, host: &str, port: u16, options: &SocketOptions) -> Result<Socket> {
let stream = Stream::connect_socks5_stream(proxy, host, port, options)?;
Ok(Socket::new(stream))
}

View File

@@ -17,7 +17,7 @@ pub struct TlsData {
impl TlsData {
pub fn to_lua(&self) -> Result<AnyLuaValue> {
let v = serde_json::to_value(&self)?;
let v = serde_json::to_value(self)?;
let v = LuaJsonValue::from(v).into();
Ok(v)
}

View File

@@ -8,11 +8,13 @@ pub use chrootable_https::{Client, HttpClient, Resolver, Response};
use chrootable_https::http::HttpTryFrom;
use chrootable_https::http::uri::Parts;
use chrootable_https::http::request::Builder;
use data_encoding::BASE64;
use rand::{Rng, thread_rng};
use rand::distributions::Alphanumeric;
use serde::{Serialize, Deserialize};
use std::collections::{HashMap, HashSet};
use std::fmt;
use std::fmt::Write;
use std::iter;
use std::net::SocketAddr;
use std::ops::Deref;
@@ -160,9 +162,9 @@ impl HttpRequest {
// add headers
if let Some(ref auth) = self.basic_auth {
use chrootable_https::header::AUTHORIZATION;
let &(ref user, ref password) = auth;
let (user, password) = auth;
let auth = base64::encode(&format!("{}:{}", user, password));
let auth = BASE64.encode(format!("{}:{}", user, password).as_bytes());
let auth = format!("Basic {}", auth);
req.header(AUTHORIZATION, auth.as_str());
}
@@ -251,7 +253,8 @@ impl HttpRequest {
if !cookies.is_empty() {
cookies += "; ";
}
cookies.push_str(&format!("{}={}", key, value));
// it's a write to a String, so panic if re-allocation fails is fine
write!(cookies, "{}={}", key, value).expect("out of memory");
}
if !cookies.is_empty() {
@@ -317,7 +320,7 @@ impl HttpRequest {
impl From<HttpRequest> for AnyLuaValue {
fn from(req: HttpRequest) -> AnyLuaValue {
let v = serde_json::to_value(&req).unwrap();
let v = serde_json::to_value(req).unwrap();
LuaJsonValue::from(v).into()
}
}

View File

@@ -62,7 +62,7 @@ pub fn decode(x: &str) -> Result<AnyLuaValue> {
}
#[inline]
fn append_text(stack: &mut Vec<XmlElement>, text: String) {
fn append_text(stack: &mut [XmlElement], text: String) {
if let Some(tail) = stack.last_mut() {
if let Some(prev) = tail.text.as_mut() {
prev.push_str(&text);

View File

@@ -6,6 +6,7 @@ use crate::cal::{ActivityGrade, DateArg};
use crate::models::*;
use std::collections::HashMap;
use std::collections::VecDeque;
use std::fmt::Write;
const MONTH_LINES: i32 = 7;
@@ -54,11 +55,11 @@ fn chunk_months(ctx: &DateContext, months: &[DateSpec]) -> String {
}
fn days_in_month(year: i32, month: u32) -> i64 {
let start = Utc.ymd(year, month, 1);
let start = Utc.with_ymd_and_hms(year, month, 1, 0, 0, 0).single().expect("Datetime is not unique");
let end = if month == 12 {
Utc.ymd(year + 1, 1, 1)
Utc.with_ymd_and_hms(year + 1, 1, 1, 0, 0, 0).single().expect("Datetime is not unique")
} else {
Utc.ymd(year, month + 1, 1)
Utc.with_ymd_and_hms(year, month + 1, 1, 0, 0, 0).single().expect("Datetime is not unique")
};
end.signed_duration_since(start).num_days()
}
@@ -151,7 +152,7 @@ impl DateSpec {
bail!("Too many datespec args");
}
let today = Utc::today();
let today = Utc::now();
let ds = match (args.get(0), args.get(1), context) {
(None, _, None) => DateSpec::YearMonth((today.year(), today.month())),
(None, _, Some(context)) => DateSpec::YearMonthContext((today.year(), today.month(), context)),
@@ -171,8 +172,8 @@ impl DateSpec {
pub fn start(&self) -> NaiveDate {
match self {
DateSpec::Year(year) => NaiveDate::from_ymd(*year, 1, 1),
DateSpec::YearMonth((year, month)) => NaiveDate::from_ymd(*year, *month, 1),
DateSpec::Year(year) => NaiveDate::from_ymd_opt(*year, 1, 1).expect("Invalid month/day"),
DateSpec::YearMonth((year, month)) => NaiveDate::from_ymd_opt(*year, *month, 1).expect("Invalid month/day"),
DateSpec::YearMonthContext((year, month, context)) => {
let mut year = *year - (*context / 12) as i32;
let context = context % 12;
@@ -182,21 +183,21 @@ impl DateSpec {
} else {
month - context
};
NaiveDate::from_ymd(year, month, 1)
NaiveDate::from_ymd_opt(year, month, 1).expect("Invalid month/day")
},
}
}
pub fn end(&self) -> NaiveDate {
match self {
DateSpec::Year(year) => NaiveDate::from_ymd(year + 1, 1, 1),
DateSpec::Year(year) => NaiveDate::from_ymd_opt(year + 1, 1, 1).expect("Invalid month/day"),
DateSpec::YearMonth((year, month)) => {
let (year, month) = if *month == 12 {
(*year + 1, 1)
} else {
(*year, *month + 1)
};
NaiveDate::from_ymd(year, month, 1)
NaiveDate::from_ymd_opt(year, month, 1).expect("Invalid month/day")
},
DateSpec::YearMonthContext((year, month, _context)) => {
let (year, month) = if *month == 12 {
@@ -204,7 +205,7 @@ impl DateSpec {
} else {
(*year, *month + 1)
};
NaiveDate::from_ymd(year, month, 1)
NaiveDate::from_ymd_opt(year, month, 1).expect("Invalid month/day")
},
}
}
@@ -220,10 +221,10 @@ impl DateSpec {
DateSpec::YearMonth((year, month)) => {
let mut w = String::new();
let start = Utc.ymd(*year, *month, 1);
let start = Utc.with_ymd_and_hms(*year, *month, 1, 0, 0, 0).single().expect("Datetime is not unique");
let days = days_in_month(*year, *month) as u32;
w.push_str(&format!("{:^21}\n", start.format("%B %Y")));
writeln!(w, "{:^21}", start.format("%B %Y")).expect("out of memory");
w.push_str(" Su Mo Tu We Th Fr Sa\n");
let mut cur_week_day = start.weekday();
@@ -232,7 +233,7 @@ impl DateSpec {
let mut week_written = week_progress * 3;
for cur_day in 1..=days {
let date = NaiveDate::from_ymd(*year, *month, cur_day);
let date = NaiveDate::from_ymd_opt(*year, *month, cur_day).expect("Invalid month/day");
if !ctx.is_future(&date) {
let activity = ctx.activity_for_day(&date);
@@ -244,7 +245,7 @@ impl DateSpec {
} else {
w.push(' ');
}
w.push_str(&format!("{:2}", cur_day));
write!(w, "{:2}", cur_day).expect("out of memory");
week_written += 3;
w.push_str("\x1b[0m");
@@ -296,7 +297,7 @@ mod tests {
DateContext {
events: HashMap::new(),
max: 0,
today: NaiveDate::from_ymd(2020, 5, 30),
today: NaiveDate::from_ymd_opt(2020, 5, 30).unwrap(),
}
}
@@ -324,9 +325,9 @@ mod tests {
let ctx = DateContext {
events,
max: 0,
today: NaiveDate::from_ymd(2020, 6, 6),
today: NaiveDate::from_ymd_opt(2020, 6, 6).unwrap(),
};
let grade = ctx.activity_for_day(&NaiveDate::from_ymd(2020, 6, 6));
let grade = ctx.activity_for_day(&NaiveDate::from_ymd_opt(2020, 6, 6).unwrap());
assert_eq!(grade, ActivityGrade::None);
}

View File

@@ -5,6 +5,7 @@ use chrono::prelude::*;
use crate::cal::{ActivityGrade, DateArg};
use crate::models::*;
use std::collections::HashMap;
use std::fmt::Write;
const MIN_PER_DAY: u32 = 1440;
@@ -13,7 +14,7 @@ fn round_to_slice(time: &NaiveDateTime, slice_duration: u32) -> NaiveDateTime {
let hour = time.hour();
let mins = time.minute();
let slice = mins - (mins % slice_duration);
date.and_hms(hour, slice, 0)
date.and_hms_opt(hour, slice, 0).expect("Invalid hour/min/sec")
}
fn setup_graph_map(events: &[Activity], slice_duration: u32) -> (HashMap<NaiveDateTime, u64>, u64) {
@@ -109,7 +110,7 @@ pub struct DateTimeSpec {
impl DateTimeSpec {
pub fn from_args(args: &[DateArg], context: Option<u32>) -> Result<DateTimeSpec> {
let today = Utc::today().naive_utc();
let today = Utc::now().date_naive();
if args.is_empty() {
let mut start = today;
@@ -156,7 +157,7 @@ impl DateTimeSpec {
// add legend
w.push_str(&" ".repeat(11));
for x in 0..24 {
w.push_str(&format!("{:02}", x));
write!(w, "{:02}", x).expect("out of memory");
for i in 0..ctx.hour_width() {
if i >= 2 {
@@ -175,7 +176,7 @@ impl DateTimeSpec {
let mut mins = 0;
for _ in 0..(MIN_PER_DAY / ctx.slice_duration) {
let time = date.and_hms(hours, mins, 0);
let time = date.and_hms_opt(hours, mins, 0).expect("Invalid hour/min/sec");
if !ctx.is_future(&time) {
let activity = ctx.activity_for_slice(&time);

View File

@@ -18,7 +18,7 @@ pub struct TimeSpec {
impl TimeSpec {
fn resolve(s: &str, now: NaiveDateTime) -> Result<Self> {
let today = NaiveDateTime::new(now.date(), NaiveTime::from_hms(0, 0, 0));
let today = NaiveDateTime::new(now.date(), NaiveTime::from_hms_opt(0, 0, 0).expect("Invalid hour/min/sec"));
let datetime = match s {
"today" => today,
@@ -122,8 +122,8 @@ mod tests {
use super::*;
fn datetime() -> NaiveDateTime {
let date = chrono::NaiveDate::from_ymd(2020, 3, 14);
let time = chrono::NaiveTime::from_hms(16, 20, 23);
let date = chrono::NaiveDate::from_ymd_opt(2020, 3, 14).unwrap();
let time = chrono::NaiveTime::from_hms_opt(16, 20, 23).unwrap();
NaiveDateTime::new(date, time)
}

View File

@@ -34,8 +34,8 @@ impl Cmd for Args {
.context("Failed to parse date spec")?;
let filter = ActivityFilter {
topic: None,
since: Some(dts.start().and_hms(0, 0, 0)),
until: Some(dts.end().and_hms(23, 59, 59)),
since: Some(dts.start().and_hms_opt(0, 0, 0).expect("Invalid hour/min/sec")),
until: Some(dts.end().and_hms_opt(23, 59, 59).expect("Invalid hour/min/sec")),
location: false,
};
let events = Activity::query(rl.db(), &filter)?;
@@ -53,12 +53,12 @@ impl Cmd for Args {
.context("Failed to parse date spec")?;
let filter = ActivityFilter {
topic: None,
since: Some(ds.start().and_hms(0, 0, 0)),
until: Some(ds.end().and_hms(23, 59, 59)),
since: Some(ds.start().and_hms_opt(0, 0, 0).expect("Invalid hour/min/sec")),
until: Some(ds.end().and_hms_opt(23, 59, 59).expect("Invalid hour/min/sec")),
location: false,
};
let events = Activity::query(rl.db(), &filter)?;
let ctx = DateContext::new(&events, Utc::today().naive_utc());
let ctx = DateContext::new(&events, Utc::now().date_naive());
println!("{}", ds.to_term_string(&ctx));
}
Ok(())

View File

@@ -2,12 +2,12 @@ use crate::errors::*;
use crate::cmd::Cmd;
use crate::engine::Module;
// use crate::models::*;
use crate::notify::{self, Notification};
use crate::options::{self, Opt};
use crate::shell::Shell;
use crate::term;
use sn0int_std::ratelimits::Ratelimiter;
use std::fmt::Write;
use structopt::StructOpt;
use structopt::clap::AppSettings;
@@ -52,19 +52,19 @@ pub struct ExecArgs {
}
fn print_summary(module: &Module, sent: usize, errors: usize) {
let mut out = if sent == 1 {
String::from("Sent 1 notification")
} else {
format!("Sent {} notifications", sent)
};
let mut out = if sent == 1 {
String::from("Sent 1 notification")
} else {
format!("Sent {} notifications", sent)
};
out.push_str(&format!(" with {}", module.canonical()));
write!(out, " with {}", module.canonical()).expect("out of memory");
if errors > 0 {
out.push_str(&format!(" ({} errors)", errors));
}
if errors > 0 {
write!(out, " ({} errors)", errors).expect("out of memory");
}
term::info(&out);
term::info(&out);
}
fn send(args: SendArgs, rl: &mut Shell) -> Result<()> {

View File

@@ -105,7 +105,7 @@ fn rescope_to_queue<T, F1, F2, F3>(ctx: &mut Context, db: &Database, interactive
// check if there are filters to be applied
let filter = if let Some(target) = &ctx.target {
if let Some(filter) = get_filter(&target) {
if let Some(filter) = get_filter(target) {
// we've selected this specific entity type and there's a filter
filter.parse_optional()
.context("Filter is invalid")?
@@ -180,8 +180,10 @@ impl Cmd for Args {
let rules = rl.db().autonoscope();
term::success(&format!("Loaded {} rules", rules.len()));
let mut ctx = Context::default();
ctx.target = self.target;
let mut ctx = Context {
target: self.target,
..Default::default()
};
rescope_to_queue::<Domain, _, _, _>(&mut ctx, rl.db(), self.interactive, |t| t.domains(), |entity| {
for rule in rules.domains() {

View File

@@ -21,7 +21,7 @@ pub struct Config {
impl Config {
pub fn load() -> Result<Config> {
let path = Config::path()?;
Config::load_from(&path)
Config::load_from(path)
}
pub fn path() -> Result<PathBuf> {

View File

@@ -5,6 +5,7 @@ use diesel::expression::SqlLiteral;
use diesel::expression::sql_literal::sql;
use diesel::sql_types::Bool;
use diesel::prelude::*;
use std::fmt::Write;
use strum_macros::{EnumString, IntoStaticStr};
use crate::autonoscope::{RuleSet, RuleType};
use crate::models::*;
@@ -502,14 +503,14 @@ impl Filter {
for arg in args {
if ["=", "!=", "<", ">", "<=", ">=", "like"].contains(&arg.to_lowercase().as_str()) {
expect_value = true;
query += &format!(" {}", arg);
write!(query, " {}", arg)?;
continue;
}
if let Some(idx) = arg.find('=') {
if idx != 0 {
let (key, value) = arg.split_at(idx);
query += &format!(" {} = {}", key, Self::escape(&value[1..]));
write!(query, " {} = {}", key, Self::escape(&value[1..]))?;
continue;
}
}
@@ -519,7 +520,7 @@ impl Filter {
query.push_str(&Self::escape(arg));
expect_value = false;
} else {
query += &format!(" {}", arg);
write!(query, " {}", arg)?;
}
}
debug!("Parsed query: {:?}", query);

View File

@@ -300,7 +300,7 @@ impl State for LuaState {
let id = self.random_id();
let sock = if let Some(proxy) = self.resolve_proxy_options(&options.proxy)? {
Socket::connect_socks5(proxy, host, port, options)?
Socket::connect_socks5(*proxy, host, port, options)?
} else {
Socket::connect(&self.dns_config, host, port, options)?
};

View File

@@ -77,7 +77,7 @@ impl<'a> Library<'a> {
}
pub fn private_modules(path: &Path) -> Result<bool> {
let metadata = fs::symlink_metadata(&path)?.file_type();
let metadata = fs::symlink_metadata(path)?.file_type();
if metadata.is_symlink() {
debug!("Folder is a symlink, flagging modules as private");
return Ok(true);

View File

@@ -47,7 +47,7 @@ impl IpcParent {
}
pub fn send_start(&mut self, start: &StartCommand) -> Result<()> {
let start = serde_json::to_value(&start)?;
let start = serde_json::to_value(start)?;
self.send(&start)?;
Ok(())
}
@@ -71,6 +71,10 @@ impl IpcParent {
let mut line = String::new();
let len = self.stdout.read_line(&mut line)?;
if len == 0 {
bail!("Sandbox child has crashed");
}
let event = serde_json::from_str(&line[..len])?;
debug!("IpcParent received: {:?}", event);
Ok(event)

View File

@@ -94,7 +94,7 @@ impl KeyRing {
}
pub fn load(path: &Path) -> Result<KeyRing> {
let buf = fs::read(&path)
let buf = fs::read(path)
.context("Failed to read keyring file")?;
serde_json::from_slice(&buf)
.map_err(Error::from)
@@ -103,7 +103,7 @@ impl KeyRing {
pub fn save(&self) -> Result<()> {
let path = Self::path()?;
let buf = serde_json::to_string(&self)?;
fs::write(&path, buf)
fs::write(path, buf)
.context("Failed to save keyring")?;
Ok(())
}
@@ -111,7 +111,7 @@ impl KeyRing {
pub fn insert(&mut self, key: KeyName, secret: Option<String>) -> Result<()> {
// get the namespace or create a new one
let mut x = self.keys.remove(&key.namespace)
.unwrap_or_else(HashMap::new);
.unwrap_or_default();
// insert key into namespace
x.insert(key.name, secret);
// add namespace backinto keyring
@@ -176,7 +176,7 @@ impl KeyRing {
pub fn grant_access(&mut self, module: &Module, namespace: String) {
let mut grants = self.grants.remove(&namespace)
.unwrap_or_else(HashSet::new);
.unwrap_or_default();
grants.insert(module.id());
self.grants.insert(namespace, grants);
}
@@ -208,7 +208,7 @@ pub struct KeyRingEntry {
impl KeyRingEntry {
pub fn to_lua(&self) -> Result<AnyLuaValue> {
let v = serde_json::to_value(&self)?;
let v = serde_json::to_value(self)?;
let v = LuaJsonValue::from(v).into();
Ok(v)
}

View File

@@ -1,6 +1,8 @@
#![allow(clippy::too_many_arguments)]
#![allow(clippy::type_complexity)]
#![allow(clippy::large_enum_variant)]
// because of diesel
#![allow(clippy::extra_unused_lifetimes)]
#![warn(unused_extern_crates)]
use hlua_badtouch as hlua;

View File

@@ -35,7 +35,7 @@ fn run_run(gargs: &Args, args: &args::Run, config: &Config) -> Result<()> {
.to_str()
.ok_or_else(|| format_err!("Failed to decode filename"))?;
Module::load(&path.to_path_buf(), "anonymous", filename, true)
Module::load(path, "anonymous", filename, true)
.context(format!("Failed to parse {:?}", path))?
} else {
rl.library().get(module)?

View File

@@ -9,21 +9,21 @@ pub fn sn0int_dir() -> Result<PathBuf> {
.ok_or_else(|| format_err!("Failed to find data directory"))?;
let path = path.join("sn0int");
fs::create_dir_all(&path)
.context("Failed to create data directory")?;
.context("Failed to create sn0int data directory")?;
Ok(path)
}
pub fn history_path() -> Result<PathBuf> {
let path = sn0int_dir()?;
let path = path.join("history");
let path = sn0int_dir()?
.join("history");
Ok(path)
}
pub fn module_dir() -> Result<PathBuf> {
let path = sn0int_dir()?;
let path = path.join("modules");
let path = sn0int_dir()?
.join("modules");
fs::create_dir_all(&path)
.context("Failed to create module directory")?;
.context("Failed to create modules directory")?;
Ok(path)
}
@@ -31,16 +31,15 @@ pub fn data_dir() -> Result<PathBuf> {
let path = sn0int_dir()?
.join("data");
fs::create_dir_all(&path)
.context("Failed to create module directory")?;
.context("Failed to create data directory")?;
Ok(path)
}
pub fn workspace_dir(workspace: &Workspace) -> Result<PathBuf> {
let path = sn0int_dir()?
.join("data")
let path = data_dir()?
.join(workspace.as_str());
fs::create_dir_all(&path)
.context("Failed to create module directory")?;
.context("Failed to create workspace directory")?;
Ok(path)
}
@@ -48,7 +47,7 @@ pub fn blobs_dir(workspace: &Workspace) -> Result<PathBuf> {
let path = workspace_dir(workspace)?
.join("blobs");
fs::create_dir_all(&path)
.context("Failed to create module directory")?;
.context("Failed to create blobs directory")?;
Ok(path)
}
@@ -57,7 +56,7 @@ pub fn cache_dir() -> Result<PathBuf> {
.ok_or_else(|| format_err!("Failed to find cache directory"))?;
let path = path.join("sn0int");
fs::create_dir_all(&path)
.context("Failed to create cache directory")?;
.context("Failed to create sn0int cache directory")?;
Ok(path)
}

View File

@@ -24,13 +24,13 @@ pub struct Repl<'a> {
}
impl<'a> Repl<'a> {
pub fn new(lua: Lua<'a>, state: Arc<LuaState>) -> Repl<'a> {
let rl = Readline::with(ReplCompleter::default());
Repl {
pub fn new(lua: Lua<'a>, state: Arc<LuaState>) -> Result<Repl<'a>> {
let rl = Readline::with(ReplCompleter::default())?;
Ok(Repl {
rl,
lua,
state,
}
})
}
fn update_globals(&mut self) {
@@ -63,7 +63,7 @@ impl<'a> Repl<'a> {
Ok(val) => {
if val != AnyLuaValue::LuaNil {
let mut out = String::new();
format_lua(&mut out, &val);
format_lua(&mut out, &val).expect("out of memory");
println!("{}", out);
}
if let Some(err) = self.state.last_error() {
@@ -104,7 +104,7 @@ pub fn run(config: &Config) -> Result<()> {
let tx = DummyIpcChild::create();
let (lua, state) = ctx::ctx(env, tx);
let mut repl = Repl::new(lua, state);
let mut repl = Repl::new(lua, state)?;
println!(r#":: sn0int v{} lua repl
Assign variables with `a = sn0int_version()` and `return a` to print

View File

@@ -3,7 +3,7 @@ use crate::errors::*;
use crate::engine::ctx::State;
use crate::engine::structs::{byte_array, lua_bytes};
use crate::hlua::{self, AnyLuaValue};
use data_encoding::{Specification, Encoding};
use data_encoding::{BASE64, Specification, Encoding};
use std::sync::Arc;
@@ -19,7 +19,7 @@ fn spec(symbols: &str, padding: &str) -> Result<Encoding> {
pub fn base64_decode(lua: &mut hlua::Lua, state: Arc<dyn State>) {
lua.set("base64_decode", hlua::function1(move |bytes: String| -> Result<AnyLuaValue> {
base64::decode(&bytes)
BASE64.decode(bytes.as_bytes())
.map_err(|err| state.set_error(err.into()))
.map(|bytes| lua_bytes(&bytes))
}))
@@ -29,7 +29,7 @@ pub fn base64_encode(lua: &mut hlua::Lua, state: Arc<dyn State>) {
lua.set("base64_encode", hlua::function1(move |bytes: AnyLuaValue| -> Result<String> {
byte_array(bytes)
.map_err(|err| state.set_error(err))
.map(|bytes| base64::encode(&bytes))
.map(|bytes| BASE64.encode(&bytes))
}))
}

View File

@@ -2,9 +2,8 @@ use crate::errors::*;
use crate::engine::ctx::State;
use crate::engine::structs::{byte_array, lua_bytes};
use crate::hlua::{self, AnyLuaValue};
use digest::{Digest, Update, BlockInput, FixedOutput, Reset};
use digest::generic_array::ArrayLength;
use hmac::{Hmac, Mac, NewMac};
use digest::{Digest, core_api::BlockSizeUser};
use hmac::{Mac, SimpleHmac};
use std::sync::Arc;
@@ -12,7 +11,7 @@ pub fn md5(lua: &mut hlua::Lua, state: Arc<dyn State>) {
lua.set("md5", hlua::function1(move |bytes: AnyLuaValue| -> Result<AnyLuaValue> {
byte_array(bytes)
.map_err(|err| state.set_error(err))
.map(|bytes| lua_bytes(&md5::Md5::digest(&bytes)))
.map(|bytes| lua_bytes(&md5::Md5::digest(bytes)))
}))
}
@@ -20,7 +19,7 @@ pub fn sha1(lua: &mut hlua::Lua, state: Arc<dyn State>) {
lua.set("sha1", hlua::function1(move |bytes: AnyLuaValue| -> Result<AnyLuaValue> {
byte_array(bytes)
.map_err(|err| state.set_error(err))
.map(|bytes| lua_bytes(&sha1::Sha1::digest(&bytes)))
.map(|bytes| lua_bytes(&sha1::Sha1::digest(bytes)))
}))
}
@@ -28,7 +27,7 @@ pub fn sha2_256(lua: &mut hlua::Lua, state: Arc<dyn State>) {
lua.set("sha2_256", hlua::function1(move |bytes: AnyLuaValue| -> Result<AnyLuaValue> {
byte_array(bytes)
.map_err(|err| state.set_error(err))
.map(|bytes| lua_bytes(&sha2::Sha256::digest(&bytes)))
.map(|bytes| lua_bytes(&sha2::Sha256::digest(bytes)))
}))
}
@@ -36,7 +35,7 @@ pub fn sha2_512(lua: &mut hlua::Lua, state: Arc<dyn State>) {
lua.set("sha2_512", hlua::function1(move |bytes: AnyLuaValue| -> Result<AnyLuaValue> {
byte_array(bytes)
.map_err(|err| state.set_error(err))
.map(|bytes| lua_bytes(&sha2::Sha512::digest(&bytes)))
.map(|bytes| lua_bytes(&sha2::Sha512::digest(bytes)))
}))
}
@@ -44,7 +43,7 @@ pub fn sha3_256(lua: &mut hlua::Lua, state: Arc<dyn State>) {
lua.set("sha3_256", hlua::function1(move |bytes: AnyLuaValue| -> Result<AnyLuaValue> {
byte_array(bytes)
.map_err(|err| state.set_error(err))
.map(|bytes| lua_bytes(&sha3::Sha3_256::digest(&bytes)))
.map(|bytes| lua_bytes(&sha3::Sha3_256::digest(bytes)))
}))
}
@@ -52,20 +51,17 @@ pub fn sha3_512(lua: &mut hlua::Lua, state: Arc<dyn State>) {
lua.set("sha3_512", hlua::function1(move |bytes: AnyLuaValue| -> Result<AnyLuaValue> {
byte_array(bytes)
.map_err(|err| state.set_error(err))
.map(|bytes| lua_bytes(&sha3::Sha3_512::digest(&bytes)))
.map(|bytes| lua_bytes(&sha3::Sha3_512::digest(bytes)))
}))
}
fn hmac<D>(secret: AnyLuaValue, msg: AnyLuaValue) -> Result<AnyLuaValue>
where
D: Update + BlockInput + FixedOutput + Reset + Default + Clone,
D::BlockSize: ArrayLength<u8> + Clone,
D::OutputSize: ArrayLength<u8>,
where D: Digest + BlockSizeUser
{
let secret = byte_array(secret)?;
let msg = byte_array(msg)?;
let mut mac = match Hmac::<D>::new_from_slice(&secret) {
let mut mac = match SimpleHmac::<D>::new_from_slice(&secret) {
Ok(mac) => mac,
Err(_) => bail!("Invalid key length"),
};

View File

@@ -3,9 +3,9 @@ use crate::errors::*;
use crate::engine::ctx::State;
use crate::engine::structs::byte_array;
use crate::hlua::{self, AnyLuaValue};
use std::fmt::Write;
use std::sync::Arc;
// TODO: consider deprecating this function, replace with hex_{en,de}code and hex_custom_{en,de}code
pub fn hex(lua: &mut hlua::Lua, state: Arc<dyn State>) {
lua.set("hex", hlua::function1(move |bytes: AnyLuaValue| -> Result<String> {
@@ -15,7 +15,7 @@ pub fn hex(lua: &mut hlua::Lua, state: Arc<dyn State>) {
let mut out = String::new();
for b in bytes {
out += &format!("{:02x}", b);
write!(out, "{:02x}", b).expect("out of memory");
}
out

View File

@@ -7,7 +7,7 @@ use crate::json;
pub fn json_decode(lua: &mut hlua::Lua, state: Arc<dyn State>) {
lua.set("json_decode", hlua::function1(move |x: String| -> Result<AnyLuaValue> {
json::decode(&x)
json::decode(x)
.map_err(|err| state.set_error(err))
}))
}

View File

@@ -1,31 +1,32 @@
use crate::errors::*;
use crate::engine::ctx::State;
use crate::hlua::{self, AnyLuaValue};
use std::fmt::Write;
use std::sync::Arc;
pub fn format_lua(out: &mut String, x: &AnyLuaValue) {
pub fn format_lua(out: &mut String, x: &AnyLuaValue) -> Result<()> {
match *x {
AnyLuaValue::LuaNil => out.push_str("null"),
AnyLuaValue::LuaString(ref x) => out.push_str(&format!("{:?}", x)),
AnyLuaValue::LuaNumber(ref x) => out.push_str(&format!("{:?}", x)),
AnyLuaValue::LuaAnyString(ref x) => out.push_str(&format!("{:?}", x.0)),
AnyLuaValue::LuaBoolean(ref x) => out.push_str(&format!("{:?}", x)),
AnyLuaValue::LuaString(ref x) => write!(out, "{:?}", x)?,
AnyLuaValue::LuaNumber(ref x) => write!(out, "{:?}", x)?,
AnyLuaValue::LuaAnyString(ref x) => write!(out, "{:?}", x.0)?,
AnyLuaValue::LuaBoolean(ref x) => write!(out, "{:?}", x)?,
AnyLuaValue::LuaArray(ref x) => {
out.push('{');
let mut first = true;
for &(ref k, ref v) in x {
for (k, v) in x {
if !first {
out.push_str(", ");
}
let mut key = String::new();
format_lua(&mut key, k);
format_lua(&mut key, k)?;
let mut value = String::new();
format_lua(&mut value, v);
format_lua(&mut value, v)?;
out.push_str(&format!("{}: {}", key, value));
write!(out, "{}: {}", key, value)?;
first = false;
}
@@ -33,12 +34,14 @@ pub fn format_lua(out: &mut String, x: &AnyLuaValue) {
},
AnyLuaValue::LuaOther => out.push_str("LuaOther"),
}
Ok(())
}
pub fn info(lua: &mut hlua::Lua, state: Arc<dyn State>) {
lua.set("info", hlua::function1(move |val: AnyLuaValue| {
let mut out = String::new();
format_lua(&mut out, &val);
format_lua(&mut out, &val).expect("out of memory");
state.info(out);
}))
}
@@ -46,7 +49,7 @@ pub fn info(lua: &mut hlua::Lua, state: Arc<dyn State>) {
pub fn debug(lua: &mut hlua::Lua, state: Arc<dyn State>) {
lua.set("debug", hlua::function1(move |val: AnyLuaValue| {
let mut out = String::new();
format_lua(&mut out, &val);
format_lua(&mut out, &val).expect("out of memory");
state.debug(out);
}))
}
@@ -79,7 +82,7 @@ pub fn print(lua: &mut hlua::Lua, _: Arc<dyn State>) {
lua.set("print", hlua::function1(move |val: AnyLuaValue| {
// println!("{:?}", val);
let mut out = String::new();
format_lua(&mut out, &val);
format_lua(&mut out, &val).expect("out of memory");
eprintln!("{}", out);
}))
}

View File

@@ -73,7 +73,7 @@ pub fn ws_recv_json(lua: &mut hlua::Lua, state: Arc<dyn State>) {
.map_err(|err| state.set_error(err))?;
let json = if let Some(json) = json {
let json = json::decode(&json)
let json = json::decode(json)
.map_err(|err| state.set_error(err))?;
Some(json)
} else {

View File

@@ -13,11 +13,11 @@ pub fn init() -> Result<()> {
ctx.allow_syscall(Syscall::sigaltstack)?;
ctx.allow_syscall(Syscall::munmap)?;
ctx.allow_syscall(Syscall::fcntl)?;
#[cfg(not(any(target_arch = "x86_64", target_arch = "aarch64")))]
#[cfg(not(any(target_arch = "x86_64", target_arch = "aarch64", target_arch = "riscv64")))]
ctx.allow_syscall(Syscall::fcntl64)?;
ctx.allow_syscall(Syscall::uname)?;
ctx.allow_syscall(Syscall::close)?;
#[cfg(not(target_arch = "aarch64"))]
#[cfg(not(any(target_arch = "aarch64", target_arch = "riscv64")))]
ctx.allow_syscall(Syscall::poll)?;
#[cfg(target_arch = "aarch64")]
ctx.allow_syscall(Syscall::ppoll)?;
@@ -29,7 +29,7 @@ pub fn init() -> Result<()> {
ctx.allow_syscall(Syscall::connect)?;
#[cfg(target_arch = "x86")]
ctx.allow_syscall(Syscall::socketcall)?;
#[cfg(not(target_arch = "aarch64"))]
#[cfg(not(any(target_arch = "aarch64", target_arch = "riscv64")))]
ctx.allow_syscall(Syscall::epoll_wait)?;
ctx.allow_syscall(Syscall::epoll_pwait)?;
ctx.allow_syscall(Syscall::getrandom)?;
@@ -44,7 +44,7 @@ pub fn init() -> Result<()> {
ctx.allow_syscall(Syscall::getsockopt)?;
#[cfg(not(target_arch = "arm"))]
ctx.allow_syscall(Syscall::mmap)?;
#[cfg(not(any(target_arch = "x86_64", target_arch = "aarch64")))]
#[cfg(not(any(target_arch = "x86_64", target_arch = "aarch64", target_arch = "riscv64")))]
ctx.allow_syscall(Syscall::mmap2)?;
ctx.allow_syscall(Syscall::mremap)?;
ctx.allow_syscall(Syscall::mprotect)?;
@@ -54,6 +54,8 @@ pub fn init() -> Result<()> {
ctx.allow_syscall(Syscall::sched_yield)?;
ctx.allow_syscall(Syscall::setsockopt)?;
ctx.allow_syscall(Syscall::madvise)?;
ctx.allow_syscall(Syscall::rt_sigaction)?;
ctx.allow_syscall(Syscall::rseq)?;
#[cfg(target_arch = "x86")]
ctx.allow_syscall(Syscall::time)?;
ctx.allow_syscall(Syscall::clock_gettime)?;
@@ -71,12 +73,14 @@ pub fn init() -> Result<()> {
ctx.allow_syscall(Syscall::gettimeofday)?;
ctx.allow_syscall(Syscall::membarrier)?;
ctx.allow_syscall(Syscall::statx)?;
ctx.allow_syscall(Syscall::fstat)?;
ctx.allow_syscall(Syscall::lseek)?;
#[cfg(target_arch = "arm")]
ctx.allow_syscall(Syscall::_llseek)?;
ctx.allow_syscall(Syscall::clone3)?;
ctx.set_action_for_syscall(Action::Errno(1), Syscall::openat)?;
#[cfg(not(target_arch = "aarch64"))]
#[cfg(not(any(target_arch = "aarch64", target_arch = "riscv64")))]
ctx.set_action_for_syscall(Action::Errno(1), Syscall::open)?;
ctx.load()?;

View File

@@ -174,9 +174,9 @@ pub struct Shell<'a> {
}
impl<'a> Shell<'a> {
pub fn new(config: &'a Config, db: Database, blobs: BlobStorage, psl: PslReader, library: Library<'a>, keyring: KeyRing) -> Shell<'a> {
pub fn new(config: &'a Config, db: Database, blobs: BlobStorage, psl: PslReader, library: Library<'a>, keyring: KeyRing) -> Result<Shell<'a>> {
let h = CmdCompleter::default();
let rl = Readline::with(h);
let rl = Readline::with(h)?;
let prompt = Prompt::new(db.name().to_string());
@@ -197,7 +197,7 @@ impl<'a> Shell<'a> {
rl.reload_module_cache();
rl.reload_keyring_cache();
rl
Ok(rl)
}
#[inline(always)]
@@ -571,7 +571,7 @@ pub fn init<'a>(args: &Args, config: &'a Config, verbose_init: bool) -> Result<S
}
autoupdate.check_background(config, library.list());
let mut rl = Shell::new(config, db, blobs, psl, library, keyring);
let mut rl = Shell::new(config, db, blobs, psl, library, keyring)?;
ttl::reap_expired(&mut rl)?;

View File

@@ -10,35 +10,29 @@ pub struct Readline<T: rustyline::Helper> {
impl Readline<()> {
#[inline]
pub fn new() -> Readline<()> {
pub fn new() -> Result<Readline<()>> {
Readline::init(None)
}
}
impl Default for Readline<()> {
fn default() -> Self {
Self::new()
}
}
impl<T: rustyline::Helper> Readline<T> {
#[inline]
pub fn with(helper: T) -> Readline<T> {
pub fn with(helper: T) -> Result<Readline<T>> {
Readline::init(Some(helper))
}
fn init(helper: Option<T>) -> Readline<T> {
fn init(helper: Option<T>) -> Result<Readline<T>> {
let rl_config = rustyline::Config::builder()
.completion_type(CompletionType::List)
.edit_mode(EditMode::Emacs)
.build();
let mut rl: Editor<T> = Editor::with_config(rl_config);
let mut rl: Editor<T> = Editor::with_config(rl_config)?;
rl.set_helper(helper);
Readline {
Ok(Readline {
rl,
}
})
}
#[inline]

View File

@@ -66,7 +66,7 @@ impl AutoUpdater {
pub fn save(&self) -> Result<()> {
let config = serde_json::to_string(&self)?;
fs::write(AutoUpdater::path()?, &config)
fs::write(AutoUpdater::path()?, config)
.context("Failed to write auto-update state")?;
Ok(())
}

View File

@@ -15,7 +15,7 @@ pub fn random_string(len: usize) -> String {
}
pub fn read_line(prompt: &str) -> Result<String> {
let mut rl = rustyline::Editor::<()>::new();
let mut rl = rustyline::Editor::<()>::new()?;
let mut line = rl.readline(prompt)
.map_err(|err| match err {
ReadlineError::Eof => format_err!("Failed to read line from input"),

View File

@@ -15,6 +15,7 @@ use crate::ratelimits::{Ratelimiter, RatelimitResponse};
use crate::shell::Shell;
use sn0int_std::ratelimits::RatelimitSender;
use std::collections::HashMap;
use std::fmt::Write;
use std::result;
use std::sync::{mpsc, Arc, Mutex};
use std::time::Duration;
@@ -204,7 +205,7 @@ impl DatabaseEvent {
// TODO: we don't want to copy the match arms everywhere
let mut subject = format!("New activity: {:?}", object.topic);
if let Some(uniq) = &object.uniq {
subject += &format!(" ({:?})", uniq);
write!(subject, " ({:?})", uniq).expect("out of memory");
}
let topic = format!("activity:{}", object.topic);
Self::notify(rl, spinner, ratelimit, &topic, subject);
@@ -213,20 +214,20 @@ impl DatabaseEvent {
fn spinner_log_new_activity<T: SpinLogger>(spinner: &mut T, object: &NewActivity, verbose: u64) {
let mut log = format!("{:?} ", object.topic);
if let Some(uniq) = &object.uniq {
log.push_str(&format!("({:?}) ", uniq));
write!(log, "({:?}) ", uniq).expect("out of memory");
}
log.push_str(&format!("@ {}", object.time));
write!(log, "@ {}", object.time).expect("out of memory");
if let (Some(ref lat), Some(ref lon)) = (object.latitude, object.longitude) {
log.push_str(&format!(" ({}, {}", lat, lon));
write!(log, " ({}, {}", lat, lon).expect("out of memory");
if let Some(radius) = &object.radius {
log.push_str(&format!(" | {}m", radius));
write!(log, " | {}m", radius).expect("out of memory");
}
log.push(')');
}
if verbose > 0 {
log.push_str(&format!(": {}", object.content));
write!(log, ": {}", object.content).expect("out of memory");
}
spinner.log(&log);
@@ -487,6 +488,7 @@ pub fn spawn(rl: &mut Shell,
tx.send(Event2::Start);
let event = match ipc::parent::run(module, &tx, arg, keyring, verbose, has_stdin, proxy, user_agent, options, blobs) {
Ok(exit) => exit,
// TODO: this should include the whole error chain
Err(err) => ExitEvent::SetupFailed(err.to_string()),
};
tx.send(Event2::Exit(event));