void * pop3pchild(void * data) { #define param ((struct clientparam*)data) int i=0, res; unsigned char buf[320]; unsigned char *se; if(socksend(param->clisock, (unsigned char *)"+OK Proxy\r\n", 11, conf.timeouts[STRING_S])!=11) {RETURN (611);} i = sockgetlinebuf(param, CLIENT, buf, sizeof(buf) - 10, '\n', conf.timeouts[STRING_S]); while(i > 4 && strncasecmp((char *)buf, "USER", 4)){ if(!strncasecmp((char *)buf, "QUIT", 4)){ socksend(param->clisock, (unsigned char *)"+OK\r\n", 5,conf.timeouts[STRING_S]); RETURN(0); } socksend(param->clisock, (unsigned char *)"-ERR need USER first\r\n", 22, conf.timeouts[STRING_S]); i = sockgetlinebuf(param, CLIENT, buf, sizeof(buf) - 10, '\n', conf.timeouts[STRING_S]); } if(i<6) {RETURN(612);} buf[i] = 0; if ((se=(unsigned char *)strchr((char *)buf, '\r'))) *se = 0; if (strncasecmp((char *)buf, "USER ", 5)){RETURN (614);} if(!param->hostname && param->remsock == INVALID_SOCKET) { if(parseconnusername((char *)buf +5, param, 0, 110)){RETURN(615);} } else if(parseusername((char *)buf + 5, param, 0)) {RETURN(616);} param->operation = CONNECT; res = (*param->authfunc)(param); if(res) {RETURN(res);} i = sockgetlinebuf(param, SERVER, buf, sizeof(buf) - 1, '\n', conf.timeouts[STRING_L]); param->statssrv+=i; if( i < 3 ) {RETURN(621);} buf[i] = 0; if(strncasecmp((char *)buf, "+OK", 3)||!strncasecmp((char *)buf+4, "PROXY", 5)){RETURN(622);} if( socksend(param->remsock, (unsigned char *)"USER ", 5, conf.timeouts[STRING_S])!= 5 || socksend(param->remsock, param->extusername, strlen((char *)param->extusername), conf.timeouts[STRING_S]) <= 0 || socksend(param->remsock, (unsigned char *)"\r\n", 2, conf.timeouts[STRING_S])!=2) {RETURN(623);} param->statscli += (strlen((char *)param->extusername) + 7); RETURN (sockmap(param, 180)); CLEANRET: if(param->hostname&¶m->extusername) { sprintf((char *)buf, "%.64s@%.128s%c%hu", param->extusername, param->hostname, (ntohs(param->sins.sin_port)==110)?0:':', ntohs(param->sins.sin_port)); (*param->logfunc)(param, buf); } else (*param->logfunc)(param, NULL); if(param->clisock != INVALID_SOCKET) { if ((param->res > 0 && param->res < 100) || (param->res > 611 && param->res <700)) socksend(param->clisock, (unsigned char *)"-ERR\r\n", 6,conf.timeouts[STRING_S]); } freeparam(param); return (NULL); }
void * tcppmchild(void * data) { #define param ((struct clientparam*)data) int res; param->hostname = param->target; param->sins.sin_port = param->targetport; param->operation = CONNECT; res = (*param->authfunc)(param); param->hostname = NULL; if(res) {RETURN(res);} RETURN (sockmap(param, conf.timeouts[CONNECTION_L])); CLEANRET: (*param->logfunc)(param, NULL); freeparam(param); return (NULL); }
static void setparam(int argc, char **argv) { char **newparam; char **ap; ap = newparam = ckmalloc((argc + 1) * sizeof *ap); while (*argv) { *ap++ = savestr(*argv++); } *ap = NULL; freeparam(&shellparam); shellparam.malloc = 1; shellparam.nparam = argc; shellparam.p = newparam; shellparam.optp = NULL; shellparam.reset = 1; shellparam.optnext = NULL; }
void setparam(char **argv) { char **newparam; char **ap; int nparam; for (nparam = 0 ; argv[nparam] ; nparam++); ap = newparam = ckmalloc((nparam + 1) * sizeof *ap); while (*argv) { *ap++ = savestr(*argv++); } *ap = NULL; freeparam(&shellparam); shellparam.malloc = 1; shellparam.nparam = nparam; shellparam.p = newparam; shellparam.optnext = NULL; }
void * sockschild(struct clientparam* param) { int res; unsigned i=0; SOCKET s; unsigned size; SASIZETYPE sasize; unsigned char * buf=NULL; unsigned char c; unsigned char command=0; struct pollfd fds[3]; int ver=0; int havepass = 0; struct sockaddr_in sin; int len; param->req.sin_addr.s_addr = 0; param->service = S_SOCKS; if(!(buf = myalloc(BUFSIZE))) {RETURN(21);} memset(buf, 0, BUFSIZE); if ((ver = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_L], 0)) != 5 && ver != 4) { RETURN(401); } /* version */ param->service = ver; if(ver == 5){ if ((i = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(441);} /* nmethods */ for (; i; i--) { if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(442);} if (res == 2 && !param->srv->nouser) { havepass = res; } } buf[0] = 5; buf[1] = havepass; if(socksend(param->clisock, buf, 2, conf.timeouts[STRING_S])!=2){RETURN(402);} if (havepass) { if (((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_L], 0))) != 1) { RETURN(412); } if ((i = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(443);} if (i && (unsigned)(res = sockgetlinebuf(param, CLIENT, buf, i, 0, conf.timeouts[STRING_S])) != i){RETURN(444);}; buf[i] = 0; if(!param->username)param->username = (unsigned char *)mystrdup((char *)buf); if ((i = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(445);} if (i && (unsigned)(res = sockgetlinebuf(param, CLIENT, buf, i, 0, conf.timeouts[STRING_S])) != i){RETURN(446);}; buf[i] = 0; if(!param->password)param->password = (unsigned char *)mystrdup((char *)buf); buf[0] = 1; buf[1] = 0; if(socksend(param->clisock, buf, 2, conf.timeouts[STRING_S])!=2){RETURN(402);} } if ((c = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_L], 0)) != 5) { RETURN(421); } /* version */ } if( (command = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) < 1 || command > 3){command = 0; RETURN(407);} /* command */ if(ver == 5){ if (sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0) == EOF) {RETURN(447);} /* reserved */ c = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0); /* atype */ } else { if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(448);} buf[0] = (unsigned char) res; if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(449);} buf[1] = (unsigned char) res; param->sins.sin_port = param->req.sin_port = *(unsigned short*)buf; c = 1; } switch(c) { case 1: for (i = 0; i<4; i++){ if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(450);} buf[i] = (unsigned char)res; } param->sins.sin_addr.s_addr = param->req.sin_addr.s_addr = *(unsigned long *)buf; if(command==1 && !param->req.sin_addr.s_addr) { RETURN(422); } myinet_ntoa(param->sins.sin_addr, (char *)buf); break; case 3: if ((size = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(451);} /* nmethods */ for (i=0; i<size; i++){ /* size < 256 */ if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(452);} buf[i] = (unsigned char)res; } buf[i] = 0; param->sins.sin_addr.s_addr = param->req.sin_addr.s_addr = getip(buf); if(command==1 && !param->req.sin_addr.s_addr) { RETURN(100); } break; default: RETURN(998); } if(param->hostname)myfree(param->hostname); param->hostname = (unsigned char *)mystrdup((char *)buf); if (ver == 5) { if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(453);} buf[0] = (unsigned char) res; if ((res = sockgetcharcli(param, conf.timeouts[SINGLEBYTE_S], 0)) == EOF) {RETURN(454);} buf[1] = (unsigned char) res; param->sins.sin_port = param->req.sin_port = *(unsigned short*)buf; } else { sockgetlinebuf(param, CLIENT, buf, BUFSIZE - 1, 0, conf.timeouts[STRING_S]); buf[127] = 0; if(!param->srv->nouser && *buf && !param->username)param->username = (unsigned char *)mystrdup((char *)buf); if(param->sins.sin_addr.s_addr && ntohl(param->sins.sin_addr.s_addr)<256){ param->service = S_SOCKS45; sockgetlinebuf(param, CLIENT, buf, BUFSIZE - 1, 0, conf.timeouts[STRING_S]); buf[127] = 0; if(param->hostname)myfree(param->hostname); param->hostname = (unsigned char *)mystrdup((char *)buf); param->sins.sin_addr.s_addr = param->req.sin_addr.s_addr = getip(buf); } } if(command == 1 && !param->req.sin_port) {RETURN(424);} param->sins.sin_family = AF_INET; switch(command) { case 1: param->operation = CONNECT; break; case 2: param->sins.sin_addr.s_addr = param->extip; param->sins.sin_port = param->extport?param->extport:param->req.sin_port; if ((param->remsock=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) {RETURN (11);} param->operation = BIND; break; case 3: param->sins.sin_port = param->extport?param->extport:param->req.sin_port; param->sins.sin_addr.s_addr = param->extip; if ((param->remsock=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) {RETURN (11);} param->operation = UDPASSOC; break; default: RETURN(997); } if((res = (*param->srv->authfunc)(param))) {RETURN(res);} if(command > 1) { if(bind(param->remsock,(struct sockaddr *)¶m->sins,sizeof(param->sins))) { param->sins.sin_port = 0; if(bind(param->remsock,(struct sockaddr *)¶m->sins,sizeof(param->sins)))RETURN (12); #if SOCKSTRACE > 0 fprintf(stderr, "%s:%hu binded to communicate with server\n", inet_ntoa(param->sins.sin_addr), ntohs(param->sins.sin_port) ); fflush(stderr); #endif } sasize = sizeof(struct sockaddr_in); getsockname(param->remsock, (struct sockaddr *)¶m->sins, &sasize); if(command == 3) { param->ctrlsock = param->clisock; param->clisock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); if(param->clisock == INVALID_SOCKET) {RETURN(11);} sin.sin_family = AF_INET; sin.sin_addr.s_addr = param->srv->intip; sin.sin_port = htons(0); if(bind(param->clisock,(struct sockaddr *)&sin,sizeof(struct sockaddr_in))) {RETURN (12);} #if SOCKSTRACE > 0 fprintf(stderr, "%s:%hu binded to communicate with client\n", inet_ntoa(sin.sin_addr), ntohs(sin.sin_port) ); fflush(stderr); #endif } } param->res = 0; CLEANRET: if(param->clisock != INVALID_SOCKET){ sasize = sizeof(struct sockaddr_in); if(command != 3) getsockname(param->remsock, (struct sockaddr *)&sin, &sasize); else getsockname(param->clisock, (struct sockaddr *)&sin, &sasize); #if SOCKSTRACE > 0 fprintf(stderr, "Sending confirmation to client with code %d for %s with %s:%hu\n", param->res, commands[command], inet_ntoa(sin.sin_addr), ntohs(sin.sin_port) ); fflush(stderr); #endif if(ver == 5){ buf[0] = 5; buf[1] = param->res%10; buf[2] = 0; buf[3] = 1; memcpy(buf+4, &sin.sin_addr.s_addr, 4); memcpy(buf+8, &sin.sin_port, 2); socksend((command == 3)?param->ctrlsock:param->clisock, buf, 10, conf.timeouts[STRING_S]); } else{ buf[0] = 0; buf[1] = 90 + (param->res%10); memcpy(buf+2, &sin.sin_port, 2); memcpy(buf+4, &sin.sin_addr.s_addr, 4); socksend(param->clisock, buf, 8, conf.timeouts[STRING_S]); } if (param->res == 0) { switch(command) { case 1: if(param->redirectfunc){ if(buf)myfree(buf); return (*param->redirectfunc)(param); } param->res = sockmap(param, conf.timeouts[CONNECTION_L]); break; case 2: listen (param->remsock, 1); fds[0].fd = param->remsock; fds[1].fd = param->clisock; fds[0].events = fds[1].events = POLLIN; res = poll(fds, 2, conf.timeouts[(param->req.sin_addr.s_addr)?CONNECTION_S:CONNECTION_L] * 1000); if (res < 1 || fds[1].revents) { res = 460; break; } sasize = sizeof(param->sins); s = accept(param->remsock, (struct sockaddr *)¶m->sins, &sasize); closesocket(param->remsock); param->remsock = s; if(s == INVALID_SOCKET) { param->res = 462; break; } if(param->req.sin_addr.s_addr && param->req.sin_addr.s_addr != param->sins.sin_addr.s_addr) { param->res = 470; break; } #if SOCKSTRACE > 0 fprintf(stderr, "Sending incoming connection to client with code %d for %s with %s:%hu\n", param->res, commands[command], inet_ntoa(param->sins.sin_addr), ntohs(param->sins.sin_port) ); fflush(stderr); #endif if(ver == 5){ memcpy (buf+4, ¶m->sins.sin_addr, 4); memcpy (buf+8, ¶m->sins.sin_port, 2); socksend(param->clisock, buf, 10, conf.timeouts[STRING_S]); } else { memcpy (buf+2, ¶m->sins.sin_port, 2); memcpy (buf+4, ¶m->sins.sin_addr, 4); socksend(param->clisock, buf, 8, conf.timeouts[STRING_S]); } param->res = sockmap(param, conf.timeouts[CONNECTION_S]); break; case 3: param->sins.sin_addr.s_addr = param->req.sin_addr.s_addr; param->sins.sin_port = param->req.sin_port; myfree(buf); if(!(buf = myalloc(LARGEBUFSIZE))) {RETURN(21);} for(;;){ fds[0].fd = param->remsock; fds[1].fd = param->clisock; fds[2].fd = param->ctrlsock; fds[2].events = fds[1].events = fds[0].events = POLLIN; res = poll(fds, 3, conf.timeouts[CONNECTION_L]*1000); if(res <= 0) { param->res = 463; break; } if (fds[2].revents) { param->res = 0; break; } if (fds[1].revents) { sasize = sizeof(struct sockaddr_in); if((len = recvfrom(param->clisock, buf, 65535, 0, (struct sockaddr *)&sin, &sasize)) <= 10) { param->res = 464; break; } if(sin.sin_addr.s_addr != param->sinc.sin_addr.s_addr){ param->res = 465; break; } if(buf[0] || buf[1] || buf[2]) { param->res = 466; break; } switch(buf[3]) { case 1: i = 8; memcpy(¶m->sins.sin_addr.s_addr, buf+4, 4); break; case 3: size = buf[4]; for (i=4; size; i++, size--){ buf[i] = buf[i+1]; } buf[i++] = 0; param->sins.sin_addr.s_addr = getip(buf+4); break; default: RETURN(996); } memcpy(¶m->sins.sin_port, buf+i, 2); i+=2; sasize = sizeof(param->sins); if(len > (int)i){ if(socksendto(param->remsock, ¶m->sins, buf+i, len - i, conf.timeouts[SINGLEBYTE_L]*1000) <= 0){ param->res = 467; break; } param->statscli+=(len - i); param->nwrites++; #if SOCKSTRACE > 1 fprintf(stderr, "UDP packet relayed from client to %s:%hu size %d, header %d\n", inet_ntoa(param->sins.sin_addr), ntohs(param->sins.sin_port), (len - i), i ); fprintf(stderr, "client address is assumed to be %s:%hu\n", inet_ntoa(sin.sin_addr), ntohs(sin.sin_port) ); fflush(stderr); #endif } } if (fds[0].revents) { struct sockaddr_in tsin; sasize = sizeof(tsin); buf[0]=buf[1]=buf[2]=0; buf[3]=1; if((len = recvfrom(param->remsock, buf+10, 65535 - 10, 0, (struct sockaddr *)&tsin, &sasize)) <= 0) { param->res = 468; break; } param->statssrv+=len; param->nreads++; memcpy(buf+4, &tsin.sin_addr.s_addr, 4); memcpy(buf+8, &tsin.sin_port, 2); sasize = sizeof(param->sins); if(socksendto(param->clisock, &sin, buf, len + 10, conf.timeouts[SINGLEBYTE_L]*1000) <=0){ param->res = 469; break; } #if SOCKSTRACE > 1 fprintf(stderr, "UDP packet relayed to client from %s:%hu size %d\n", inet_ntoa(tsin.sin_addr), ntohs(tsin.sin_port), len ); fflush(stderr); #endif } } break; default: param->res = 417; break; } } } if(command > 3) command = 0; if(buf){ sprintf((char *)buf, "%s ", commands[command]); if(param->hostname){ sprintf((char *)buf + strlen((char *)buf), "%.265s", param->hostname); } else myinet_ntoa(param->req.sin_addr, (char *)buf+strlen((char *)buf)); sprintf((char *)buf+strlen((char *)buf), ":%hu", ntohs(param->req.sin_port)); (*param->srv->logfunc)(param, buf); myfree(buf); } freeparam(param); return (NULL); }
static void evalcommand(union node *cmd, int flags, struct backcmd *backcmd) { union node *argp; struct arglist arglist; struct arglist varlist; char **argv; int argc; char **envp; int varflag; struct strlist *sp; int mode; int pip[2]; struct cmdentry cmdentry; struct job *jp; struct jmploc jmploc; struct jmploc *savehandler; char *savecmdname; struct shparam saveparam; struct localvar *savelocalvars; struct parsefile *savetopfile; volatile int e; char *lastarg; int realstatus; int do_clearcmdentry; const char *path = pathval(); /* First expand the arguments. */ TRACE(("evalcommand(%p, %d) called\n", (void *)cmd, flags)); arglist.lastp = &arglist.list; varlist.lastp = &varlist.list; varflag = 1; jp = NULL; do_clearcmdentry = 0; oexitstatus = exitstatus; exitstatus = 0; for (argp = cmd->ncmd.args ; argp ; argp = argp->narg.next) { if (varflag && isassignment(argp->narg.text)) { expandarg(argp, varflag == 1 ? &varlist : &arglist, EXP_VARTILDE); continue; } else if (varflag == 1) varflag = isdeclarationcmd(&argp->narg) ? 2 : 0; expandarg(argp, &arglist, EXP_FULL | EXP_TILDE); } *arglist.lastp = NULL; *varlist.lastp = NULL; expredir(cmd->ncmd.redirect); argc = 0; for (sp = arglist.list ; sp ; sp = sp->next) argc++; /* Add one slot at the beginning for tryexec(). */ argv = stalloc(sizeof (char *) * (argc + 2)); argv++; for (sp = arglist.list ; sp ; sp = sp->next) { TRACE(("evalcommand arg: %s\n", sp->text)); *argv++ = sp->text; } *argv = NULL; lastarg = NULL; if (iflag && funcnest == 0 && argc > 0) lastarg = argv[-1]; argv -= argc; /* Print the command if xflag is set. */ if (xflag) { char sep = 0; const char *p, *ps4; ps4 = expandstr(ps4val()); out2str(ps4 != NULL ? ps4 : ps4val()); for (sp = varlist.list ; sp ; sp = sp->next) { if (sep != 0) out2c(' '); p = strchr(sp->text, '='); if (p != NULL) { p++; outbin(sp->text, p - sp->text, out2); out2qstr(p); } else out2qstr(sp->text); sep = ' '; } for (sp = arglist.list ; sp ; sp = sp->next) { if (sep != 0) out2c(' '); /* Disambiguate command looking like assignment. */ if (sp == arglist.list && strchr(sp->text, '=') != NULL && strchr(sp->text, '\'') == NULL) { out2c('\''); out2str(sp->text); out2c('\''); } else out2qstr(sp->text); sep = ' '; } out2c('\n'); flushout(&errout); } /* Now locate the command. */ if (argc == 0) { /* Variable assignment(s) without command */ cmdentry.cmdtype = CMDBUILTIN; cmdentry.u.index = BLTINCMD; cmdentry.special = 0; } else { static const char PATH[] = "PATH="; int cmd_flags = 0, bltinonly = 0; /* * Modify the command lookup path, if a PATH= assignment * is present */ for (sp = varlist.list ; sp ; sp = sp->next) if (strncmp(sp->text, PATH, sizeof(PATH) - 1) == 0) { path = sp->text + sizeof(PATH) - 1; /* * On `PATH=... command`, we need to make * sure that the command isn't using the * non-updated hash table of the outer PATH * setting and we need to make sure that * the hash table isn't filled with items * from the temporary setting. * * It would be better to forbit using and * updating the table while this command * runs, by the command finding mechanism * is heavily integrated with hash handling, * so we just delete the hash before and after * the command runs. Partly deleting like * changepatch() does doesn't seem worth the * bookinging effort, since most such runs add * directories in front of the new PATH. */ clearcmdentry(); do_clearcmdentry = 1; } for (;;) { if (bltinonly) { cmdentry.u.index = find_builtin(*argv, &cmdentry.special); if (cmdentry.u.index < 0) { cmdentry.u.index = BLTINCMD; argv--; argc++; break; } } else find_command(argv[0], &cmdentry, cmd_flags, path); /* implement the bltin and command builtins here */ if (cmdentry.cmdtype != CMDBUILTIN) break; if (cmdentry.u.index == BLTINCMD) { if (argc == 1) break; argv++; argc--; bltinonly = 1; } else if (cmdentry.u.index == COMMANDCMD) { if (argc == 1) break; if (!strcmp(argv[1], "-p")) { if (argc == 2) break; if (argv[2][0] == '-') { if (strcmp(argv[2], "--")) break; if (argc == 3) break; argv += 3; argc -= 3; } else { argv += 2; argc -= 2; } path = _PATH_STDPATH; clearcmdentry(); do_clearcmdentry = 1; } else if (!strcmp(argv[1], "--")) { if (argc == 2) break; argv += 2; argc -= 2; } else if (argv[1][0] == '-') break; else { argv++; argc--; } cmd_flags |= DO_NOFUNC; bltinonly = 0; } else break; } /* * Special builtins lose their special properties when * called via 'command'. */ if (cmd_flags & DO_NOFUNC) cmdentry.special = 0; } /* Fork off a child process if necessary. */ if (((cmdentry.cmdtype == CMDNORMAL || cmdentry.cmdtype == CMDUNKNOWN) && ((flags & EV_EXIT) == 0 || have_traps())) || ((flags & EV_BACKCMD) != 0 && (cmdentry.cmdtype != CMDBUILTIN || !safe_builtin(cmdentry.u.index, argc, argv)))) { jp = makejob(cmd, 1); mode = FORK_FG; if (flags & EV_BACKCMD) { mode = FORK_NOJOB; if (pipe(pip) < 0) error("Pipe call failed: %s", strerror(errno)); } if (cmdentry.cmdtype == CMDNORMAL && cmd->ncmd.redirect == NULL && varlist.list == NULL && (mode == FORK_FG || mode == FORK_NOJOB) && !disvforkset() && !iflag && !mflag) { vforkexecshell(jp, argv, environment(), path, cmdentry.u.index, flags & EV_BACKCMD ? pip : NULL); goto parent; } if (forkshell(jp, cmd, mode) != 0) goto parent; /* at end of routine */ if (flags & EV_BACKCMD) { FORCEINTON; close(pip[0]); if (pip[1] != 1) { dup2(pip[1], 1); close(pip[1]); } flags &= ~EV_BACKCMD; } flags |= EV_EXIT; } /* This is the child process if a fork occurred. */ /* Execute the command. */ if (cmdentry.cmdtype == CMDFUNCTION) { #ifdef DEBUG trputs("Shell function: "); trargs(argv); #endif saveparam = shellparam; shellparam.malloc = 0; shellparam.reset = 1; shellparam.nparam = argc - 1; shellparam.p = argv + 1; shellparam.optnext = NULL; INTOFF; savelocalvars = localvars; localvars = NULL; reffunc(cmdentry.u.func); savehandler = handler; if (setjmp(jmploc.loc)) { freeparam(&shellparam); shellparam = saveparam; popredir(); unreffunc(cmdentry.u.func); poplocalvars(); localvars = savelocalvars; funcnest--; handler = savehandler; longjmp(handler->loc, 1); } handler = &jmploc; funcnest++; redirect(cmd->ncmd.redirect, REDIR_PUSH); INTON; for (sp = varlist.list ; sp ; sp = sp->next) mklocal(sp->text); exitstatus = oexitstatus; evaltree(getfuncnode(cmdentry.u.func), flags & (EV_TESTED | EV_EXIT)); INTOFF; unreffunc(cmdentry.u.func); poplocalvars(); localvars = savelocalvars; freeparam(&shellparam); shellparam = saveparam; handler = savehandler; funcnest--; popredir(); INTON; if (evalskip == SKIPFUNC) { evalskip = 0; skipcount = 0; } if (jp) exitshell(exitstatus); } else if (cmdentry.cmdtype == CMDBUILTIN) { #ifdef DEBUG trputs("builtin command: "); trargs(argv); #endif mode = (cmdentry.u.index == EXECCMD)? 0 : REDIR_PUSH; if (flags == EV_BACKCMD) { memout.nleft = 0; memout.nextc = memout.buf; memout.bufsize = 64; mode |= REDIR_BACKQ; } savecmdname = commandname; savetopfile = getcurrentfile(); cmdenviron = varlist.list; e = -1; savehandler = handler; if (setjmp(jmploc.loc)) { e = exception; if (e == EXINT) exitstatus = SIGINT+128; else if (e != EXEXIT) exitstatus = 2; goto cmddone; } handler = &jmploc; redirect(cmd->ncmd.redirect, mode); outclearerror(out1); /* * If there is no command word, redirection errors should * not be fatal but assignment errors should. */ if (argc == 0) cmdentry.special = 1; listsetvar(cmdenviron, cmdentry.special ? 0 : VNOSET); if (argc > 0) bltinsetlocale(); commandname = argv[0]; argptr = argv + 1; nextopt_optptr = NULL; /* initialize nextopt */ builtin_flags = flags; exitstatus = (*builtinfunc[cmdentry.u.index])(argc, argv); flushall(); if (outiserror(out1)) { warning("write error on stdout"); if (exitstatus == 0 || exitstatus == 1) exitstatus = 2; } cmddone: if (argc > 0) bltinunsetlocale(); cmdenviron = NULL; out1 = &output; out2 = &errout; freestdout(); handler = savehandler; commandname = savecmdname; if (jp) exitshell(exitstatus); if (flags == EV_BACKCMD) { backcmd->buf = memout.buf; backcmd->nleft = memout.nextc - memout.buf; memout.buf = NULL; } if (cmdentry.u.index != EXECCMD) popredir(); if (e != -1) { if ((e != EXERROR && e != EXEXEC) || cmdentry.special) exraise(e); popfilesupto(savetopfile); if (flags != EV_BACKCMD) FORCEINTON; } } else { #ifdef DEBUG trputs("normal command: "); trargs(argv); #endif redirect(cmd->ncmd.redirect, 0); for (sp = varlist.list ; sp ; sp = sp->next) setvareq(sp->text, VEXPORT|VSTACK); envp = environment(); shellexec(argv, envp, path, cmdentry.u.index); /*NOTREACHED*/ } goto out; parent: /* parent process gets here (if we forked) */ if (mode == FORK_FG) { /* argument to fork */ INTOFF; exitstatus = waitforjob(jp, &realstatus); INTON; if (iflag && loopnest > 0 && WIFSIGNALED(realstatus)) { evalskip = SKIPBREAK; skipcount = loopnest; } } else if (mode == FORK_NOJOB) { backcmd->fd = pip[0]; close(pip[1]); backcmd->jp = jp; } out: if (lastarg) setvar("_", lastarg, 0); if (do_clearcmdentry) clearcmdentry(); }
static void evalcommand(union node *cmd, int flags, struct backcmd *backcmd) { struct stackmark smark; union node *argp; struct arglist arglist; struct arglist varlist; char **argv; int argc; char **envp; int varflag; struct strlist *sp; int mode; int pip[2]; struct cmdentry cmdentry; struct job *jp; struct jmploc jmploc; struct jmploc *savehandler; char *savecmdname; struct shparam saveparam; struct localvar *savelocalvars; volatile int e; char *lastarg; int realstatus; int do_clearcmdentry; /* First expand the arguments. */ TRACE(("evalcommand(%p, %d) called\n", (void *)cmd, flags)); setstackmark(&smark); arglist.lastp = &arglist.list; varlist.lastp = &varlist.list; varflag = 1; do_clearcmdentry = 0; oexitstatus = exitstatus; exitstatus = 0; for (argp = cmd->ncmd.args ; argp ; argp = argp->narg.next) { char *p = argp->narg.text; if (varflag && is_name(*p)) { do { p++; } while (is_in_name(*p)); if (*p == '=') { expandarg(argp, &varlist, EXP_VARTILDE); continue; } } expandarg(argp, &arglist, EXP_FULL | EXP_TILDE); varflag = 0; } *arglist.lastp = NULL; *varlist.lastp = NULL; expredir(cmd->ncmd.redirect); argc = 0; for (sp = arglist.list ; sp ; sp = sp->next) argc++; argv = stalloc(sizeof (char *) * (argc + 1)); for (sp = arglist.list ; sp ; sp = sp->next) { TRACE(("evalcommand arg: %s\n", sp->text)); *argv++ = sp->text; } *argv = NULL; lastarg = NULL; if (iflag && funcnest == 0 && argc > 0) lastarg = argv[-1]; argv -= argc; /* Print the command if xflag is set. */ if (xflag) { char sep = 0; const char *p; out2str(ps4val()); for (sp = varlist.list ; sp ; sp = sp->next) { if (sep != 0) outc(' ', &errout); p = sp->text; while (*p != '=' && *p != '\0') out2c(*p++); if (*p != '\0') { out2c(*p++); out2qstr(p); } sep = ' '; } for (sp = arglist.list ; sp ; sp = sp->next) { if (sep != 0) outc(' ', &errout); /* Disambiguate command looking like assignment. */ if (sp == arglist.list && strchr(sp->text, '=') != NULL && strchr(sp->text, '\'') == NULL) { out2c('\''); out2str(sp->text); out2c('\''); } else out2qstr(sp->text); sep = ' '; } outc('\n', &errout); flushout(&errout); } /* Now locate the command. */ if (argc == 0) { /* Variable assignment(s) without command */ cmdentry.cmdtype = CMDBUILTIN; cmdentry.u.index = BLTINCMD; cmdentry.special = 1; } else { static const char PATH[] = "PATH="; char *path = pathval(); /* * Modify the command lookup path, if a PATH= assignment * is present */ for (sp = varlist.list ; sp ; sp = sp->next) if (strncmp(sp->text, PATH, sizeof(PATH) - 1) == 0) { path = sp->text + sizeof(PATH) - 1; /* * On `PATH=... command`, we need to make * sure that the command isn't using the * non-updated hash table of the outer PATH * setting and we need to make sure that * the hash table isn't filled with items * from the temporary setting. * * It would be better to forbit using and * updating the table while this command * runs, by the command finding mechanism * is heavily integrated with hash handling, * so we just delete the hash before and after * the command runs. Partly deleting like * changepatch() does doesn't seem worth the * bookinging effort, since most such runs add * directories in front of the new PATH. */ clearcmdentry(0); do_clearcmdentry = 1; } find_command(argv[0], &cmdentry, 1, path); if (cmdentry.cmdtype == CMDUNKNOWN) { /* command not found */ exitstatus = 127; flushout(&errout); return; } /* implement the bltin builtin here */ if (cmdentry.cmdtype == CMDBUILTIN && cmdentry.u.index == BLTINCMD) { for (;;) { argv++; if (--argc == 0) break; if ((cmdentry.u.index = find_builtin(*argv, &cmdentry.special)) < 0) { outfmt(&errout, "%s: not found\n", *argv); exitstatus = 127; flushout(&errout); return; } if (cmdentry.u.index != BLTINCMD) break; } } } /* Fork off a child process if necessary. */ if (cmd->ncmd.backgnd || (cmdentry.cmdtype == CMDNORMAL && ((flags & EV_EXIT) == 0 || have_traps())) || ((flags & EV_BACKCMD) != 0 && (cmdentry.cmdtype != CMDBUILTIN || cmdentry.u.index == CDCMD || cmdentry.u.index == DOTCMD || cmdentry.u.index == EVALCMD)) || (cmdentry.cmdtype == CMDBUILTIN && cmdentry.u.index == COMMANDCMD)) { jp = makejob(cmd, 1); mode = cmd->ncmd.backgnd; if (flags & EV_BACKCMD) { mode = FORK_NOJOB; if (pipe(pip) < 0) error("Pipe call failed: %s", strerror(errno)); } if (forkshell(jp, cmd, mode) != 0) goto parent; /* at end of routine */ if (flags & EV_BACKCMD) { FORCEINTON; close(pip[0]); if (pip[1] != 1) { dup2(pip[1], 1); close(pip[1]); } } flags |= EV_EXIT; } /* This is the child process if a fork occurred. */ /* Execute the command. */ if (cmdentry.cmdtype == CMDFUNCTION) { #ifdef DEBUG trputs("Shell function: "); trargs(argv); #endif redirect(cmd->ncmd.redirect, REDIR_PUSH); saveparam = shellparam; shellparam.malloc = 0; shellparam.reset = 1; shellparam.nparam = argc - 1; shellparam.p = argv + 1; shellparam.optnext = NULL; INTOFF; savelocalvars = localvars; localvars = NULL; reffunc(cmdentry.u.func); INTON; savehandler = handler; if (setjmp(jmploc.loc)) { if (exception == EXSHELLPROC) freeparam(&saveparam); else { freeparam(&shellparam); shellparam = saveparam; } unreffunc(cmdentry.u.func); poplocalvars(); localvars = savelocalvars; handler = savehandler; longjmp(handler->loc, 1); } handler = &jmploc; for (sp = varlist.list ; sp ; sp = sp->next) mklocal(sp->text); funcnest++; exitstatus = oexitstatus; if (flags & EV_TESTED) evaltree(getfuncnode(cmdentry.u.func), EV_TESTED); else evaltree(getfuncnode(cmdentry.u.func), 0); funcnest--; INTOFF; unreffunc(cmdentry.u.func); poplocalvars(); localvars = savelocalvars; freeparam(&shellparam); shellparam = saveparam; handler = savehandler; popredir(); INTON; if (evalskip == SKIPFUNC) { evalskip = 0; skipcount = 0; } if (flags & EV_EXIT) exitshell(exitstatus); } else if (cmdentry.cmdtype == CMDBUILTIN) { #ifdef DEBUG trputs("builtin command: "); trargs(argv); #endif mode = (cmdentry.u.index == EXECCMD)? 0 : REDIR_PUSH; if (flags == EV_BACKCMD) { memout.nleft = 0; memout.nextc = memout.buf; memout.bufsize = 64; mode |= REDIR_BACKQ; } savecmdname = commandname; cmdenviron = varlist.list; e = -1; savehandler = handler; if (setjmp(jmploc.loc)) { e = exception; exitstatus = (e == EXINT)? SIGINT+128 : 2; goto cmddone; } handler = &jmploc; redirect(cmd->ncmd.redirect, mode); if (cmdentry.special) listsetvar(cmdenviron); commandname = argv[0]; argptr = argv + 1; nextopt_optptr = NULL; /* initialize nextopt */ builtin_flags = flags; exitstatus = (*builtinfunc[cmdentry.u.index])(argc, argv); flushall(); cmddone: cmdenviron = NULL; out1 = &output; out2 = &errout; freestdout(); if (e != EXSHELLPROC) { commandname = savecmdname; if (flags & EV_EXIT) { exitshell(exitstatus); } } handler = savehandler; if (e != -1) { if ((e != EXERROR && e != EXEXEC) || cmdentry.special) exraise(e); FORCEINTON; } if (cmdentry.u.index != EXECCMD) popredir(); if (flags == EV_BACKCMD) { backcmd->buf = memout.buf; backcmd->nleft = memout.nextc - memout.buf; memout.buf = NULL; } } else { #ifdef DEBUG trputs("normal command: "); trargs(argv); #endif clearredir(); redirect(cmd->ncmd.redirect, 0); for (sp = varlist.list ; sp ; sp = sp->next) setvareq(sp->text, VEXPORT|VSTACK); envp = environment(); shellexec(argv, envp, pathval(), cmdentry.u.index); /*NOTREACHED*/ } goto out; parent: /* parent process gets here (if we forked) */ if (mode == FORK_FG) { /* argument to fork */ INTOFF; exitstatus = waitforjob(jp, &realstatus); INTON; if (iflag && loopnest > 0 && WIFSIGNALED(realstatus)) { evalskip = SKIPBREAK; skipcount = loopnest; } } else if (mode == FORK_NOJOB) { backcmd->fd = pip[0]; close(pip[1]); backcmd->jp = jp; } out: if (lastarg) setvar("_", lastarg, 0); if (do_clearcmdentry) clearcmdentry(0); popstackmark(&smark); }
int MODULEMAINFUNC (int argc, char** argv){ SOCKET sock = INVALID_SOCKET; int i=0; SASIZETYPE size; pthread_t thread; struct clientparam defparam; int demon=0; struct clientparam * newparam; char *s; int error = 0; unsigned sleeptime; struct extparam myconf; unsigned char buf[256]; struct pollfd fds; int opt = 1; PROXYFUNC pf; FILE *fp = NULL; int maxchild; int silent = 0; int nlog = 5000; char loghelp[] = #ifdef STDMAIN " -d go to background (daemon)\n" #endif " -fFORMAT logging format (see documentation)\n" " -l log to stderr\n" " -lFILENAME log to FILENAME\n" " -bBUFSIZE size of network buffer (default 4096 for TCP, 16384 for UDP)\n" " -l@IDENT log to syslog IDENT\n" " -t be silenT (do not log service start/stop)\n" " -iIP ip address or internal interface (clients are expected to connect)\n" " -eIP ip address or external interface (outgoing connection will have this)\n"; int childcount=0; pthread_mutex_t counter_mutex; int new_sock = INVALID_SOCKET; struct linger lg; #ifdef STDMAIN signal(SIGPIPE, SIG_IGN); pthread_attr_init(&pa); pthread_attr_setstacksize(&pa,PTHREAD_STACK_MIN + 16384); pthread_attr_setdetachstate(&pa,PTHREAD_CREATE_DETACHED); #endif pf = childdef.pf; memcpy(&myconf, &conf, sizeof(myconf)); memset(&defparam, 0, sizeof(struct clientparam)); defparam.version = paused; defparam.childcount = &childcount; defparam.logfunc = myconf.logfunc; defparam.authfunc = myconf.authfunc; defparam.aclnum = myconf.aclnum; defparam.service = childdef.service; defparam.usentlm = 1; defparam.stdlog = NULL; defparam.time_start = time(NULL); maxchild = myconf.maxchild; #ifndef STDMAIN if(!conf.services){ conf.services = &defparam; } else { defparam.next = conf.services; conf.services = conf.services->prev = &defparam; } #endif pthread_mutex_init(defparam.counter_mutex = &counter_mutex, NULL); for (i=1; i<argc; i++) { if(*argv[i]=='-') { switch(argv[i][1]) { case 'd': if(!demon)daemonize(); demon = 1; break; case 'l': defparam.logfunc = logstdout; defparam.logtarget = (unsigned char*)mystrdup(argv[i]); if(argv[i][2]) { #ifdef STDMAIN if(argv[i][2]=='@'){ openlog(argv[i]+3, LOG_PID, LOG_DAEMON); defparam.logfunc = logsyslog; } else #endif { fp = fopen(argv[i] + 2, "a"); if (fp) { defparam.stdlog = fp; fseek(fp, 0L, SEEK_END); } } } break; case 'i': myconf.intip = getip((unsigned char *)argv[i]+2); break; case 'e': myconf.extip = getip((unsigned char *)argv[i]+2); break; case 'p': myconf.intport = atoi(argv[i]+2); break; case 'b': myconf.bufsize = atoi(argv[i]+2); break; case 'n': defparam.usentlm = 0; break; case 'f': defparam.logformat = (unsigned char *)argv[i] + 2; break; case 't': silent = 1; break; case 's': case 'a': myconf.singlepacket = 1 + atoi(argv[i]+2); break; default: error = 1; break; } } else break; } #ifndef STDMAIN if(childdef.port) { #endif #ifndef PORTMAP if (error || i!=argc) { #ifndef STDMAIN haveerror = 1; conf.threadinit = 0; #endif fprintf(stderr, "Usage: %s options\n" "Available options are:\n" "%s" " -pPORT - service port to accept connections\n" "%s" "\tExample: %s -i127.0.0.1\n\n" "%s", argv[0], loghelp, childdef.helpmessage, argv[0], #ifdef STDMAIN copyright #else "" #endif ); return (1); } #endif #ifndef STDMAIN } else { #endif #ifndef NOPORTMAP if (error || argc != i+3 || *argv[i]=='-'|| (myconf.intport = atoi(argv[i]))==0 || (defparam.targetport = htons((unsigned short)atoi(argv[i+2])))==0) { #ifndef STDMAIN haveerror = 1; conf.threadinit = 0; #endif fprintf(stderr, "Usage: %s options" " [-e<external_ip>] <port_to_bind>" " <target_hostname> <target_port>\n" "Available options are:\n" "%s" "%s" "\tExample: %s -d -i127.0.0.1 6666 serv.somehost.ru 6666\n\n" "%s", argv[0], loghelp, childdef.helpmessage, argv[0], #ifdef STDMAIN copyright #else "" #endif ); return (1); } defparam.target = (unsigned char *)mystrdup(argv[i+1]); #endif #ifndef STDMAIN } #endif if(!defparam.logformat){ defparam.logformat = myconf.logformat; } if(defparam.logformat){ if(*defparam.logformat == '-' && (s = strchr((char *)defparam.logformat + 1, '+')) && s[1]){ *s = 0; defparam.nonprintable = (unsigned char *)mystrdup((char *)defparam.logformat + 1); defparam.replace = s[1]; defparam.logformat = (unsigned char *)mystrdup(s + 2); *s = '+'; } else defparam.logformat = (unsigned char *)mystrdup((char *)defparam.logformat); } defparam.sinc.sin_addr.s_addr = defparam.intip = myconf.intip; if(!myconf.intport)myconf.intport = childdef.port; defparam.sinc.sin_port = defparam.intport = htons(myconf.intport); defparam.sins.sin_addr.s_addr = defparam.extip = myconf.extip; defparam.sins.sin_port = defparam.extport = htons(myconf.extport); defparam.remsock = defparam.clisock = defparam.ctrlsock = INVALID_SOCKET; defparam.sins.sin_family = defparam.sinc.sin_family = AF_INET; defparam.singlepacket = myconf.singlepacket; defparam.bufsize = myconf.bufsize; #ifndef STDMAIN conf.threadinit = 0; #endif lg.l_onoff = 1; lg.l_linger = conf.timeouts[STRING_L]; if( (sock=socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) { perror("socket()"); return -2; } fcntl(sock,F_SETFL,O_NONBLOCK); defparam.srvsock = sock; if(setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (unsigned char *)&opt, sizeof(int)))perror("setsockopt()"); size = sizeof(defparam.sinc); for(sleeptime = SLEEPTIME * 100; bind(sock, (struct sockaddr*)&defparam.sinc, size)==-1; usleep(sleeptime)) { sprintf((char *)buf, "bind(): %s", strerror(errno)); (*defparam.logfunc)(&defparam, buf); sleeptime = (sleeptime<<1); if(!sleeptime) { closesocket(sock); return -3; } } if(listen (sock, 1 + (maxchild>>4))==-1) { sprintf((char *)buf, "listen(): %s", strerror(errno)); (*defparam.logfunc)(&defparam, buf); return -4; } defparam.threadid = (unsigned)pthread_self(); if(!silent){ sprintf((char *)buf, "Accepting connections [%u/%u]", (unsigned)getpid(), (unsigned)pthread_self()); (*defparam.logfunc)(&defparam, buf); } defparam.sinc.sin_addr.s_addr = defparam.sins.sin_addr.s_addr = 0; defparam.sinc.sin_port = defparam.sins.sin_port = 0; fds.fd = sock; fds.events = POLLIN; for (;;) { for(;;){ while((paused == defparam.version && childcount >= myconf.maxchild)){ nlog++; if(nlog > 5000) { sprintf((char *)buf, "Warning: too many connected clients (%d/%d)", childcount, myconf.maxchild); (*defparam.logfunc)(&defparam, buf); nlog = 0; } usleep(SLEEPTIME); } if (paused != defparam.version) break; if (fds.events & POLLIN) { error = poll(&fds, 1, 1000); } else { usleep(SLEEPTIME); continue; } if (error >= 1) break; if (error == 0) continue; sprintf((char *)buf, "poll(): %s/%d", strerror(errno), errno); (*defparam.logfunc)(&defparam, buf); if(errno != EAGAIN) break; continue; } if(paused != defparam.version) break; size = sizeof(defparam.sinc); new_sock = accept(sock, (struct sockaddr*)&defparam.sinc, &size); if(new_sock == INVALID_SOCKET){ sprintf((char *)buf, "accept(): %s", strerror(errno)); (*defparam.logfunc)(&defparam, buf); continue; } fcntl(new_sock,F_SETFL,O_NONBLOCK); setsockopt(new_sock, SOL_SOCKET, SO_LINGER, (unsigned char *)&lg, sizeof(lg)); setsockopt(new_sock, SOL_SOCKET, SO_OOBINLINE, (unsigned char *)&opt, sizeof(int)); if(! (newparam = myalloc (sizeof(defparam)))){ closesocket(new_sock); defparam.res = 21; (*defparam.logfunc)(&defparam, (unsigned char *)"Memory Allocation Failed"); usleep(SLEEPTIME); continue; }; memcpy(newparam, &defparam, sizeof(defparam)); clearstat(newparam); newparam->clisock = new_sock; newparam->child = newparam->prev = newparam->next = NULL; newparam->parent = &defparam; pthread_mutex_lock(&counter_mutex); if(!defparam.child)defparam.child = newparam; else { newparam->next = defparam.child; defparam.child = defparam.child->prev = newparam; } if((error = pthread_create(&thread, &pa, pf, (void *)newparam))){ sprintf((char *)buf, "pthread_create(): %s", strerror(error)); (*defparam.logfunc)(&defparam, buf); freeparam(newparam); } else { childcount++; newparam->threadid = (unsigned)thread; } pthread_mutex_unlock(&counter_mutex); memset(&defparam.sinc, 0, sizeof(defparam.sinc)); while(!fds.events)usleep(SLEEPTIME); } if(defparam.srvsock != INVALID_SOCKET) closesocket(defparam.srvsock); if(!silent) defparam.logfunc(&defparam, (unsigned char *)"Exiting thread"); defparam.service = S_ZOMBIE; while(defparam.child) usleep(SLEEPTIME * 100); defparam.threadid = 0; if(fp) fclose(fp); if(defparam.target) myfree(defparam.target); if(defparam.logtarget) myfree(defparam.logtarget); if(defparam.logformat) myfree(defparam.logformat); if(defparam.nonprintable) myfree(defparam.nonprintable); #ifndef STDMAIN if(defparam.next)defparam.next->prev = defparam.prev; if(defparam.prev)defparam.prev->next = defparam.next; else conf.services = defparam.next; #endif pthread_mutex_destroy(&counter_mutex); return 0; }
void * ftpprchild(struct clientparam* param) { int i=0, res; unsigned char *buf; unsigned char *se; int status = 0; int inbuf; int pasv = 0; SOCKET sc = INVALID_SOCKET, ss = INVALID_SOCKET, clidatasock = INVALID_SOCKET; SASIZETYPE sasize; char * req = NULL; struct linger lg; struct pollfd fds; if(!(buf = myalloc(BUFSIZE))) RETURN(876); param->ctrlsock = param->clisock; param->operation = CONNECT; lg.l_onoff = 1; lg.l_linger = conf.timeouts[STRING_L];; if(socksend(param->ctrlsock, (unsigned char *)"220 Ready\r\n", 11, conf.timeouts[STRING_S])!=11) {RETURN (801);} for(;;){ i = sockgetlinebuf(param, CLIENT, buf, BUFSIZE - 10, '\n', conf.timeouts[CONNECTION_S]); if(!i) { RETURN(0); } if(i<4) {RETURN(802);} buf[i] = 0; if ((se=(unsigned char *)strchr((char *)buf, '\r'))) *se = 0; if (req) myfree (req); req = NULL; if (!strncasecmp((char *)buf, "OPEN ", 5)){ if(parsehostname((char *)buf+5, param, 21)){RETURN(803);} if(param->remsock != INVALID_SOCKET) { so._shutdown(param->remsock, SHUT_RDWR); so._closesocket(param->remsock); param->remsock = INVALID_SOCKET; } if((res = (*param->srv->authfunc)(param))) {RETURN(res);} param->ctrlsocksrv = param->remsock; if(socksend(param->ctrlsock, (unsigned char *)"220 Ready\r\n", 11, conf.timeouts[STRING_S])!=11) {RETURN (801);} status = 1; } else if (!strncasecmp((char *)buf, "USER ", 5)){ if(parseconnusername((char *)buf +5, param, 0, 21)){RETURN(804);} if(!status){ if((res = (*param->srv->authfunc)(param))) {RETURN(res);} param->ctrlsocksrv = param->remsock; } if(socksend(param->ctrlsock, (unsigned char *)"331 ok\r\n", 8, conf.timeouts[STRING_S])!=8) {RETURN (807);} status = 2; } else if (!strncasecmp((char *)buf, "PASS ", 5)){ param->extpassword = (unsigned char *)mystrdup((char *)buf+5); inbuf = BUFSIZE; res = ftplogin(param, (char *)buf, &inbuf); param->res = res; if(inbuf && inbuf != BUFSIZE && socksend(param->ctrlsock, buf, inbuf, conf.timeouts[STRING_S])!=inbuf) {RETURN (807);} if(!res) status = 3; sprintf((char *)buf, "%.64s@%.128s%c%hu", param->extusername, param->hostname, (ntohs(param->sins.sin_port)==21)?0:':', ntohs(param->sins.sin_port)); req = mystrdup((char *)buf); #ifndef WITHMAIN { int action, reqbufsize, reqsize; reqbufsize = BUFSIZE; reqsize = (int)strlen(buf) + 1; action = handlereqfilters(param, &buf, &reqbufsize, 0, &reqsize); if(action == HANDLED){ RETURN(0); } if(action != PASS) RETURN(877); } #endif } else if (status >= 3 && ( (!strncasecmp((char *)buf, "PASV", 4) && (pasv = 1)) || (!strncasecmp((char *)buf, "PORT ", 5) && !(pasv = 0)) )){ #ifndef WITHMAIN { int action, reqbufsize, reqsize; reqbufsize = BUFSIZE; reqsize = (int)strlen(buf) + 1; action = handlehdrfilterscli(param, &buf, &reqbufsize, 0, &reqsize); if(action == HANDLED){ RETURN(0); } if(action != PASS) RETURN(878); } #endif if(sc != INVALID_SOCKET) { so._shutdown(sc, SHUT_RDWR); so._closesocket(sc); sc = INVALID_SOCKET; } if(ss != INVALID_SOCKET) { so._shutdown(ss, SHUT_RDWR); so._closesocket(ss); ss = INVALID_SOCKET; } if(clidatasock != INVALID_SOCKET) { so._shutdown(clidatasock, SHUT_RDWR); so._closesocket(clidatasock); clidatasock = INVALID_SOCKET; } if ((clidatasock=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) {RETURN(821);} sasize = sizeof(struct sockaddr_in); if(so._getsockname(param->ctrlsock, (struct sockaddr *)¶m->sinc, &sasize)){RETURN(824);} param->sinc.sin_port = 0; if(so._bind(clidatasock, (struct sockaddr *)¶m->sinc, sasize)){RETURN(822);} if (pasv) { if(so._listen(clidatasock, 1)) {RETURN(823);} if(so._getsockname(clidatasock, (struct sockaddr *)¶m->sinc, &sasize)){RETURN(824);} sprintf((char *)buf, "227 OK (%u,%u,%u,%u,%u,%u)\r\n", (unsigned)(((unsigned char *)(¶m->sinc.sin_addr.s_addr))[0]), (unsigned)(((unsigned char *)(¶m->sinc.sin_addr.s_addr))[1]), (unsigned)(((unsigned char *)(¶m->sinc.sin_addr.s_addr))[2]), (unsigned)(((unsigned char *)(¶m->sinc.sin_addr.s_addr))[3]), (unsigned)(((unsigned char *)(¶m->sinc.sin_port))[0]), (unsigned)(((unsigned char *)(¶m->sinc.sin_port))[1]) ); } else { unsigned long b1, b2, b3, b4; unsigned short b5, b6; if(sscanf((char *)buf+5, "%lu,%lu,%lu,%lu,%hu,%hu", &b1, &b2, &b3, &b4, &b5, &b6)!=6) {RETURN(828);} param->sinc.sin_family = AF_INET; param->sinc.sin_port = htons((unsigned short)((b5<<8)^b6)); param->sinc.sin_addr.s_addr = htonl((b1<<24)^(b2<<16)^(b3<<8)^b4); if(so._connect(clidatasock, (struct sockaddr *)¶m->sinc, sasize)) { so._closesocket(clidatasock); clidatasock = INVALID_SOCKET; RETURN(826); } sprintf(buf, "200 OK\r\n"); } #ifndef WITHMAIN { int action, reqbufsize, reqsize; reqbufsize = BUFSIZE; reqsize = (int)strlen(buf) + 1; action = handlehdrfilterssrv(param, &buf, &reqbufsize, 0, &reqsize); if(action == HANDLED){ RETURN(0); } if(action != PASS) RETURN(879); } #endif if(socksend(param->ctrlsock, buf, (int)strlen((char *)buf), conf.timeouts[STRING_S])!=(int)strlen((char *)buf)) {RETURN (825);} status = 4; } else if (status == 4 && ( !(strncasecmp((char *)buf, "RETR ", 5) && (param->operation = FTP_GET)) || !(strncasecmp((char *)buf, "LIST", 4) && (param->operation = FTP_LIST))|| !(strncasecmp((char *)buf, "NLST ", 5) && (param->operation = FTP_LIST)) || !(strncasecmp((char *)buf, "MLSD", 4) && (param->operation = FTP_LIST)) || !(strncasecmp((char *)buf, "APPE ", 5) && (param->operation = FTP_PUT)) || !(strncasecmp((char *)buf, "STOR ", 5) && (param->operation = FTP_PUT)) )){ int arg = (buf[4] && buf[5])? 1:0; int ressent = 0; #ifndef WITHMAIN { int action, reqbufsize, reqsize; reqbufsize = BUFSIZE; reqsize = (int)strlen(buf) + 1; action = handlehdrfilterscli(param, &buf, &reqbufsize, 0, &reqsize); if(action == HANDLED){ RETURN(0); } if(action != PASS) RETURN(880); } #endif if(clidatasock == INVALID_SOCKET) { RETURN (829);} if(pasv){ memset(&fds, 0, sizeof(fds)); fds.fd = clidatasock; fds.events = POLLIN; res = so._poll (&fds, 1, conf.timeouts[STRING_L]*1000); if(res != 1) { RETURN(857); } sasize = sizeof(struct sockaddr_in); ss = so._accept(clidatasock, (struct sockaddr *)¶m->sinc, &sasize); if (ss == INVALID_SOCKET) { RETURN (858);} so._shutdown(clidatasock, SHUT_RDWR); so._closesocket(clidatasock); clidatasock = ss; ss = INVALID_SOCKET; } if(clidatasock == INVALID_SOCKET){RETURN(828);} req = mystrdup((char *)buf); buf[4] = 0; status = 3; ss = ftpcommand(param, buf, arg? buf+5 : NULL); if (ss == INVALID_SOCKET) { so._shutdown(clidatasock, SHUT_RDWR); so._closesocket(clidatasock); clidatasock = INVALID_SOCKET; if(socksend(param->ctrlsock, (unsigned char *)"550 err\r\n", 9, conf.timeouts[STRING_S])!=9) {RETURN (831);} continue; } if(socksend(param->ctrlsock, (unsigned char *)"125 data\r\n", 10, conf.timeouts[STRING_S]) != 10) { param->remsock = INVALID_SOCKET; RETURN (832); } if(param->srvoffset < param->srvinbuf)while((i = sockgetlinebuf(param, SERVER, buf, BUFSIZE, '\n', 0)) > 3){ if(socksend(param->ctrlsock, buf, i, conf.timeouts[STRING_S])!=i) {RETURN(833);} if(isnumber(*buf) && buf[3] != '-') { ressent = 1; break; } } sc = param->remsock; param->remsock = ss; so._setsockopt(param->remsock, SOL_SOCKET, SO_LINGER, (unsigned char *)&lg, sizeof(lg)); so._setsockopt(clidatasock, SOL_SOCKET, SO_LINGER, (unsigned char *)&lg, sizeof(lg)); param->clisock = clidatasock; res = sockmap(param, conf.timeouts[CONNECTION_S]); if(param->remsock != INVALID_SOCKET) { so._shutdown (param->remsock, SHUT_RDWR); so._closesocket(param->remsock); } if(param->clisock != INVALID_SOCKET) { so._shutdown (param->clisock, SHUT_RDWR); so._closesocket(param->clisock); } param->clisock = param->ctrlsock; param->remsock = sc; sc = INVALID_SOCKET; ss = INVALID_SOCKET; clidatasock = INVALID_SOCKET; if(!ressent){ while((i = sockgetlinebuf(param, SERVER, buf, BUFSIZE, '\n', conf.timeouts[STRING_L])) > 3){ if(socksend(param->ctrlsock, buf, i, conf.timeouts[STRING_S])!=i) {RETURN(833);} if(isnumber(*buf) && buf[3] != '-') break; } if(i < 3) {RETURN(834);} } } else { if(status < 3) { if(socksend(param->remsock, (unsigned char *)"530 login\r\n", 11, conf.timeouts[STRING_S])!=1) {RETURN (810);} continue; } if(!strncasecmp((char *)buf, "QUIT", 4)) status = 5; if(!strncasecmp((char *)buf, "CWD ", 4)) req = mystrdup((char *)buf); i = (int)strlen((char *)buf); buf[i++] = '\r'; buf[i++] = '\n'; if(socksend(param->remsock, buf, i, conf.timeouts[STRING_S])!=i) {RETURN (811);} param->statscli += i; param->nwrites++; while((i = sockgetlinebuf(param, SERVER, buf, BUFSIZE, '\n', conf.timeouts[STRING_L])) > 0){ if(socksend(param->ctrlsock, buf, i, conf.timeouts[STRING_S])!=i) {RETURN (812);} if(i > 4 && isnumber(*buf) && buf[3] != '-') break; } if(status == 5) {RETURN (0);} if(i < 3) {RETURN (813);} } sasize = sizeof(struct sockaddr_in); if(so._getpeername(param->ctrlsock, (struct sockaddr *)¶m->sinc, &sasize)){RETURN(819);} if(req && (param->statscli || param->statssrv)){ (*param->srv->logfunc)(param, (unsigned char *)req); } } CLEANRET: if(sc != INVALID_SOCKET) { so._shutdown(sc, SHUT_RDWR); so._closesocket(sc); } if(ss != INVALID_SOCKET) { so._shutdown(ss, SHUT_RDWR); so._closesocket(ss); } if(clidatasock != INVALID_SOCKET) { so._shutdown(clidatasock, SHUT_RDWR); so._closesocket(clidatasock); } sasize = sizeof(struct sockaddr_in); so._getpeername(param->ctrlsock, (struct sockaddr *)¶m->sinc, &sasize); if(param->res != 0 || param->statscli || param->statssrv ){ (*param->srv->logfunc)(param, (unsigned char *)((req && (param->res > 802))? req:NULL)); } if(req) myfree(req); if(buf) myfree(buf); freeparam(param); return (NULL); }
STATIC void evalcommand(shinstance *psh, union node *cmd, int flags, struct backcmd *backcmd) { struct stackmark smark; union node *argp; struct arglist arglist; struct arglist varlist; char **argv; int argc; char **envp; int varflag; struct strlist *sp; int mode; int pip[2]; struct cmdentry cmdentry; struct job *jp; struct jmploc jmploc; struct jmploc *volatile savehandler; char *volatile savecmdname; volatile struct shparam saveparam; struct localvar *volatile savelocalvars; volatile int e; char *lastarg; const char *path = pathval(psh); volatile int temp_path; #if __GNUC__ /* Avoid longjmp clobbering */ (void) &argv; (void) &argc; (void) &lastarg; (void) &flags; #endif psh->vforked = 0; /* First expand the arguments. */ TRACE((psh, "evalcommand(0x%lx, %d) called\n", (long)cmd, flags)); setstackmark(psh, &smark); psh->back_exitstatus = 0; arglist.lastp = &arglist.list; varflag = 1; /* Expand arguments, ignoring the initial 'name=value' ones */ for (argp = cmd->ncmd.args ; argp ; argp = argp->narg.next) { char *p = argp->narg.text; if (varflag && is_name(*p)) { do { p++; } while (is_in_name(*p)); if (*p == '=') continue; } expandarg(psh, argp, &arglist, EXP_FULL | EXP_TILDE); varflag = 0; } *arglist.lastp = NULL; expredir(psh, cmd->ncmd.redirect); /* Now do the initial 'name=value' ones we skipped above */ varlist.lastp = &varlist.list; for (argp = cmd->ncmd.args ; argp ; argp = argp->narg.next) { char *p = argp->narg.text; if (!is_name(*p)) break; do p++; while (is_in_name(*p)); if (*p != '=') break; expandarg(psh, argp, &varlist, EXP_VARTILDE); } *varlist.lastp = NULL; argc = 0; for (sp = arglist.list ; sp ; sp = sp->next) argc++; argv = stalloc(psh, sizeof (char *) * (argc + 1)); for (sp = arglist.list ; sp ; sp = sp->next) { TRACE((psh, "evalcommand arg: %s\n", sp->text)); *argv++ = sp->text; } *argv = NULL; lastarg = NULL; if (iflag(psh) && psh->funcnest == 0 && argc > 0) lastarg = argv[-1]; argv -= argc; /* Print the command if xflag is set. */ if (xflag(psh)) { char sep = 0; out2str(psh, ps4val(psh)); for (sp = varlist.list ; sp ; sp = sp->next) { if (sep != 0) outc(sep, &psh->errout); out2str(psh, sp->text); sep = ' '; } for (sp = arglist.list ; sp ; sp = sp->next) { if (sep != 0) outc(sep, &psh->errout); out2str(psh, sp->text); sep = ' '; } outc('\n', &psh->errout); flushout(&psh->errout); } /* Now locate the command. */ if (argc == 0) { cmdentry.cmdtype = CMDSPLBLTIN; cmdentry.u.bltin = bltincmd; } else { static const char PATH[] = "PATH="; int cmd_flags = DO_ERR; /* * Modify the command lookup path, if a PATH= assignment * is present */ for (sp = varlist.list; sp; sp = sp->next) if (strncmp(sp->text, PATH, sizeof(PATH) - 1) == 0) path = sp->text + sizeof(PATH) - 1; do { int argsused, use_syspath; find_command(psh, argv[0], &cmdentry, cmd_flags, path); if (cmdentry.cmdtype == CMDUNKNOWN) { psh->exitstatus = 127; flushout(&psh->errout); goto out; } /* implement the 'command' builtin here */ if (cmdentry.cmdtype != CMDBUILTIN || cmdentry.u.bltin != bltincmd) break; cmd_flags |= DO_NOFUNC; argsused = parse_command_args(psh, argc, argv, &use_syspath); if (argsused == 0) { /* use 'type' builting to display info */ cmdentry.u.bltin = typecmd; break; } argc -= argsused; argv += argsused; if (use_syspath) path = syspath(psh) + 5; } while (argc != 0); if (cmdentry.cmdtype == CMDSPLBLTIN && cmd_flags & DO_NOFUNC) /* posix mandates that 'command <splbltin>' act as if <splbltin> was a normal builtin */ cmdentry.cmdtype = CMDBUILTIN; } /* Fork off a child process if necessary. */ if (cmd->ncmd.backgnd || (cmdentry.cmdtype == CMDNORMAL && (flags & EV_EXIT) == 0) || ((flags & EV_BACKCMD) != 0 && ((cmdentry.cmdtype != CMDBUILTIN && cmdentry.cmdtype != CMDSPLBLTIN) || cmdentry.u.bltin == dotcmd || cmdentry.u.bltin == evalcmd))) { INTOFF; jp = makejob(psh, cmd, 1); mode = cmd->ncmd.backgnd; if (flags & EV_BACKCMD) { mode = FORK_NOJOB; if (sh_pipe(psh, pip) < 0) error(psh, "Pipe call failed"); } #ifdef DO_SHAREDVFORK /* It is essential that if DO_SHAREDVFORK is defined that the * child's address space is actually shared with the parent as * we rely on this. */ if (cmdentry.cmdtype == CMDNORMAL) { pid_t pid; savelocalvars = psh->localvars; psh->localvars = NULL; psh->vforked = 1; switch (pid = vfork()) { case -1: TRACE((psh, "Vfork failed, errno=%d\n", errno)); INTON; error(psh, "Cannot vfork"); break; case 0: /* Make sure that exceptions only unwind to * after the vfork(2) */ if (setjmp(jmploc.loc)) { if (psh->exception == EXSHELLPROC) { /* We can't progress with the vfork, * so, set vforked = 2 so the parent * knows, and _exit(); */ psh->vforked = 2; sh__exit(psh, 0); } else { sh__exit(psh, psh->exerrno); } } savehandler = psh->handler; psh->handler = &jmploc; listmklocal(psh, varlist.list, VEXPORT | VNOFUNC); forkchild(psh, jp, cmd, mode, psh->vforked); break; default: psh->handler = savehandler; /* restore from vfork(2) */ poplocalvars(psh); psh->localvars = savelocalvars; if (psh->vforked == 2) { psh->vforked = 0; (void)sh_waitpid(psh, pid, NULL, 0); /* We need to progress in a normal fork fashion */ goto normal_fork; } psh->vforked = 0; forkparent(psh, jp, cmd, mode, pid); goto parent; } } else { normal_fork: #endif if (forkshell(psh, jp, cmd, mode) != 0) goto parent; /* at end of routine */ FORCEINTON; #ifdef DO_SHAREDVFORK } #endif if (flags & EV_BACKCMD) { if (!psh->vforked) { FORCEINTON; } shfile_close(&psh->fdtab, pip[0]); if (pip[1] != 1) { movefd(psh, pip[1], 1); } } flags |= EV_EXIT; } /* This is the child process if a fork occurred. */ /* Execute the command. */ switch (cmdentry.cmdtype) { case CMDFUNCTION: #ifdef DEBUG trputs(psh, "Shell function: "); trargs(psh, argv); #endif redirect(psh, cmd->ncmd.redirect, REDIR_PUSH); saveparam = psh->shellparam; psh->shellparam.malloc = 0; psh->shellparam.reset = 1; psh->shellparam.nparam = argc - 1; psh->shellparam.p = argv + 1; psh->shellparam.optnext = NULL; INTOFF; savelocalvars = psh->localvars; psh->localvars = NULL; INTON; if (setjmp(jmploc.loc)) { if (psh->exception == EXSHELLPROC) { freeparam(psh, (volatile struct shparam *) &saveparam); } else { freeparam(psh, &psh->shellparam); psh->shellparam = saveparam; } poplocalvars(psh); psh->localvars = savelocalvars; psh->handler = savehandler; longjmp(psh->handler->loc, 1); } savehandler = psh->handler; psh->handler = &jmploc; listmklocal(psh, varlist.list, 0); /* stop shell blowing its stack */ if (++psh->funcnest > 1000) error(psh, "too many nested function calls"); evaltree(psh, cmdentry.u.func, flags & EV_TESTED); psh->funcnest--; INTOFF; poplocalvars(psh); psh->localvars = savelocalvars; freeparam(psh, &psh->shellparam); psh->shellparam = saveparam; psh->handler = savehandler; popredir(psh); INTON; if (psh->evalskip == SKIPFUNC) { psh->evalskip = 0; psh->skipcount = 0; } if (flags & EV_EXIT) exitshell(psh, psh->exitstatus); break; case CMDBUILTIN: case CMDSPLBLTIN: #ifdef DEBUG trputs(psh, "builtin command: "); trargs(psh, argv); #endif mode = (cmdentry.u.bltin == execcmd) ? 0 : REDIR_PUSH; if (flags == EV_BACKCMD) { psh->memout.nleft = 0; psh->memout.nextc = psh->memout.buf; psh->memout.bufsize = 64; mode |= REDIR_BACKQ; } e = -1; savehandler = psh->handler; savecmdname = psh->commandname; psh->handler = &jmploc; if (!setjmp(jmploc.loc)) { /* We need to ensure the command hash table isn't * corruped by temporary PATH assignments. * However we must ensure the 'local' command works! */ if (path != pathval(psh) && (cmdentry.u.bltin == hashcmd || cmdentry.u.bltin == typecmd)) { savelocalvars = psh->localvars; psh->localvars = 0; mklocal(psh, path - 5 /* PATH= */, 0); temp_path = 1; } else temp_path = 0; redirect(psh, cmd->ncmd.redirect, mode); /* exec is a special builtin, but needs this list... */ psh->cmdenviron = varlist.list; /* we must check 'readonly' flag for all builtins */ listsetvar(psh, varlist.list, cmdentry.cmdtype == CMDSPLBLTIN ? 0 : VNOSET); psh->commandname = argv[0]; /* initialize nextopt */ psh->argptr = argv + 1; psh->optptr = NULL; /* and getopt */ #if 0 /** @todo fix getop usage! */ #if defined(__FreeBSD__) || defined(__EMX__) || defined(__APPLE__) optreset = 1; optind = 1; #else optind = 0; /* init */ #endif #endif psh->exitstatus = cmdentry.u.bltin(psh, argc, argv); } else { e = psh->exception; psh->exitstatus = e == EXINT ? SIGINT + 128 : e == EXEXEC ? psh->exerrno : 2; } psh->handler = savehandler; output_flushall(psh); psh->out1 = &psh->output; psh->out2 = &psh->errout; freestdout(psh); if (temp_path) { poplocalvars(psh); psh->localvars = savelocalvars; } psh->cmdenviron = NULL; if (e != EXSHELLPROC) { psh->commandname = savecmdname; if (flags & EV_EXIT) exitshell(psh, psh->exitstatus); } if (e != -1) { if ((e != EXERROR && e != EXEXEC) || cmdentry.cmdtype == CMDSPLBLTIN) exraise(psh, e); FORCEINTON; } if (cmdentry.u.bltin != execcmd) popredir(psh); if (flags == EV_BACKCMD) { backcmd->buf = psh->memout.buf; backcmd->nleft = (int)(psh->memout.nextc - psh->memout.buf); psh->memout.buf = NULL; } break; default: #ifdef DEBUG trputs(psh, "normal command: "); trargs(psh, argv); #endif clearredir(psh, psh->vforked); redirect(psh, cmd->ncmd.redirect, psh->vforked ? REDIR_VFORK : 0); if (!psh->vforked) for (sp = varlist.list ; sp ; sp = sp->next) setvareq(psh, sp->text, VEXPORT|VSTACK); envp = environment(psh); shellexec(psh, argv, envp, path, cmdentry.u.index, psh->vforked); break; } goto out; parent: /* parent process gets here (if we forked) */ if (mode == FORK_FG) { /* argument to fork */ psh->exitstatus = waitforjob(psh, jp); } else if (mode == FORK_NOJOB) { backcmd->fd = pip[0]; shfile_close(&psh->fdtab, pip[1]); backcmd->jp = jp; } FORCEINTON; out: if (lastarg) /* dsl: I think this is intended to be used to support * '_' in 'vi' command mode during line editing... * However I implemented that within libedit itself. */ setvar(psh, "_", lastarg, 0); popstackmark(psh, &smark); if (eflag(psh) && psh->exitstatus && !(flags & EV_TESTED)) exitshell(psh, psh->exitstatus); }
void * adminchild(struct clientparam* param) { int i, res; char * buf; char username[256]; char *sb; char *req = NULL; struct printparam pp; int contentlen = 0; int isform = 0; pp.inbuf = 0; pp.cp = param; buf = myalloc(LINESIZE); if(!buf) {RETURN(555);} i = sockgetlinebuf(param, CLIENT, (unsigned char *)buf, LINESIZE - 1, '\n', conf.timeouts[STRING_S]); if(i<5 || ((buf[0]!='G' || buf[1]!='E' || buf[2]!='T' || buf[3]!=' ' || buf[4]!='/') && (buf[0]!='P' || buf[1]!='O' || buf[2]!='S' || buf[3]!='T' || buf[4]!=' ' || buf[5]!='/'))) { RETURN(701); } buf[i] = 0; sb = strchr(buf+5, ' '); if(!sb){ RETURN(702); } *sb = 0; req = mystrdup(buf + ((*buf == 'P')? 6 : 5)); while((i = sockgetlinebuf(param, CLIENT, (unsigned char *)buf, LINESIZE - 1, '\n', conf.timeouts[STRING_S])) > 2){ buf[i] = 0; if(i > 19 && (!strncasecmp(buf, "authorization", 13))){ sb = strchr(buf, ':'); if(!sb)continue; ++sb; while(isspace(*sb))sb++; if(!*sb || strncasecmp(sb, "basic", 5)){ continue; } sb+=5; while(isspace(*sb))sb++; i = de64((unsigned char *)sb, (unsigned char *)username, 255); if(i<=0)continue; username[i] = 0; sb = strchr((char *)username, ':'); if(sb){ *sb = 0; if(param->password)myfree(param->password); param->password = (unsigned char *)mystrdup(sb+1); } if(param->username) myfree(param->username); param->username = (unsigned char *)mystrdup(username); continue; } else if(i > 15 && (!strncasecmp(buf, "content-length:", 15))){ sb = buf + 15; while(isspace(*sb))sb++; contentlen = atoi(sb); } else if(i > 13 && (!strncasecmp(buf, "content-type:", 13))){ sb = buf + 13; while(isspace(*sb))sb++; if(!strncasecmp(sb, "x-www-form-urlencoded", 21)) isform = 1; } } param->operation = ADMIN; if(isform && contentlen) { printstr(&pp, "HTTP/1.0 100 Continue\r\n\r\n"); stdpr(&pp, NULL, 0); } res = (*param->srv->authfunc)(param); if(res && res != 10) { printstr(&pp, authreq); RETURN(res); } if(param->srv->singlepacket || param->redirected){ if(*req == 'C') req[1] = 0; else *req = 0; } sprintf(buf, ok, conf.stringtable?(char *)conf.stringtable[2]:"3proxy", conf.stringtable?(char *)conf.stringtable[2]:"3[APA3A] tiny proxy", conf.stringtable?(char *)conf.stringtable[3]:""); if(*req != 'S') printstr(&pp, buf); switch(*req){ case 'C': printstr(&pp, counters); { struct trafcount *cp; int num = 0; for(cp = conf.trafcounter; cp; cp = cp->next, num++){ int inbuf = 0; if(cp->ace && (param->srv->singlepacket || param->redirected)){ if(!ACLmatches(cp->ace, param))continue; } if(req[1] == 'S' && atoi(req+2) == num) cp->disabled=0; if(req[1] == 'D' && atoi(req+2) == num) cp->disabled=1; inbuf += sprintf(buf, "<tr>" "<td>%s</td><td><A HREF=\'/C%c%d\'>%s</A></td><td>", (cp->comment)?cp->comment:" ", (cp->disabled)?'S':'D', num, (cp->disabled)?"NO":"YES" ); if(!cp->ace || !cp->ace->users){ inbuf += sprintf(buf+inbuf, "<center>ANY</center>"); } else { inbuf += printuserlist(buf+inbuf, LINESIZE-800, cp->ace->users, ",<br />\r\n"); } inbuf += sprintf(buf+inbuf, "</td><td>"); if(!cp->ace || !cp->ace->src){ inbuf += sprintf(buf+inbuf, "<center>ANY</center>"); } else { inbuf += printiplist(buf+inbuf, LINESIZE-512, cp->ace->src, ",<br />\r\n"); } inbuf += sprintf(buf+inbuf, "</td><td>"); if(!cp->ace || !cp->ace->dst){ inbuf += sprintf(buf+inbuf, "<center>ANY</center>"); } else { inbuf += printiplist(buf+inbuf, LINESIZE-512, cp->ace->dst, ",<br />\r\n"); } inbuf += sprintf(buf+inbuf, "</td><td>"); if(!cp->ace || !cp->ace->ports){ inbuf += sprintf(buf+inbuf, "<center>ANY</center>"); } else { inbuf += printportlist(buf+inbuf, LINESIZE-128, cp->ace->ports, ",<br />\r\n"); } if(cp->type == NONE) { inbuf += sprintf(buf+inbuf, "</td><td colspan=\'6\' align=\'center\'>exclude from limitation</td></tr>\r\n" ); } else { inbuf += sprintf(buf+inbuf, "</td><td>%.3f</td>" "<td>MB%s</td>" "<td>%.3f MB</td>" "<td>%s</td>", (1024.0 * (float)cp->traflimgb) + (float)cp->traflim/1048576.0, rotations[cp->type], (1024.0 * (float)cp->trafgb) + (float)cp->traf/1048576.0, cp->cleared?ctime(&cp->cleared):"never" ); inbuf += sprintf(buf + inbuf, "<td>%s</td>" "<td>%i</td>" "</tr>\r\n", cp->updated?ctime(&cp->updated):"never", cp->number ); } printstr(&pp, buf); } } printstr(&pp, counterstail); break; case 'R': conf.needreload = 1; printstr(&pp, "<h3>Reload scheduled</h3>"); break; case 'S': { if(req[1] == 'X'){ printstr(&pp, style); break; } printstr(&pp, xml); printval(conf.services, TYPE_SERVER, 0, &pp); printstr(&pp, postxml); } break; case 'F': { FILE *fp; char buf[256]; fp = confopen(); if(!fp){ printstr(&pp, "<h3><font color=\"red\">Failed to open config file</font></h3>"); break; } printstr(&pp, "<h3>Please be careful editing config file remotely</h3>"); printstr(&pp, "<form method=\"POST\" action=\"/U\"><textarea cols=\"80\" rows=\"30\" name=\"conffile\">"); while(fgets(buf, 256, fp)){ printstr(&pp, buf); } if(!writable) fclose(fp); printstr(&pp, "</textarea><br><input type=\"Submit\"></form>"); break; } case 'U': { int l=0; int error = 0; if(!writable || fseek(writable, 0, 0)){ error = 1; } while((i = sockgetlinebuf(param, CLIENT, (unsigned char *)buf, LINESIZE - 1, '+', conf.timeouts[STRING_S])) > 0){ if(i > (contentlen - l)) i = (contentlen - l); buf[i] = 0; if(!l){ if(strncasecmp(buf, "conffile=", 9)) error = 1; } if(!error){ decodeurl((unsigned char *)buf, 1); fprintf(writable, "%s", l? buf : buf + 9); } l += i; if(l >= contentlen) break; } if(writable && !error){ fflush(writable); #ifndef _WINCE ftruncate(fileno(writable), ftell(writable)); #endif } printstr(&pp, error? "<h3><font color=\"red\">Config file is not writable</font></h3>Make sure you have \"writable\" command in configuration file": "<h3>Configuration updated</h3>"); } break; default: printstr(&pp, (char *)conf.stringtable[WEBBANNERS]); break; } if(*req != 'S') printstr(&pp, tail); CLEANRET: printstr(&pp, NULL); if(buf) myfree(buf); (*param->srv->logfunc)(param, (unsigned char *)req); if(req)myfree(req); freeparam(param); return (NULL); }
void * udppmchild(struct clientparam* param) { unsigned char *buf = NULL; int res, i; #ifdef _WIN32 SASIZETYPE size; unsigned long ul = 1; #endif struct udpmap *udpmappings = NULL; struct pollfd fds[256]; if(!param->hostname)parsehostname((char *)param->srv->target, param, ntohs(param->srv->targetport)); if (!param->req.sin_addr.s_addr) { param->srv->fds.events = POLLIN; RETURN (100); } if(!param->clibuf && (!(param->clibuf=myalloc(UDPBUFSIZE)) || !(param->clibufsize = UDPBUFSIZE))){ param->srv->fds.events = POLLIN; RETURN (21); } param->cliinbuf = param->clioffset = 0; i = sockrecvfrom(param->srv->srvsock, ¶m->sinc, param->clibuf, param->clibufsize, 0); if(i<=0){ param->srv->fds.events = POLLIN; RETURN (214); } param->cliinbuf = i; #ifdef _WIN32 if((param->clisock=so._socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) { RETURN(818); } if(so._setsockopt(param->clisock, SOL_SOCKET, SO_REUSEADDR, (unsigned char *)&ul, sizeof(int))) {RETURN(820);}; ioctlsocket(param->clisock, FIONBIO, &ul); size = sizeof(struct sockaddr_in); if(so._getsockname(param->srv->srvsock, (struct sockaddr *)¶m->sins, &size)) {RETURN(21);}; if(so._bind(param->clisock,(struct sockaddr *)¶m->sins,sizeof(struct sockaddr_in))) { RETURN(822); } #else param->clisock = param->srv->srvsock; #endif param->sins.sin_family = AF_INET; param->sins.sin_port = htons(0); param->sins.sin_addr.s_addr = param->extip; if ((param->remsock=so._socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) {RETURN (11);} if(so._bind(param->remsock,(struct sockaddr *)¶m->sins,sizeof(param->sins))) {RETURN (12);} #ifdef _WIN32 ioctlsocket(param->remsock, FIONBIO, &ul); #else fcntl(param->remsock,F_SETFL,O_NONBLOCK); #endif param->sins.sin_addr.s_addr = param->req.sin_addr.s_addr; param->sins.sin_port = param->req.sin_port; param->operation = UDPASSOC; if((res = (*param->srv->authfunc)(param))) {RETURN(res);} if(param->srv->singlepacket) { param->srv->fds.events = POLLIN; } param->res = sockmap(param, conf.timeouts[(param->srv->singlepacket)?SINGLEBYTE_L:STRING_L]); if(!param->srv->singlepacket) { param->srv->fds.events = POLLIN; } CLEANRET: if(buf)myfree(buf); (*param->srv->logfunc)(param, NULL); #ifndef _WIN32 param->clisock = INVALID_SOCKET; #endif freeparam(param); return (NULL); }
void * dnsprchild(struct clientparam* param) { unsigned long ip = 0; unsigned char *bbuf; unsigned char *buf, *s1, *s2; char * host = NULL; unsigned char c; SASIZETYPE size; int res, i; int len; unsigned type=0; unsigned ttl; unsigned char addr[16]; #ifdef _WIN32 unsigned long ul = 1; #endif if(!(bbuf = myalloc(BUFSIZE+2))){ param->srv->fds.events = POLLIN; RETURN (21); } buf = bbuf+2; size = sizeof(param->sincr); i = so._recvfrom(param->srv->srvsock, buf, BUFSIZE, 0, (struct sockaddr *)¶m->sincr, &size); size = sizeof(param->sinsl); getsockname(param->srv->srvsock, (struct sockaddr *)¶m->sincl, &size); #ifdef _WIN32 if((param->clisock=so._socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) { RETURN(818); } ioctlsocket(param->clisock, FIONBIO, &ul); if(so._setsockopt(param->clisock, SOL_SOCKET, SO_REUSEADDR, (unsigned char *)&ul, sizeof(int))) {RETURN(820);}; if(so._bind(param->clisock,(struct sockaddr *)¶m->sincl,sizeof(param->sincl))) { RETURN(822); } #else param->clisock = param->srv->srvsock; #endif param->srv->fds.events = POLLIN; if(i < 0) { RETURN(813); } buf[BUFSIZE - 1] = 0; if(i<=13 || i>1000){ RETURN (814); } param->operation = DNSRESOLVE; if((res = (*param->srv->authfunc)(param))) {RETURN(res);} if(buf[4]!=0 || buf[5]!=1) RETURN(816); for(len = 12; len<i; len+=(c+1)){ c = buf[len]; if(!c)break; buf[len] = '.'; } if(len > (i-4)) {RETURN(817);} host = mystrdup((char *)buf+13); if(!host) {RETURN(21);} for(s2 = buf + 12; (s1 = (unsigned char *)strchr((char *)s2 + 1, '.')); s2 = s1)*s2 = (unsigned char)((s1 - s2) - 1); *s2 = (len - (int)(s2 - buf)) - 1; type = ((unsigned)buf[len+1])*256 + (unsigned)buf[len+2]; if((type==0x01 || type==0x1c) && !param->srv->singlepacket){ ip = udpresolve((type==0x1c)?AF_INET6:AF_INET, (unsigned char *)host, addr, &ttl, param, 0); } len+=5; if(ip){ buf[2] = 0x85; buf[3] = 0x80; buf[6] = 0; buf[7] = 1; buf[8] = buf[9] = buf[10] = buf[11] = 0; memset(buf+len, 0, 16); buf[len] = 0xc0; buf[len+1] = 0x0c; buf[len+3] = type; buf[len+5] = 1; ttl = htonl(ttl); memcpy(buf + len + 6, &ttl, 4); buf[len+11] = type==1? 4:16; memcpy(buf+len+12,(void *)&addr,type==1? 4:16); len+=(type==1?16:28); } else if(type == 0x0c) { unsigned a, b, c, d; sscanf(host, "%u.%u.%u.%u", &a, &b, &c, &d); ip = htonl((d<<24) ^ (c<<16) ^ (b<<8) ^ a); if(*SAFAMILY(¶m->sincl) == AF_INET && ip == *(unsigned long*)SAADDR(¶m->sincl)){ buf[2] = 0x85; buf[3] = 0x80; buf[6] = 0; buf[7] = 1; buf[8] = buf[9] = buf[10] = buf[11] = 0; memset(buf+len, 0, 20); buf[len] = 0xc0; buf[len+1] = 0x0c; buf[len+3] = 0x0c; buf[len+5] = 1; ttl = htonl(3600); memcpy(buf + len + 6, &ttl, 4); buf[len+11] = 7; buf[len+12] = 6; memcpy(buf+len+13,(void *)"3proxy",6); len+=20; } else ip = 0; } if(!ip && numservers){ if((param->remsock=so._socket(SASOCK(&nservers[0].addr), nservers[0].usetcp? SOCK_STREAM:SOCK_DGRAM, nservers[0].usetcp?IPPROTO_TCP:IPPROTO_UDP)) == INVALID_SOCKET) { RETURN(818); } memset(¶m->sinsl, 0, sizeof(param->sinsl)); *SAFAMILY(¶m->sinsl) = *SAFAMILY(&nservers[0].addr); if(so._bind(param->remsock,(struct sockaddr *)¶m->sinsl,sizeof(param->sinsl))) { RETURN(819); } memcpy(¶m->sinsr, &nservers[0].addr, sizeof(param->sinsr)); if(nservers[0].usetcp) { if(so._connect(param->remsock,(struct sockaddr *)¶m->sinsr,sizeof(param->sinsr))) RETURN(830); buf-=2; *(unsigned short*)buf = htons(i); i+=2; } else { #ifdef _WIN32 /* ioctlsocket(param->remsock, FIONBIO, &ul); */ #else /* fcntl(param->remsock,F_SETFL,O_NONBLOCK); */ #endif } if(socksendto(param->remsock, (struct sockaddr *)¶m->sinsr, buf, i, conf.timeouts[SINGLEBYTE_L]*1000) != i){ RETURN(820); } param->statscli64 += i; param->nwrites++; len = sockrecvfrom(param->remsock, (struct sockaddr *)¶m->sinsr, buf, BUFSIZE, 15000); if(len <= 13) { RETURN(821); } param->statssrv64 += len; param->nreads++; if(nservers[0].usetcp) { unsigned short us; us = ntohs(*(unsigned short *)buf); if(us > 4096) RETURN(833); buf += 2; len -= 2; if(len < us) len += sockgetlinebuf(param, SERVER, buf+len, us - len, 0, conf.timeouts[SINGLEBYTE_L]); if(len != us) RETURN(832); } if(buf[6] || buf[7]){ if(socksendto(param->clisock, (struct sockaddr *)¶m->sincr, buf, len, conf.timeouts[SINGLEBYTE_L]*1000) != len){ RETURN(822); } RETURN(0); } } if(!ip) { buf[2] = 0x85; buf[3] = 0x83; } res = socksendto(param->clisock, (struct sockaddr *)¶m->sincr, buf, len, conf.timeouts[SINGLEBYTE_L]*1000); if(res != len){RETURN(819);} if(!ip) {RETURN(888);} CLEANRET: if(param->res!=813){ sprintf((char *)buf, "%04x/%s/", (unsigned)type, host?host:""); if(ip && type == 0x01 || type == 0x1c){ myinet_ntop(type == 0x01? AF_INET:AF_INET6, addr, buf+strlen(buf), 64); } (*param->srv->logfunc)(param, buf); } if(bbuf)myfree(bbuf); if(host)myfree(host); #ifndef _WIN32 param->clisock = INVALID_SOCKET; #endif freeparam(param); return (NULL); }