added sessvc as session supervisor

first code for password changing
This commit is contained in:
ilsimo 2007-04-07 16:20:08 +00:00
parent e9a9c8dc97
commit 9c4b9f8390
11 changed files with 514 additions and 81 deletions

View File

@ -6,8 +6,7 @@ SESMANOBJ = sesman.o config.o tcp.o sig.o session.o env.o \
scp.o scp_v0.o scp_v1.o thread.o lock.o \
$(LIBSCPOBJ)
SESRUNOBJ = sesrun.o config.o tcp.o lock.o \
os_calls.o d3des.o list.o file.o log.o
SESSVCOBJ = sessvc.o os_calls.o
DESTDIR = /usr/local/xrdp
CFGDIR = /etc/xrdp
@ -16,14 +15,15 @@ MANDIR = /usr/local/man
DOCDIR = /usr/doc/xrdp
DEFINES = -DSESMAN_CFG_FILE=\"$(CFGDIR)/sesman.ini\" \
-DSESMAN_PID_FILE=\"$(PIDDIR)/sesman.pid\" -DDEBUG
-DSESMAN_PID_FILE=\"$(PIDDIR)/sesman.pid\" \
-DSESMAN_SESSVC_FILE=\"$(DESTDIR)/sessvc\" \
-DDEBUG
CFLAGS = -Wall -O2 -I../common -I/usr/include/nptl $(DEFINES)
LDFLAGS = -L /usr/gnu/lib -I/usr/include/nptl -L/usr/lib/nptl -lpthread $(DEFINES)
LDFLAGS = -L /usr/gnu/lib -I/usr/include/nptl -L/usr/lib/nptl -lpthread -ldl $(DEFINES)
C_OS_FLAGS = $(CFLAGS) -c
CC = gcc
all: pam tools
nopam: no-pam tools
@ -31,35 +31,36 @@ nopam: no-pam tools
kerberos: kerberos-base tools
no-pam: $(SESMANOBJ) verify_user.o
$(CC) $(LDFLAGS) -o sesman $(SESMANOBJ) verify_user.o -ldl -lcrypt
$(CC) $(LDFLAGS) -o sesman $(SESMANOBJ) verify_user.o -lcrypt
pam: $(SESMANOBJ) verify_user_pam.o
$(CC) $(LDFLAGS) -o sesman $(SESMANOBJ) verify_user_pam.o -ldl -lpam
$(CC) $(LDFLAGS) -o sesman $(SESMANOBJ) verify_user_pam.o -lpam
pam_userpass: $(SESMANOBJ) verify_user_pam_userpass.o
$(CC) $(LDFLAGS) -o sesman $(SESMANOBJ) verify_user_pam_userpass.o -ldl -lpam -lpam_userpass
$(CC) $(LDFLAGS) -o sesman $(SESMANOBJ) verify_user_pam_userpass.o -lpam -lpam_userpass
kerberos-base: $(SESMANOBJ) verify_user_kerberos.o
$(CC) $(LDFLAGS) -o sesman $(SESMANOBJ) verify_user_kerberos.o -ldl -lkrb5
$(CC) $(LDFLAGS) -o sesman $(SESMANOBJ) verify_user_kerberos.o -lkrb5
tools: $(SESRUNOBJ)
$(CC) $(LDFLAGS) -o sesrun $(SESRUNOBJ) -ldl
sessvc: $(SESSVCOBJ)
$(CC) $(LDFLAGS) -o sessvc $(SESSVCOBJ)
tools: sessvc
make -C tools
clean:
rm -f $(SESMANOBJ) verify_user.o verify_user_pam.o verify_user_pam_userpass.o sesman sesrun.o sesrun
rm -f $(SESMANOBJ) verify_user.o verify_user_pam.o verify_user_pam_userpass.o sesman sesrun.o sesrun sessvc.o sessvc
make -C tools clean
install:
install sesman $(DESTDIR)/sesman
install sesrun $(DESTDIR)/sesrun
install startwm.sh $(DESTDIR)/startwm.sh
install sesman.ini $(CFGDIR)/sesman.ini
install sessvc $(DESTDIR)/sessvc
make -C tools install
installdeb:
install sesman $(DESTDIRDEB)/usr/lib/xrdp/sesman
install sesrun $(DESTDIRDEB)/usr/lib/xrdp/sesrun
install startwm.sh $(DESTDIRDEB)/usr/lib/xrdp/startwm.sh
install sesman.ini $(DESTDIRDEB)/etc/xrdp/sesman.ini

