commit
d2f0741fd4
13 changed files with 1803 additions and 0 deletions
@ -0,0 +1,38 @@
|
||||
CC = gcc
|
||||
CFLAGS = -Wall -c -o
|
||||
LDFLAGS = -Wall -lcrypt -o
|
||||
EXE = userv
|
||||
RM = rm -f
|
||||
|
||||
OBJECTS = main.o data.o networking.o misc.o common.o logging.o signal.o context.o
|
||||
|
||||
all: $(OBJECTS) |
||||
$(CC) $(LDFLAGS) $(EXE) $(OBJECTS)
|
||||
|
||||
clean: |
||||
$(RM) $(OBJECTS) $(EXE)
|
||||
|
||||
main.o: main.c |
||||
$(CC) $(CFLAGS) main.o main.c
|
||||
|
||||
data.o: data.c |
||||
$(CC) $(CFLAGS) data.o data.c
|
||||
|
||||
networking.o: networking.c |
||||
$(CC) $(CFLAGS) networking.o networking.c
|
||||
|
||||
misc.o: misc.c |
||||
$(CC) $(CFLAGS) misc.o misc.c
|
||||
|
||||
common.o: common.c |
||||
$(CC) $(CFLAGS) common.o common.c
|
||||
|
||||
logging.o: logging.c |
||||
$(CC) $(CFLAGS) logging.o logging.c
|
||||
|
||||
signal.o: signal.c |
||||
$(CC) $(CFLAGS) signal.o signal.c
|
||||
|
||||
context.o: context.c |
||||
$(CC) $(CFLAGS) context.o context.c
|
||||
|
@ -0,0 +1,77 @@
|
||||
Lines beginning with "S:" are server messages. |
||||
Lines beginning with "C:" are client messages. |
||||
|
||||
S: <listening on port 8778> |
||||
C: <connecting> |
||||
If the client is from an allowed IP: |
||||
S: R |
||||
Or else: |
||||
S: D |
||||
S: <close connection> |
||||
|
||||
From now on, we assume that a connection is already built to the server |
||||
|
||||
C: L <uname> <pass> |
||||
If the client is already logged in: |
||||
S: L |
||||
If uname or pass is missing: |
||||
S: E |
||||
If the specified user is not allowed to login: |
||||
S: D |
||||
If the specified uname/pass combination is bad: |
||||
S: B |
||||
If login successful: |
||||
S: S |
||||
|
||||
C: Q |
||||
S: S |
||||
S: <close connection> |
||||
|
||||
C: U <uid> |
||||
If client hasn't login yet: |
||||
S: L |
||||
If uid is not numeric: |
||||
S: E |
||||
If uid is used: |
||||
S: U |
||||
If uid is free: |
||||
S:F |
||||
|
||||
C: N <uname> |
||||
If client hasn't login yet: |
||||
S: L |
||||
If uname exists: |
||||
S: U |
||||
If uname doesn't exist: |
||||
S: F |
||||
|
||||
C: A <uname>:<uid>:<teacher?>:<samba?>:<passwd>:<comment> |
||||
If client hasn't login yet: |
||||
S: L |
||||
If uid, teacher?, samba?, passwd or comment is not specified |
||||
S: E |
||||
If uid is not numeric: |
||||
S: E |
||||
If uid or uname is used: |
||||
S: E |
||||
If teacher? not 0 nor 1, and samba? not 0 nor 1 |
||||
S: E |
||||
If tempfile or scriptfile couldn't be created: |
||||
S: F |
||||
If user couldn't be created: |
||||
S: F |
||||
If user has been created: |
||||
S: S |
||||
|
||||
C: D <uname> |
||||
If client hasn't login yet: |
||||
S: L |
||||
If uname doesn't exist: |
||||
S: E |
||||
If scriptfile couldn't be created: |
||||
S: F |
||||
If user cannot be deleted: |
||||
S: F |
||||
If user is deleted: |
||||
S: S |
||||
|
@ -0,0 +1,5 @@
|
||||
This project is a high-school attempt to create centralized user |
||||
management, long before I heard about LDAP and the likes. |
||||
|
||||
I release this as a public domain, I guess you can learn this-and-that |
||||
from it. |
@ -0,0 +1,189 @@
|
||||
/*
|
||||
* UserServer/0.1 |
||||
* common.c - Common functions |
||||
* |
||||
* Copyright (C) 2002 Gergely Polonkai |
||||
* Copyright (C) 2002-2006 P-Team Programmers' Group |
||||
* |
||||
* This program is free software; you can redistribute it and/or |
||||
* modify it under the terms of 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 recieved a copy of the GNU General Public License |
||||
* along with this program; if not, write to Free Software |
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA, 02111-1307, USA. |
||||
* |
||||
* GNU GPL is in doc/COPYING |
||||
*/ |
||||
|
||||
#include <stdio.h> |
||||
#include <string.h> |
||||
#include <ctype.h> |
||||
#include <stdlib.h> |
||||
#include <pwd.h> |
||||
#include <crypt.h> |
||||
|
||||
#include "userv.h" |
||||
#include "functions.h" |
||||
|
||||
char table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; |
||||
|
||||
int |
||||
ParseConfig(void) { |
||||
FILE *cf; |
||||
char buf[1024]; |
||||
char *line; |
||||
int nl = 0; |
||||
|
||||
if ((cf = fopen("/etc/userv.conf", "r")) == NULL) |
||||
return ERR_NOCF; |
||||
|
||||
memset(&buf, 0, 1024); |
||||
while (fgets((char *)&buf, 1023, cf)) { |
||||
char *param; |
||||
int i; |
||||
|
||||
nl++; |
||||
if ((line = trim(buf, NULL))) { |
||||
if (strncmp(line, "listen ", 7) == 0) { |
||||
param = strchr(line, ' ') + 1; |
||||
for (i = 0; i < strlen(param); i++) |
||||
if (isspace(*(param + i))) { |
||||
*(param + i) = 0; |
||||
break; |
||||
} |
||||
if (!valid_ip(param)) |
||||
return nl; |
||||
if (AddListen(param) != ERR_OK) |
||||
return ERR_NOMEM; |
||||
} |
||||
if (strncmp(line, "confserv ", 9) == 0) { |
||||
param = strchr(line, ' ') + 1; |
||||
for (i = 0; i < strlen(param); i++) |
||||
if (isspace(*(param + 1))) { |
||||
*(param + i) = 0; |
||||
break; |
||||
} |
||||
if (!valid_ip(param)) |
||||
return nl; |
||||
if (AddConfig(param) != ERR_OK) |
||||
return ERR_NOMEM; |
||||
} |
||||
if (strncmp(line, "server ", 7) == 0) { |
||||
param = strchr(line, ' ') + 1; |
||||
for (i = 0; i < strlen(param); i++) |
||||
if (isspace(*(param + 1))) { |
||||
*(param + i) = 0; |
||||
break; |
||||
} |
||||
if (!valid_ip(param)) |
||||
return nl; |
||||
if (AddPeer(param) != ERR_OK) |
||||
return ERR_NOMEM; |
||||
} |
||||
if (strncmp(line, "client ", 7) == 0) { |
||||
param = strchr(line, ' ') + 1; |
||||
for (i = 0; i < strlen(param); i++) |
||||
if (isspace(*(param + i))) { |
||||
*(param + i) = 0; |
||||
break; |
||||
} |
||||
if (!valid_ip(param)) |
||||
return nl; |
||||
if (AddClient(param) != ERR_OK) |
||||
return ERR_NOMEM; |
||||
} |
||||
if (strncmp(line, "user ", 5) == 0) { |
||||
param = strchr(line, ' ') + 1; |
||||
for (i = 0; i < strlen(param); i++) |
||||
if (isspace(*(param + i))) { |
||||
*(param + i) = 0; |
||||
break; |
||||
} |
||||
if (!valid_user(param)) |
||||
return nl; |
||||
if (AddUser(param) != ERR_OK) |
||||
return ERR_NOMEM; |
||||
} |
||||
free(line); |
||||
} |
||||
memset(buf, 0, 1024); |
||||
} |
||||
fclose(cf); |
||||
|
||||
return ERR_OK; |
||||
} |
||||
|
||||
int |
||||
Is_UID_exist(uid_t uid) { |
||||
if (getpwuid(uid) == NULL) |
||||
return 0; |
||||
return 1; |
||||
} |
||||
|
||||
int |
||||
pwcheck(char *uname, char *passw) { |
||||
struct passwd *pwentry; |
||||
char buf[1024]; |
||||
FILE *fd; |
||||
char *pwd; |
||||
|
||||
if ((pwentry = getpwnam(uname)) == NULL) |
||||
return ERR_NOUSER; |
||||
|
||||
if (strcmp(pwentry->pw_passwd, "x") == 0) { |
||||
if ((fd = fopen("/etc/shadow", "r")) == NULL) |
||||
return ERR_NOSHADOW; |
||||
|
||||
memset(&buf, 0, 1024); |
||||
while (fgets((char *)&buf, 1023, fd)) { |
||||
if (strncmp((char *)&buf, uname, strlen(uname)) == 0) |
||||
break; |
||||
memset(&buf, 0, 1024); |
||||
} |
||||
fclose(fd); |
||||
} else |
||||
strcpy((char *)&buf, pwentry->pw_passwd); |
||||
|
||||
pwd = strchr((char *)&buf, ':') + 1; |
||||
if (pwd - 1 == NULL) |
||||
return ERR_NOPASS; |
||||
|
||||
*(strchr(pwd, ':')) = 0; |
||||
|
||||
if (strcmp(crypt(passw, pwd), pwd) == 0) |
||||
return ERR_OK; |
||||
|
||||
return ERR_BADPASS; |
||||
} |
||||
|
||||
void |
||||
salt(char *where) { |
||||
int i; |
||||
if (!where) |
||||
return; |
||||
|
||||
strncpy(where, "$1$", 3); |
||||
for (i = 3; i < 11; i++) |
||||
where[i] = table[(int)(1.0 * strlen(table) * rand() / (RAND_MAX + 1.0))]; |
||||
where[11] = '$'; |
||||
where[12] = 0; |
||||
} |
||||
|
||||
void |
||||
tempname(char *where, size_t len) { |
||||
int i; |
||||
if (!where) |
||||
return; |
||||
|
||||
for (i = 0; i < len; i++) |
||||
where[i] = table[(int)(1.0 * strlen(table) * rand() / (RAND_MAX + 1.0))]; |
||||
where[len] = 0; |
||||
} |
||||
|
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* UserServer/0.1 |
||||
* context.c - Context debugging |
||||
* |
||||
* Copyright (C) 2002 Gergely Polonkai |
||||
* Copyright (C) 2002-2006 P-Team Programmers' Group |
||||
* |
||||
* This program is free software; you can redistribute it and/or |
||||
* modify it under the terms of 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 recieved a copy of the GNU General Public License |
||||
* along with this program; if not, write to Free Software |
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA, 02111-1307, USA. |
||||
* |
||||
* GNU GPL is in doc/COPYING |
||||
*/ |
||||
|
||||
#include "userv.h" |
||||
#include "functions.h" |
||||
|
||||
#ifdef CONTEXT_DEBUG |
||||
# include <string.h> |
||||
# include <stdio.h> |
||||
|
||||
char fn[40] = ""; |
||||
int ln = 0; |
||||
|
||||
void |
||||
n_Context(char *fname, int line) { |
||||
memset(&fn, 0, 40); |
||||
strncpy((char *)&fn, fname, 39); |
||||
ln = line; |
||||
} |
||||
|
||||
void |
||||
n_PrintContext(void) { |
||||
Log(MT_MSG, "Last context was at %s:%d", fn, ln); |
||||
} |
||||
|
||||
#endif |
||||
|
@ -0,0 +1,251 @@
|
||||
/*
|
||||
* UserServer/0.1 |
||||
* data.c - Handling local data |
||||
* |
||||
* Copyright (C) 2002 Gergely Polonkai |
||||
* Copyright (C) 2002-2006 P-Team Programmers' Group |
||||
* |
||||
* This program is free software; you can redistribute it and/or |
||||
* modify it under the terms of 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 recieved a copy of the GNU General Public License |
||||
* along with this program; if not, write to Free Software |
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA, 02111-1307, USA. |
||||
* |
||||
* GNU GPL is in doc/COPYING |
||||
*/ |
||||
|
||||
#include <string.h> |
||||
#include <stdlib.h> |
||||
#include <unistd.h> |
||||
|
||||
#include "userv.h" |
||||
#include "functions.h" |
||||
|
||||
int |
||||
AddListen(char *IP) { |
||||
LST *temp; |
||||
char *ip; |
||||
|
||||
if ((ip = strdup(IP)) == NULL) |
||||
return ERR_NOMEM; |
||||
|
||||
if (laddr) { |
||||
temp = laddr; |
||||
while (temp->next) |
||||
temp = temp->next; |
||||
if ((temp->next = malloc(LSTS)) == NULL) |
||||
return ERR_NOMEM; |
||||
temp->next->next = NULL; |
||||
temp->next->IP = ip; |
||||
} else { |
||||
if ((laddr = malloc(LSTS)) == NULL) |
||||
return ERR_NOMEM; |
||||
laddr->next = NULL; |
||||
laddr->IP = ip; |
||||
} |
||||
|
||||
return ERR_OK; |
||||
} |
||||
|
||||
int |
||||
AddConfig(char *IP) { |
||||
SST *temp; |
||||
char *ip; |
||||
|
||||
if ((ip = strdup(IP)) == NULL) |
||||
return ERR_NOMEM; |
||||
|
||||
if (saddr) { |
||||
temp = saddr; |
||||
while (temp->next) |
||||
temp = temp->next; |
||||
if ((temp->next = malloc(SSTS)) == NULL) |
||||
return ERR_NOMEM; |
||||
temp->next->next = NULL; |
||||
temp->next->IP = ip; |
||||
} else { |
||||
if ((saddr = malloc(SSTS)) == NULL) |
||||
return ERR_NOMEM; |
||||
saddr->next = NULL; |
||||
saddr->IP = ip; |
||||
} |
||||
|
||||
return ERR_OK; |
||||
} |
||||
|
||||
int |
||||
AddPeer(char *IP) { |
||||
PST *temp; |
||||
char *ip; |
||||
|
||||
if ((ip = strdup(IP)) == NULL) |
||||
return ERR_NOMEM; |
||||
|
||||
if (paddr) { |
||||
temp = paddr; |
||||
while (temp->next) |
||||
temp = temp->next; |
||||
if ((temp->next = malloc(SSTS)) == NULL) |
||||
return ERR_NOMEM; |
||||
temp->next->next = NULL; |
||||
temp->next->IP = ip; |
||||
} else { |
||||
if ((paddr = malloc(SSTS)) == NULL) |
||||
return ERR_NOMEM; |
||||
paddr->next = NULL; |
||||
paddr->IP = ip; |
||||
} |
||||
|
||||
return ERR_OK; |
||||
} |
||||
|
||||
int |
||||
AddClient(char *IP) { |
||||
CST *temp; |
||||
char *ip; |
||||
|
||||
if ((ip = strdup(IP)) == NULL) |
||||
return ERR_NOMEM; |
||||
|
||||
if (caddr) { |
||||
temp = caddr; |
||||
while (temp->next) |
||||
temp = temp->next; |
||||
if ((temp->next = malloc(CSTS)) == NULL) |
||||
return ERR_NOMEM; |
||||
temp->next->next = NULL; |
||||
temp->next->IP = ip; |
||||
} else { |
||||
if ((caddr = malloc(CSTS)) == NULL) |
||||
return ERR_NOMEM; |
||||
caddr->next = NULL; |
||||
caddr->IP = ip; |
||||
} |
||||
|
||||
return ERR_OK; |
||||
} |
||||
|
||||
int |
||||
AddUser(char *name) { |
||||
UST *temp; |
||||
char *un; |
||||
|
||||
if ((un = strdup(name)) == NULL) |
||||
return ERR_NOMEM; |
||||
|
||||
if (auser) { |
||||
temp = auser; |
||||
while (temp->next) |
||||
temp = temp->next; |
||||
if ((temp->next = malloc(USTS)) == NULL) |
||||
return ERR_NOMEM; |
||||
temp->next->next = NULL; |
||||
temp->next->uname = un; |
||||
} else { |
||||
if ((auser = malloc(USTS)) == NULL) |
||||
return ERR_NOMEM; |
||||
auser->next = NULL; |
||||
auser->uname = un; |
||||
} |
||||
|
||||
return ERR_OK; |
||||
} |
||||
|
||||
void |
||||
CleanUp(int type) { |
||||
if (laddr) { |
||||
LST *temp; |
||||
temp = laddr->next; |
||||
if (laddr->IP) |
||||
free(laddr->IP); |
||||
free(laddr); |
||||
while (temp) { |
||||
LST *t = temp; |
||||
temp = temp->next; |
||||
if (t->IP) |
||||
free(t->IP); |
||||
free(t); |
||||
} |
||||
} |
||||
laddr = NULL; |
||||
|
||||
if (paddr) { |
||||
PST *temp; |
||||
temp = paddr->next; |
||||
if (paddr->IP) |
||||
free(paddr->IP); |
||||
free(paddr); |
||||
while (temp) { |
||||
PST *t = temp; |
||||
temp = temp->next; |
||||
if (t->IP) |
||||
free(t->IP); |
||||
free(t); |
||||
} |
||||
} |
||||
paddr = NULL; |
||||
|
||||
if (saddr) { |
||||
SST *temp; |
||||
temp = saddr->next; |
||||
if (saddr->IP) |
||||
free(saddr->IP); |
||||
free(saddr); |
||||
while (temp) { |
||||
SST *t = temp; |
||||
temp = temp->next; |
||||
if (t->IP) |
||||
free(t->IP); |
||||
free(t); |
||||
} |
||||
} |
||||
saddr = NULL; |
||||
|
||||
if (caddr) { |
||||
CST *temp; |
||||
temp = caddr->next; |
||||
if (caddr->IP) |
||||
free(caddr->IP); |
||||
free(caddr); |
||||
while (temp) { |
||||
CST *t = temp; |
||||
temp = temp->next; |
||||
if (t->IP) |
||||
free(t->IP); |
||||
free(t); |
||||
} |
||||
} |
||||
caddr = NULL; |
||||
|
||||
if (auser) { |
||||
UST *temp; |
||||
temp = auser->next; |
||||
if (auser->uname) |
||||
free(auser->uname); |
||||
free(auser); |
||||
while (temp) { |
||||
UST *t = temp; |
||||
temp = temp->next; |
||||
if (t->uname) |
||||
free(t->uname); |
||||
free(t); |
||||
} |
||||
} |
||||
auser = NULL; |
||||
|
||||
while (nconn) { |
||||
if ((nconn->sfd != -1) && (type == 0) && (nconn->type == CT_CLIENT)) |
||||
Send(nconn->sfd, "T\n"); |
||||
DelConn(nconn->sfd); |
||||
} |
||||
nconn = NULL; |
||||
} |
||||
|
@ -0,0 +1,35 @@
|
||||
#ifndef _US_FUNCTIONS_H |
||||
# define _US_FUNCTIONS_H |
||||
|
||||
# include <sys/types.h> |
||||
# include "userv.h" |
||||
|
||||
int AddListen(char *); |
||||
int AddClient(char *); |
||||
int AddUser(char *); |
||||
int AddConfig(char *); |
||||
int AddPeer(char *); |
||||
void CleanUp(int); |
||||
int StartListening(void); |
||||
int valid_user(char *); |
||||
int valid_ip(char *); |
||||
char *trim(char *, char *); |
||||
int ip_allowed(char *); |
||||
int MainLoop(void); |
||||
int ParseConfig(void); |
||||
int pwcheck(char *, char *); |
||||
int IsNum(char *); |
||||
int Is_UID_exist(uid_t); |
||||
void salt(char *); |
||||
void tempname(char *, size_t); |
||||
int user_allowed(char *); |
||||
void Log(int, char *, ...); |
||||
void SetSignals(void); |
||||
void Send(int, char *, ...); |
||||
void DelConn(int); |
||||
# ifdef CONTEXT_DEBUG |
||||
void n_Context(char *, int); |
||||
void n_PrintContext(void); |
||||
# endif |
||||
|
||||
#endif /* _US_FUNCTIONS_H */ |
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* UserServer/0.1 |
||||
* logging.c - Logging facility |
||||
* |
||||
* Copyright (C) 2002 Gergely Polonkai |
||||
* Copyright (C) 2002-2006 P-Team Programmers' Group |
||||
* |
||||
* This program is free software; you can redistribute it and/or |
||||
* modify it under the terms of 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 recieved a copy of the GNU General Public License |
||||
* along with this program; if not, write to Free Software |
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA, 02111-1307, USA. |
||||
* |
||||
* GNU GPL is in doc/COPYING |
||||
*/ |
||||
|
||||
#include <syslog.h> |
||||
#include <stdio.h> |
||||
#include <stdarg.h> |
||||
#include <unistd.h> |
||||
#include <time.h> |
||||
|
||||
#include "userv.h" |
||||
#include "functions.h" |
||||
|
||||
static char *month[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; |
||||
|
||||
void |
||||
Log(int type, char *fmt, ...) { |
||||
char buf1[256]; |
||||
va_list ap; |
||||
FILE *lf; |
||||
int prior; |
||||
time_t now; |
||||
struct tm *tm; |
||||
|
||||
va_start(ap, fmt); |
||||
vsnprintf(buf1, 255, fmt, ap); |
||||
va_end(ap); |
||||
if ((lf = fopen("/var/log/userv.log", "a")) != NULL) { |
||||
now = time(NULL); |
||||
tm = localtime((const time_t *)&now); |
||||
|
||||
fprintf(lf, "%s %2d %02d:%02d:%02d UserServer[%d] %s: %s\n", month[tm->tm_mon], tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, getpid(), (type == MT_ERROR) ? "ERR" : "MSG", buf1); |
||||
|
||||
fclose(lf); |
||||
} |
||||
|
||||
openlog("UserServer", LOG_PID, LOG_DAEMON); |
||||
prior = LOG_DAEMON; |
||||
prior |= (type == MT_ERROR) ? LOG_ERR : LOG_NOTICE; |
||||
syslog(prior, "%s: %s", (type == MT_ERROR) ? "ERR" : "MSG", buf1); |
||||
closelog(); |
||||
} |
||||
|
@ -0,0 +1,116 @@
|
||||
/*
|
||||
* UserServer/0.1 |
||||
* main.c - Main facility |
||||
* |
||||
* Copyright (C) 2002 Gergely Polonkai |
||||
* Copyright (C) 2002-2006 P-Team Programmers' Group |
||||
* |
||||
* This program is free software; you can redistribute it and/or |
||||
* modify it under the terms of 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 recieved a copy of the GNU General Public License |
||||
* along with this program; if not, write to Free Software |
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA, 02111-1307, USA. |
||||
* |
||||
* GNU GPL is in doc/COPYING |
||||
*/ |
||||
|
||||
#define USERV_MAIN |
||||
|
||||
#include <stdio.h> |
||||
#include <unistd.h> |
||||
#include <sys/time.h> |
||||
#include <time.h> |
||||
#include <stdlib.h> |
||||
|
||||
#include "userv.h" |
||||
#include "functions.h" |
||||
|
||||
LST *laddr = NULL; |
||||
CST *caddr = NULL; |
||||
UST *auser = NULL; |
||||
NST *nconn = NULL; |
||||
SST *saddr = NULL; |
||||
PST *paddr = NULL; |
||||
|
||||
int |
||||
main(void) { |
||||
int t; |
||||
struct timeval tv; |
||||
FILE *pf; |
||||
|
||||
SetSignals(); |
||||
|
||||
if (daemon(1, 0) == -1) { |
||||
Log(MT_ERROR, "Couldn't detach from controlling terminal"); |
||||
CleanUp(0); |
||||
unlink("/var/run/userv.pid"); |
||||
return -1; |
||||
} |
||||
|
||||
if ((pf = fopen("/var/run/userv.pid", "w")) == NULL) { |
||||
Log(MT_ERROR, "Unable to create pidfile"); |
||||
return -1; |
||||
} |
||||
fprintf(pf, "%d\n", getpid()); |
||||
fclose(pf); |
||||
|
||||
if (gettimeofday(&tv, NULL) != 0) { |
||||
Log(MT_ERROR, "Unable to get system time"); |
||||
unlink("/var/run/userv.pid"); |
||||
return -1; |
||||
} |
||||
srand(tv.tv_usec); |
||||
|
||||
if (geteuid() != 0) { |
||||
Log(MT_ERROR, "This server MUST be run as root!"); |
||||
unlink("/var/run/userv.pid"); |
||||
return -1; |
||||
} |
||||
|
||||
t = ParseConfig(); |
||||
if (t != 0) { |
||||
CleanUp(0); |
||||
unlink("/var/run/userv.pid"); |
||||
} |
||||
if (t > 0) { |
||||
Log(MT_ERROR, "Erronous line at /etc/userv.conf:%d", t); |
||||
return -1; |
||||
} else if (t < 0) { |
||||
switch (ParseConfig()) { |
||||
case ERR_NOCF: |
||||
Log(MT_ERROR, "Config file /etc/userv.conf doesn't exist"); |
||||
return -1; |
||||
case ERR_NOMEM: |
||||
Log(MT_ERROR, "Not enough memory while processing /etc/userv.conf"); |
||||
return -1; |
||||
default: |
||||
Log(MT_ERROR, "Undefined error\n"); |
||||
return -2; |
||||
} |
||||
} |
||||
|
||||
if (StartListening() != ERR_OK) { |
||||
Log(MT_ERROR, "Error occured while starting networking"); |
||||
CleanUp(0); |
||||
unlink("/var/run/userv.pid"); |
||||
return -1; |
||||
} |
||||
|
||||
if (MainLoop() != ERR_OK) |
||||
Log(MT_ERROR, "Error during loop"); |
||||
|
||||
unlink("/var/run/userv.pid"); |
||||
|
||||
CleanUp(0); |
||||
|
||||
return 0; |
||||
} |
||||
|
@ -0,0 +1,162 @@
|
||||
/*
|
||||
* UserServer/0.1 |
||||
* misc.c - Miscellanous functions |
||||
* |
||||
* Copyright (C) 2002 Gergely Polonkai |
||||
* Copyright (C) 2002-2006 P-Team Programmers' Group |
||||
* |
||||
* This program is free software; you can redistribute it and/or |
||||
* modify it under the terms of 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 recieved a copy of the GNU General Public License |
||||
* along with this program; if not, write to Free Software |
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA, 02111-1307, USA. |
||||
* |
||||
* GNU GPL is in doc/COPYING |
||||
*/ |
||||
|
||||
#include <string.h> |
||||
#include <ctype.h> |
||||
#include <stdlib.h> |
||||
#include <pwd.h> |
||||
|
||||
#include "userv.h" |
||||
#include "functions.h" |
||||
|
||||
char *trim(char *text, char *spc) { |
||||
int start, end; |
||||
char *b; |
||||
|
||||
if (spc) { |
||||
for (start = 0; start < strlen(text); start++) |
||||
if (!strchr(spc, *(text + start))) |
||||
break; |
||||
for (end = strlen(text) - 1; end >= 0; end--) |
||||
if (!strchr(spc, *(text + end))) |
||||
break; |
||||
} else { |
||||
for (start = 0; start < strlen(text); start++) |
||||
if (!isspace(*(text + start))) |
||||
break; |
||||
for (end = strlen(text) - 1; end >= 0; end--) |
||||
if (!isspace(*(text + end))) |
||||
break; |
||||
} |
||||
if (end == -1) |
||||
return NULL; |
||||
|
||||
if ((b = malloc(end - start + 2)) == NULL) |
||||
return NULL; |
||||
memset(b, 0, end - start + 2); |
||||
|
||||
strncpy(b, text + start, end - start + 1); |
||||
|
||||
return b; |
||||
} |
||||
|
||||
int |
||||
valid_ip(char *addr) { |
||||
int i, np = 0, nn = 0; |
||||
|
||||
if (!addr) |
||||
return 0; |
||||
|
||||
if (strlen(addr) > 15) |
||||
return 0; |
||||
|
||||
if (!isdigit(addr[0])) |
||||
return 0; |
||||
|
||||
for (i = 0; i < strlen(addr); i++) { |
||||
if (*(addr + i) == '.') |
||||
np++; |
||||
if ((*(addr + i) != '.') && (!isdigit(*(addr + i)))) |
||||
return 0; |
||||
} |
||||
|
||||
if (np != 3) |
||||
return 0; |
||||
|
||||
np = 0; |
||||
|
||||
for (i = 0; i < strlen(addr); i++) { |
||||
if (*(addr + i) == '.') { |
||||
if (np) |
||||
return 0; |
||||
np = 1; |
||||
nn = 0; |
||||
} |
||||
if (*(addr + i) != '.') { |
||||
np = 0; |
||||
nn++; |
||||
if (nn == 4) |
||||
return 0; |
||||
} |
||||
if (i > 0) |
||||
if ((*(addr + i - 1) == '0') && (*(addr + i) != '.')) |
||||
return 0; |
||||
} |
||||
|
||||
if (strcmp(addr, "0.0.0.0") == 0) |
||||
return 0; |
||||
|
||||
if (strcmp(addr, "255.255.255.255") == 0) |
||||
return 0; |
||||
|
||||
return 1; |
||||
} |
||||
|
||||
int |
||||
valid_user(char *name) { |
||||
if (getpwnam(name) == NULL) |
||||
return 0; |
||||
return 1; |
||||
} |
||||
|
||||
int |
||||
ip_allowed(char *IP) { |
||||
CST *temp = caddr; |
||||
while (temp) { |
||||
if (strcmp(IP, temp->IP) == 0) |
||||
return 1; |
||||
temp = temp->next; |
||||
} |
||||
return 0; |
||||
} |
||||
|
||||
int |
||||
user_allowed(char *uname) { |
||||
UST *temp = auser; |
||||
|
||||
if (strcmp(uname, "root") == 0) |
||||
return 0; |
||||
|
||||
while (temp) { |
||||
if (strcmp(uname, temp->uname) == 0) |
||||
return 1; |
||||
temp = temp->next; |
||||
} |
||||
return 0; |
||||
} |
||||
|
||||
int |
||||
IsNum(char *str) { |
||||
int i; |
||||
|
||||
if (!str) |
||||
return 0; |
||||
|
||||
for (i = 0; i < strlen(str); i++) |
||||
if (!isdigit(*(str + i))) |
||||
return 0; |
||||
|
||||
return 1; |
||||
} |
||||
|
@ -0,0 +1,645 @@
|
||||
/*
|
||||
* UserServer/0.1 |
||||
* networking.c - Handling network connections |
||||
* |
||||
* Copyright (C) 2002 Gergely Polonkai |
||||
* Copyright (C) 2002-2006 P-Team Programmers' Group |
||||
* |
||||
* This program is free software; you can redistribute it and/or |
||||
* modify it under the terms of 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 recieved a copy of the GNU General Public License |
||||
* along with this program; if not, write to Free Software |
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA, 02111-1307, USA. |
||||
* |
||||
* GNU GPL is in doc/COPYING |
||||
*/ |
||||
|
||||
#define _GNU_SOURCE |
||||
|
||||
#include <stdio.h> |
||||
#include <string.h> |
||||
#include <stdlib.h> |
||||
#include <sys/socket.h> |
||||
#include <sys/types.h> |
||||
#include <netinet/in.h> |
||||
#include <arpa/inet.h> |
||||
#include <time.h> |
||||
#include <unistd.h> |
||||
#include <string.h> |
||||
#include <ctype.h> |
||||
#include <crypt.h> |
||||
#include <sys/wait.h> |
||||
#include <stdarg.h> |
||||
|
||||
#include "userv.h" |
||||
#include "functions.h" |
||||
|
||||
fd_set master, readable; |
||||
int maxfd = 0; |
||||
|
||||
int |
||||
AddConn(int type, int sfd, char *IP) { |
||||
char *ip; |
||||
|
||||
if ((ip = strdup(IP)) == NULL) |
||||
return ERR_NOMEM; |
||||
|
||||
if (nconn) { |
||||
NST *temp = nconn; |
||||
while (temp->next) |
||||
temp = temp->next; |
||||
if ((temp->next = malloc(NSTS)) == NULL) { |
||||
free(ip); |
||||
return ERR_NOMEM; |
||||
} |
||||
temp->next->next = NULL; |
||||
temp->next->IP = ip; |
||||
temp->next->type = type; |
||||
temp->next->sfd = sfd; |
||||
temp->next->timeout = 0; |
||||
temp->next->loggedin = 0; |
||||
} else { |
||||
if ((nconn = malloc(NSTS)) == NULL) { |
||||
free(ip); |
||||
return ERR_NOMEM; |
||||
} |
||||
nconn->next = NULL; |
||||
nconn->IP = ip; |
||||
nconn->type = type; |
||||
nconn->sfd = sfd; |
||||
nconn->timeout = 0; |
||||
nconn->loggedin = 0; |
||||
} |
||||
FD_SET(sfd, &master); |
||||
if (sfd > maxfd) |
||||
maxfd = sfd; |
||||
return ERR_OK; |
||||
} |
||||
|
||||
void |
||||
DelConn(int sfd) { |
||||
NST *temp = nconn; |
||||
NST *p = NULL; |
||||
NST *n; |
||||
|
||||
while (temp) { |
||||
n = temp->next; |
||||
if (temp->sfd == sfd) { |
||||
if (temp->IP) |
||||
free(temp->IP); |
||||
if (sfd != -1) |
||||
close(sfd); |
||||
if (p) |
||||
p->next = temp->next; |
||||
else |
||||
nconn = n; |
||||
free(temp); |
||||
FD_CLR(sfd, &master); |
||||
return; |
||||
} |
||||
p = temp; |
||||
temp = temp->next; |
||||
} |
||||
} |
||||
|
||||
int |
||||
Type(int sfd) { |
||||
NST *temp = nconn; |
||||
while (temp) { |
||||
if (temp->sfd == sfd) |
||||
return temp->type; |
||||
temp = temp->next; |
||||
} |
||||
return CT_NONE; |
||||
} |
||||
|
||||
int |
||||
LoggedIn(int sfd) { |
||||
NST *temp = nconn; |
||||
while (temp) { |
||||
if (temp->sfd == sfd) |
||||
return temp->loggedin; |
||||
temp = temp->next; |
||||
} |
||||
return 0; |
||||
} |
||||
|
||||
int |
||||
SetLogin(int sfd, char *uname) { |
||||
if (uname) { |
||||
char *un; |
||||
NST *temp = nconn; |
||||
|
||||
if ((un = strdup(uname)) == NULL) |
||||
return ERR_NOMEM; |
||||
else { |
||||
while (temp) { |
||||
if (temp->sfd == sfd) { |
||||
temp->loggedin = 1; |
||||
temp->uname = un; |
||||
return ERR_OK; |
||||
} |
||||
temp = temp->next; |
||||
} |
||||
} |
||||
} |
||||
|
||||
return ERR_NOUSER; |
||||
} |
||||
|
||||
char * |
||||
GetIP(int sfd) { |
||||
NST *temp = nconn; |
||||
|
||||
while (temp) { |
||||
if (temp->sfd == sfd) |
||||
return temp->IP; |
||||
temp = temp->next; |
||||
} |
||||
return NULL; |
||||
} |
||||
|
||||
char * |
||||
GetUser(int sfd) { |
||||
NST *temp = nconn; |
||||
|
||||
while (temp) { |
||||
if (temp->sfd == sfd) |
||||
return temp->uname; |
||||
temp = temp->next; |
||||
} |
||||
return NULL; |
||||
} |
||||
|
||||
void |
||||
IncTimeout(int sfd) { |
||||
NST *temp = nconn; |
||||
while (temp) { |
||||
if (temp->sfd == sfd) { |
||||
temp->timeout++; |
||||
return; |
||||
} |
||||
if (temp->timeout == 600) { |
||||
Log(MT_MSG, "Timeout at %s", GetIP(sfd)); |
||||
DelConn(temp->sfd); |
||||
return; |
||||
} |
||||
temp = temp->next; |
||||
} |
||||
} |
||||
|
||||
int |
||||
StartListening(void) { |
||||
{ |
||||
LST *temp; |
||||
|
||||
FD_ZERO(&master); |
||||
FD_ZERO(&readable); |
||||
|
||||
temp = laddr; |
||||
while (temp) if (temp->IP) { |
||||
int sfd; |
||||
struct sockaddr_in la; |
||||
int yes = 1; |
||||
|
||||
if ((sfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) |
||||
return ERR_SOCKET; |
||||
if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) |
||||
return ERR_OPT; |
||||
|
||||
la.sin_family = AF_INET; |
||||
la.sin_addr.s_addr = inet_addr(temp->IP); |
||||
la.sin_port = htons(8778); |
||||
memset(&(la.sin_zero), 0, 8); |
||||
|
||||
if (bind(sfd, (struct sockaddr *)&la, sizeof(la)) == -1) |
||||
return ERR_BIND; |
||||
|
||||
if (listen(sfd, 10) == -1) |
||||
return ERR_LISTEN; |
||||
|
||||
if (AddConn(CT_LISTEN, sfd, temp->IP) != ERR_OK) |
||||
return ERR_NOMEM; |
||||
|
||||
temp = temp->next; |
||||
} |
||||
} |
||||
|
||||
{ |
||||
SST *temp; |
||||
|
||||
temp = saddr; |
||||
while (temp) if (temp->IP) { |
||||
int sfd; |
||||
struct sockaddr_in la; |
||||
int yes = 1; |
||||
|
||||
if ((sfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) |
||||
return ERR_SOCKET; |
||||
if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) |
||||
return ERR_OPT; |
||||
|
||||
la.sin_family = AF_INET; |
||||
la.sin_addr.s_addr = inet_addr(temp->IP); |
||||
la.sin_port = htons(8777); |
||||
memset(&(la.sin_zero), 0, 8); |
||||
|
||||
if (bind(sfd, (struct sockaddr *)&la, sizeof(la)) == -1) |
||||
return ERR_BIND; |
||||
|
||||
if (listen(sfd, 10) == -1) |
||||
return ERR_LISTEN; |
||||
|
||||
if (AddConn(CT_CONFIG, sfd, temp->IP) != ERR_OK) |
||||
return ERR_NOMEM; |
||||
|
||||
temp = temp->next; |
||||
} |
||||
} |
||||
|
||||
return ERR_OK; |
||||
} |
||||
|
||||
void |
||||
Send(int sfd, char *msg, ...) { |
||||
va_list ap; |
||||
|
||||
va_start(ap, msg); |
||||
vdprintf(sfd, msg, ap); |
||||
va_end(ap); |
||||
} |
||||
|
||||
int |
||||
MainLoop(void) { |
||||
struct timeval tv; |
||||
|
||||
while (1) { |
||||
int t; |
||||
readable = master; |
||||
tv.tv_sec = 1; |
||||
tv.tv_usec = 0; |
||||
|
||||
t = select(maxfd + 1, &readable, NULL, NULL, &tv); |
||||
if (t != -1) { |
||||
int i; |
||||
|
||||
for (i = 0; i <= maxfd; i++) { |
||||
if (FD_ISSET(i, &readable)) { |
||||
if (Type(i) == CT_LISTEN) { |
||||
struct sockaddr_in ra; |
||||
int al = sizeof(ra); |
||||
int nfd; |
||||
|
||||
if ((nfd = accept(i, (struct sockaddr *)&ra, &al)) != -1) { |
||||
if (ip_allowed(inet_ntoa(ra.sin_addr))) { |
||||
AddConn(CT_CLIENT, nfd, inet_ntoa(ra.sin_addr)); |
||||
Log(MT_MSG, "Connection from allowed IP %s", inet_ntoa(ra.sin_addr)); |
||||
Send(nfd, "R\n"); |
||||
} else { |
||||
Send(nfd, "D\n"); |
||||
Log(MT_MSG, "Attempted connection from denied IP %s", inet_ntoa(ra.sin_addr)); |
||||
close(nfd); |
||||
} |
||||
} |
||||
} |
||||
if (Type(i) == CT_CONFIG) { |
||||
struct sockaddr_in ra; |
||||
int al = sizeof(ra); |
||||
int nfd; |
||||
|
||||
if ((nfd = accept(i, (struct sockaddr *)&ra, &al)) != -1) { |
||||
if (ip_allowed(inet_ntoa(ra.sin_addr))) { |
||||
PST *temp = paddr->next; |
||||
Send(nfd, "P %s\n", paddr->IP); |
||||
while (temp) { |
||||
Send(nfd, "P %s\n", temp->IP); |
||||
temp = temp->next; |
||||
} |
||||
Send(nfd, "S\n"); |
||||
close(nfd); |
||||
Log(MT_MSG, "Sent configuration to %s", inet_ntoa(ra.sin_addr)); |
||||
} else { |
||||
Send(nfd, "D\n"); |
||||
Log(MT_MSG, "Attempted connection from denied IP %s", inet_ntoa(ra.sin_addr)); |
||||
close(nfd); |
||||
} |
||||
} |
||||
} |
||||
if (Type(i) == CT_CLIENT) { |
||||
int r; |
||||
char buf[1024]; |
||||
|
||||
memset(&buf, 0, 1024); |
||||
r = recv(i, &buf, 1023, 0); |
||||
if (r == 0) { |
||||
Log(MT_MSG, "Connection closed from %s", GetIP(i)); |
||||
DelConn(i); |
||||
} |
||||
if (r > 0) { |
||||
char *line = trim(buf, NULL); |
||||
if (line) { |
||||
if (strncmp(line, "L ", 2) == 0) { |
||||
if (LoggedIn(i)) |
||||
Send(i, "L\n"); |
||||
else { |
||||
char *uname, *passw; |
||||
int start; |
||||
|
||||
for (start = 1; start < strlen(line); start++) |
||||
if (isspace(*(line + start))) |
||||
break; |
||||
uname = trim(line + start, NULL); |
||||
|
||||
for (start = 1; start < strlen(uname); start++) |
||||
if (isspace(*(uname + start))) |
||||
break; |
||||
|
||||
passw = trim(uname + start, NULL); |
||||
|
||||
for (start = 0; start < strlen(uname); start++) |
||||
if (isspace(*(uname + start))) |
||||
*(uname + start) = 0; |
||||
|
||||
if (!uname || !passw) |
||||
Send(i, "E\n"); |
||||
else { |
||||
if (!user_allowed(uname)) { |
||||
Log(MT_MSG, "Attempted login by denied user %s from %s", uname, GetIP(i)); |
||||
Send(i, "D\n"); |
||||
} else { |
||||
if (pwcheck(uname, passw) != ERR_OK) { |
||||
Log(MT_MSG, "Login with bad password by %s from %s", uname, GetIP(i)); |
||||
Send(i, "B\n"); |
||||
} else { |
||||
if (SetLogin(i, uname) == ERR_OK) { |
||||
Log(MT_MSG, "Successful login by %s at %s", uname, GetIP(i)); |
||||
Send(i, "S\n"); |
||||
} else { |
||||
Log(MT_MSG, "Failed to log in user %s from %s", uname, GetIP(i)); |
||||
Send(i, "F\n"); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
} |
||||
if (strcmp(line, "Q") == 0) { |
||||
Send(i, "S\n"); |
||||
Log(MT_MSG, "Quit from %s, by %s", GetIP(i), GetUser(i)); |
||||
DelConn(i); |
||||
} |
||||
if (strncmp(line, "U ", 2) == 0) { |
||||
if (!LoggedIn(i)) |
||||
Send(i, "L\n"); |
||||
else { |
||||
int start; |
||||
char *param; |
||||
|
||||
for (start = 2; start < strlen(line); start++) |
||||
if (!isspace(*(line + start))) |
||||
break; |
||||
param = line + start; |
||||
for (start = 0; start < strlen(param); start++) |
||||
if (isspace(*(param + start))) |
||||
break; |
||||
*(param + start) = 0; |
||||
if (!IsNum(param)) |
||||
Send(i, "E\n"); |
||||
else { |
||||