summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLAN-TW <lantw44@gmail.com>2013-10-23 02:07:30 +0800
committerLAN-TW <lantw44@gmail.com>2013-10-23 02:07:30 +0800
commit0cd8997ea2de12bf7da2cabc6956f4a008e18c7c (patch)
tree5ecf5e84e13abecbdeb491e4ba256aa252d9a2a9
parenta490b98a996d16aa9544f7144e02034c04c50f59 (diff)
downloadcn2013-0cd8997ea2de12bf7da2cabc6956f4a008e18c7c.tar.gz
cn2013-0cd8997ea2de12bf7da2cabc6956f4a008e18c7c.tar.zst
cn2013-0cd8997ea2de12bf7da2cabc6956f4a008e18c7c.zip
HW1: 加入使用者身份相關內容
-rw-r--r--hw1/Makefile.am24
-rw-r--r--hw1/basic-array.c133
-rw-r--r--hw1/basic-array.h65
-rw-r--r--hw1/basic-array2.c27
-rw-r--r--hw1/basic-arrstr.c48
-rw-r--r--hw1/configure.ac1
-rw-r--r--hw1/session.c84
7 files changed, 378 insertions, 4 deletions
diff --git a/hw1/Makefile.am b/hw1/Makefile.am
index b314c9b..a35e644 100644
--- a/hw1/Makefile.am
+++ b/hw1/Makefile.am
@@ -1,7 +1,25 @@
+NULL =
+
EXTRA_DIST = autogen.sh
+
bin_PROGRAMS = ras-server
noinst_LIBRARIES = libbasic.a libras.a
-libbasic_a_SOURCES = xwrap.c xwrap.h basic-list.c basic-list.h
-libras_a_SOURCES = socktool.c socktool.h connection.c connection.h
-ras_server_SOURCES = server-main.c server.c server.h session.c session.h
+
+libbasic_a_SOURCES = \
+ xwrap.c xwrap.h \
+ basic-list.c basic-list.h \
+ basic-array.c basic-arrstr.c basic-array2.c basic-array.h \
+ $(NULL)
+
+libras_a_SOURCES = \
+ socktool.c socktool.h \
+ connection.c connection.h \
+ $(NULL)
+
+ras_server_SOURCES = \
+ server.c server.h \
+ session.c session.h \
+ server-main.c \
+ $(NULL)
+
ras_server_LDADD = $(top_builddir)/libbasic.a $(top_builddir)/libras.a
diff --git a/hw1/basic-array.c b/hw1/basic-array.c
new file mode 100644
index 0000000..5d5f61e
--- /dev/null
+++ b/hw1/basic-array.c
@@ -0,0 +1,133 @@
+#include "xwrap.h"
+#include <stdlib.h>
+#include <string.h>
+#include "basic-array.h"
+
+Array* array_create_setmax(int itemsize, int len, int maxlen){
+ if(itemsize <= 0 || len < 0 || maxlen < len){
+ return NULL;
+ }
+ Array* arr = (Array*)xmalloc(sizeof(Array));
+ if(arr == NULL){
+ return NULL;
+ }
+ arr->arr_itemsize = itemsize;
+ arr->arr_curlen = len;
+ arr->arr_maxlen = maxlen;
+ if(maxlen != 0){
+ arr->arr_data = xmalloc(itemsize * maxlen);
+ if(arr->arr_data == NULL){
+ free(arr);
+ return NULL;
+ }
+ }else{
+ arr->arr_data = NULL;
+ }
+ return arr;
+}
+
+Array* array_create(int itemsize, int len){
+ return array_create_setmax(itemsize, len, len);
+}
+
+void array_free(Array* arr){
+ if(arr->arr_data != NULL){
+ free(arr->arr_data);
+ }
+ free(arr);
+}
+
+int array_pushback(Array* arr, const void* data){
+ if((arr->arr_maxlen) < (arr->arr_curlen + 1)){
+ if(arr->arr_maxlen != 0){
+ if(array_setmax(arr, arr->arr_maxlen*2) < 0){
+ return -1;
+ }
+ }else{
+ if(array_setmax(arr, 1) < 0){
+ return -1;
+ }
+ }
+ }
+ memcpy(array_vp(arr, arr->arr_curlen), data, arr->arr_itemsize);
+ arr->arr_curlen++;
+ return 0;
+}
+
+int array_setlen(Array* arr, int len){
+ if(len > (arr->arr_maxlen)){
+ if(array_setmax(arr, len) < 0){
+ return -1;
+ }else{
+ arr->arr_curlen = len;
+ }
+ }else{
+ arr->arr_curlen = len;
+ return 0;
+ }
+ return 0;
+}
+
+int array_setmax(Array* arr, int max){
+ void* newptr;
+ if(arr->arr_data == NULL){
+ newptr = xmalloc((arr->arr_itemsize)*max);
+ if(newptr == NULL){
+ return -1;
+ }else{
+ arr->arr_maxlen = max;
+ arr->arr_data = newptr;
+ return 0;
+ }
+ }
+ newptr = realloc(arr->arr_data, (arr->arr_itemsize)*max);
+ if(newptr == NULL){
+ return -1;
+ }else{
+ arr->arr_maxlen = max;
+ arr->arr_data = newptr;
+ }
+ return 0;
+}
+
+int array_strip(Array* arr){
+ if(arr->arr_data == NULL){
+ return 0;
+ }
+ Array* newptr;
+ /* 其實縮小空間營該一定會成功才對......
+ * 不過還是保險一點,加個判斷式,別說 memory leak 是我害的
+ * 當然也是避免編譯器一直跳 warning
+ */
+ if((arr->arr_maxlen) > (arr->arr_curlen)){
+ arr->arr_maxlen = arr->arr_curlen;
+ newptr = realloc(arr->arr_data, (arr->arr_curlen)*(arr->arr_itemsize));
+ if(newptr == NULL){
+ return -1;
+ }
+ arr->arr_data = newptr;
+ }
+ return 0;
+}
+
+/* 基本上直接玩 struct 的函式還是少用吧 */
+void* array_drop_struct(Array* arr){
+ void* toreturn = arr->arr_data;
+ free(arr);
+ return toreturn;
+}
+
+Array* array_make_struct(void* data, int itemsize, int len, int maxlen){
+ if(itemsize <= 0 || len < 0 || maxlen < len){
+ return NULL;
+ }
+ Array* arr = (Array*)xmalloc(sizeof(Array));
+ if(arr == NULL){
+ return NULL;
+ }
+ arr->arr_itemsize = itemsize;
+ arr->arr_curlen = len;
+ arr->arr_maxlen = maxlen;
+ arr->arr_data = data;
+ return arr;
+}
diff --git a/hw1/basic-array.h b/hw1/basic-array.h
new file mode 100644
index 0000000..ee0de42
--- /dev/null
+++ b/hw1/basic-array.h
@@ -0,0 +1,65 @@
+#include "xwrap.h"
+#ifndef L4LIB_DYNAMIC_ARRAY
+#define L4LIB_DYNAMIC_ARRAY
+
+#include <stdio.h> /* 取得 FILE */
+
+/*********** 一維陣列 ***********/
+
+typedef struct l4lib_dyn_arr{
+ int arr_itemsize; /* 每個項目的大小 */
+ int arr_curlen; /* 陣列總長度 */
+ int arr_maxlen; /* 陣列最大長度 */
+ void* arr_data; /* 資料區 */
+} Array ;
+
+Array* array_create_setmax(int, int, int);
+Array* array_create(int, int);
+void array_free(Array*);
+int array_pushback(Array*, const void*);
+#define array_popback(arr) (((arr)->arr_curlen)--)
+#define array_getlen(arr) ((arr)->arr_curlen)
+int array_setlen(Array*, int);
+#define array_getmax(arr) ((arr)->arr_maxlen)
+int array_setmax(Array*, int);
+int array_strip(Array*);
+#define array_itemsize(arr) ((arr)->arr_itemsize)
+#define array_data(arr) ((arr)->arr_data)
+#define array_v(arr, type, num) \
+ (*(((type*)((arr)->arr_data))+(num)))
+#define array_vp(arr, num) \
+ ((void*)(((char*)((arr)->arr_data))+(((arr)->arr_itemsize)*(num))))
+
+#define array_readline() (array_filereadline_delim(stdin, '\n'))
+#define array_readline_delim(delim) (array_filereadline_delim(stdin, (delim)))
+#define array_filereadline(infile) (array_filereadline_delim((infile), '\n'))
+Array* array_filereadline_delim(FILE*, int);
+
+Array* array_dup(const Array*);
+int array_combine(Array*, const Array*);
+
+void* array_drop_struct(Array*);
+Array* array_make_struct(void*, int, int, int);
+
+/*********** 二維陣列 (其實是用一維陣列來模擬,功能有限) ***********/
+
+typedef struct l4lib_dyn_2darr{
+ int arr_itemsize; /* 每個項目的大小 */
+ int arr_lenx; /* 陣列 x 方向長度 */
+ int arr_leny; /* 陣列 y 方向長度 */
+ void* arr_data; /* 資料區 */
+} ArrayTwo ;
+
+ArrayTwo* array_two_create(int, int, int);
+void array_two_free(ArrayTwo*);
+#define array_two_getlenx(arr) ((arr)->arr_lenx)
+#define array_two_getleny(arr) ((arr)->arr_leny)
+#define array_two_itemsize(arr) ((arr)->arr_itemsize)
+#define array_two_data(arr) ((arr)->arr_data)
+#define array_two_v(arr, type, numx, numy) \
+ (*(((type*)((arr)->arr_data))+((numx)*(array_two_getleny(arr)))+(numy)))
+#define array_two_vp(arr, numx, numy) \
+ ((void*)(((char*)((arr)->arr_data))+ \
+ ((arr)->arr_itemsize)*((numx)*(array_two_getleny(arr))+(numy))))
+
+#endif
diff --git a/hw1/basic-array2.c b/hw1/basic-array2.c
new file mode 100644
index 0000000..848ec67
--- /dev/null
+++ b/hw1/basic-array2.c
@@ -0,0 +1,27 @@
+#include "xwrap.h"
+#include <stdlib.h>
+#include "basic-array.h"
+
+ArrayTwo* array_two_create(int itemsize, int lenx, int leny){
+ if(lenx <= 0 || leny <= 0 || itemsize <= 0){
+ return NULL;
+ }
+ ArrayTwo* arr = (ArrayTwo*)xmalloc(sizeof(ArrayTwo));
+ if(arr == NULL){
+ return NULL;
+ }
+ arr->arr_itemsize = itemsize;
+ arr->arr_lenx = lenx;
+ arr->arr_leny = leny;
+ arr->arr_data = xmalloc(itemsize*lenx*leny);
+ if(arr->arr_data == NULL){
+ free(arr);
+ return NULL;
+ }
+ return arr;
+}
+
+void array_two_free(ArrayTwo* arr){
+ free(arr->arr_data);
+ free(arr);
+}
diff --git a/hw1/basic-arrstr.c b/hw1/basic-arrstr.c
new file mode 100644
index 0000000..f15bd22
--- /dev/null
+++ b/hw1/basic-arrstr.c
@@ -0,0 +1,48 @@
+#include "xwrap.h"
+#include <string.h>
+#include "basic-array.h"
+
+Array* array_dup(const Array* arr){
+ Array* newarr = array_create_setmax(
+ array_itemsize(arr), array_getlen(arr), array_getmax(arr));
+ if(newarr == NULL){
+ return NULL;
+ }
+ memcpy(newarr->arr_data, arr->arr_data,
+ array_getlen(arr) * array_itemsize(arr));
+ return newarr;
+}
+
+int array_combine(Array* arr, const Array* att){
+ if(array_itemsize(arr) != array_itemsize(att)){
+ return -2;
+ }
+ if(array_setlen(arr, array_getlen(arr) + array_getlen(att)) < 0){
+ return -1;
+ }
+ memcpy(array_vp(arr, array_getlen(arr)), att->arr_data,
+ array_getlen(att) * array_itemsize(att));
+ return 0;
+}
+
+Array* array_filereadline_delim(FILE* infile, int chr){
+ Array* newarr = array_create(1, 0);
+ if(newarr == NULL){
+ return NULL;
+ }
+ int c;
+ char towrite;
+ while((c = getc(infile)) != chr && !feof(infile)){
+ towrite = c;
+ if(array_pushback(newarr, (void*)&towrite) < 0){
+ array_free(newarr);
+ return NULL;
+ }
+ }
+ towrite = '\0';
+ if(array_pushback(newarr, (void*)&towrite) < 0){
+ array_free(newarr);
+ return NULL;
+ }
+ return newarr;
+}
diff --git a/hw1/configure.ac b/hw1/configure.ac
index b85f2d5..e13206a 100644
--- a/hw1/configure.ac
+++ b/hw1/configure.ac
@@ -27,6 +27,7 @@ AC_TYPE_UINT16_T
# Checks for library functions.
AC_FUNC_MALLOC
AC_FUNC_REALLOC
+AC_CHECK_FUNCS([setgroups initgroups])
AC_CONFIG_FILES([Makefile])
AC_OUTPUT
diff --git a/hw1/session.c b/hw1/session.c
index dd416a8..40a0e65 100644
--- a/hw1/session.c
+++ b/hw1/session.c
@@ -8,6 +8,7 @@
#include "socktool.h"
#include "connection.h"
#include "server.h"
+#include "basic-array.h"
#include <errno.h>
#include <grp.h>
@@ -92,7 +93,7 @@ int ras_session_read_header (RasSession* session) {
next = oneline + onelinelen;
} else {
*space = '\0';
- for (space++; *space != '\0' && *space != ' '; space++);
+ for (space++; *space == '\0' && *space == ' '; space++);
next = space;
}
@@ -110,6 +111,87 @@ int ras_session_read_header (RasSession* session) {
return -1;
}
+ struct passwd* login_user = NULL;
+ if (*next != '\0') {
+ login_user = getpwnam (next);
+ if (login_user == NULL) {
+ const char baduser_msg[] = "Error: User not found.\n";
+ const int baduser_len = STATIC_STRLEN (baduser_msg);
+ ras_socktool_write_string (RAS_CONN (session)->fd, baduser_msg, baduser_len);
+ ras_session_log (session, "user %s cannot be found", next);
+ free (oneline);
+ return -1;
+ }
+ }
+
+ free (oneline);
+
+ if (RAS_CONN (session)->perm == RAS_CONN_PERM_RESTRICTED) {
+ uid_t real_uid = getuid ();
+ if (login_user != NULL && login_user->pw_uid != real_uid) {
+ const char rest_msg[] = "Error: You are not permitted to login from here.\n";
+ const int rest_len = STATIC_STRLEN (rest_msg);
+ ras_socktool_write_string (RAS_CONN (session)->fd, rest_msg, rest_len);
+ ras_session_log (session, "user %s is not permitted", login_user->pw_name);
+ return -1;
+ }
+ setuid (real_uid);
+ } else {
+ const char sufail_msg[] = "Error: Unable to change the user credential.\n";
+ const int sufail_len = STATIC_STRLEN (sufail_msg);
+ int rval;
+
+#if defined(HAVE_INITGROUPS)
+ rval = initgroups (login_user->pw_name, login_user->pw_gid);
+#elif defined(HAVE_SETGROUPS)
+ struct group* groupentry;
+ Array* grouplist = array_create (sizeof (gid_t), 1);
+ int errno_saved;
+
+ array_pushback (grouplist, &login_user->pw_gid);
+ setgrent ();
+ while ((groupentry = getgrent ()) != NULL) {
+ for (int i = 0; groupentry->gr_mem[i] != NULL; i++) {
+ if (strcmp (groupentry->gr_mem[i], login_user->pw_name) == 0) {
+ array_pushback (grouplist, &groupentry->gr_gid);
+ }
+ }
+ }
+ endgrent ();
+
+ rval = setgroups (array_getlen (grouplist), array_data (grouplist));
+
+ errno_saved = errno;
+ array_free (grouplist);
+ errno = errno_saved;
+#endif
+
+ if (rval < 0) {
+ write (RAS_CONN (session)->fd, sufail_msg, sufail_len);
+ ras_session_log (session,
+ "cannot set supplementary groups: %s", strerror (errno));
+ return -1;
+ }
+
+ rval = setgid (login_user->pw_gid);
+ if (rval < 0) {
+ write (RAS_CONN (session)->fd, sufail_msg, sufail_len);
+ ras_session_log (session,
+ "cannot set primary group to %d: %s",
+ login_user->pw_gid, strerror (errno));
+ return -1;
+ }
+
+ rval = setuid (login_user->pw_uid);
+ if (rval < 0) {
+ write (RAS_CONN (session)->fd, sufail_msg, sufail_len);
+ ras_session_log (session,
+ "cannot set user to %s (uid = %d): %s",
+ login_user->pw_name, login_user->pw_uid, strerror (errno));
+ return -1;
+ }
+ }
+
return 0;
}