130 lines
4.5 KiB
C
130 lines
4.5 KiB
C
|
/*
|
||
|
RegisterEmail A webservice for selfhosted email servers to make it easy registering Emails (And optionally Enabling SSH)
|
||
|
Copyright (C) 2024 Mike Nolan
|
||
|
|
||
|
This program is free software: you can redistribute it and/or modify
|
||
|
it under the terms of the GNU General Public License as published by
|
||
|
the Free Software Foundation, either version 3 of the License, or
|
||
|
(at your option) any later version.
|
||
|
|
||
|
This program is distributed in the hope that it will be useful,
|
||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
GNU General Public License for more details.
|
||
|
|
||
|
You should have received a copy of the GNU General Public License
|
||
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||
|
*/
|
||
|
#include <jansson.h>
|
||
|
#include <stdio.h>
|
||
|
#include <sysexits.h>
|
||
|
#include <string.h>
|
||
|
#include <sys/types.h>
|
||
|
#include <pwd.h>
|
||
|
#include <shadow.h>
|
||
|
#include <crypt.h>
|
||
|
#include <stdbool.h>
|
||
|
const char* required_user = "tesses";
|
||
|
const char* mail = "mail";
|
||
|
const char* deny_group = "no_ssh";
|
||
|
const char* sudoer_group = "sudo";
|
||
|
void create_user(const char* username, const char* password, const char* fullname)
|
||
|
{
|
||
|
char cmdline[1024];
|
||
|
snprintf(cmdline,sizeof(cmdline),"/sbin/adduser %s",username);
|
||
|
FILE* f=popen(cmdline,"w");
|
||
|
fprintf(f,"%s\n%s\n%s\n\n\n\n\ny\n",password,password,fullname);
|
||
|
fflush(f);
|
||
|
fclose(f);
|
||
|
|
||
|
snprintf(cmdline,sizeof(cmdline),"/sbin/usermod -aG %s %s",mail, username);
|
||
|
system(cmdline);
|
||
|
}
|
||
|
void block_ssh(const char* username)
|
||
|
{
|
||
|
char cmdline[1024];
|
||
|
snprintf(cmdline,sizeof(cmdline),"/sbin/usermod -aG %s %s",deny_group,username);
|
||
|
system(cmdline);
|
||
|
}
|
||
|
|
||
|
void enable_sudo(const char* username)
|
||
|
{
|
||
|
char cmdline[1024];
|
||
|
snprintf(cmdline,sizeof(cmdline),"/sbin/usermod -aG %s %s",sudoer_group,username);
|
||
|
system(cmdline);
|
||
|
}
|
||
|
//https://stackoverflow.com/a/63173069
|
||
|
bool password_correct(const char* user, const char* password)
|
||
|
{
|
||
|
struct passwd* passwdEntry = getpwnam( user );
|
||
|
if ( !passwdEntry )
|
||
|
{
|
||
|
printf( "User '%s' doesn't exist\n", user );
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
if ( 0 != strcmp( passwdEntry->pw_passwd, "x" ) )
|
||
|
{
|
||
|
return strcmp( passwdEntry->pw_passwd, crypt( password, passwdEntry->pw_passwd ) ) == 0;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// password is in shadow file
|
||
|
struct spwd* shadowEntry = getspnam( user );
|
||
|
if ( !shadowEntry )
|
||
|
{
|
||
|
printf( "Failed to read shadow entry for user '%s'\n", user );
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
return strcmp( shadowEntry->sp_pwdp, crypt( password, shadowEntry->sp_pwdp ) ) == 0;
|
||
|
}
|
||
|
}
|
||
|
int main(int argc,char** argv)
|
||
|
{
|
||
|
struct json_t* json=json_loadf(stdin,0,NULL);
|
||
|
if(json)
|
||
|
{
|
||
|
struct json_t* username= json_object_get(json,"username");
|
||
|
struct json_t* password=json_object_get(json,"password");
|
||
|
struct json_t* admin_username = json_object_get(json,"admin_user");
|
||
|
struct json_t* admin_password = json_object_get(json,"admin_pass");
|
||
|
struct json_t* full_name = json_object_get(json,"fullname");
|
||
|
struct json_t* has_sudo = json_object_get(json,"has_sudo");
|
||
|
struct json_t* can_login_ssh = json_object_get(json,"can_login_ssh");
|
||
|
|
||
|
if(json_typeof(username) == JSON_STRING && json_typeof(password) == JSON_STRING && json_typeof(admin_username) == JSON_STRING && json_typeof(admin_password) == JSON_STRING && json_typeof(full_name) == JSON_STRING)
|
||
|
{
|
||
|
if(json_string_length(username) > 256) return 1;
|
||
|
const char* _username = json_string_value(username);
|
||
|
const char* _password = json_string_value(password);
|
||
|
const char* _admin_user = json_string_value(admin_username);
|
||
|
const char* _admin_pass = json_string_value(admin_password);
|
||
|
const char* _fullname = json_string_value(full_name);
|
||
|
if(strcmp(_admin_user,required_user) != 0 || !password_correct(_admin_user,_admin_pass))
|
||
|
{
|
||
|
return EX_NOPERM;
|
||
|
}
|
||
|
create_user(_username,_password,_fullname);
|
||
|
if(json_typeof(has_sudo) == JSON_TRUE)
|
||
|
{
|
||
|
enable_sudo(_username);
|
||
|
}
|
||
|
|
||
|
if(json_typeof(can_login_ssh) == JSON_FALSE)
|
||
|
{
|
||
|
block_ssh(_username);
|
||
|
}
|
||
|
|
||
|
json_decref(json);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
json_decref(json);
|
||
|
|
||
|
return EX_DATAERR;
|
||
|
}
|
||
|
return EX_DATAERR;
|
||
|
}
|