View File

@ -70,4 +70,31 @@ auth_end(long in_val);
int DEFAULT_CC
auth_set_env(long in_val);
#define AUTH_PWD_CHG_OK 0
#define AUTH_PWD_CHG_CHANGE 1
#define AUTH_PWD_CHG_CHANGE_MANDATORY 2
#define AUTH_PWD_CHG_NOT_NOW 3
#define AUTH_PWD_CHG_ERROR 4
/**
*
* @brief FIXME
* @param in_val
* @return 0 on success, 1 on failure
*
*/
int DEFAULT_CC
auth_check_pwd_chg(char* user);
/**
*
* @brief FIXME
* @param in_val
* @return 0 on success, 1 on failure
*
*/
int DEFAULT_CC
auth_change_pwd(char* user, char* newpwd);
#endif

View File

@ -50,4 +50,8 @@
#define SESMAN_PID_FILE "./sesman.pid"
#endif
#ifndef SESMAN_SESSVC_FILE
#define SESMAN_SESSVC_FILE "./sessvc"
#endif
#endif

View File

@ -1,4 +1,5 @@
[Globals]
ListenAddress=127.0.0.1
ListenPort=3350
EnableUserWindowManager=1
UserWindowManager=startwm.sh

View File

@ -28,6 +28,9 @@
#include "sesman.h"
#include "libscp_types.h"
//#include "unistd.h"
//#include "stdio.h"
extern unsigned char g_fixedkey[8];
extern struct config_sesman g_cfg; /* config.h */
struct session_chain* g_sessions;
@ -109,6 +112,46 @@ x_server_running(int display)
return x_running;
}
static void DEFAULT_CC
session_start_sessvc(int xpid, int wmpid, long data)
{
struct list* sessvc_params;
char text[256];
char wmpid_str[25];
char xpid_str[25];
/* new style waiting for clients */
g_sprintf(wmpid_str, "%d", wmpid);
g_sprintf(xpid_str, "%d", xpid);
log_message(LOG_LEVEL_INFO, "starting sessvc xpid=%s wmpid=%s ",xpid_str, wmpid_str);
sessvc_params = list_create();
sessvc_params->auto_free = 1;
/* building parameters */
list_add_item(sessvc_params, (long)g_strdup(SESMAN_SESSVC_FILE));
list_add_item(sessvc_params, (long)g_strdup(xpid_str));
list_add_item(sessvc_params, (long)g_strdup(wmpid_str));
list_add_item(sessvc_params, 0); /* mandatory */
g_execvp(SESMAN_SESSVC_FILE, ((char**)sessvc_params->items));
list_delete(sessvc_params);
//#warning FIXME sessvc PATH!!
//execlp("/usr/local/xrdp/sessvc", "/usr/local/xrdp/sessvc", xpid_str, wmpid_str, 0);
/* if we get here there's some error */
//strerror_r(errno, text, 255);
log_message(LOG_LEVEL_ALWAYS, "Error in execlp for sessvc: %s", text);
/* keep the old waitpid if some error occurs during execlp */
g_waitpid(wmpid);
g_sigterm(xpid);
g_sigterm(wmpid);
g_sleep(1000);
auth_end(data);
g_exit(0);
}
/******************************************************************************/
int DEFAULT_CC
session_start(int width, int height, int bpp, char* username, char* password,
@ -181,7 +224,7 @@ for user %s denied", username);
if (pid == -1)
{
}
else if (pid == 0) /* child */
else if (pid == 0) /* child sesman */
{
g_unset_signals();
auth_start_session(data, display);
@ -192,7 +235,7 @@ for user %s denied", username);
if (wmpid == -1)
{
}
else if (wmpid == 0) /* child */
else if (wmpid == 0) /* child (child sesman) xserver */
{
/* give X a bit to start */
g_sleep(1000);
@ -222,7 +265,7 @@ for user %s denied", username);
username, g_getpid());
g_exit(0);
}
else /* parent */
else /* parent (child sesman) */
{
xpid = g_fork();
if (xpid == -1)
@ -285,18 +328,14 @@ for user %s denied", username);
username, g_getpid());
g_exit(1);
}
else /* parent */
else /* parent (child sesman)*/
{
g_waitpid(wmpid);
g_sigterm(xpid);
g_sigterm(wmpid);
g_sleep(1000);
auth_end(data);
g_exit(0);
/* new style waiting for clients */
session_start_sessvc(xpid, wmpid, data);
}
}
}
else /* parent */
else /* parent sesman process */
{
/* let the other threads go on */
lock_fork_release();
@ -433,6 +472,36 @@ session_kill(int pid)
return SESMAN_SESSION_KILL_NOTFOUND;
}
/******************************************************************************/
void DEFAULT_CC
session_sigkill_all()
{
struct session_chain* tmp;
/*THREAD-FIX require chain lock */
lock_chain_acquire();
tmp=g_sessions;
while (tmp != 0)
{
if (tmp->item == 0)
{
log_message(LOG_LEVEL_ERROR, "found null session descriptor!");
}
else
{
g_sigterm(tmp->item->pid);
}
/* go on */
tmp=tmp->next;
}
/*THREAD-FIX release chain lock */
lock_chain_release();
}
/******************************************************************************/
struct session_item* DEFAULT_CC
session_get_bypid(int pid)

