/* * Copyright (c) 1996-2007, OpenFWTK Development Group * All rights reserved. See LICENSE. */ /* cvs-gw proxy for cvs pserver protocol see: http://rai16.informatik.uni-stuttgart.de/doc/cvs/html-cvsclient/cvsclient_toc.html for detailed protocol description */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "firewall.h" #include "firewall2.h" #include "fwfunc.h" #ifndef MIN # define MIN(a, b) (((a) > (b)) ? (b) : (a)) #endif static int extendperm = 0; static int transparent = 0; static unsigned int user_limit = 31; static unsigned int pass_limit = 31; static unsigned int retr_file_limit = 0; /* default: unlimited */ static unsigned int send_file_limit = 0; /* default: unlimited */ static char mode[MAX_STR] = "ro"; static char separator[1] = "$"; static char **validests = (char **)0; static char **validusers = (char **)0; extern struct fwstats proxy_stats; extern Cfg* proxy_confp; static Cfg *confp; static int cdscp = 0; static int sdscp = 0; extern void proxy_parse_options(Cfg *cf, fwparm options[]); extern Cfg* proxy_init(int ac, char *av[]); extern void proxy_exit(void); extern void proxy_update_operation(char *op); extern int get_resp (int server_fd, int client_fd, int flag, unsigned int op_type); extern void resolve_flags (int server_fd, int client_fd, char *command, int flags, int argc, char **argv); extern int auth_perm(Cfg*, char*, char*, char*, char**); extern int conn_server(char *srv, int portnum, int priv, char *rbuf); extern int enargv(char *buf, char **av, int avsiz, char *tobuf, int bsiz); extern time_t dgets_timeout(int sec); /*Control flags*/ #define MLINE 00020 /* Waiting for multiline response */ #define MNEXTLINE 00040 /* Waiting for undeclareted command from client at the next line*/ #define FTRANSMISSION 00100 /* deam! another shit with lame code =) */ #define ENDRESPONSE 00200 /* server response is done */ #define PARTPATHNAME 00400 /* pathname to files in responses contains two parts (path in repository and obsolute server path) */ #define NEWENTRIESLINE 01000 /* Some as MNEXLINE */ #define CHECKFLAGS 02000 /* Allowing or Disallowing some server responses */ #define OP_INTERNAL 04000 /* This one for internal use only*/ int get_response(int server_fd, int flags); int ok_resp( char *buff); int make_file_transmission(int client_fd, int server_fd, int flags, char **argv); void pre_check(int op_type, char *command, int flags, int argc, char **argv); static void handle_term(int); static int server_fd; /*Usefull flags*/ #define SERVER_COMMANDS 0100000 #define CLIENT_COMMANDS 0010000 #define PSERVERPORT 2401 #define KSERVERPORT 1999 /* Not emplimented yet by the promlems with kerberos */ #define AUTHFLDS 5 /* Number of fields in auth section */ #define MAXCOMFILESZ 1024 /* Maximum size of the single file what user can put in cvs-repository (IN kBytes) */ #define MAXBUFSZ 2048 #define MAXLINELEN 1024 #define MAXRESP 1024 /* Maximum size of user command */ #define MAXCMDNUM 64 #define RESPONSE 1 #define REQUEST 0 /*some definitions for so library*/ #define SO_LNONE 0 #define SO_LLF 3 /* Auth fields, is it required in further in logs? */ char authflds[AUTHFLDS][MAXLINELEN]; /* 1 - is cvs path */ /* 2 - is username */ /* 3 - is password [Not needed at this time, */ /* (trivially encoded by Password scrambling algorithm),*/ /* but who knows? =)] */ /*0 & 4 is auth tags */ char syslog_msg[MAXBUFSZ]; char client_msg[MAXBUFSZ]; static void close_all() { if(strlen(client_msg)) sosayn(0, client_msg, MIN(MAXLINELEN - 1,strlen(client_msg))); else { bzero(client_msg, sizeof(client_msg)); snprintf(client_msg, MAXBUFSZ, "E Some problems with client-proxy-server connection\n"\ "E serv:port - %.100s:%hd\n" \ "error 0\n", proxy_stats. dst,proxy_stats.port); sosayn(0, client_msg, MIN(MAXLINELEN - 1,strlen(client_msg))); } if(*syslog_msg) syslog(LLEV, "%.256s", syslog_msg); else { syslog(LLEV, "going down on internal error: %s", strerror(errno)); } if(server_fd > 0) close(server_fd); close(0); proxy_exit(); } static void handle_term (sig) int sig; { bzero(syslog_msg, sizeof(syslog_msg)); snprintf(syslog_msg, MAXBUFSZ, "going down on signal SIGTERM"); close_all(); proxy_exit(); } static int conn_cvs_server(buff) char *buff; { int server_fd = -1; char *ptr, *s, *t; char server[sizeof(proxy_stats.dst)]; int port = PSERVERPORT; int have_error = 0; /*Flag for error configuration data */ char username[MAXLINELEN]; char authline[MAXLINELEN]; bzero(username, sizeof(username)); /*Take out username, server and port(? if exist the last one)*/ if (!(*proxy_stats.dst)) { bzero(authline, sizeof(authline)); bzero(server, sizeof(server)); strncpy(authline, authflds[2], MIN(MAXLINELEN, strlen(authflds[2]))); s = authline; if((t = index(authline, separator[0])) != NULL) if((ptr = strtok(s, separator)) != NULL) strncpy(username, ptr, sizeof(username) - 1); if(strlen(username) && (t = index(authline + strlen(username) + 1, separator[0])) != NULL) { if((ptr = strtok(NULL, separator)) != NULL) { strncpy(server, ptr, 64); if((ptr = strtok(NULL, "@")) != NULL) port = atoi(ptr); else have_error = 1; } else have_error = 2; } else { if((ptr = strtok(NULL, separator)) != NULL) strncpy(server, ptr, 64); else have_error = 3; } } else { strncpy(username, authflds[2], sizeof(username) -1); } if(have_error) { snprintf(syslog_msg, MAXBUFSZ, "cannot parse CVSROOT data %.100s:%hd - %s", proxy_stats.dst,proxy_stats.port,strerror(errno)); snprintf(client_msg, MAXBUFSZ, "E Fatal error, aborting.\n" \ "E Check yours CVSROOT, can't connect server:port %.100s:%hd\n" \ "E Username = %.20s Server=%.20s\n" \ "error 0\n", proxy_stats.dst, proxy_stats.port, username, server); close_all(); } if(strlen(username) > user_limit) { snprintf(syslog_msg, MAXBUFSZ, "Username \"%.10s\"length too long, max %hd", username, user_limit); close_all(); } if(strlen(authflds[3]) > pass_limit) { snprintf(syslog_msg, MAXBUFSZ, "Encoded password length too long, max %hd", pass_limit); close_all(); } if (searchlist(username,validusers)) { snprintf(client_msg, MAXBUFSZ, "E access denied\n" \ "error 0\n"); snprintf(syslog_msg, MAXBUFSZ, "deny host=%.512s/%.20s" \ " access for user %s(access for this user denied)", proxy_stats.rladdr, proxy_stats.riaddr, username); close_all(); } if (!(*proxy_stats.dst)) { strlcpy(proxy_stats.dst, server, sizeof(proxy_stats.dst)); proxy_stats.port = port; } if (proxy_check_dest(validests, extendperm)) { snprintf(client_msg,MAXBUFSZ,"E CVS gateway denied destination access\n" \ "error 0\n"); snprintf(syslog_msg, MAXBUFSZ, "deny host=%.512s/%.20s" \ "access for user %s(access to destination host denied)", proxy_stats.rladdr, proxy_stats.riaddr, username); close_all(); } /*Building auth message for cvs-server*/ snprintf(buff, 256, "%.255s\n" \ "%.1024s\n" \ "%.1024s\n" \ "%.1024s\n" \ "%.255s", authflds[0], authflds[1], username, authflds[3], authflds[4] ); /*Setting up connection with cvs-server*/ proxy_update_operation("CONNECTING"); if((server_fd = conn_server(proxy_stats.dst,proxy_stats.port,0,(char *)0)) < 0) { snprintf(syslog_msg, MAXBUFSZ, "cannot connect to server [%s:%hd] %s", proxy_stats.dst, proxy_stats.port, strerror(errno)); snprintf(client_msg, MAXBUFSZ, "E Fatal error, aborting.\n" \ "E can't connect to the server %.100s:%hd\nerror 0\n", proxy_stats.dst, proxy_stats.port); close_all(); } return(server_fd); } int do_noargs(server_fd, client_fd, command, flags, argc, argv) int server_fd; int client_fd; char *command; int flags; int argc; char **argv; { if (argc != 1) { return 1; } else { if(sosayn(server_fd, argv[0], strlen(argv[0]))) return -1; if (server_fd) proxy_stats.outbytes += strlen(argv[0]) + 1; else proxy_stats.inbytes += strlen(argv[0]) + 1; resolve_flags (server_fd, client_fd, command, flags, argc, argv); return(0); } } /* * Handle cvs commands that take single message number as argument */ int do_message(server_fd, client_fd, command, flags, argc, argv) int server_fd; int client_fd; char *command; int flags; int argc; char **argv; { char buff[MAXBUFSZ]; bzero(buff,sizeof(buff)); if (argc != 2) { syslog(LLEV,"command syntax error: %.100s", command); snprintf(buff,MAXBUFSZ, "E syntax error\nE cmd:%.100s\nerror", command); if(sosayn(0, buff,strlen(buff))) return(-1); return(1); } else { snprintf(buff, MAXBUFSZ - 1, "%.100s %.100s", argv[0], argv[1]); if(sosayn(server_fd, buff, strlen(buff))) return(-1); if (server_fd) proxy_stats.outbytes += strlen(buff) + 1; else proxy_stats.inbytes += strlen(buff) + 1; resolve_flags (server_fd, client_fd, command, flags, argc, argv); } return(0); } /* * Handle generic cvs command - no advanced parsing here */ int do_generic(server_fd, client_fd, command, flags, argc, argv) int server_fd; int client_fd; char *command; int flags; int argc; char **argv; { char *p; p = command; if(sosayn(server_fd, command, strlen(command))) return(-1); if (server_fd) proxy_stats.outbytes += strlen(command) + 1; else proxy_stats.inbytes += strlen(command) + 1; resolve_flags (server_fd, client_fd, command, flags, argc, argv); return(0); } /* * Handle commands that take filename as parameter (no advanced * parsing implemented yet, but here is the place to do) */ int do_path(server_fd, client_fd, command, flags, argc, argv) int server_fd; int client_fd; char *command; int flags; int argc; char **argv; { char *p; p = command; if(sosayn(server_fd, command, strlen(command))) return(-1); if (server_fd) proxy_stats.outbytes += strlen(command) + 1; else proxy_stats.inbytes += strlen(command) + 1; resolve_flags (server_fd, client_fd, command, flags, argc, argv); return(0); } /* * Handle commands that take relative filename as parameter */ int do_rpath(server_fd, client_fd, command, flags, argc, argv) int server_fd; int client_fd; char *command; int flags; int argc; char **argv; { char *p; p = command; if(sosayn(server_fd, command, strlen(command))) return(-1); if (server_fd) proxy_stats.outbytes += strlen(command) + 1; else proxy_stats.inbytes += strlen(command) + 1; resolve_flags (server_fd, client_fd, command, flags, argc, argv); return(0); } /* * Handle commands that take Entry line as parameter (no advanced * parsing implemented yet, but here is the place to do) */ int do_entry(server_fd, client_fd, command, flags, argc, argv) int server_fd; int client_fd; char *command; int flags; int argc; char **argv; { char *p; p = command; if(sosayn(server_fd, command, strlen(command))) return(-1); if (server_fd) proxy_stats.outbytes += strlen(command) + 1; else proxy_stats.inbytes += strlen(command) + 1; resolve_flags (server_fd, client_fd, command, flags, argc, argv); return(0); } /* * Handle commands that require no response */ int do_noresponse(server_fd, client_fd, command, flags, argc, argv) int server_fd; int client_fd; int flags; char *command; int argc; char **argv; { if(sosayn(server_fd, command, strlen(command))) return(-1); if (server_fd) proxy_stats.outbytes += strlen(command) + 1; else proxy_stats.inbytes += strlen(command) + 1; resolve_flags (server_fd, client_fd, command, flags, argc, argv); return(0); } /* * Handle restricted and unemplemented commands */ int do_restricted(server_fd, client_fd, command, flags, argc, argv) int server_fd; int client_fd; int flags; char *command; int argc; char **argv; { syslog(LLEV,"restricted command: %.128s",command); sosay(0,"E operation restricted\nerror 0\n"); return(0); } #include "responses.h" #include "requests.h" static fwparm options[] = { {FWPARM_LIST, "-dest", (char*) &validests}, {FWPARM_LIST, "-user", (char*) &validusers}, {FWPARM_CHAR, "-separator", (char*) &separator}, {FWPARM_BOOL, "-transparent", (char*) &transparent}, {FWPARM_BOOL, "-extnd", (char*) &extendperm}, {FWPARM_STRING, "-plug-to", (char*) proxy_stats.dst}, {FWPARM_STRING, "-mode", (char*) mode}, {FWPARM_PORT, "-port", (char*) &proxy_stats.port}, {FWPARM_INT, "-retr-file-limit", (char*) &retr_file_limit}, {FWPARM_INT, "-send-file-limit", (char*) &send_file_limit}, {FWPARM_OPLOG, "-log-response", (char*) &cvs_gw_res_descr}, {FWPARM_OPDENY, "-deny-response", (char*) &cvs_gw_res_descr}, {FWPARM_OPLOG, "-log-request", (char*) &cvs_gw_req_descr}, {FWPARM_OPDENY, "-deny-request", (char*) &cvs_gw_req_descr}, {FWPARM_DSCP, "-client-dscp", (char*) &cdscp}, {FWPARM_DSCP, "-server-dscp", (char*) &sdscp}, {0, 0, 0} }; int get_resp(server_fd, client_fd, flags, op_type) int server_fd; int client_fd; int flags; unsigned int op_type; { char buff[MAXBUFSZ]; int size = 0; int f_res_nextline = 0; char tokbuf[MAXBUFSZ]; char *tokav[56]; int tokac; if(!((op_type == REQUEST) || (op_type == RESPONSE))) return(-1); while(1) { bzero(buff, sizeof(buff)); sotimeout(600L); if((size = sogets(server_fd, buff, sizeof(buff)))== -1) { break; } else { int msg_int; const struct hash_entry *he_resp; int (*handler)(int, int, char*,int,int,char**); buff[size - 1] = '\0'; tokac = 0; bzero(tokbuf, sizeof(tokbuf)); bzero(tokav, sizeof(tokav)); tokac = enargv(buff, tokav, 56, tokbuf, sizeof(tokbuf)); if(!tokav[0]) continue; if(op_type == REQUEST) he_resp = find_vhe2(&cvs_gw_req_descr, tokav[0], strlen(tokav[0])); else he_resp = find_vhe2(&cvs_gw_res_descr, tokav[0], strlen(tokav[0])); if (!he_resp) { if(f_res_nextline) { #ifdef DEBUG syslog(LLEV,"%.20s:%.4s@%.20s: cmd[not-parsed] %.100s", proxy_stats.rladdr, authflds[1], proxy_stats.dst, buff); #endif do_generic(client_fd, server_fd, buff, OP_LOG, tokac,tokav); } else { syslog(LLEV,"unknown cvs command %.100s", tokav[0]); sosay(0,"E command unknown or out of state\nerror 0\n"); continue; } } else { f_res_nextline = 0; proxy_update_operation(buff); if (he_resp->flags & MNEXTLINE) f_res_nextline = 1; if (he_resp->flags & OP_LOG) syslog(LLEV,"%.20s:%.4s@%.20s: cmd %.100s", proxy_stats.rladdr, authflds[2], proxy_stats.dst, buff); if (he_resp->flags & OP_DENY) { syslog(LLEV,"deny host=%.512s/%.20s operation %.100s", proxy_stats.rladdr, proxy_stats.riaddr, buff); sosay(0,"E operation denied\nerror 0\n"); continue; } if(extendperm && (he_resp->flags & OP_XTND)) { msg_int = auth_perm(proxy_confp, proxy_stats.authuser, "cvs-gw", proxy_stats.riaddr, tokav); if(msg_int == 1 || msg_int == -1) { syslog(LLEV,"deny host=%.512s/%.20s operation %.100s - extended permissions",proxy_stats.rladdr,proxy_stats.riaddr,buff); sosay(0,"E operation denied\nerror 0\n"); continue; } } handler = he_resp->handler; if(op_type == REQUEST) { assert(CVS_GW_REQ_HANDLER (handler)); } else { assert(CVS_GW_RES_HANDLER (handler)); } /* (void)pre_check(op_type, buff, he_resp->flags, tokac, tokav); */ (void)handler(client_fd, server_fd, buff, he_resp->flags, tokac,tokav); if (he_resp->flags & ENDRESPONSE) return(0); } } } return(0); } int make_file_transmission(client_fd, server_fd, flags, argv) int client_fd; int server_fd; int flags; char **argv; { int i = 0; int rd = 0; unsigned int fsz = 0, count = 0; char rline[MAXLINELEN], buff[MAXBUFSZ]; bzero(buff, sizeof(buff)); bzero(rline, sizeof(rline)); /*Read file mode and send it to the cvs-server */ if((rd=sogets(client_fd, rline, sizeof(rline))) != -1) { rline[rd -1] = '\0'; if(sosayn(server_fd, rline, strlen(rline))) return(-1); /*Read file size */ bzero(rline, sizeof(rline)); if((rd = sogets(client_fd, rline, sizeof(rline)))) { rline[rd -1] = '\0'; if((fsz = atoi(rline))) { if((fsz > retr_file_limit) && client_fd && retr_file_limit) { snprintf(syslog_msg, MAXBUFSZ, "retr file size limit exceeded"); close_all(); } if((fsz > send_file_limit) && !client_fd && send_file_limit) { snprintf(syslog_msg, MAXBUFSZ, "send file size limit exceeded"); close_all(); } if (flags & OP_LOG) syslog(LLEV, "file in '%.100s' size is '%d' bytes", argv[0], fsz); if(sosayn(server_fd, rline, strlen(rline))) { return -1; } /*Lets do it! */ count = fsz; rd = 0; i = 0; while((rd < fsz) && (count)) { if(((i = soread(client_fd, buff, MIN(sizeof(buff), count))) <= 0)) { snprintf(client_msg, MAXBUFSZ, "E Client connection error\n" \ "E serv:port - %.100s:%hd\n" \ "error 0\n", proxy_stats. dst,proxy_stats.port); snprintf(syslog_msg, MAXBUFSZ, "Client connection failed, error: %s", strerror(errno)); close_all(); exit(2); } if((sowrite(server_fd, buff, i) != i)) { snprintf(client_msg, MAXBUFSZ, "E Server connection error\n" \ "E serv:port - %.100s:%hd\n" \ "error 0\n", proxy_stats. dst,proxy_stats.port); snprintf(syslog_msg, MAXBUFSZ, "Server connection failed, error: %s", strerror(errno)); close_all(); } if (client_fd) proxy_stats.inbytes += i; else proxy_stats.outbytes += i; rd += i; count -=i; bzero(buff, sizeof(buff)); proxy_update_status(); } (void) sosetline(SO_LLF); if(count != 0) close_all(); } else { return 0; } } else{ return -1; } } else { return -1; } return 1; } static int read_client_auth(descr) int descr; { int rd = -1, sz = 0, i = 0; char tmp[MAXLINELEN]; while(i < AUTHFLDS) { bzero(tmp, sizeof(tmp)); bzero(authflds[i], sizeof(authflds[i])); if((rd = sogets(descr, tmp, sizeof(tmp))) <= 0) return 0; tmp[rd - 1] = '\0'; strncpy(authflds[i++], tmp, MIN(MAXLINELEN, rd)); sz += rd; } return sz; } static int auth_response(response) char *response; { #define ASW_SZ 10 char secc[ASW_SZ]; char deny[ASW_SZ]; strncpy(secc, "I LOVE YOU", ASW_SZ); strncpy(deny, "I HATE YOU", ASW_SZ); if(!(strncmp(response, secc, ASW_SZ))) return 1; /*Auth is successful */ if(!(strncmp(response, deny, ASW_SZ))) return 0; /*Access denied */ return -1; /*Unknown answer - closing connection anyway */ } int check_commands (flag, argc, argv) int flag; int argc; char **argv; { int i = 0; unsigned int count = 0; struct hash_descr *descr = NULL; struct hash_entry *he; if(argc < 5) { syslog(LLEV,"CHECK IS FAILED $argc is too short"); return 0; } if(flag & SERVER_COMMANDS) { descr = (struct hash_descr *)&cvs_gw_req_descr; count = sizeof(cvs_gw_req_data)/(sizeof(struct hash_entry)); } else { if(flag & CLIENT_COMMANDS) { descr = (struct hash_descr *)&cvs_gw_res_descr; count = sizeof(cvs_gw_res_data)/(sizeof(struct hash_entry)); } else { snprintf(syslog_msg,MAXBUFSZ,"unknown cvs-gw internal error"); snprintf(client_msg,MAXBUFSZ,"E internal proxy error\nerror 0\n"); close_all(); } } while(count--) { if((he = (struct hash_entry *)&descr->data[count])) { if(he->flags & OP_DENY) he->flags |= OP_INTERNAL; else he->flags |= OP_DENY; } } /* Allow a bit*/ while(argc - 1> i++) { if ((he = find_vhe2(descr, argv[i], strlen(argv[i])))) { if(!(he->flags & OP_INTERNAL)) he->flags ^= OP_DENY; else he->flags ^= OP_INTERNAL; } else syslog(LLEV,"warning: unknown command %.100s",argv[i]); } return 0; } void init_readonly(void) { /*List of commands, must grad read-only mode */ /*Not sure that this list is full, what i missed???*/ int i = 0; unsigned int count; struct hash_descr *descr; struct hash_entry *he; char deny_commands[][20] = { {"ci"}, {"tag"}, {"admin"}, {"watchers"}, {"editors"}, {"annotate"}, {"rtag"}, {"rannotate"}, {"add"}, {"remove"}, {"watch-on"}, {"watch-off"}, {"watch-add"}, {"watch-remove"}, {"release"}, {"other-request"}, {"import"}, {0}, }; descr = (struct hash_descr *)&cvs_gw_req_descr; count = sizeof(cvs_gw_req_data)/(sizeof(struct hash_entry)); for(i=0;*deny_commands[i];i++) { if ((he = find_vhe2(descr, deny_commands[i], strlen(deny_commands[i])))) { he->flags |= OP_DENY; syslog(LLEV, "REQUEST command[%d] \"%.20s\" is denied",i, deny_commands[i]); } else { syslog(LLEV, "Can not find such REQUEST command[%d] \"%.20s\", denied" \ "action have no affect", i,deny_commands[i]); } } } void resolve_flags (server_fd, client_fd, command, flags, argc, argv) int server_fd; int client_fd; char *command; int flags; int argc; char **argv; { char buff[MAXBUFSZ]; bzero(buff,sizeof(buff)); if (!flags) return; if(flags & CHECKFLAGS) { if(client_fd) check_commands (SERVER_COMMANDS, argc, argv); else check_commands (CLIENT_COMMANDS, argc, argv); } if(flags & PARTPATHNAME) { bzero(buff, sizeof(buff)); sogets(client_fd, buff, sizeof(buff)); buff[strlen(buff) - 1] = '\0'; sosayn(server_fd, buff, strlen(buff)); } if(flags & NEWENTRIESLINE) { bzero(buff, sizeof(buff)); sogets(client_fd, buff, sizeof(buff)); buff[strlen(buff) - 1] = '\0'; if (flags & OP_LOG) syslog(LLEV,"New Entry tag %s", buff); sosayn(server_fd, buff, strlen(buff)); } if(flags & MLINE) { if(client_fd) get_resp(server_fd, client_fd, flags, REQUEST); else get_resp(server_fd, client_fd, flags, RESPONSE); } if(flags & FTRANSMISSION) { make_file_transmission(client_fd, server_fd, flags, argv); } return; } int main(argc, argv) int argc; char *argv[]; { char buf[MAXBUFSZ+1]; int size = 0, i = 0, auth = 0; struct sigaction act; char *s_mode; bzero(syslog_msg, sizeof(syslog_msg)); bzero(client_msg, sizeof(client_msg)); bzero((char *)&act, sizeof(act)); act.sa_flags = 0; sigemptyset(&act.sa_mask); sigaddset(&act.sa_mask, SIGTERM); act.sa_handler = handle_term; sigaction(SIGTERM, &act, NULL); (void) sosetline(SO_LLF); proxy_stats.port = 0; proxy_init(argc, argv); proxy_chroot_setugid(); if (cdscp) proxy_set_dscp(0,cdscp); proxy_stats.inbytes = 0; proxy_stats.outbytes = 0; if((confp = proxy_conf_hosts(proxy_confp,proxy_stats.rladdr,proxy_stats.riaddr))) proxy_parse_options(confp, options); else { snprintf(buf,MAXBUFSZ,"E Access denied\nerror 0\n"); sosayn(0, buf, strlen(buf)); proxy_exit(); } if(!proxy_stats.port) proxy_stats.port = PSERVERPORT; s_mode = proxy_conf_string(proxy_confp, "mode"); if (s_mode) (void)strncpy(mode, s_mode, sizeof(mode)); if(!strncmp(mode,"ro",sizeof(mode))) { (void)init_readonly(); } else { if(strncmp(mode,"rw",sizeof(mode))) syslog(LLEV, "fwtkcfgerr: bad \"mode\" option in config"); } user_limit = proxy_conf_int(proxy_confp,"user-limit",1,MAXLINELEN-1,user_limit); pass_limit = proxy_conf_int(proxy_confp,"pass-limit",1,MAXLINELEN-1,pass_limit); bzero(buf, sizeof(buf)); /*AUTH AUTH AUTH AUTH AUTH AUTH AUTH AUTH AUTH AUTH AUTH AUTH AUTH AUTH */ /*AUTH AUTH AUTH AUTH AUTH AUTH AUTH AUTH AUTH AUTH AUTH AUTH AUTH AUTH */ /*AUTH AUTH AUTH AUTH AUTH AUTH AUTH AUTH AUTH AUTH AUTH AUTH AUTH AUTH */ sotimeout(PROXY_TIMEOUT); if((size = read_client_auth(0)) == -1) { snprintf(syslog_msg, MAXBUFSZ, "Client connection error: %s", strerror(errno)); close_all(); } proxy_stats.inbytes += size; bzero(buf, sizeof(buf)); server_fd = conn_cvs_server(buf); if (sdscp) proxy_set_dscp(server_fd,sdscp); proxy_update_operation("AUTHENTICATION"); if(sosayn(server_fd, buf, strlen(buf))) { snprintf(syslog_msg, MAXBUFSZ, "Server write error: %s", strerror(errno)); snprintf(client_msg, MAXBUFSZ, "E Server write error\n" \ "E serv:port - %.100s:%hd\n" \ "error 0\n", proxy_stats. dst,proxy_stats.port); close_all(); } bzero(buf, sizeof(buf)); if((size = soread(server_fd, buf, 1024)) == -1) { snprintf(syslog_msg, MAXBUFSZ, "Server read error"); snprintf(client_msg, MAXBUFSZ, "E Server read error\n" \ "E serv:port - %.100s:%hd\n" \ "error 0\n", proxy_stats. dst,proxy_stats.port); close_all(); } if(size && (auth = auth_response(buf)) > 0) { buf[size - 1] = '\0'; if(sosayn(0, buf, size)) { snprintf(syslog_msg, MAXBUFSZ, "Client write error: %s",strerror(errno)); close_all(); } proxy_stats.outbytes += size; bzero(buf, sizeof(buf)); } else { if(!size) { snprintf(syslog_msg, MAXBUFSZ, "Server is silent"); snprintf(client_msg, MAXBUFSZ, "E No answer from server\n" \ "E serv:port - %.100s:%hd\n" \ "error 0\n", proxy_stats. dst,proxy_stats.port); close_all(); } else { if(auth == 0) { snprintf(syslog_msg, MAXBUFSZ, "user failed to authenticate to server"); strlcpy(client_msg, buf, sizeof(client_msg)); proxy_stats.outbytes += size; close_all(); } else { snprintf(syslog_msg, MAXBUFSZ, "Can't undestand srv response: %.100s", buf); strlcpy(client_msg,"I HATE YOU\n", 11); proxy_stats.outbytes += 11; close_all(); } } } /* ENDAUTH */ i = 0; if(fcntl(server_fd, F_GETFL, O_NONBLOCK) != O_NONBLOCK) if(fcntl(server_fd, F_GETFL, O_NONBLOCK) == -1) syslog(LLEV,"setting up the fd_flag for server_fd fd failed"); proxy_update_operation("IDLE"); get_resp(0, server_fd, 0, REQUEST); proxy_exit(); return 0; }