2021-05-30 14:17:13 +02:00
# include <Log.h>
# include <TAPIInlineQuery.h>
# include <TAPIMarkup.h>
# include <TAPIManager.h>
# include <functional> //std bind
# include <signal.h> // signal
# include <fstream>
2021-07-31 11:00:28 +02:00
# include <sched.h> //unshare
# include <unistd.h> //getpid
# include <sys/mount.h> // umount
# include <sys/prctl.h>
# include <seccomp.h>
# include <fcntl.h>
# include <sys/capability.h>
2021-05-30 14:17:13 +02:00
# include <nlohmann/json.hpp>
using json = nlohmann : : json ;
# include "bot.h"
static bool run = true ;
void sig_handler ( int sig_num ) {
Log : : info < < " signalHandler triggered " ;
run = false ;
( void ) sig_num ;
}
class CommandStart : public TelegramAPI : : Command {
public :
CommandStart ( ) : TelegramAPI : : Command ( " /start " ) { }
virtual bool process ( TelegramAPI : : Manager * m , const TelegramAPI : : Message & msg ) {
TelegramAPI : : InlineKeyboard kb ;
kb . addButton ( TelegramAPI : : InlineButton : : createSwitchInlineQuery ( " Open in Chat " ) , 0 ) ;
return m - > sendMessage ( msg . chat . id , " This bot is inline only. " , kb ) ;
}
} ;
2021-07-31 11:00:28 +02:00
static bool enableSecurity ( ) {
// create new mount and user namespace
if ( unshare ( CLONE_NEWUSER | CLONE_NEWNS ) = = - 1 ) {
Log : : warn < < " unsahre(NEWUSER|NEWNS) failed: " < < strerror ( errno ) ;
}
Log : : info < < " new userid: " < < getuid ( ) ;
// chroot in current directory
if ( chroot ( " ./ " ) = = - 1 ) {
Log : : fatal < < " chroot failed " < < strerror ( errno ) ;
return false ;
}
//setup seccomp
scmp_filter_ctx scmp = seccomp_init ( SCMP_ACT_KILL_PROCESS ) ;
if ( ! scmp ) {
Log : : fatal < < " init seccmp failed " ;
return false ;
}
seccomp_rule_add ( scmp , SCMP_ACT_ALLOW , SCMP_SYS ( brk ) , 0 ) ;
seccomp_rule_add ( scmp , SCMP_ACT_ALLOW , SCMP_SYS ( poll ) , 0 ) ;
seccomp_rule_add ( scmp , SCMP_ACT_ALLOW , SCMP_SYS ( openat ) , 1 , SCMP_A2_64 ( SCMP_CMP_MASKED_EQ , ~ ( O_RDONLY | O_NONBLOCK | O_CLOEXEC ) , 0 ) ) ; // datein nur readonly und ggf nonblock öffnen
seccomp_rule_add ( scmp , SCMP_ACT_ALLOW , SCMP_SYS ( read ) , 0 ) ;
seccomp_rule_add ( scmp , SCMP_ACT_ALLOW , SCMP_SYS ( write ) , 0 ) ;
seccomp_rule_add ( scmp , SCMP_ACT_ALLOW , SCMP_SYS ( stat ) , 0 ) ;
seccomp_rule_add ( scmp , SCMP_ACT_ALLOW , SCMP_SYS ( close ) , 0 ) ;
seccomp_rule_add ( scmp , SCMP_ACT_ALLOW , SCMP_SYS ( exit ) , 0 ) ;
seccomp_rule_add ( scmp , SCMP_ACT_ALLOW , SCMP_SYS ( exit_group ) , 0 ) ;
seccomp_rule_add ( scmp , SCMP_ACT_ALLOW , SCMP_SYS ( rt_sigaction ) , 0 ) ;
2021-08-10 03:05:42 +02:00
seccomp_rule_add ( scmp , SCMP_ACT_ALLOW , SCMP_SYS ( writev ) , 0 ) ;
seccomp_rule_add ( scmp , SCMP_ACT_ALLOW , SCMP_SYS ( readv ) , 0 ) ;
seccomp_rule_add ( scmp , SCMP_ACT_ALLOW , SCMP_SYS ( pwritev ) , 0 ) ;
seccomp_rule_add ( scmp , SCMP_ACT_ALLOW , SCMP_SYS ( preadv ) , 0 ) ;
seccomp_rule_add ( scmp , SCMP_ACT_ALLOW , SCMP_SYS ( pwritev2 ) , 0 ) ;
seccomp_rule_add ( scmp , SCMP_ACT_ALLOW , SCMP_SYS ( preadv2 ) , 0 ) ;
2021-08-10 15:21:08 +02:00
seccomp_rule_add ( scmp , SCMP_ACT_ALLOW , SCMP_SYS ( restart_syscall ) , 0 ) ;
2021-08-11 19:51:08 +02:00
seccomp_rule_add ( scmp , SCMP_ACT_ALLOW , SCMP_SYS ( futex ) , 0 ) ;
2021-10-17 14:43:21 +02:00
seccomp_rule_add ( scmp , SCMP_ACT_ALLOW , SCMP_SYS ( connect ) , 0 ) ;
2021-08-20 17:58:24 +02:00
seccomp_rule_add ( scmp , SCMP_ACT_ALLOW , SCMP_SYS ( socketpair ) , 0 ) ; // what?
2021-10-17 14:43:21 +02:00
seccomp_rule_add ( scmp , SCMP_ACT_ALLOW , SCMP_SYS ( socket ) , 0 ) ;
seccomp_rule_add ( scmp , SCMP_ACT_ALLOW , SCMP_SYS ( setsockopt ) , 0 ) ;
seccomp_rule_add ( scmp , SCMP_ACT_ALLOW , SCMP_SYS ( getsockopt ) , 0 ) ;
seccomp_rule_add ( scmp , SCMP_ACT_ALLOW , SCMP_SYS ( set_robust_list ) , 0 ) ;
seccomp_rule_add ( scmp , SCMP_ACT_ALLOW , SCMP_SYS ( get_robust_list ) , 0 ) ;
2021-10-23 18:46:56 +02:00
seccomp_rule_add ( scmp , SCMP_ACT_ALLOW , SCMP_SYS ( sendmmsg ) , 0 ) ;
seccomp_rule_add ( scmp , SCMP_ACT_ALLOW , SCMP_SYS ( sendmsg ) , 0 ) ;
2021-10-17 14:43:21 +02:00
seccomp_rule_add ( scmp , SCMP_ACT_ALLOW , SCMP_SYS ( uname ) , 0 ) ;
2021-08-20 17:58:24 +02:00
seccomp_rule_add ( scmp , SCMP_ACT_ALLOW , SCMP_SYS ( clone ) , 0 ) ; // curl wants to spawn threads
2021-08-29 11:49:42 +02:00
seccomp_rule_add ( scmp , SCMP_ACT_ALLOW , SCMP_SYS ( mmap ) , 0 ) ;
seccomp_rule_add ( scmp , SCMP_ACT_ALLOW , SCMP_SYS ( munmap ) , 0 ) ;
2021-08-10 15:21:08 +02:00
2021-07-31 11:00:28 +02:00
//apply seccomp
int err = seccomp_load ( scmp ) ;
if ( err ! = 0 ) {
seccomp_release ( scmp ) ;
Log : : fatal < < " could not load seccomp " < < strerror ( err ) ;
return false ;
}
seccomp_release ( scmp ) ;
/*
//drop all capabilities and apply nobody uid
const uid_t nobody = 65534 ;
const gid_t groups [ ] = { 65534 } ;
if ( cap_setgroups ( groups [ 0 ] , 1 , groups ) ! = 0 ) {
Log : : fatal < < " cap_setgroups() failed: " < < strerror ( errno ) ;
return false ;
}
if ( cap_setuid ( nobody ) ! = 0 ) {
Log : : fatal < < " cap_setuid() failed: " < < strerror ( errno ) ;
return false ;
}
if ( cap_set_mode ( CAP_MODE_NOPRIV ) ! = 0 ) {
Log : : fatal < < " cap_set_mode(CAP_MODE_NOPRIV) failed: " < < strerror ( errno ) ;
return false ;
}
*/
2021-08-10 03:05:42 +02:00
2021-07-31 11:00:28 +02:00
return true ;
}
2021-05-30 14:17:13 +02:00
int main ( int argc , const char * * argv ) {
Log : : init ( ) ;
Log : : setConsoleLogLevel ( Log : : Level : : TRACE ) ;
Log : : addLogfile ( " log.txt " , Log : : Level : : WARN ) ;
# if __unix__
Log : : setColoredOutput ( true ) ;
# endif
2021-07-31 11:00:28 +02:00
Log : : info < < " Hello, World! pid: " < < getpid ( ) < < " userid: " < < getuid ( ) ;
2021-05-30 14:17:13 +02:00
//read config
std : : ifstream configfile ( " config.json " ) ;
json j ;
configfile > > j ;
FontBot bot ;
TelegramAPI : : Manager tapi ( j [ " telegram " ] [ " apikey " ] ) ;
2021-07-31 11:00:28 +02:00
if ( ! enableSecurity ( ) )
return 1 ;
// test seccomp settings
// Log::info << "try to open this file";
// int fd = open(argv[0], O_WRONLY);
// Log::fatal << "ok";
2021-05-30 14:17:13 +02:00
std : : unique_ptr < TelegramAPI : : Command > cmd ( new CommandStart ( ) ) ;
tapi . registerCommand ( std : : move ( cmd ) ) ;
namespace pl = std : : placeholders ;
tapi . setInlineQueryHandler ( std : : bind ( & FontBot : : handleInline , & bot , pl : : _1 , pl : : _2 ) ) ;
signal ( SIGINT , sig_handler ) ;
while ( run ) {
tapi . getUpdates ( ) ;
}
Log : : stop ( ) ;
return 0 ;
}
2021-08-29 11:49:42 +02:00