View File

@ -103,6 +103,15 @@ session_start(int width, int height, int bpp, char* username, char* password,
int DEFAULT_CC
session_kill(int pid);
/**
*
* @brief sends sigkill to all sessions
* @return
*
*/
void DEFAULT_CC
session_sigkill_all();
/**
*
* @brief retrieves a session's descriptor

68
sesman/sessvc.c Normal file
View File

@ -0,0 +1,68 @@
/*
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 2 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, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
xrdp: A Remote Desktop Protocol server.
Copyright (C) Jay Sorg 2005-2007
*/
/**
*
* @file sessvc.c
* @brief Session supervisor
* @author Simone Fedele
*
*/
#include "os_calls.h"
#include "arch.h"
#include "log.h"
#include <sys/types.h>
#include <errno.h>
pid_t wm_pid;
pid_t x_pid;
void DEFAULT_CC
signal_handler(int sig)
{
g_sigterm(x_pid);
g_sigterm(wm_pid);
g_exit(0);
}
/******************************************************************************/
int DEFAULT_CC
main(int argc, char** argv)
{
int ret=0;
x_pid = g_atoi(argv[1]);
wm_pid = g_atoi(argv[2]);
g_printf("\n[sessvc] Setting signal handler\n");
g_signal(9, signal_handler); /* SIGKILL */
g_signal(15, signal_handler); /* SIGTERM */
g_signal(17, signal_handler); /* SIGCHLD */
g_printf("\n[sessvc] Waiting for X (pid %d) and WM (pid %d)\n", x_pid, wm_pid);
ret = g_waitpid(wm_pid);
g_sigterm(x_pid);
g_printf("\n[sessvc] WM is dead (waitpid said %d, errno is %d). exiting...\n", ret, errno);
return 0;
}

View File

@ -49,6 +49,8 @@ sig_sesman_shutdown(int sig)
g_tcp_close(g_sck);
session_sigkill_all();
g_file_delete(SESMAN_PID_FILE);
}

View File

