* Added useradd and passwd tools. They allow adding new users and
changing a user's password, like on other platforms (just a bit more bare-bones :-)). * Moved login from src/bin/network/login/ to src/bin/multiuser/. * login correctly checks the shadow password now. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@25041 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -181,6 +181,7 @@ SubInclude HAIKU_TOP src bin make ;
|
|||||||
SubInclude HAIKU_TOP src bin makebootable ;
|
SubInclude HAIKU_TOP src bin makebootable ;
|
||||||
#SubInclude HAIKU_TOP src bin makeudfimage ;
|
#SubInclude HAIKU_TOP src bin makeudfimage ;
|
||||||
SubInclude HAIKU_TOP src bin mkdos ;
|
SubInclude HAIKU_TOP src bin mkdos ;
|
||||||
|
SubInclude HAIKU_TOP src bin multiuser ;
|
||||||
SubInclude HAIKU_TOP src bin patch ;
|
SubInclude HAIKU_TOP src bin patch ;
|
||||||
SubInclude HAIKU_TOP src bin pc ;
|
SubInclude HAIKU_TOP src bin pc ;
|
||||||
SubInclude HAIKU_TOP src bin pcmcia-cs ;
|
SubInclude HAIKU_TOP src bin pcmcia-cs ;
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
SubDir HAIKU_TOP src bin multiuser ;
|
||||||
|
|
||||||
|
UsePrivateKernelHeaders ;
|
||||||
|
UsePrivateHeaders app ;
|
||||||
|
UsePrivateHeaders libroot ;
|
||||||
|
UsePrivateHeaders shared ;
|
||||||
|
|
||||||
|
StaticLibrary libmultiuser_utils.a : multiuser_utils.cpp ;
|
||||||
|
|
||||||
|
BinCommand login : login.cpp : libmultiuser_utils.a ;
|
||||||
|
|
||||||
|
BinCommand passwd : passwd.cpp : libmultiuser_utils.a ;
|
||||||
|
|
||||||
|
BinCommand useradd : useradd.cpp : libmultiuser_utils.a ;
|
||||||
|
|
||||||
|
# set set-uid bit on passwd
|
||||||
|
MODE on passwd = 04755 ;
|
||||||
@@ -19,6 +19,8 @@
|
|||||||
#include <termios.h>
|
#include <termios.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "multiuser_utils.h"
|
||||||
|
|
||||||
|
|
||||||
extern const char* __progname;
|
extern const char* __progname;
|
||||||
const char* kProgramName = __progname;
|
const char* kProgramName = __progname;
|
||||||
@@ -118,11 +120,12 @@ login(const char* user, struct passwd** _passwd)
|
|||||||
return status;
|
return status;
|
||||||
|
|
||||||
struct passwd* passwd = getpwnam(user);
|
struct passwd* passwd = getpwnam(user);
|
||||||
if (passwd == NULL || passwd->pw_passwd == NULL)
|
struct spwd* spwd = getspnam(user);
|
||||||
return B_ERROR;
|
|
||||||
|
|
||||||
// TODO: do a real password check!
|
bool ok = verify_password(passwd, spwd, password);
|
||||||
if (strcmp(password, passwd->pw_passwd))
|
memset(password, 0, sizeof(password));
|
||||||
|
|
||||||
|
if (!ok)
|
||||||
return B_PERMISSION_DENIED;
|
return B_PERMISSION_DENIED;
|
||||||
|
|
||||||
*_passwd = passwd;
|
*_passwd = passwd;
|
||||||
@@ -0,0 +1,167 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2008, Ingo Weinhold, [email protected]. All Rights Reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "multiuser_utils.h"
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <termios.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <AutoDeleter.h>
|
||||||
|
|
||||||
|
#include <user_group.h>
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
read_password(const char* prompt, char* password, size_t bufferSize,
|
||||||
|
bool useStdio)
|
||||||
|
{
|
||||||
|
FILE* in = stdin;
|
||||||
|
FILE* out = stdout;
|
||||||
|
|
||||||
|
// open tty
|
||||||
|
FILE* tty = NULL;
|
||||||
|
if (!useStdio) {
|
||||||
|
// TODO: Open tty with O_NOCTTY!
|
||||||
|
tty = fopen("/dev/tty", "w+");
|
||||||
|
if (tty == NULL) {
|
||||||
|
fprintf(stderr, "Error: Failed to open tty: %s\n", strerror(errno));
|
||||||
|
return errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
in = tty;
|
||||||
|
out = tty;
|
||||||
|
}
|
||||||
|
CObjectDeleter<FILE, int> ttyCloser(tty, fclose);
|
||||||
|
|
||||||
|
// disable echo
|
||||||
|
int inFD = fileno(in);
|
||||||
|
struct termios termAttrs;
|
||||||
|
if (tcgetattr(inFD, &termAttrs) != 0) {
|
||||||
|
fprintf(in, "Error: Failed to get tty attributes: %s\n",
|
||||||
|
strerror(errno));
|
||||||
|
return errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
tcflag_t localFlags = termAttrs.c_lflag;
|
||||||
|
termAttrs.c_lflag &= ~ECHO;
|
||||||
|
|
||||||
|
if (tcsetattr(inFD, TCSANOW, &termAttrs) != 0) {
|
||||||
|
fprintf(in, "Error: Failed to set tty attributes: %s\n",
|
||||||
|
strerror(errno));
|
||||||
|
return errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t error = B_OK;
|
||||||
|
|
||||||
|
// prompt and read pwd
|
||||||
|
fprintf(out, prompt);
|
||||||
|
fflush(out);
|
||||||
|
|
||||||
|
if (fgets(password, bufferSize, in) == NULL) {
|
||||||
|
fprintf(out, "\nError: Failed to read from tty: %s\n", strerror(errno));
|
||||||
|
error = errno != 0 ? errno : B_ERROR;
|
||||||
|
} else
|
||||||
|
fputc('\n', out);
|
||||||
|
|
||||||
|
// chop off trailing newline
|
||||||
|
if (error == B_OK) {
|
||||||
|
size_t len = strlen(password);
|
||||||
|
if (len > 0 && password[len - 1] == '\n')
|
||||||
|
password[len - 1] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
// restore the terminal attributes
|
||||||
|
termAttrs.c_lflag = localFlags;
|
||||||
|
tcsetattr(inFD, TCSANOW, &termAttrs);
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool
|
||||||
|
verify_password(passwd* passwd, spwd* spwd, const char* plainPassword)
|
||||||
|
{
|
||||||
|
if (passwd == NULL)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// check whether we need to check the shadow password
|
||||||
|
const char* requiredPassword = passwd->pw_passwd;
|
||||||
|
if (strcmp(requiredPassword, "x") == 0) {
|
||||||
|
if (spwd == NULL) {
|
||||||
|
// Mmh, we're suppose to check the shadow password, but we don't
|
||||||
|
// have it. Bail out.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
requiredPassword = spwd->sp_pwdp;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If no password is required, we're done.
|
||||||
|
if (requiredPassword == NULL || strlen(requiredPassword) == 0)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// crypt and check it
|
||||||
|
char* encryptedPassword = crypt(plainPassword, requiredPassword);
|
||||||
|
|
||||||
|
return (strcmp(encryptedPassword, requiredPassword) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! Checks whether the user needs to authenticate with a password, and, if
|
||||||
|
necessary, asks for it, and checks it.
|
||||||
|
\a passwd must always be given, \a spwd only if there exists an entry
|
||||||
|
for the user.
|
||||||
|
*/
|
||||||
|
status_t
|
||||||
|
authenticate_user(const char* prompt, passwd* passwd, spwd* spwd, int maxTries,
|
||||||
|
bool useStdio)
|
||||||
|
{
|
||||||
|
// check whether a password is need at all
|
||||||
|
if (verify_password(passwd, spwd, ""))
|
||||||
|
return B_OK;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
// prompt the user for the password
|
||||||
|
char plainPassword[MAX_SHADOW_PWD_PASSWORD_LEN];
|
||||||
|
status_t error = read_password(prompt, plainPassword,
|
||||||
|
sizeof(plainPassword), useStdio);
|
||||||
|
if (error != B_OK)
|
||||||
|
return error;
|
||||||
|
|
||||||
|
// check it
|
||||||
|
bool ok = verify_password(passwd, spwd, plainPassword);
|
||||||
|
memset(plainPassword, 0, sizeof(plainPassword));
|
||||||
|
if (ok)
|
||||||
|
return B_OK;
|
||||||
|
|
||||||
|
fprintf(stderr, "Incorrect password.\n");
|
||||||
|
if (--maxTries <= 0)
|
||||||
|
return B_PERMISSION_DENIED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
authenticate_user(const char* prompt, const char* user, passwd** _passwd,
|
||||||
|
spwd** _spwd, int maxTries, bool useStdio)
|
||||||
|
{
|
||||||
|
struct passwd* passwd = getpwnam(user);
|
||||||
|
struct spwd* spwd = getspnam(user);
|
||||||
|
|
||||||
|
status_t error = authenticate_user(prompt, passwd, spwd, maxTries,
|
||||||
|
useStdio);
|
||||||
|
if (error == B_OK) {
|
||||||
|
if (_passwd)
|
||||||
|
*_passwd = passwd;
|
||||||
|
if (_spwd)
|
||||||
|
*_spwd = spwd;
|
||||||
|
}
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2008, Ingo Weinhold, [email protected]. All Rights Reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef MULTIUSER_UTILS_H
|
||||||
|
#define MULTIUSER_UTILS_H
|
||||||
|
|
||||||
|
#include <pwd.h>
|
||||||
|
#include <shadow.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <SupportDefs.h>
|
||||||
|
|
||||||
|
|
||||||
|
status_t read_password(const char* prompt, char* password, size_t bufferSize,
|
||||||
|
bool useStdio);
|
||||||
|
|
||||||
|
bool verify_password(passwd* passwd, spwd* spwd, const char* plainPassword);
|
||||||
|
|
||||||
|
status_t authenticate_user(const char* prompt, passwd* passwd, spwd* spwd,
|
||||||
|
int maxTries, bool useStdio);
|
||||||
|
status_t authenticate_user(const char* prompt, const char* user,
|
||||||
|
passwd** _passwd, spwd** _spwd, int maxTries, bool useStdio);
|
||||||
|
|
||||||
|
|
||||||
|
#endif // MULTIUSER_UTILS_H
|
||||||
@@ -0,0 +1,145 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2008, Ingo Weinhold, [email protected]. All Rights Reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <pwd.h>
|
||||||
|
#include <shadow.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <termios.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <OS.h>
|
||||||
|
|
||||||
|
#include <RegistrarDefs.h>
|
||||||
|
#include <user_group.h>
|
||||||
|
#include <util/KMessage.h>
|
||||||
|
|
||||||
|
#include <AutoDeleter.h>
|
||||||
|
|
||||||
|
#include "multiuser_utils.h"
|
||||||
|
|
||||||
|
|
||||||
|
extern const char *__progname;
|
||||||
|
|
||||||
|
|
||||||
|
static const char* kUsage =
|
||||||
|
"Usage: %s [ <user name> ]\n"
|
||||||
|
;
|
||||||
|
|
||||||
|
static void
|
||||||
|
print_usage_and_exit(bool error)
|
||||||
|
{
|
||||||
|
fprintf(error ? stderr : stdout, kUsage, __progname);
|
||||||
|
exit(error ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, const char* const* argv)
|
||||||
|
{
|
||||||
|
if (argc > 2)
|
||||||
|
print_usage_and_exit(true);
|
||||||
|
|
||||||
|
const char* user = NULL;
|
||||||
|
if (argc == 2)
|
||||||
|
user = argv[1];
|
||||||
|
|
||||||
|
if (geteuid() != 0) {
|
||||||
|
fprintf(stderr, "Error: You need to be root.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// this is a set-uid tool -- get the real UID
|
||||||
|
uid_t uid = getuid();
|
||||||
|
|
||||||
|
// get the passwd entry
|
||||||
|
struct passwd* passwd;
|
||||||
|
if (user != NULL) {
|
||||||
|
passwd = getpwnam(user);
|
||||||
|
if (passwd == NULL) {
|
||||||
|
fprintf(stderr, "Error: No user with name \"%s\".\n", user);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (uid != 0 && passwd->pw_uid != uid) {
|
||||||
|
fprintf(stderr, "Error: Only root can change the passwd for other "
|
||||||
|
"users.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
passwd = getpwuid(uid);
|
||||||
|
if (passwd == NULL) {
|
||||||
|
fprintf(stderr, "Error: Ugh! Couldn't get passwd entry for uid "
|
||||||
|
"%d.\n", uid);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
user = passwd->pw_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if not root, the user needs to authenticate
|
||||||
|
if (uid != 0) {
|
||||||
|
if (authenticate_user("old password: ", passwd, getspnam(user), 1,
|
||||||
|
false) != B_OK) {
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// read new password
|
||||||
|
char password[LINE_MAX];
|
||||||
|
if (read_password("new password: ", password, sizeof(password), false)
|
||||||
|
!= B_OK) {
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strlen(password) >= MAX_SHADOW_PWD_PASSWORD_LEN) {
|
||||||
|
fprintf(stderr, "Error: The password is too long.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// read password again
|
||||||
|
char repeatedPassword[LINE_MAX];
|
||||||
|
if (read_password("repeat new password: ", repeatedPassword,
|
||||||
|
sizeof(repeatedPassword), false) != B_OK) {
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// passwords need to match
|
||||||
|
if (strcmp(password, repeatedPassword) != 0) {
|
||||||
|
fprintf(stderr, "Error: passwords don't match\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(repeatedPassword, 0, sizeof(repeatedPassword));
|
||||||
|
|
||||||
|
// crypt it
|
||||||
|
char* encryptedPassword;
|
||||||
|
if (strlen(password) > 0) {
|
||||||
|
encryptedPassword = crypt(password, user);
|
||||||
|
memset(password, 0, sizeof(password));
|
||||||
|
} else
|
||||||
|
encryptedPassword = password;
|
||||||
|
|
||||||
|
// prepare request for the registrar
|
||||||
|
KMessage message(BPrivate::B_REG_UPDATE_USER);
|
||||||
|
if (message.AddInt32("uid", passwd->pw_uid) != B_OK
|
||||||
|
|| message.AddString("password", "x") != B_OK
|
||||||
|
|| message.AddString("shadow password", encryptedPassword) != B_OK) {
|
||||||
|
fprintf(stderr, "Error: Out of memory!\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// send the request
|
||||||
|
KMessage reply;
|
||||||
|
status_t error = send_authentication_request_to_registrar(message, reply);
|
||||||
|
if (error != B_OK) {
|
||||||
|
fprintf(stderr, "Error: Failed to create user: %s\n", strerror(error));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,192 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2008, Ingo Weinhold, [email protected]. All Rights Reserved.
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <getopt.h>
|
||||||
|
#include <pwd.h>
|
||||||
|
#include <shadow.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <termios.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <OS.h>
|
||||||
|
#include <parsedate.h>
|
||||||
|
|
||||||
|
#include <RegistrarDefs.h>
|
||||||
|
#include <user_group.h>
|
||||||
|
#include <util/KMessage.h>
|
||||||
|
|
||||||
|
#include <AutoDeleter.h>
|
||||||
|
|
||||||
|
#include "multiuser_utils.h"
|
||||||
|
|
||||||
|
|
||||||
|
extern const char *__progname;
|
||||||
|
|
||||||
|
|
||||||
|
static const char* kUsage =
|
||||||
|
"Usage: %s [ -d <home> ] [ -e <expiration> ] [ -f <inactive> ] [ -g <gid> ]\n"
|
||||||
|
" [ -s <shell> ] [ -n <real name> ]\n"
|
||||||
|
;
|
||||||
|
|
||||||
|
static void
|
||||||
|
print_usage_and_exit(bool error)
|
||||||
|
{
|
||||||
|
fprintf(error ? stderr : stdout, kUsage, __progname);
|
||||||
|
exit(error ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, const char* const* argv)
|
||||||
|
{
|
||||||
|
const char* home = "/boot/home";
|
||||||
|
int expiration = 99999;
|
||||||
|
int inactive = -1;
|
||||||
|
gid_t gid = 100;
|
||||||
|
const char* shell = "/bin/sh";
|
||||||
|
const char* realName = "";
|
||||||
|
|
||||||
|
int min = -1;
|
||||||
|
int max = -1;
|
||||||
|
int warn = 7;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
static struct option sLongOptions[] = {
|
||||||
|
{ "help", no_argument, 0, 'h' },
|
||||||
|
{ 0, 0, 0, 0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
opterr = 0; // don't print errors
|
||||||
|
int c = getopt_long(argc, (char**)argv, "d:e:f:g:hn:s:", sLongOptions,
|
||||||
|
NULL);
|
||||||
|
if (c == -1)
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
switch (c) {
|
||||||
|
case 'd':
|
||||||
|
home = optarg;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'e':
|
||||||
|
expiration = parsedate(optarg, time(NULL)) / (3600 * 24);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'f':
|
||||||
|
inactive = atoi(optarg);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'g':
|
||||||
|
gid = atoi(optarg);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'h':
|
||||||
|
print_usage_and_exit(false);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'n':
|
||||||
|
realName = optarg;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 's':
|
||||||
|
shell = optarg;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
print_usage_and_exit(true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (optind != argc - 1)
|
||||||
|
print_usage_and_exit(true);
|
||||||
|
|
||||||
|
const char* user = argv[optind];
|
||||||
|
|
||||||
|
if (geteuid() != 0) {
|
||||||
|
fprintf(stderr, "Error: You need to be root.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// check, if user already exists
|
||||||
|
if (getpwnam(user) != NULL) {
|
||||||
|
fprintf(stderr, "Error: User \"%s\" already exists.\n", user);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// read password
|
||||||
|
char password[LINE_MAX];
|
||||||
|
if (read_password("password for user: ", password, sizeof(password),
|
||||||
|
false) != B_OK) {
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strlen(password) >= MAX_SHADOW_PWD_PASSWORD_LEN) {
|
||||||
|
fprintf(stderr, "Error: The password is too long.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// read password again
|
||||||
|
char repeatedPassword[LINE_MAX];
|
||||||
|
if (read_password("repeat password: ", repeatedPassword,
|
||||||
|
sizeof(repeatedPassword), false) != B_OK) {
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// passwords need to match
|
||||||
|
if (strcmp(password, repeatedPassword) != 0) {
|
||||||
|
fprintf(stderr, "Error: passwords don't match\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(repeatedPassword, 0, sizeof(repeatedPassword));
|
||||||
|
|
||||||
|
// crypt it
|
||||||
|
char* encryptedPassword;
|
||||||
|
if (strlen(password) > 0) {
|
||||||
|
encryptedPassword = crypt(password, user);
|
||||||
|
memset(password, 0, sizeof(password));
|
||||||
|
} else
|
||||||
|
encryptedPassword = password;
|
||||||
|
|
||||||
|
// find an unused UID
|
||||||
|
uid_t uid = 1000;
|
||||||
|
while (getpwuid(uid) != NULL)
|
||||||
|
uid++;
|
||||||
|
|
||||||
|
// prepare request for the registrar
|
||||||
|
KMessage message(BPrivate::B_REG_UPDATE_USER);
|
||||||
|
if (message.AddInt32("uid", uid) != B_OK
|
||||||
|
|| message.AddInt32("gid", gid) != B_OK
|
||||||
|
|| message.AddString("name", user) != B_OK
|
||||||
|
|| message.AddString("password", "x") != B_OK
|
||||||
|
|| message.AddString("home", home) != B_OK
|
||||||
|
|| message.AddString("shell", shell) != B_OK
|
||||||
|
|| message.AddString("real name", realName) != B_OK
|
||||||
|
|| message.AddString("shadow password", encryptedPassword) != B_OK
|
||||||
|
|| message.AddInt32("min", min) != B_OK
|
||||||
|
|| message.AddInt32("max", max) != B_OK
|
||||||
|
|| message.AddInt32("warn", warn) != B_OK
|
||||||
|
|| message.AddInt32("inactive", inactive) != B_OK
|
||||||
|
|| message.AddInt32("expiration", expiration) != B_OK
|
||||||
|
|| message.AddInt32("flags", 0) != B_OK
|
||||||
|
|| message.AddBool("add user", true) != B_OK) {
|
||||||
|
fprintf(stderr, "Error: Out of memory!\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// send the request
|
||||||
|
KMessage reply;
|
||||||
|
status_t error = send_authentication_request_to_registrar(message, reply);
|
||||||
|
if (error != B_OK) {
|
||||||
|
fprintf(stderr, "Error: Failed to create user: %s\n", strerror(error));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -5,7 +5,6 @@ SubInclude HAIKU_TOP src bin network atftpd ;
|
|||||||
SubInclude HAIKU_TOP src bin network ftp ;
|
SubInclude HAIKU_TOP src bin network ftp ;
|
||||||
SubInclude HAIKU_TOP src bin network ftpd ;
|
SubInclude HAIKU_TOP src bin network ftpd ;
|
||||||
SubInclude HAIKU_TOP src bin network ifconfig ;
|
SubInclude HAIKU_TOP src bin network ifconfig ;
|
||||||
SubInclude HAIKU_TOP src bin network login ;
|
|
||||||
SubInclude HAIKU_TOP src bin network mount_nfs ;
|
SubInclude HAIKU_TOP src bin network mount_nfs ;
|
||||||
SubInclude HAIKU_TOP src bin network nc ;
|
SubInclude HAIKU_TOP src bin network nc ;
|
||||||
SubInclude HAIKU_TOP src bin network netstat ;
|
SubInclude HAIKU_TOP src bin network netstat ;
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
SubDir HAIKU_TOP src bin network login ;
|
|
||||||
|
|
||||||
BinCommand login :
|
|
||||||
login.cpp
|
|
||||||
;
|
|
||||||
Reference in New Issue
Block a user