diff options
author | LAN-TW <lantw44@gmail.com> | 2013-10-23 02:07:30 +0800 |
---|---|---|
committer | LAN-TW <lantw44@gmail.com> | 2013-10-23 02:07:30 +0800 |
commit | 0cd8997ea2de12bf7da2cabc6956f4a008e18c7c (patch) | |
tree | 5ecf5e84e13abecbdeb491e4ba256aa252d9a2a9 | |
parent | a490b98a996d16aa9544f7144e02034c04c50f59 (diff) | |
download | cn2013-0cd8997ea2de12bf7da2cabc6956f4a008e18c7c.tar.gz cn2013-0cd8997ea2de12bf7da2cabc6956f4a008e18c7c.tar.zst cn2013-0cd8997ea2de12bf7da2cabc6956f4a008e18c7c.zip |
HW1: 加入使用者身份相關內容
-rw-r--r-- | hw1/Makefile.am | 24 | ||||
-rw-r--r-- | hw1/basic-array.c | 133 | ||||
-rw-r--r-- | hw1/basic-array.h | 65 | ||||
-rw-r--r-- | hw1/basic-array2.c | 27 | ||||
-rw-r--r-- | hw1/basic-arrstr.c | 48 | ||||
-rw-r--r-- | hw1/configure.ac | 1 | ||||
-rw-r--r-- | hw1/session.c | 84 |
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; } |