@ -1,21 +1,27 @@
# sesman makefile
# sesman tools makefile
SESTESTOBJ = sestest.o tcp.o \
os_calls.o d3des.o list.o file.o \
libscp_v1c.o
SESRUNOBJ = sesrun.o config.o tcp.o \
os_calls.o d3des.o list.o file.o log.o
DEFINES = -DLIBSCP_CLIENT
CFLAGS = -Wall -O2 -I../../common -I../ -I/usr/include/nptl $(DEFINES)
#LDFLAGS = -L /usr/gnu/lib -I/usr/include/nptl -L/usr/lib/nptl -lpthread -ldl $(DEFINES)
LDFLAGS = -L /usr/gnu/lib -ldl $(DEFINES)
LDFLAGS = -L /usr/gnu/lib -I/usr/include/nptl -L/usr/lib/nptl -lpthread -ldl $(DEFINES)
#LDFLAGS = -L /usr/gnu/lib -ldl $(DEFINES)
C_OS_FLAGS = $(CFLAGS) -c -g
CC = gcc
all: sestest
all: stest srun
sestest: $(SESTESTOBJ)
stest: $(SESTESTOBJ)
$(CC) $(LDFLAGS) -o sestest $(SESTESTOBJ)
srun: $(SESRUNOBJ)
$(CC) $(LDFLAGS) -o sesrun $(SESRUNOBJ)
os_calls.o: ../../common/os_calls.c
$(CC) $(C_OS_FLAGS) ../../common/os_calls.c
@ -28,14 +34,25 @@ list.o: ../../common/list.c
file.o: ../../common/file.c
$(CC) $(C_OS_FLAGS) ../../common/file.c
log.o: ../../common/file.c
$(CC) $(C_OS_FLAGS) ../../common/log.c
tcp.o: ../tcp.c
$(CC) $(C_OS_FLAGS) ../tcp.c
config.o: ../config.c
$(CC) $(C_OS_FLAGS) ../config.c
libscp_v1c.o: ../libscp_v1c.c
$(CC) $(C_OS_FLAGS) ../libscp_v1c.c
clean:
rm $(SESTESTOBJ) sestest
rm *.o sestest sesrun
install:
#install
install sesrun $(DESTDIR)/sesrun
install sestest $(DESTDIR)/sestest
installdeb:
install sesrun $(DESTDIRDEB)/usr/lib/xrdp/sesrun
install sestest $(DESTDIRDEB)/usr/lib/xrdp/sestest

125
sesman/tools/sesrun.c Normal file
View File

@ -0,0 +1,125 @@
/*
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 2 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, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
xrdp: A Remote Desktop Protocol server.
Copyright (C) Jay Sorg 2005-2007
*/
/**
*
* @file sesrun.c
* @brief An utility to start a session
* @author Jay Sorg, Simone Fedele
*
*/
#include "sesman.h"
int g_sck;
int g_pid;
struct config_sesman g_cfg; /* config.h */
/******************************************************************************/
int DEFAULT_CC
main(int argc, char** argv)
{
int sck;
int code;
int i;
int size;
int version;
int width;
int height;
int bpp;
int display;
struct stream* in_s;
struct stream* out_s;
char* username;
char* password;
long data;
if (0 != config_read(&g_cfg))
{
g_printf("sesrun: error reading config. quitting.\n");
return 1;
}
g_pid = g_getpid();
if (argc == 1)
{
g_printf("xrdp session starter v0.1\n");
g_printf("\nusage:\n");
g_printf("sesrun <server> <username> <password> <width> <height> <bpp>\n");
}
else if (argc == 7)
{
username = argv[2];
password = argv[3];
width = g_atoi(argv[4]);
height = g_atoi(argv[5]);
bpp = g_atoi(argv[6]);
make_stream(in_s);
init_stream(in_s, 8192);
make_stream(out_s);
init_stream(out_s, 8192);
sck = g_tcp_socket();
if (g_tcp_connect(sck, argv[1], "3350") == 0)
{
s_push_layer(out_s, channel_hdr, 8);
out_uint16_be(out_s, 0); /* code */
i = g_strlen(username);
out_uint16_be(out_s, i);
out_uint8a(out_s, username, i);
i = g_strlen(password);
out_uint16_be(out_s, i);
out_uint8a(out_s, password, i);
out_uint16_be(out_s, width);
out_uint16_be(out_s, height);
out_uint16_be(out_s, bpp);
s_mark_end(out_s);
s_pop_layer(out_s, channel_hdr);
out_uint32_be(out_s, 0); /* version */
out_uint32_be(out_s, out_s->end - out_s->data); /* size */
tcp_force_send(sck, out_s->data, out_s->end - out_s->data);
if (tcp_force_recv(sck, in_s->data, 8) == 0)
{
in_uint32_be(in_s, version);
in_uint32_be(in_s, size);
init_stream(in_s, 8192);
if (tcp_force_recv(sck, in_s->data, size - 8) == 0)
{
if (version == 0)
{
in_uint16_be(in_s, code);
if (code == 3)
{
in_uint16_be(in_s, data);
in_uint16_be(in_s, display);
g_printf("ok %d display %d\n", data, display);
}
}
}
}
}
else
{
g_printf("connect error\n");
}
g_tcp_close(sck);
free_stream(in_s);
free_stream(out_s);
}
return 0;
}

