diff --git a/.gitignore b/.gitignore index 9fa3b1b..62abd91 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,4 @@ *.exe *.out *.app +.idea \ No newline at end of file diff --git a/libnss_http/Makefile b/libnss_http/Makefile index 79d0a08..a97c4fe 100644 --- a/libnss_http/Makefile +++ b/libnss_http/Makefile @@ -5,9 +5,7 @@ LD_SONAME=-Wl,-soname,libnss_http.so.2 LIBRARY=libnss_http.so.2.0 LINKS=libnss_http.so.2 libnss_http.so -DESTDIR=/ -PREFIX=$(DESTDIR)/usr -LIBDIR=$(PREFIX)/lib +LIBDIR=/lib64 BUILD=.libs default: build @@ -29,9 +27,12 @@ nss_http_services: nss_http-passwd nss_http-group nss_http-shadow nss_http: nss_http_build_dir nss_http_services $(CC) $(CFLAGS) -c nss_http.c -o $(BUILD)/nss_http.o + $(CC) $(CFLAGS) -c nss_http-config.c -o $(BUILD)/nss_http-config.o + $(CC) -shared $(LD_SONAME) -o $(BUILD)/$(LIBRARY) \ $(BUILD)/nss_http.o \ + $(BUILD)/nss_http-config.o \ $(BUILD)/nss_http-passwd.o \ $(BUILD)/nss_http-group.o \ $(BUILD)/nss_http-shadow.o \ diff --git a/libnss_http/nss_http-config.c b/libnss_http/nss_http-config.c new file mode 100644 index 0000000..7f0ee3b --- /dev/null +++ b/libnss_http/nss_http-config.c @@ -0,0 +1,115 @@ +#include "nss_http.h" + +/* define ip and hostname struct*/ +struct host +{ + char hostname[128]; + char ip[128]; +}; + +void readconfig(struct config *configstruct, char *filename) +{ + // fix httpser & port wrong result + memset(configstruct->httpserver, '\0', sizeof(configstruct->httpserver)); + memset(configstruct->port, '\0', sizeof(configstruct->port)); + memset(configstruct->debug, '\0', sizeof(configstruct->debug)); + FILE *file = fopen (filename, "r"); + + if (file != NULL) + { + char line[MAXBUF]; + + while(fgets(line, sizeof(line), file) != NULL) + { + // remove \n + if(strlen(line) != sizeof(line)-1){line[strlen(line)-1] = '\0';} + char *cfline; + + // escape comment line + if (strncmp(DELIM, line, strlen(DELIM)) == 0) continue; + cfline = strstr((char *)line,DELIM); + // pointer + cfline = cfline + strlen(DELIM); + char *part = strtok(line, DELIM); + + if (strcmp(part, "HTTPSERVER") == 0) + { + memcpy(configstruct->httpserver,cfline,strlen(cfline)); + } + else if (strcmp(part, "PORT") == 0) + { + memcpy(configstruct->port,cfline,strlen(cfline)); + } + else if (strcmp(part, "DEBUG") == 0) + { + memcpy(configstruct->debug,cfline,strlen(cfline)); + } + else if (strcmp(part, "TIMEOUT") == 0) + { + char *e; + errno=0; + // force convert string to long number + configstruct->timeout = strtoll(cfline, &e, 0); + } + } + fclose(file); + } + else + fprintf(stderr, "读取配置文件失败!"); +} + +/*Network part*/ +void networks(struct host *hosts) +{ + memset(hosts->ip, '\0', sizeof(hosts->ip)); + memset(hosts->hostname, '\0', sizeof(hosts->hostname)); + //get hostname + gethostname(hosts->hostname, 128); + + //get default interface + FILE *f; + char line[100], *interface, *c; + f = fopen("/proc/net/route", "r"); + while(fgets(line, 100, f)) + { + interface = strtok(line , " \t"); + c = strtok(NULL , " \t"); + if(interface!=NULL && c!=NULL) + { + if(strcmp(c , "00000000") == 0) break; + } + } + + /* get ip from default interface*/ + int fd; + struct ifreq ifr; + fd = socket(AF_INET, SOCK_DGRAM, 0); + ifr.ifr_addr.sa_family = AF_INET; + strncpy(ifr.ifr_name, interface, IFNAMSIZ-1); + ioctl(fd, SIOCGIFADDR, &ifr); + close(fd); + snprintf(hosts->ip, 128, inet_ntoa(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr)); +} + + +void genurl(char* url, const char *type, const char *key) +{ + struct config con; + struct host hosts; + readconfig(&con, CONFIG_FILE); + networks(&hosts); + if (strlen(key) == 0){ + snprintf(url, 512, "http://%s:%s/%s?userid=%d&ip=%s&hostname=%s", con.httpserver, con.port, type,getuid(), hosts.ip, hosts.hostname); + } + else if ( strlen(key) != 0){ + snprintf(url, 512, "http://%s:%s/%s?%s&userid=%d&ip=%s&hostname=%s", con.httpserver, con.port, type, key, getuid(), hosts.ip, hosts.hostname); + } +} + +void debug_print(const char *func) +{ + struct config con; + readconfig(&con, CONFIG_FILE); + if (strcmp("true", con.debug) == 0) + fprintf(stderr, "NSS DEBUG: Called %s \n", func); +} \ No newline at end of file diff --git a/libnss_http/nss_http-group.c b/libnss_http/nss_http-group.c index 9f18e46..a7aafed 100644 --- a/libnss_http/nss_http-group.c +++ b/libnss_http/nss_http-group.c @@ -13,7 +13,7 @@ static int ent_json_idx = 0; static int pack_group_struct(json_t *root, struct group *result, char *buffer, size_t buflen) { - + DEBUG_LOG; char *next_buf = buffer; size_t bufleft = buflen; @@ -75,7 +75,8 @@ _nss_http_setgrent_locked(int stayopen) json_t *json_root; json_error_t json_error; - snprintf(url, 512, "http://" NSS_HTTP_SERVER ":" NSS_HTTP_PORT "/group"); + //generator url + genurl(url, "group", ""); char *response = nss_http_request(url); if (!response) { @@ -104,6 +105,7 @@ _nss_http_setgrent_locked(int stayopen) enum nss_status _nss_http_setgrent(int stayopen) { + DEBUG_LOG; enum nss_status ret; NSS_HTTP_LOCK(); ret = _nss_http_setgrent_locked(stayopen); @@ -128,6 +130,7 @@ _nss_http_endgrent_locked(void) enum nss_status _nss_http_endgrent(void) { + DEBUG_LOG; enum nss_status ret; NSS_HTTP_LOCK(); ret = _nss_http_endgrent_locked(); @@ -176,6 +179,7 @@ _nss_http_getgrent_r_locked(struct group *result, char *buffer, size_t buflen, i enum nss_status _nss_http_getgrent_r(struct group *result, char *buffer, size_t buflen, int *errnop) { + DEBUG_LOG; enum nss_status ret; NSS_HTTP_LOCK(); ret = _nss_http_getgrent_r_locked(result, buffer, buflen, errnop); @@ -192,7 +196,9 @@ _nss_http_getgrgid_r_locked(gid_t gid, struct group *result, char *buffer, size_ json_t *json_root; json_error_t json_error; - snprintf(url, 512, "http://" NSS_HTTP_SERVER ":" NSS_HTTP_PORT "/group?gid=%d", gid); + char key[128]; + sprintf(key, "gid=%d", gid); + genurl(url, "group", key); char *response = nss_http_request(url); if (!response) { @@ -230,6 +236,7 @@ _nss_http_getgrgid_r_locked(gid_t gid, struct group *result, char *buffer, size_ enum nss_status _nss_http_getgrgid_r(gid_t gid, struct group *result, char *buffer, size_t buflen, int *errnop) { + DEBUG_LOG; enum nss_status ret; NSS_HTTP_LOCK(); ret = _nss_http_getgrgid_r_locked(gid, result, buffer, buflen, errnop); @@ -245,7 +252,9 @@ _nss_http_getgrnam_r_locked(const char *name, struct group *result, char *buffer json_t *json_root; json_error_t json_error; - snprintf(url, 512, "http://" NSS_HTTP_SERVER ":" NSS_HTTP_PORT "/group?name=%s", name); + char key[128]; + sprintf(key, "name=%s", name); + genurl(url, "group", key); char *response = nss_http_request(url); if (!response) { @@ -284,6 +293,7 @@ _nss_http_getgrnam_r_locked(const char *name, struct group *result, char *buffer enum nss_status _nss_http_getgrnam_r(const char *name, struct group *result, char *buffer, size_t buflen, int *errnop) { + DEBUG_LOG; enum nss_status ret; NSS_HTTP_LOCK(); ret = _nss_http_getgrnam_r_locked(name, result, buffer, buflen, errnop); diff --git a/libnss_http/nss_http-passwd.c b/libnss_http/nss_http-passwd.c index a788731..17e1fb8 100644 --- a/libnss_http/nss_http-passwd.c +++ b/libnss_http/nss_http-passwd.c @@ -13,7 +13,7 @@ static int ent_json_idx = 0; static int pack_passwd_struct(json_t *root, struct passwd *result, char *buffer, size_t buflen) { - + DEBUG_LOG; char *next_buf = buffer; size_t bufleft = buflen; @@ -85,7 +85,7 @@ _nss_http_setpwent_locked(int stayopen) json_t *json_root; json_error_t json_error; - snprintf(url, 512, "http://" NSS_HTTP_SERVER ":" NSS_HTTP_PORT "/passwd"); + genurl(url, "passwd", ""); char *response = nss_http_request(url); if (!response) { @@ -114,6 +114,7 @@ _nss_http_setpwent_locked(int stayopen) enum nss_status _nss_http_setpwent(int stayopen) { + DEBUG_LOG; enum nss_status ret; NSS_HTTP_LOCK(); ret = _nss_http_setpwent_locked(stayopen); @@ -138,6 +139,7 @@ _nss_http_endpwent_locked(void) enum nss_status _nss_http_endpwent(void) { + DEBUG_LOG; enum nss_status ret; NSS_HTTP_LOCK(); ret = _nss_http_endpwent_locked(); @@ -186,6 +188,7 @@ _nss_http_getpwent_r_locked(struct passwd *result, char *buffer, size_t buflen, enum nss_status _nss_http_getpwent_r(struct passwd *result, char *buffer, size_t buflen, int *errnop) { + DEBUG_LOG; enum nss_status ret; NSS_HTTP_LOCK(); ret = _nss_http_getpwent_r_locked(result, buffer, buflen, errnop); @@ -202,7 +205,10 @@ _nss_http_getpwuid_r_locked(uid_t uid, struct passwd *result, char *buffer, size json_t *json_root; json_error_t json_error; - snprintf(url, 512, "http://" NSS_HTTP_SERVER ":" NSS_HTTP_PORT "/passwd?uid=%d", uid); + char key[128]; + sprintf(key, "uid=%d", uid); + genurl(url, "passwd", key); + char *response = nss_http_request(url); if (!response) { @@ -240,6 +246,7 @@ _nss_http_getpwuid_r_locked(uid_t uid, struct passwd *result, char *buffer, size enum nss_status _nss_http_getpwuid_r(uid_t uid, struct passwd *result, char *buffer, size_t buflen, int *errnop) { + DEBUG_LOG; enum nss_status ret; NSS_HTTP_LOCK(); ret = _nss_http_getpwuid_r_locked(uid, result, buffer, buflen, errnop); @@ -255,7 +262,9 @@ _nss_http_getpwnam_r_locked(const char *name, struct passwd *result, char *buffe json_t *json_root; json_error_t json_error; - snprintf(url, 512, "http://" NSS_HTTP_SERVER ":" NSS_HTTP_PORT "/passwd?name=%s", name); + char key[128]; + sprintf(key, "name=%s", name); + genurl(url, "passwd", key); char *response = nss_http_request(url); if (!response) { @@ -293,6 +302,7 @@ _nss_http_getpwnam_r_locked(const char *name, struct passwd *result, char *buffe enum nss_status _nss_http_getpwnam_r(const char *name, struct passwd *result, char *buffer, size_t buflen, int *errnop) { + DEBUG_LOG; enum nss_status ret; NSS_HTTP_LOCK(); ret = _nss_http_getpwnam_r_locked(name, result, buffer, buflen, errnop); diff --git a/libnss_http/nss_http-shadow.c b/libnss_http/nss_http-shadow.c index 1169256..0445190 100644 --- a/libnss_http/nss_http-shadow.c +++ b/libnss_http/nss_http-shadow.c @@ -13,7 +13,7 @@ static int ent_json_idx = 0; static int pack_shadow_struct(json_t *root, struct spwd *result, char *buffer, size_t buflen) { - + DEBUG_LOG; char *next_buf = buffer; size_t bufleft = buflen; @@ -77,7 +77,8 @@ _nss_http_setspent_locked(int stayopen) json_t *json_root; json_error_t json_error; - snprintf(url, 512, "http://" NSS_HTTP_SERVER ":" NSS_HTTP_PORT "/shadow"); + + genurl(url, "shadow", ""); char *response = nss_http_request(url); if (!response) { @@ -106,6 +107,7 @@ _nss_http_setspent_locked(int stayopen) enum nss_status _nss_http_setspent(int stayopen) { + DEBUG_LOG; enum nss_status ret; NSS_HTTP_LOCK(); ret = _nss_http_setspent_locked(stayopen); @@ -130,6 +132,7 @@ _nss_http_endspent_locked(void) enum nss_status _nss_http_endspent(void) { + DEBUG_LOG; enum nss_status ret; NSS_HTTP_LOCK(); ret = _nss_http_endspent_locked(); @@ -178,6 +181,7 @@ _nss_http_getspent_r_locked(struct spwd *result, char *buffer, size_t buflen, in enum nss_status _nss_http_getspent_r(struct spwd *result, char *buffer, size_t buflen, int *errnop) { + DEBUG_LOG; enum nss_status ret; NSS_HTTP_LOCK(); ret = _nss_http_getspent_r_locked(result, buffer, buflen, errnop); @@ -193,7 +197,9 @@ _nss_http_getspnam_r_locked(const char *name, struct spwd *result, char *buffer, json_t *json_root; json_error_t json_error; - snprintf(url, 512, "http://" NSS_HTTP_SERVER ":" NSS_HTTP_PORT "/shadow?name=%s", name); + char key[128]; + sprintf(key, "name=%s", name); + genurl(url, "shadow", key); char *response = nss_http_request(url); if (!response) { @@ -227,10 +233,11 @@ _nss_http_getspnam_r_locked(const char *name, struct spwd *result, char *buffer, } -// Find a shadow by name +// Find a shadow entry by name enum nss_status _nss_http_getspnam_r(const char *name, struct spwd *result, char *buffer, size_t buflen, int *errnop) { + DEBUG_LOG; enum nss_status ret; NSS_HTTP_LOCK(); ret = _nss_http_getspnam_r_locked(name, result, buffer, buflen, errnop); diff --git a/libnss_http/nss_http.c b/libnss_http/nss_http.c index bbaaf66..8dba048 100644 --- a/libnss_http/nss_http.c +++ b/libnss_http/nss_http.c @@ -14,12 +14,12 @@ j_strlen(json_t *str) return strlen(json_string_value(str)); } - +//unknow static size_t write_response(void *ptr, size_t size, size_t nmemb, void *stream) { + DEBUG_LOG; struct response *result = (struct response *)stream; size_t required_len = result->pos + size * nmemb; - if(required_len >= NSS_HTTP_INITIAL_BUFFER_SIZE - 1) { if (required_len < NSS_HTTP_MAX_BUFFER_SIZE) @@ -42,9 +42,18 @@ static size_t write_response(void *ptr, size_t size, size_t nmemb, void *stream) } +long gettimeout(void) +{ + struct config con; + readconfig(&con, CONFIG_FILE); + return con.timeout; +} + +// char * nss_http_request(const char *url) { + DEBUG_LOG; CURL *curl = NULL; CURLcode status; struct curl_slist *headers = NULL; @@ -63,8 +72,9 @@ nss_http_request(const char *url) curl_easy_setopt(curl, CURLOPT_URL, url); headers = curl_slist_append(headers, "User-Agent: NSS-HTTP"); - curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); + curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, gettimeout()); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_response); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &write_result); @@ -93,4 +103,3 @@ nss_http_request(const char *url) return NULL; } - diff --git a/libnss_http/nss_http.h b/libnss_http/nss_http.h index 7416dac..e422ed9 100644 --- a/libnss_http/nss_http.h +++ b/libnss_http/nss_http.h @@ -1,6 +1,10 @@ #ifndef NSS_HTTP_H #define NSS_HTTP_H +//gethostname not work fine on c99 mode +#define _BSD_SOURCE + + #include #include #include @@ -12,13 +16,42 @@ #include #include #include +#include +//networks +#include +#include +#include +#include +#include +#include + +//config file location +#define CONFIG_FILE "/etc/nss_http.conf" +//debug mode +#define DEBUG_LOG debug_print(__FUNCTION__) -#define NSS_HTTP_SERVER "localhost" -#define NSS_HTTP_PORT "9669" +//buffer size #define NSS_HTTP_INITIAL_BUFFER_SIZE (256 * 1024) /* 256 KB */ #define NSS_HTTP_MAX_BUFFER_SIZE (10 * 1024 * 1024) /* 10 MB */ +//nss_http-config part +#define MAXBUF 1024 +#define DELIM "=" + +// define nss_http.conf key&value model +struct config +{ + char httpserver[MAXBUF]; + char port[MAXBUF]; + char debug[MAXBUF]; + long timeout; +}; + +//funcitons extern char *nss_http_request(const char *); extern size_t j_strlen(json_t *); +extern void readconfig(struct config *con, char *filename); +extern void debug_print(const char *func); +extern void genurl(char* url, const char *type, const char *key); #endif /* NSS_HTTP_H */ diff --git a/mannul.md b/mannul.md new file mode 100644 index 0000000..562180c --- /dev/null +++ b/mannul.md @@ -0,0 +1,49 @@ +### NSS(name service switch)配置 +``` +passwd: files http +shadow: files http +group: files http +``` +### NSS 模块不必实现所有的DB访问需求 + No service module is forced to have functions for all databases and all kinds to access them. +If a function is not available it is simply treated as if the function would return unavail + +### 系统查询http模块的规则: /lib64/libnss_modulename.so +如:/lib64/libnss_files.so, /lib64/libnss_http.so + +### 函数命名规则 +getxxent: 例如:getgrent, getpwent which means get group entries and password entries +getxxent_r: 例如:getgrent_r + +### 函数解析 + +http://man.chinaunix.net/develop/c&c++/linux_c/function/07.html + +getgrent: 返回一个指向group结构体的指针 +第一次call返回第一条group记录,以此类推,知道返回null或者错误 +setgrent: 使getgrent重新搜索group文件,也就是说从第一条开始 +endgrent: 当group上的所有操作完成后, 关闭group文件 + + + +###setgrent()用来将getgrent()的读写地址指回组文件开头。 + + +endgrent 关闭组文件(由getgrent打开的密码文件) + +endpwent 关闭密码文件(有getpwent打开的密码文件) + +fgetent 从指定的文件来读取组格式 +fgetgrent()会从参数stream指定的文件读取一行数据,然后以group结构将该数据返回。参数stream所指定的文件必须和、etc/group相同的格式。group结构定义请参考getgrent()。 +返回值,返回group结构数据,如果返回NULL则表示已无数据,或有错误发生。 + +fgetpwent(从指定的文件来读取密码格式) +fgetpwent()会从参数stream指定的文件读取一行数据,然后以passwd结构将该数据返回。参数stream所指定的文件必须和/etc/passwd相同的格式。passwd结构定义请参考getpwent()。 +返回值 返回passwd结构数据,如果返回NULL则表示已无数据,或有错误发生。 + +getegid(取得有效的组识别码) + +### 对于加_r的解释, 大概意思就是可以重入的函数,类似cursor,一次读取一条,下一次读取下一条 而不加r的函数就是一次性读取所有的数据 +The functions getgrent_r() and fgetgrent_r() are the reentrant versions of getgrent(3) and fgetgrent(3). +The former reads the next group entry from the stream initialized by setgrent(3). The latter reads the next group entry from the stream fp. + diff --git a/nss_http.conf b/nss_http.conf new file mode 100644 index 0000000..efa6f7f --- /dev/null +++ b/nss_http.conf @@ -0,0 +1,8 @@ +# http server localtion +HTTPSERVER=localhost +# http server port +PORT=9669 +# debug modle +#DEBUG=true +#timeout for http +TIMEOUT=3