3proxy/src/msnpr.c
2014-12-13 23:20:00 +03:00

233 lines
5.6 KiB
C

/*
3APA3A simpliest proxy server
(c) 2002-2008 by ZARAZA <3APA3A@security.nnov.ru>
please read License Agreement
*/
#include "proxy.h"
#ifndef PORTMAP
#define PORTMAP
#endif
#define RETURN(xxx) { param->res = xxx; goto CLEANRET; }
struct msn_cookie {
struct msn_cookie *next;
unsigned char *userid;
char * connectstring;
};
static struct msn_cookie *msn_cookies = NULL;
pthread_mutex_t msn_cookie_mutex;
int msn_cookie_mutex_init = 0;
static void msn_clear(void *fo){
};
static FILTER_ACTION msn_srv(void *fc, struct clientparam * param, unsigned char ** buf_p, int * bufsize_p, int offset, int * length_p){
unsigned char *data = *buf_p + offset;
int len = (int)(*length_p - offset);
struct sockaddr_in sa;
SASIZETYPE size = sizeof(sa);
struct msn_cookie *cookie;
char tmpbuf[256];
char *sp1, *sp2, *sp3;
if(*bufsize_p - *length_p < 32) return CONTINUE;
if(len < 10 || len > 220) return CONTINUE;
data[len] = 0;
sp1 = data + 3;
if(data[0] == 'X' && data[1] == 'F' && data[2] == 'R' && data[3] == ' '){
if(!(sp2 = strchr(sp1 + 1, ' ')) || !(sp2 = strchr(sp2 + 1, ' '))|| !(sp3 = strchr(sp2 + 1, ' '))) return CONTINUE;
}
else if(data[0] == 'R' && data[1] == 'N' && data[2] == 'G' && data[3] == ' '){
if(!(sp2 = strchr(sp1 + 1, ' ')) || !(sp3 = strchr(sp2 + 1, ' '))) return CONTINUE;
}
else return CONTINUE;
*sp2 = 0;
*sp3 = 0;
if(getsockname(param->clisock, (struct sockaddr *)&sa, &size)==-1) {
return CONTINUE;
};
cookie = myalloc(sizeof(struct msn_cookie));
cookie->connectstring = mystrdup(sp2 + 1);
cookie->userid = mystrdup(param->username);
pthread_mutex_lock(&msn_cookie_mutex);
cookie->next = msn_cookies;
msn_cookies = cookie;
pthread_mutex_unlock(&msn_cookie_mutex);
strcpy(tmpbuf, data);
len = (int)strlen(tmpbuf);
tmpbuf[len++] = ' ';
len+=myinet_ntop(*SAFAMILY(&sa), SAADDR(&sa), tmpbuf+len, 64);
sprintf(tmpbuf+len, ":%hu %s", ntohs(sa.sin_port), sp3 + 1);
len = (int)strlen(tmpbuf);
memcpy(*buf_p + offset, tmpbuf, len);
*length_p = offset + len;
return CONTINUE;
}
static struct filter msnfilter = {
NULL,
"msnfilter",
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
*msn_srv,
*msn_clear,
NULL
};
void * msnprchild(struct clientparam* param) {
int res, len;
unsigned char *buf;
int buflen = 256;
char *sp1, *sp2, *sp3;
char *verstr = NULL;
int id;
struct msn_cookie *cookie, *prevcookie=NULL;
int sec = 0;
struct filterp **newfilters;
int skip = 0;
struct filterp msnfilterp = {
&msnfilter,
(void *)&skip
};
if(!msn_cookie_mutex_init){
msn_cookie_mutex_init = 1;
pthread_mutex_init(&msn_cookie_mutex, NULL);
}
buf = myalloc(buflen);
res = sockgetlinebuf(param, CLIENT, buf, 240, '\n', conf.timeouts[STRING_S]);
if(res < 10) RETURN(1201);
buf[res] = 0;
if(!(sp1 = strchr(buf, ' ')) || !(sp2 = strchr(sp1 + 1, ' ')) || !(sp3 = strchr(sp2 + 1, ' ')) || ((int)(sp3-sp2)) < 6) RETURN(1202);
if((buf[0] == 'U' && buf[1] == 'S' && buf[2] == 'R') ||
(buf[0] == 'A' && buf[1] == 'N' && buf[2] == 'S')){
len = 1 + (int)(sp3 - sp2);
param->username = myalloc(len - 1);
memcpy(param->username, sp2 + 1, len - 2);
sec = 1;
}
else if(buf[0] != 'V' || buf[1] != 'E' || buf[2] != 'R') {RETURN(1203);}
else {
id = atoi(sp1 + 1);
verstr = mystrdup(buf);
if(socksend(param->clisock, buf, res, conf.timeouts[STRING_S])!=res) {RETURN (1204);}
res = sockgetlinebuf(param, CLIENT, buf, 240, '\n', conf.timeouts[STRING_S]);
if(res < 10) RETURN(1205);
buf[res] = 0;
if(buf[0] != 'C' || buf[1] != 'V' || buf[2] != 'R' || !(sp1=strrchr(buf,' ')) || (len = (int)strlen(sp1+1)) < 3) RETURN(1206);
param->username = myalloc(len - 1);
memcpy(param->username, sp1 + 1, len - 2);
}
param->username[len - 2] = 0;
param->operation = CONNECT;
pthread_mutex_lock(&msn_cookie_mutex);
for(cookie = msn_cookies; cookie; cookie = cookie->next){
if(!strcmp(param->username, cookie->userid)){
parsehostname(cookie->connectstring, param, ntohs(param->srv->targetport));
if(prevcookie)prevcookie->next = cookie->next;
else msn_cookies = cookie->next;
myfree(cookie->connectstring);
myfree(cookie->userid);
myfree(cookie);
break;
}
prevcookie = cookie;
}
pthread_mutex_unlock(&msn_cookie_mutex);
if(!cookie) {
if(sec) RETURN(1233);
parsehostname((char *)param->srv->target, param, ntohs(param->srv->targetport));
}
res = (*param->srv->authfunc)(param);
if(res) {RETURN(res);}
if(!sec){
len = (int)strlen(verstr);
if(socksend(param->remsock, verstr, len, conf.timeouts[STRING_S])!= len) {RETURN (1207);}
param->statscli64 += len;
myfree(verstr);
verstr = mystrdup(buf);
len = sockgetlinebuf(param, SERVER, buf, 240, '\n', conf.timeouts[STRING_S]);
if(len < 10) RETURN(1208);
param->statssrv64 += len;
strcpy(buf, verstr);
}
len = (int)strlen(buf);
if((res=handledatfltcli(param, &buf, &buflen, 0, &len))!=PASS) RETURN(res);
if(socksend(param->remsock, buf, len, conf.timeouts[STRING_S])!= len) {RETURN (1207);}
param->statscli64 += len;
if(sec){
RETURN(sockmap(param, conf.timeouts[CONNECTION_L]));
}
param->ndatfilterssrv++;
newfilters = myalloc(param->ndatfilterssrv * sizeof(struct filterp *));
if(param->ndatfilterssrv > 1){
memcpy(newfilters, param->datfilterssrv, (param->ndatfilterssrv - 1) * sizeof(struct filterp *));
myfree(param->datfilterssrv);
}
param->datfilterssrv = newfilters;
newfilters[param->ndatfilterssrv - 1] = &msnfilterp;
param->res = sockmap(param, conf.timeouts[CONNECTION_L]);
param->ndatfilterssrv--;
CLEANRET:
if(verstr)myfree(verstr);
if(buf)myfree(buf);
(*param->srv->logfunc)(param, NULL);
freeparam(param);
return (NULL);
}
#ifdef WITHMAIN
struct proxydef childdef = {
msnprchild,
0,
0,
S_MSNPR,
""
};
#include "proxymain.c"
#endif