From 963ddf09000baf8e2a34fd51c1897ff295337e17 Mon Sep 17 00:00:00 2001 From: Nishi Date: Fri, 11 Oct 2024 19:30:59 +0000 Subject: [PATCH] added pam git-svn-id: file:///raid/svn-personal/rbuild/trunk@8 c68d3453-7f82-0740-9748-1d72386a946b --- PAM/rbuild | 7 ++++ README | 2 + Server/auth.c | 76 ++++++++++++++++++++++++++++++++++++ Server/config.c | 78 +++++++++++++++++++++++++++++++++++++ Server/main.c | 4 ++ Server/rbs_auth.h | 4 ++ Server/rbs_config.h | 12 ++++++ Server/server.c | 95 +++++++++++++++++++++++++++++++++++++++++++-- config.h | 8 ++++ 9 files changed, 282 insertions(+), 4 deletions(-) create mode 100644 PAM/rbuild create mode 100644 config.h diff --git a/PAM/rbuild b/PAM/rbuild new file mode 100644 index 0000000..36ff444 --- /dev/null +++ b/PAM/rbuild @@ -0,0 +1,7 @@ +# $Id$ +# vim: syntax=pamconf + +auth required pam_unix.so +account required pam_unix.so +password required pam_deny.so +session required pam_deny.so diff --git a/README b/README index c80c831..ee7a428 100644 --- a/README +++ b/README @@ -1 +1,3 @@ Remote builder. Useful for cross-compiling, just to reduce your resource usage, etc. + +You probably want to copy PAM/rbuild to /etc/pam.d to get PAM authentication working. diff --git a/Server/auth.c b/Server/auth.c index c196dcb..ec4d4f1 100644 --- a/Server/auth.c +++ b/Server/auth.c @@ -2,6 +2,14 @@ #include "rbs_auth.h" +#include "rbs_config.h" + +#include +#include + +#include +#include + #ifdef HAS_PAM_AUTH #include #endif @@ -37,3 +45,71 @@ const char* rbs_none_auth = "not available" #endif ; + +#ifdef HAS_PAM_AUTH +int rbs_pam_conv(int nmsg, const struct pam_message** msg, struct pam_response** resp, void* appdata){ + int i; + *resp = malloc(sizeof(**resp) * nmsg); + for(i = 0; i < nmsg; i++){ + if((*msg)[i].msg_style == PAM_PROMPT_ECHO_OFF || (*msg)[i].msg_style == PAM_PROMPT_ECHO_ON){ + (*resp)[i].resp = cm_strdup((const char*)appdata); + (*resp)[i].resp_retcode = 0; + } + } + return PAM_SUCCESS; +} + +CMBOOL rbs_auth_pam(const char* username, const char* password){ + CMBOOL state = CMFALSE; + struct pam_conv conv; + pam_handle_t* pamh = NULL; + int retval; + conv.conv = rbs_pam_conv; + conv.appdata_ptr = (void*)password; + retval = pam_start("rbuild", NULL, &conv, &pamh); + if(retval == PAM_SUCCESS){ + retval = pam_set_item(pamh, PAM_USER, username); + } + if(retval == PAM_SUCCESS){ + retval = pam_authenticate(pamh, 0); + } + if(retval == PAM_SUCCESS){ + retval = pam_acct_mgmt(pamh, 0); + } + if(retval == PAM_SUCCESS){ + state = CMTRUE; + } + pam_end(pamh, retval); + return state; +} +#endif + +CMBOOL rbs_auth(const char* section, const char* username, const char* password){ + char* auth = cm_strdup(rbs_config_get(section, "auth")); + int i; + char* arg = NULL; + CMBOOL state = CMFALSE; + for(i = 0; auth[i] != 0; i++){ + if(auth[i] == ':'){ + arg = auth + i + 1; + auth[i] = 0; + break; + } + } +#ifdef HAS_NONE_AUTH + if(strcmp(auth, "none") == 0){ + state = CMTRUE; + }else +#endif +#ifdef HAS_PAM_AUTH + if(strcmp(auth, "pam") == 0){ + state = rbs_auth_pam(username, password); + }else +#endif + if(1){ + free(auth); + return CMFALSE; + } + free(auth); + return state; +} diff --git a/Server/config.c b/Server/config.c index cbf772c..b757eca 100644 --- a/Server/config.c +++ b/Server/config.c @@ -2,19 +2,97 @@ #include "rbs_config.h" +#include #include +#include +#include +#include #include +extern CMBOOL run_inetd; + +struct rbs_section sections[1024]; +int used_sections = -1; + extern char* rbs_config; void rbs_config_init(void){ + int i; + for(i = 0; i <= used_sections; i++){ + int j; + for(j = 0; j < sections[i].used; j++){ + free(sections[i].attr[j].key); + free(sections[i].attr[j].value); + } + free(sections[i].name); + } + used_sections = -1; +} + +char* rbs_config_get(const char* section, const char* key){ + int i; + for(i = 0; i <= used_sections; i++){ + if(strcmp(sections[i].name, section) == 0){ + int j; + for(j = 0; j < sections[i].used; j++){ + if(strcmp(sections[i].attr[j].key, key) == 0) return sections[i].attr[j].value; + } + } + } + return ""; } CMBOOL rbs_config_parse(void){ FILE* f = fopen(rbs_config, "r"); if(f != NULL){ + struct stat s; + if(stat(rbs_config, &s) == 0){ + char* buf = malloc(s.st_size + 1); + int i; + int incr = 0; + buf[s.st_size] = 0; + fread(buf, 1, s.st_size, f); + for(i = 0;; i++){ + if(buf[i] == 0 || buf[i] == '\n'){ + char oldc = buf[i]; + char* line; + buf[i] = 0; + + line = buf + incr; + if(strlen(line) > 0 && line[0] != '#'){ + if(line[0] == '[' && line[strlen(line) - 1] == ']'){ + line[strlen(line) - 1] = 0; + used_sections++; + sections[used_sections].name = cm_strdup(line + 1); + sections[used_sections].used = 0; + if(!run_inetd) printf("Adding section `%s'\n", line + 1); + }else if(used_sections == -1){ + }else{ + int j; + for(j = 0; line[j] != 0; j++){ + if(line[j] == '='){ + line[j] = 0; + sections[used_sections].attr[sections[used_sections].used].key = cm_strdup(line); + sections[used_sections].attr[sections[used_sections].used].value = cm_strdup(line + j + 1); + if(!run_inetd) printf("\t%s: `%s'\n", line, line + j + 1); + sections[used_sections].used++; + break; + } + } + } + } + + incr = i + 1; + if(oldc == 0) break; + }else if(buf[i] == '\r'){ + buf[i] = 0; + } + } + free(buf); + } fclose(f); + if(used_sections == -1) return CMFALSE; return CMTRUE; }else{ fprintf(stderr, "Could not open the config\n"); diff --git a/Server/main.c b/Server/main.c index 0a38e6a..6f02e21 100644 --- a/Server/main.c +++ b/Server/main.c @@ -20,6 +20,7 @@ extern const char* rbs_pam_auth; int main(int argc, char** argv){ int i; + CMBOOL dryrun = CMFALSE; for(i = 1; i < argc; i++){ if(argv[i][0] == '-'){ if(strcmp(argv[i], "--inetd") == 0 || strcmp(argv[i], "-i") == 0){ @@ -31,6 +32,8 @@ int main(int argc, char** argv){ return 1; } rbs_config = argv[i]; + }else if(strcmp(argv[i], "--dry-run") == 0 || strcmp(argv[i], "-d") == 0){ + dryrun = CMTRUE; }else if(strcmp(argv[i], "--version") == 0 || strcmp(argv[i], "-V") == 0){ printf("rbuild-server version %s\n", RBUILD_VERSION); printf("Authentication methods:\n"); @@ -55,6 +58,7 @@ int main(int argc, char** argv){ fprintf(stderr, "Failed to parse config\n"); return 1; } + if(dryrun) return 0; if(!rbs_server_init()){ fprintf(stderr, "Failed to initialize\n"); return 1; diff --git a/Server/rbs_auth.h b/Server/rbs_auth.h index e811914..4ac1e49 100644 --- a/Server/rbs_auth.h +++ b/Server/rbs_auth.h @@ -3,4 +3,8 @@ #ifndef __RBS_AUTH_H__ #define __RBS_AUTH_H__ +#include + +CMBOOL rbs_auth(const char* section, const char* username, const char* password); + #endif diff --git a/Server/rbs_config.h b/Server/rbs_config.h index 538601b..0dda5e4 100644 --- a/Server/rbs_config.h +++ b/Server/rbs_config.h @@ -6,6 +6,18 @@ #include void rbs_config_init(void); +char* rbs_config_get(const char* section, const char* key); CMBOOL rbs_config_parse(void); +struct rbs_kv { + char* key; + char* value; +}; + +struct rbs_section { + char* name; + struct rbs_kv attr[128]; + int used; +}; + #endif diff --git a/Server/server.c b/Server/server.c index 6ce96c4..ea9c36e 100644 --- a/Server/server.c +++ b/Server/server.c @@ -3,6 +3,7 @@ #include "../config.h" #include "rbs_server.h" +#include "rbs_config.h" #include "rbs_auth.h" #include @@ -32,6 +33,7 @@ int server_socket; int port = 7980; CMBOOL rbs_server_init(void){ + ready = cm_strdup(RBUILD_VERSION); if(run_inetd){ return CMTRUE; }else{ @@ -87,8 +89,46 @@ void rbs_close(int sock){ #endif } +char* rbs_readline(int sock){ + char cbuf[2]; + char* line; + cbuf[1] = 0; + line = cm_strdup(""); + do{ + fd_set rfds; + struct timeval tv; + int ret; + + FD_ZERO(&rfds); + FD_SET(sock, &rfds); + tv.tv_sec = 5; + tv.tv_usec = 0; + + ret = select(FD_SETSIZE, &rfds, NULL, NULL, &tv); + if(ret <= 0){ + free(line); + return NULL; + } + if(run_inetd){ + fread(cbuf, 1, 1, stdin); + }else{ + recv(sock, cbuf, 1, 0); + } + if(cbuf[0] != '\n' && cbuf[0] != '\r'){ + char* tmp = line; + line = cm_strcat(tmp, cbuf); + free(tmp); + } + }while(cbuf[0] != '\n'); + return line; +} + void rbs_server_handler(void* sockptr){ - int sock = -1; + int sock = 0; + char* user = NULL; + char* pass = NULL; + char* section = NULL; + CMBOOL authed = CMFALSE; if(sockptr != NULL){ sock = *(int*)sockptr; free(sockptr); @@ -107,14 +147,61 @@ void rbs_server_handler(void* sockptr){ tv.tv_sec = 5; tv.tv_usec = 0; - ret = select(1, &rfds, NULL, NULL, &tv); + ret = select(FD_SETSIZE, &rfds, NULL, NULL, &tv); if(ret < 0){ break; }else if(ret == 0){ - rbs_write(sock, "TIMEOUT\n", 8); break; }else{ + char* line = rbs_readline(sock); + int i; + char* arg = NULL; + char* cmd = line; + if(line == NULL){ + break; + } + for(i = 0; line[i] != 0; i++){ + if(line[i] == ' '){ + line[i] = 0; + arg = line + i + 1; + break; + } + } + if(strcmp(cmd, "QUIT") == 0){ + free(line); + break; + }else if(strcmp(cmd, "SECTION") == 0 && arg != NULL){ + if(strcmp(rbs_config_get(arg, "auth"), "") == 0 || section != NULL){ + free(line); + break; + } + section = cm_strdup(arg); + }else if(strcmp(cmd, "USER") == 0 && arg != NULL){ + if(section == NULL || user != NULL){ + free(line); + break; + } + user = cm_strdup(arg); + }else if(strcmp(cmd, "PASS") == 0 && arg != NULL){ + if(user == NULL || pass != NULL){ + free(line); + break; + } + pass = cm_strdup(arg); + if(rbs_auth(section, user, pass)){ + rbs_write(sock, "SUCCESS\n", 8); + authed = CMTRUE; + }else{ + rbs_write(sock, "FAIL\n", 5); + free(line); + break; + } + }else{ + free(line); + break; + } + free(line); } } @@ -126,9 +213,9 @@ void rbs_server_handler(void* sockptr){ CMBOOL rbs_server_loop(void){ if(run_inetd){ + setvbuf(stdin, NULL, _IONBF, 0); rbs_server_handler(NULL); }else{ - ready = cm_strdup(RBUILD_VERSION); #ifndef WINSOCK signal(SIGCHLD, SIG_IGN); #endif diff --git a/config.h b/config.h new file mode 100644 index 0000000..4e7153b --- /dev/null +++ b/config.h @@ -0,0 +1,8 @@ +/* $Id$ */ + +#ifndef __CONFIG_H__ +#define __CONFIG_H__ + +#define RBUILD_VERSION "1.00" + +#endif -- 2.45.2