View File

@ -40,6 +40,9 @@
extern struct config_sesman g_cfg;
static int DEFAULT_CC
auth_crypt_pwd(char* pwd, char* pln, char* crp);
static int DEFAULT_CC
auth_account_disabled(struct spwd* stp);
@ -130,9 +133,6 @@ auth_set_env(long in_val)
return 0;
}
#define AUTH_NO_PWD_CHANGE 0
#define AUTH_PWD_CHANGE 1
/******************************************************************************/
int DEFAULT_CC
auth_check_pwd_chg(char* user)
@ -145,19 +145,19 @@ auth_check_pwd_chg(char* user)
spw = getpwnam(user);
if (spw == 0)
{
return AUTH_NO_PWD_CHANGE;
return AUTH_PWD_CHG_ERROR;
}
if (g_strncmp(spw->pw_passwd, "x", 3) != 0)
{
/* old system with only passwd */
return AUTH_NO_PWD_CHANGE;
return AUTH_PWD_CHG_OK;
}
/* the system is using shadow */
stp = getspnam(user);
if (stp == 0)
{
return AUTH_NO_PWD_CHANGE;
return AUTH_PWD_CHG_ERROR;
}
/* check if we need a pwd change */
@ -166,16 +166,126 @@ auth_check_pwd_chg(char* user)
if (today >= (stp->sp_lstchg + stp->sp_max - stp->sp_warn))
{
return AUTH_PWD_CHANGE;
return AUTH_PWD_CHG_CHANGE;
}
if (today >= (stp->sp_lstchg + stp->sp_max))
{
return AUTH_PWD_CHG_CHANGE_MANDATORY;
}
if (today < ((stp->sp_lstchg)+(stp->sp_min)))
{
/* cannot change pwd for now */
return AUTH_NO_PWD_CHANGE;
return AUTH_PWD_CHG_NOT_NOW;
}
return AUTH_NO_PWD_CHANGE;
return AUTH_PWD_CHG_OK;
}
int DEFAULT_CC
auth_change_pwd(char* user, char* newpwd)
{
struct passwd* spw;
struct spwd* stp;
char hash[35] = "";
long today;
FILE* fd;
if (0 != lckpwdf())
{
return 1;
}
/* open passwd */
spw = getpwnam(user);
if (spw == 0)
{
return 1;
}
if (g_strncmp(spw->pw_passwd, "x", 3) != 0)
{
/* old system with only passwd */
if (auth_crypt_pwd(spw->pw_passwd, newpwd, hash) != 0)
{
ulckpwdf();
return 1;
}
spw->pw_passwd=g_strdup(hash);
fd = fopen("/etc/passwd", "rw");
putpwent(spw, fd);
}
else
{
/* the system is using shadow */
stp = getspnam(user);
if (stp == 0)
{
return 1;
}
/* old system with only passwd */
if (auth_crypt_pwd(stp->sp_pwdp, newpwd, hash) != 0)
{
ulckpwdf();
return 1;
}
stp->sp_pwdp = g_strdup(hash);
today = g_time1() / SECS_PER_DAY;
stp->sp_lstchg = today;
stp->sp_expire = today + stp->sp_max + stp->sp_inact;
fd = fopen("/etc/shadow", "rw");
putspent(stp, fd);
}
ulckpwdf();
return 0;
}
/**
*
* @brief Password encryption
* @param pwd Old password
* @param pln Plaintext new password
* @param crp Crypted new password
*
*/
static int DEFAULT_CC
auth_crypt_pwd(char* pwd, char* pln, char* crp)
{
char salt[13] = "$1$";
int saltcnt = 0;
char* encr;
if (g_strncmp(pwd, "$1$", 3) == 0)
{
/* gnu style crypt(); */
saltcnt = 3;
while ((pwd[saltcnt] != '$') && (saltcnt < 11))
{
salt[saltcnt] = pwd[saltcnt];
saltcnt++;
}
salt[saltcnt] = '$';
salt[saltcnt + 1] = '\0';
}
else
{
/* classic two char salt */
salt[0] = pwd[0];
salt[1] = pwd[1];
salt[2] = '\0';
}
encr = crypt(pln, salt);
g_strncpy(crp, encr, 34);
return 0;
}
/**