Compare commits

...

8 Commits

Author SHA1 Message Date
Vladimir Dubrovin
a3729354b8 Allow hashtable to grow
Some checks are pending
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Waiting to run
C/C++ CI Linux / ${{ matrix.target }} (ubuntu-latest) (push) Waiting to run
C/C++ CI MacOS / ${{ matrix.target }} (macos-15) (push) Waiting to run
C/C++ CI Windows / ${{ matrix.target }} (windows-2022) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (macos-15) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-24.04-arm) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (ubuntu-latest) (push) Waiting to run
C/C++ CI cmake / ${{ matrix.target }} (windows-2022) (push) Waiting to run
2026-04-18 17:24:01 +03:00
Vladimir Dubrovin
45796f66c7 Cleanup 3proxy_crypt 2026-04-18 15:47:07 +03:00
Vladimir Dubrovin
260cbf7a3d Use uint32_t for hashtable indicies 2026-04-18 15:36:14 +03:00
Vladimir Dubrovin
bba9871ed8 Use 3proxy_crypt instead of mycrypt 2026-04-18 15:19:06 +03:00
Vladimir Dubrovin
f1af44f3a9 Refactor hashtables to use indices instead of pointers, use blake2 as a hash, mycrypt renamed to 3proxy_crypt 2026-04-18 15:12:43 +03:00
Vladimir Dubrovin
4ee7f71fb9 Использовать tablesize в хештаблице 2026-04-17 21:15:21 +03:00
Vladimir Dubrovin
98604b5421 Add hashcompact 2026-04-17 20:40:27 +03:00
Vladimir Dubrovin
a0d580b36d move hashtable/resolve/sql functions to separate files 2026-04-17 19:29:50 +03:00
23 changed files with 1434 additions and 625 deletions

1
.gitignore vendored
View File

@ -258,3 +258,4 @@ pip-log.txt
#Mr Developer
.mr.developer.cfg
CLAUDE.md
bin/3proxy_crypt

View File

@ -283,16 +283,20 @@ set(3PROXY_CORE_SOURCES
src/3proxy.c
src/auth.c
src/authradius.c
src/hash.c
src/resolve.c
src/sql.c
src/conf.c
src/datatypes.c
src/plugins.c
src/stringtable.c
)
# MD4/MD5 sources for mycrypt
# MD4/MD5/BLAKE2 sources for 3proxy_crypt
set(MD_SOURCES
src/libs/md4.c
src/libs/md5.c
src/libs/blake2b-ref.c
)
# ============================================================================
@ -345,9 +349,9 @@ target_compile_definitions(mainfunc PRIVATE MODULEMAINFUNC=mainfunc)
add_library(ftp_obj OBJECT src/ftp.c)
target_include_directories(ftp_obj PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src)
# mycrypt object for 3proxy (without WITHMAIN)
add_library(mycrypt_obj OBJECT src/mycrypt.c)
target_include_directories(mycrypt_obj PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src)
# 3proxy_crypt object for 3proxy (without WITHMAIN)
add_library(3proxy_crypt_obj OBJECT src/3proxy_crypt.c)
target_include_directories(3proxy_crypt_obj PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src)
# ============================================================================
# Main 3proxy executable
@ -362,7 +366,7 @@ add_executable(3proxy
$<TARGET_OBJECTS:common_obj>
$<TARGET_OBJECTS:base64_obj>
$<TARGET_OBJECTS:ftp_obj>
$<TARGET_OBJECTS:mycrypt_obj>
$<TARGET_OBJECTS:3proxy_crypt_obj>
)
target_include_directories(3proxy PRIVATE
@ -395,18 +399,18 @@ elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux")
endif()
endif()
# Build mycrypt utility
add_executable(mycrypt
src/mycrypt.c
# Build 3proxy_crypt utility
add_executable(3proxy_crypt
src/3proxy_crypt.c
${MD_SOURCES}
$<TARGET_OBJECTS:base64_obj>
)
target_compile_definitions(mycrypt PRIVATE WITHMAIN)
target_include_directories(mycrypt PRIVATE
target_compile_definitions(3proxy_crypt PRIVATE WITHMAIN)
target_include_directories(3proxy_crypt PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/src
${CMAKE_CURRENT_SOURCE_DIR}/src/libs
)
target_link_libraries(mycrypt PRIVATE Threads::Threads)
target_link_libraries(3proxy_crypt PRIVATE Threads::Threads)
# Build standalone proxy executables
foreach(PROXY_NAME proxy socks pop3p smtpp ftppr tcppm udppm tlspr)
@ -493,7 +497,7 @@ if(PAM_FOUND)
endif()
# Installation rules
install(TARGETS 3proxy mycrypt proxy socks pop3p smtpp ftppr tcppm udppm tlspr
install(TARGETS 3proxy 3proxy_crypt proxy socks pop3p smtpp ftppr tcppm udppm tlspr
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)

View File

@ -49,7 +49,7 @@ include Makefile.inc
install: all
if [ ! -d "/usr/local/3proxy/bin" ]; then mkdir -p /usr/local/3proxy/bin/; fi
install bin/3proxy /usr/local/3proxy/bin/3proxy
install bin/mycrypt /usr/local/3proxy/bin/mycrypt
install bin/3proxy_crypt /usr/local/3proxy/bin/3proxy_crypt
install scripts/rc.d/3proxy /usr/local/etc/rc.d/3proxy
install scripts/add3proxyuser.sh /usr/local/3proxy/bin/
if [ -s /usr/local/etc/3proxy/3proxy.cfg ]; then /usr/local/3proxy/3proxy.cfg already exists ; else install scripts/3proxy.cfg /usr/local/etc/3proxy/; fi

View File

@ -62,7 +62,7 @@ INSTALL_BIN = $(INSTALL) -m 755
INSTALL_DATA = $(INSTALL) -m 644
INSTALL_OBJS = bin/3proxy \
bin/ftppr \
bin/mycrypt \
bin/3proxy_crypt \
bin/pop3p \
bin/proxy \
bin/socks \

View File

@ -63,7 +63,7 @@ INSTALL_BIN = $(INSTALL) -m 755
INSTALL_DATA = $(INSTALL) -m 644
INSTALL_OBJS = src/3proxy \
src/ftppr \
src/mycrypt \
src/3proxy_crypt \
src/pop3p \
src/proxy \
src/socks \

View File

@ -51,7 +51,7 @@ include Makefile.inc
install: all
if [ ! -d "/usr/local/3proxy/bin" ]; then mkdir -p /usr/local/3proxy/bin/; fi
install bin/3proxy /usr/local/3proxy/bin/3proxy
install bin/mycrypt /usr/local/3proxy/bin/mycrypt
install bin/3proxy_crypt /usr/local/3proxy/bin/3proxy_crypt
install scripts/rc.d/3proxy /usr/local/etc/rc.d/3proxy
install scripts/add3proxyuser.sh /usr/local/3proxy/bin/
if [ -s /usr/local/etc/3proxy/3proxy.cfg ]; then /usr/local/3proxy/3proxy.cfg already exists ; else install scripts/3proxy.cfg /usr/local/etc/3proxy/; fi

View File

@ -200,7 +200,7 @@ sudo launchctl unload /Library/LaunchDaemons/org.3proxy.3proxy.plist
- User authentication by DNS hostname
- Authentication cache with possibility to limit user to single IP address
- Access control by username/password for SOCKSv5 and HTTP/HTTPS/FTP
- Cleartext or encrypted (crypt/MD5 or NT) passwords
- Cleartext or encrypted passwords
- Connection redirection
- Access control by requested action (CONNECT/BIND, HTTP GET/POST/PUT/HEAD/OTHER)
- All access control entries now support weekday and time limitations
@ -286,12 +286,12 @@ TLS proxy (SNI proxy) - sniffs hostname from TLS handshake
### udppm
UDP port mapping. Maps some UDP port on local machine to UDP port on remote machine. Only one user simultaneously can use UDP mapping, so it can't be used for public service in large networks. It's OK to use it to map to DNS server in small network or to map Counter-Strike server for single client (you can use few mappings on different ports for different clients in last case).
### mycrypt
Program to obtain crypted password for cleartext. Supports both MD5/crypt and NT password.
### 3proxy_crypt
Program to obtain crypted password for cleartext. Supports both salted and NT password.
```bash
mycrypt password # produces NT password
mycrypt salt password # produces MD5/crypt password with salt "salt"
3proxy_crypt password # produces NT password
3proxy_crypt salt password # produces password hash with salt "salt"
```
---

View File

@ -969,7 +969,7 @@ or
<pre>
users $"c:\Program Files\3proxy\passwords"
</pre>
It's possible to create NT and crypt passwords with the mycrypt utility included
It's possible to create NT and crypt passwords with the 3proxy_crypt utility included
in the distribution.
<br>The user list is system-wide. To manage user access to a specific service, use ACLs.
</p>

View File

@ -983,7 +983,7 @@ openssl pkcs12 -export -out client.p12 -passout pass: \
или
<pre>
users $"c:\Program Files\3proxy\passwords"</pre>
Шифрованные NT и crypt пароли можно создавать с помощью утилиты mycrypt.
Шифрованные NT и crypt пароли можно создавать с помощью утилиты 3proxy_crypt.
<br>Список пользователей един для всех служб. Разграничение доступа по службам
необходимо производить с помощью списков доступа.
</p>

View File

@ -6,7 +6,7 @@ if [ $3 ]; then
echo countin \"`wc -l /etc/3proxy/conf/counters|awk '{print $1}'`/$1\" D $3 $1 >> /etc/3proxy/conf/counters
fi
if [ $2 ]; then
echo $1:`/bin/mycrypt $$ $2` >> /etc/3proxy/conf/passwd
echo $1:`/bin/3proxy_crypt $$ $2` >> /etc/3proxy/conf/passwd
else
echo usage: $0 username password [day_limit] [bandwidth]
echo " "day_limit - traffic limit in MB per day

View File

@ -33,7 +33,7 @@ make clean
%files
/bin/3proxy
/bin/ftppr
/bin/mycrypt
/bin/3proxy_crypt
/bin/pop3p
/bin/proxy
/bin/socks

View File

@ -5,8 +5,11 @@
please read License Agreement
*/
#ifndef WITHMAIN
#include "libs/md5.h"
#endif
#include "libs/md4.h"
#include "libs/blake2.h"
#include <string.h>
#define MD5_SIZE 16
@ -64,20 +67,21 @@ unsigned char * ntpwdhash (unsigned char *szHash, const unsigned char *szPasswor
unsigned char * mycrypt(const unsigned char *pw, const unsigned char *salt, unsigned char *passwd){
const unsigned char *ep;
unsigned char *magic;
unsigned char *p;
const unsigned char *sp;
unsigned char final[MD5_SIZE];
int sl;
unsigned long l;
#ifndef WITHMAIN
if(salt[0] == '$' && salt[1] == '1' && salt[2] == '$' && (ep = (unsigned char *)strchr((char *)salt+3, '$'))) {
static unsigned char *magic = (unsigned char *)"$1$";
unsigned char *p;
const unsigned char *sp;
unsigned char final[MD5_SIZE];
int sl,pl,i;
MD5_CTX ctx,ctx1;
unsigned long l;
int pl, i;
/* Refine the Salt first */
sp = salt +3;
/* get the length of the true salt */
sl = (int)(ep - sp);
magic = (unsigned char *)"$1$";
MD5Init(&ctx);
@ -109,10 +113,6 @@ unsigned char * mycrypt(const unsigned char *pw, const unsigned char *salt, unsi
else
MD5Update(&ctx, pw, 1);
/* Now make the output string */
strcpy((char *)passwd,(char *)magic);
strncat((char *)passwd,(char *)sp,sl);
strcat((char *)passwd,"$");
MD5Final(final,&ctx);
@ -141,28 +141,42 @@ unsigned char * mycrypt(const unsigned char *pw, const unsigned char *salt, unsi
MD5Final(final,&ctx1);
}
p = passwd + strlen((char *)passwd);
l = (final[ 0]<<16) | (final[ 6]<<8) | final[12];
_crypt_to64(p,l,4); p += 4;
l = (final[ 1]<<16) | (final[ 7]<<8) | final[13];
_crypt_to64(p,l,4); p += 4;
l = (final[ 2]<<16) | (final[ 8]<<8) | final[14];
_crypt_to64(p,l,4); p += 4;
l = (final[ 3]<<16) | (final[ 9]<<8) | final[15];
_crypt_to64(p,l,4); p += 4;
l = (final[ 4]<<16) | (final[10]<<8) | final[ 5];
_crypt_to64(p,l,4); p += 4;
l = final[11] ;
_crypt_to64(p,l,2); p += 2;
*p = '\0';
/* Don't leave anything around in vm they could use. */
memset(final,0,sizeof final);
}
else
#endif
if(salt[0] == '$' && salt[1] == '3' && salt[2] == '$' && (ep = (unsigned char *)strchr((char *)salt+3, '$'))) {
sp = salt +3;
sl = (int)(ep - sp);
magic = (unsigned char *)"$3$";
blake2b(final, MD5_SIZE, pw, strlen((char *)pw), salt, strlen((char *)salt) );
}
else {
*passwd = 0;
return passwd;
}
strcpy((char *)passwd,(char *)magic);
strncat((char *)passwd,(char *)sp,sl);
strcat((char *)passwd,"$");
p = passwd + strlen((char *)passwd);
l = (final[ 0]<<16) | (final[ 6]<<8) | final[12];
_crypt_to64(p,l,4); p += 4;
l = (final[ 1]<<16) | (final[ 7]<<8) | final[13];
_crypt_to64(p,l,4); p += 4;
l = (final[ 2]<<16) | (final[ 8]<<8) | final[14];
_crypt_to64(p,l,4); p += 4;
l = (final[ 3]<<16) | (final[ 9]<<8) | final[15];
_crypt_to64(p,l,4); p += 4;
l = (final[ 4]<<16) | (final[10]<<8) | final[ 5];
_crypt_to64(p,l,4); p += 4;
l = final[11] ;
_crypt_to64(p,l,2); p += 2;
*p = '\0';
return passwd;
}
@ -176,7 +190,7 @@ int main(int argc, char* argv[]){
fprintf(stderr, "usage: \n"
"\t%s <password>\n"
"\t%s <salt> <password>\n"
"Performs NT crypt if no salt specified, MD5 crypt with salt\n"
"Performs NT crypt if no salt specified, BLAKE2 crypt with salt\n"
"This software uses:\n"
" RSA Data Security, Inc. MD4 Message-Digest Algorithm\n"
" RSA Data Security, Inc. MD5 Message-Digest Algorithm\n",
@ -190,7 +204,7 @@ int main(int argc, char* argv[]){
else {
i = (int)strlen((char *)argv[1]);
if (i > 64) argv[1][64] = 0;
sprintf((char *)buf, "$1$%s$", argv[1]);
sprintf((char *)buf, "$3$%s$", argv[1]);
printf("CR:%s\n", mycrypt((unsigned char *)argv[2], buf, buf+256));
}
return 0;

View File

@ -2,7 +2,7 @@
# 3 proxy common Makefile
#
all: $(BUILDDIR)3proxy$(EXESUFFICS) $(BUILDDIR)mycrypt$(EXESUFFICS) $(BUILDDIR)pop3p$(EXESUFFICS) $(BUILDDIR)smtpp$(EXESUFFICS) $(BUILDDIR)ftppr$(EXESUFFICS) $(BUILDDIR)tcppm$(EXESUFFICS) $(BUILDDIR)tlspr$(EXESUFFICS) $(BUILDDIR)udppm$(EXESUFFICS) $(BUILDDIR)socks$(EXESUFFICS) $(BUILDDIR)proxy$(EXESUFFICS) allplugins
all: $(BUILDDIR)3proxy$(EXESUFFICS) $(BUILDDIR)3proxy_crypt$(EXESUFFICS) $(BUILDDIR)pop3p$(EXESUFFICS) $(BUILDDIR)smtpp$(EXESUFFICS) $(BUILDDIR)ftppr$(EXESUFFICS) $(BUILDDIR)tcppm$(EXESUFFICS) $(BUILDDIR)tlspr$(EXESUFFICS) $(BUILDDIR)udppm$(EXESUFFICS) $(BUILDDIR)socks$(EXESUFFICS) $(BUILDDIR)proxy$(EXESUFFICS) allplugins
sockmap$(OBJSUFFICS): sockmap.c proxy.h structures.h
@ -119,6 +119,12 @@ srvdnspr$(OBJSUFFICS): dnspr.c proxy.h structures.h
auth$(OBJSUFFICS): auth.c proxy.h structures.h
$(CC) $(COUT)auth$(OBJSUFFICS) $(CFLAGS) auth.c
hash$(OBJSUFFICS): hash.c proxy.h structures.h
$(CC) $(COUT)hash$(OBJSUFFICS) $(CFLAGS) hash.c
resolve$(OBJSUFFICS): resolve.c proxy.h structures.h
$(CC) $(COUT)resolve$(OBJSUFFICS) $(CFLAGS) resolve.c
authradius$(OBJSUFFICS): authradius.c proxy.h structures.h
$(CC) $(COUT)authradius$(OBJSUFFICS) $(CFLAGS) authradius.c
@ -131,15 +137,11 @@ log$(OBJSUFFICS): log.c proxy.h structures.h
datatypes$(OBJSUFFICS): datatypes.c proxy.h structures.h
$(CC) $(COUT)datatypes$(OBJSUFFICS) $(CFLAGS) datatypes.c
mycrypt$(OBJSUFFICS): mycrypt.c
$(CC) $(COUT)mycrypt$(OBJSUFFICS) $(CFLAGS) mycrypt.c
mycryptmain$(OBJSUFFICS): mycrypt.c
$(CC) $(COUT)mycryptmain$(OBJSUFFICS) $(CFLAGS) $(DEFINEOPTION)WITHMAIN mycrypt.c
$(BUILDDIR)mycrypt$(EXESUFFICS): md4$(OBJSUFFICS) md5$(OBJSUFFICS) mycryptmain$(OBJSUFFICS) base64$(OBJSUFFICS)
$(LN) $(LNOUT)$(BUILDDIR)mycrypt$(EXESUFFICS) $(LDFLAGS) md4$(OBJSUFFICS) md5$(OBJSUFFICS) base64$(OBJSUFFICS) mycryptmain$(OBJSUFFICS)
3proxy_crypt$(OBJSUFFICS): 3proxy_crypt.c
$(CC) $(COUT)3proxy_crypt$(OBJSUFFICS) $(CFLAGS) 3proxy_crypt.c
3proxy_cryptmain$(OBJSUFFICS): 3proxy_crypt.c
$(CC) $(COUT)3proxy_cryptmain$(OBJSUFFICS) $(CFLAGS) $(DEFINEOPTION)WITHMAIN 3proxy_crypt.c
md4$(OBJSUFFICS): libs/md4.h libs/md4.c
$(CC) $(COUT)md4$(OBJSUFFICS) $(CFLAGS) libs/md4.c
@ -147,9 +149,15 @@ md4$(OBJSUFFICS): libs/md4.h libs/md4.c
md5$(OBJSUFFICS): libs/md5.h libs/md5.c
$(CC) $(COUT)md5$(OBJSUFFICS) $(CFLAGS) libs/md5.c
blake2$(OBJSUFFICS): libs/blake2.h libs/blake2-impl.h libs/blake2b-ref.c
$(CC) $(COUT)blake2$(OBJSUFFICS) $(CFLAGS) libs/blake2b-ref.c
$(BUILDDIR)3proxy_crypt$(EXESUFFICS): md4$(OBJSUFFICS) blake2$(OBJSUFFICS) 3proxy_cryptmain$(OBJSUFFICS) base64$(OBJSUFFICS)
$(LN) $(LNOUT)$(BUILDDIR)3proxy_crypt$(EXESUFFICS) $(LDFLAGS) md4$(OBJSUFFICS) blake2$(OBJSUFFICS) base64$(OBJSUFFICS) 3proxy_cryptmain$(OBJSUFFICS)
stringtable$(OBJSUFFICS): stringtable.c
$(CC) $(COUT)stringtable$(OBJSUFFICS) $(CFLAGS) stringtable.c
$(BUILDDIR)3proxy$(EXESUFFICS): 3proxy$(OBJSUFFICS) mainfunc$(OBJSUFFICS) srvproxy$(OBJSUFFICS) srvpop3p$(OBJSUFFICS) srvsmtpp$(OBJSUFFICS) srvftppr$(OBJSUFFICS) srvsocks$(OBJSUFFICS) srvtcppm$(OBJSUFFICS) srvtlspr$(OBJSUFFICS) srvauto$(OBJSUFFICS) srvudppm$(OBJSUFFICS) sockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) common$(OBJSUFFICS) auth$(OBJSUFFICS) authradius$(OBJSUFFICS) conf$(OBJSUFFICS) log$(OBJSUFFICS) datatypes$(OBJSUFFICS) md4$(OBJSUFFICS) md5$(OBJSUFFICS) mycrypt$(OBJSUFFICS) base64$(OBJSUFFICS) ftp$(OBJSUFFICS) stringtable$(OBJSUFFICS) srvwebadmin$(OBJSUFFICS) srvdnspr$(OBJSUFFICS) plugins$(OBJSUFFICS) $(COMPATLIBS) $(VERSIONDEP)
$(LN) $(LNOUT)$(BUILDDIR)3proxy$(EXESUFFICS) $(LDFLAGS) $(VERFILE) 3proxy$(OBJSUFFICS) mainfunc$(OBJSUFFICS) auth$(OBJSUFFICS) authradius$(OBJSUFFICS) conf$(OBJSUFFICS) datatypes$(OBJSUFFICS) srvauto$(OBJSUFFICS) srvproxy$(OBJSUFFICS) srvpop3p$(OBJSUFFICS) srvsmtpp$(OBJSUFFICS) srvftppr$(OBJSUFFICS) srvsocks$(OBJSUFFICS) srvtcppm$(OBJSUFFICS) srvtlspr$(OBJSUFFICS) srvudppm$(OBJSUFFICS) sockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) common$(OBJSUFFICS) log$(OBJSUFFICS) mycrypt$(OBJSUFFICS) md5$(OBJSUFFICS) md4$(OBJSUFFICS) base64$(OBJSUFFICS) ftp$(OBJSUFFICS) stringtable$(OBJSUFFICS) srvwebadmin$(OBJSUFFICS) srvdnspr$(OBJSUFFICS) plugins$(OBJSUFFICS) $(COMPATLIBS) $(LIBS)
$(BUILDDIR)3proxy$(EXESUFFICS): 3proxy$(OBJSUFFICS) mainfunc$(OBJSUFFICS) srvproxy$(OBJSUFFICS) srvpop3p$(OBJSUFFICS) srvsmtpp$(OBJSUFFICS) srvftppr$(OBJSUFFICS) srvsocks$(OBJSUFFICS) srvtcppm$(OBJSUFFICS) srvtlspr$(OBJSUFFICS) srvauto$(OBJSUFFICS) srvudppm$(OBJSUFFICS) sockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) common$(OBJSUFFICS) auth$(OBJSUFFICS) authradius$(OBJSUFFICS) hash$(OBJSUFFICS) resolve$(OBJSUFFICS) sql$(OBJSUFFICS) conf$(OBJSUFFICS) log$(OBJSUFFICS) datatypes$(OBJSUFFICS) md4$(OBJSUFFICS) md5$(OBJSUFFICS) blake2$(OBJSUFFICS) 3proxy_crypt$(OBJSUFFICS) base64$(OBJSUFFICS) ftp$(OBJSUFFICS) stringtable$(OBJSUFFICS) srvwebadmin$(OBJSUFFICS) srvdnspr$(OBJSUFFICS) plugins$(OBJSUFFICS) $(COMPATLIBS) $(VERSIONDEP)
$(LN) $(LNOUT)$(BUILDDIR)3proxy$(EXESUFFICS) $(LDFLAGS) $(VERFILE) 3proxy$(OBJSUFFICS) mainfunc$(OBJSUFFICS) auth$(OBJSUFFICS) authradius$(OBJSUFFICS) hash$(OBJSUFFICS) resolve$(OBJSUFFICS) sql$(OBJSUFFICS) conf$(OBJSUFFICS) datatypes$(OBJSUFFICS) srvauto$(OBJSUFFICS) srvproxy$(OBJSUFFICS) srvpop3p$(OBJSUFFICS) srvsmtpp$(OBJSUFFICS) srvftppr$(OBJSUFFICS) srvsocks$(OBJSUFFICS) srvtcppm$(OBJSUFFICS) srvtlspr$(OBJSUFFICS) srvudppm$(OBJSUFFICS) sockmap$(OBJSUFFICS) sockgetchar$(OBJSUFFICS) common$(OBJSUFFICS) log$(OBJSUFFICS) 3proxy_crypt$(OBJSUFFICS) md5$(OBJSUFFICS) blake2$(OBJSUFFICS) md4$(OBJSUFFICS) base64$(OBJSUFFICS) ftp$(OBJSUFFICS) stringtable$(OBJSUFFICS) srvwebadmin$(OBJSUFFICS) srvdnspr$(OBJSUFFICS) plugins$(OBJSUFFICS) $(COMPATLIBS) $(LIBS)

View File

@ -1035,516 +1035,3 @@ struct auth authfuncs[] = {
{NULL, NULL, NULL, ""}
};
struct hashtable dns_table = {0, 4, {0,0,0,0}, NULL, NULL, NULL};
struct hashtable dns6_table = {0, 16, {0,0,0,0}, NULL, NULL, NULL};
void nametohash(const unsigned char * name, unsigned char *hash, unsigned char *rnd){
unsigned i, j, k;
memcpy(hash, rnd, sizeof(unsigned)*4);
for(i=0, j=0, k=0; name[j]; j++){
hash[i] += (toupper(name[j]) - 32)+rnd[((toupper(name[j]))*29277+rnd[(k+j+i)%16]+k+j+i)%16];
if(++i == sizeof(unsigned)*4) {
i = 0;
k++;
}
}
}
unsigned hashindex(struct hashtable *ht, const unsigned char* hash){
unsigned t1, t2, t3, t4;
t1 = *(unsigned *)hash;
t2 = *(unsigned *)(hash + sizeof(unsigned));
t3 = *(unsigned *)(hash + (2*sizeof(unsigned)));
t4 = *(unsigned *)(hash + (3*sizeof(unsigned)));
return (t1 + (t2 * 7) + (t3 * 17) + (t4 * 29) ) % (ht->hashsize >> 2);
}
void destroyhashtable(struct hashtable *ht){
pthread_mutex_lock(&hash_mutex);
if(ht->hashtable){
myfree(ht->hashtable);
ht->hashtable = NULL;
}
if(ht->hashvalues){
myfree(ht->hashvalues);
ht->hashvalues = NULL;
}
ht->hashsize = 0;
pthread_mutex_unlock(&hash_mutex);
}
#define hvalue(I) ((struct hashentry *)((char *)ht->hashvalues + (I)*(sizeof(struct hashentry) + ht->recsize - 4)))
int inithashtable(struct hashtable *ht, unsigned nhashsize){
unsigned i;
clock_t c;
#ifdef _WIN32
struct timeb tb;
ftime(&tb);
#else
struct timeval tb;
struct timezone tz;
gettimeofday(&tb, &tz);
#endif
c = clock();
if(nhashsize<4) return 1;
pthread_mutex_lock(&hash_mutex);
if(ht->hashtable){
myfree(ht->hashtable);
ht->hashtable = NULL;
}
if(ht->hashvalues){
myfree(ht->hashvalues);
ht->hashvalues = NULL;
}
ht->hashsize = 0;
if(!(ht->hashtable = myalloc((nhashsize>>2) * sizeof(struct hashentry *)))){
pthread_mutex_unlock(&hash_mutex);
return 2;
}
if(!(ht->hashvalues = myalloc(nhashsize * (sizeof(struct hashentry) + (ht->recsize-4))))){
myfree(ht->hashtable);
ht->hashtable = NULL;
pthread_mutex_unlock(&hash_mutex);
return 3;
}
ht->hashsize = nhashsize;
ht->rnd[0] = myrand(&tb, sizeof(tb));
ht->rnd[1] = myrand(ht->hashtable, sizeof(ht->hashtable));
ht->rnd[2] = myrand(&c, sizeof(c));
ht->rnd[3] = myrand(ht->hashvalues,sizeof(ht->hashvalues));
memset(ht->hashtable, 0, (ht->hashsize>>2) * sizeof(struct hashentry *));
memset(ht->hashvalues, 0, ht->hashsize * (sizeof(struct hashentry) + ht->recsize -4));
for(i = 0; i< (ht->hashsize - 1); i++) {
hvalue(i)->next = hvalue(i+1);
}
ht->hashempty = ht->hashvalues;
pthread_mutex_unlock(&hash_mutex);
return 0;
}
void hashadd(struct hashtable *ht, const unsigned char* name, unsigned char* value, time_t expires){
struct hashentry * hen, *he;
struct hashentry ** hep;
unsigned index;
pthread_mutex_lock(&hash_mutex);
if(!ht||!value||!name||!ht->hashtable||!ht->hashempty) {
pthread_mutex_unlock(&hash_mutex);
return;
}
hen = ht->hashempty;
ht->hashempty = ht->hashempty->next;
nametohash(name, hen->hash, (unsigned char *)ht->rnd);
memcpy(hen->value, value, ht->recsize);
hen->expires = expires;
hen->next = NULL;
index = hashindex(ht, hen->hash);
for(hep = ht->hashtable + index; (he = *hep)!=NULL; ){
if(he->expires < conf.time || !memcmp(hen->hash, he->hash, sizeof(he->hash))) {
(*hep) = he->next;
he->expires = 0;
he->next = ht->hashempty;
ht->hashempty = he;
}
else hep=&(he->next);
}
hen->next = ht->hashtable[index];
ht->hashtable[index] = hen;
pthread_mutex_unlock(&hash_mutex);
}
uint32_t hashresolv(struct hashtable *ht, const unsigned char* name, unsigned char* value, uint32_t *ttl){
unsigned char hash[sizeof(unsigned)*4];
struct hashentry ** hep;
struct hashentry *he;
unsigned index;
pthread_mutex_lock(&hash_mutex);
if(!ht || !ht->hashtable || !name) {
pthread_mutex_unlock(&hash_mutex);
return 0;
}
nametohash(name, hash, (unsigned char *)ht->rnd);
index = hashindex(ht, hash);
for(hep = ht->hashtable + index; (he = *hep)!=NULL; ){
if(he->expires < conf.time) {
(*hep) = he->next;
he->expires = 0;
he->next = ht->hashempty;
ht->hashempty = he;
}
else if(!memcmp(hash, he->hash, sizeof(unsigned)*4)){
if(ttl) *ttl = (uint32_t)(he->expires - conf.time);
memcpy(value, he->value, ht->recsize);
pthread_mutex_unlock(&hash_mutex);
return 1;
}
else hep=&(he->next);
}
pthread_mutex_unlock(&hash_mutex);
return 0;
}
struct nserver nservers[MAXNSERVERS] = {{{0},0}, {{0},0}, {{0},0}, {{0},0}, {{0},0}};
struct nserver authnserver;
uint32_t udpresolve(int af, unsigned char * name, unsigned char * value, uint32_t *retttl, struct clientparam* param, int makeauth){
int i,n;
uint32_t retval;
if((af == AF_INET) && (retval = hashresolv(&dns_table, name, value, retttl))) {
return retval;
}
if((af == AF_INET6) && (retval = hashresolv(&dns6_table, name, value, retttl))) {
return retval;
}
n = (makeauth && !SAISNULL(&authnserver.addr))? 1 : numservers;
for(i=0; i<n; i++){
unsigned short nq, na;
unsigned char b[4098], *buf, *s1, *s2;
int j, k, len, flen;
SOCKET sock;
uint32_t ttl;
PROXYSOCKADDRTYPE addr;
PROXYSOCKADDRTYPE *sinsr, *sinsl;
int usetcp = 0;
unsigned short serial = 1;
buf = b+2;
sinsl = (param && !makeauth)? &param->sinsl : &addr;
sinsr = (param && !makeauth)? &param->sinsr : &addr;
memset(sinsl, 0, sizeof(addr));
memset(sinsr, 0, sizeof(addr));
if(makeauth && !SAISNULL(&authnserver.addr)){
usetcp = authnserver.usetcp;
*SAFAMILY(sinsl) = *SAFAMILY(&authnserver.addr);
}
else {
usetcp = nservers[i].usetcp;
*SAFAMILY(sinsl) = *SAFAMILY(&nservers[i].addr);
}
if((sock=so._socket(so.state, SASOCK(sinsl), usetcp?SOCK_STREAM:SOCK_DGRAM, usetcp?IPPROTO_TCP:IPPROTO_UDP)) == INVALID_SOCKET) break;
if(so._bind(so.state, sock,(struct sockaddr *)sinsl,SASIZE(sinsl))){
so._shutdown(so.state, sock, SHUT_RDWR);
so._closesocket(so.state, sock);
break;
}
if(makeauth && !SAISNULL(&authnserver.addr)){
*sinsr = authnserver.addr;
}
else {
*sinsr = nservers[i].addr;
}
if(usetcp){
if(connectwithpoll(NULL, sock,(struct sockaddr *)sinsr,SASIZE(sinsr),conf.timeouts[CONNECT_TO])) {
so._shutdown(so.state, sock, SHUT_RDWR);
so._closesocket(so.state, sock);
break;
}
#ifdef TCP_NODELAY
{
int opt = 1;
setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char *)&opt, sizeof(opt));
}
#endif
}
len = (int)strlen((char *)name);
serial = myrand(name,len);
*(unsigned short*)buf = serial; /* query id */
buf[2] = 1; /* recursive */
buf[3] = 0;
buf[4] = 0;
buf[5] = 1; /* 1 request */
buf[6] = buf[7] = 0; /* no replies */
buf[8] = buf[9] = 0; /* no ns count */
buf[10] = buf[11] = 0; /* no additional */
if(len > 255) {
len = 255;
}
memcpy(buf + 13, name, len);
len += 13;
buf[len] = 0;
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;
len++;
buf[len++] = 0;
buf[len++] = (makeauth == 1)? 0x0c : (af==AF_INET6? 0x1c:0x01); /* PTR:host address */
buf[len++] = 0;
buf[len++] = 1; /* INET */
if(usetcp){
buf-=2;
*(unsigned short*)buf = htons(len);
len+=2;
}
if(socksendto(NULL, sock, (struct sockaddr *)sinsr, buf, len, conf.timeouts[SINGLEBYTE_L]*1000) != len){
so._shutdown(so.state, sock, SHUT_RDWR);
so._closesocket(so.state, sock);
continue;
}
if(param) param->statscli64 += len;
len = sockrecvfrom(NULL, sock, (struct sockaddr *)sinsr, buf, 4096, conf.timeouts[DNS_TO]*1000);
so._shutdown(so.state, sock, SHUT_RDWR);
so._closesocket(so.state, sock);
if(len <= 13) {
continue;
}
if(param) param->statssrv64 += len;
if(usetcp){
unsigned short us;
us = ntohs(*(unsigned short*)buf);
len-=2;
buf+=2;
if(us > 4096 || us < len || (us > len && sockrecvfrom(NULL, sock, (struct sockaddr *)sinsr, buf+len, us-len, conf.timeouts[DNS_TO]*1000) != us-len)) {
continue;
}
}
if(*(unsigned short *)buf != serial)continue;
if((na = buf[7] + (((unsigned short)buf[6])<<8)) < 1) {
return 0;
}
nq = buf[5] + (((unsigned short)buf[4])<<8);
if (nq != 1) {
continue; /* we did only 1 request */
}
for(k = 13; k<len && buf[k]; k++) {
}
k++;
if( (k+4) >= len) {
continue;
}
k += 4;
if(na > 255) na = 255; /* somebody is very evil */
for (j = 0; j < na; j++) { /* now there should be answers */
while(buf[k] < 192 && buf[k] !=0 && (k+buf[k]+14) < len) k+= (buf[k] + 1);
if(!buf[k]) k--;
if((k+(af == AF_INET6?28:16)) > len) {
break;
}
flen = buf[k+11] + (((unsigned short)buf[k+10])<<8);
if((k+12+flen) > len) {
break;
}
if(makeauth != 1){
if(buf[k+2] != 0 || buf[k+3] != (af == AF_INET6?0x1c:0x1) || flen != (af == AF_INET6?16:4)) {
k+= (12 + flen);
continue; /* we need A IPv4 */
}
ttl = ntohl(*(uint32_t *)(buf + k + 6));
memcpy(value, buf + k + 12, af == AF_INET6? 16:4);
if(ttl < 0 || ttl > (3600*12)) ttl = 3600*12;
if(!ttl) ttl = 1;
hashadd(af == AF_INET6?&dns6_table:&dns_table, name, value, conf.time+ttl);
if(retttl) *retttl = ttl;
return 1;
}
else {
if(buf[k+2] != 0 || buf[k+3] != 0x0c) {
k+= (12 + flen);
continue; /* we need A PTR */
}
for (s2 = buf + k + 12; s2 < (buf + k + 12 + len) && *s2; ){
s1 = s2 + ((unsigned)*s2) + 1;
*s2 = '.';
s2 = s1;
}
*s2 = 0;
if(param->username)myfree(param->username);
param->username = (unsigned char *)mystrdup ((char *)buf + k + 13);
return udpresolve(af,param->username, value, NULL, NULL, 2);
}
}
}
return 0;
}
uint32_t myresolver(int af, unsigned char * name, unsigned char * value){
return udpresolve(af, name, value, NULL, NULL, 0);
}
uint32_t fakeresolver (int af, unsigned char *name, unsigned char * value){
memset(value, 0, af == AF_INET6? 16 : 4);
if(af == AF_INET6){
memset(value, 0, 16);
value[15] = 2;
}
else {
value[0] = 127;
value[1] = 0;
value[2] = 0;
value[3] = 2;
}
return 1;
}
#ifndef NOODBC
SQLHENV henv = NULL;
SQLHSTMT hstmt = NULL;
SQLHDBC hdbc = NULL;
char * sqlstring = NULL;
void close_sql(){
if(hstmt) {
SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
hstmt = NULL;
}
if(hdbc){
SQLDisconnect(hdbc);
SQLFreeHandle(SQL_HANDLE_DBC, hdbc);
hdbc = NULL;
}
if(henv) {
SQLFreeHandle(SQL_HANDLE_ENV, henv);
henv = NULL;
}
}
int attempt = 0;
time_t attempt_time = 0;
int init_sql(char * s){
SQLRETURN retcode;
char * datasource;
char * username;
char * password;
char * string;
if(!s) return 0;
if(!sqlstring || strcmp(sqlstring, s)){
string = sqlstring;
sqlstring=mystrdup(s);
if(string)myfree(string);
}
if(hstmt || hdbc || henv) close_sql();
attempt++;
attempt_time = time(0);
if(!henv){
retcode = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv);
if (!henv || (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO)){
henv = NULL;
return 0;
}
retcode = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0);
if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO) {
return 0;
}
}
if(!hdbc){
retcode = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc);
if (!hdbc || (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO)) {
hdbc = NULL;
SQLFreeHandle(SQL_HANDLE_ENV, henv);
henv = NULL;
return 0;
}
SQLSetConnectAttr(hdbc, SQL_LOGIN_TIMEOUT, (void*)15, 0);
}
string = mystrdup(sqlstring);
if(!string) return 0;
datasource = strtok(string, ",");
username = strtok(NULL, ",");
password = strtok(NULL, ",");
/* Connect to data source */
retcode = SQLConnect(hdbc, (SQLCHAR*) datasource, (SQLSMALLINT)strlen(datasource),
(SQLCHAR*) username, (SQLSMALLINT)((username)?strlen(username):0),
(SQLCHAR*) password, (SQLSMALLINT)((password)?strlen(password):0));
myfree(string);
if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO){
SQLFreeHandle(SQL_HANDLE_DBC, hdbc);
hdbc = NULL;
SQLFreeHandle(SQL_HANDLE_ENV, henv);
henv = NULL;
return 0;
}
retcode = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);
if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO){
close_sql();
return 0;
}
return 1;
}
void sqlerr (char *buf){
if(conf.stdlog){
fprintf(conf.stdlog, "%s\n", buf);
fflush(conf.stdlog);
}
pthread_mutex_unlock(&log_mutex);
}
unsigned char statbuf[8192];
void logsql(struct clientparam * param, const unsigned char *s) {
SQLRETURN ret;
int len;
if(param->nolog) return;
pthread_mutex_lock(&log_mutex);
len = dobuf(param, statbuf, s, (unsigned char *)"\'");
if(attempt > 5){
time_t t;
t = time(0);
if (t - attempt_time < 180){
sqlerr((char *)statbuf);
return;
}
}
if(!hstmt){
if(!init_sql(sqlstring)) {
sqlerr((char *)statbuf);
return;
}
}
if(hstmt){
ret = SQLExecDirect(hstmt, (SQLCHAR *)statbuf, (SQLINTEGER)len);
if(ret != SQL_SUCCESS && ret != SQL_SUCCESS_WITH_INFO){
close_sql();
if(!init_sql(sqlstring)){
sqlerr((char *)statbuf);
return;
}
if(hstmt) {
ret = SQLExecDirect(hstmt, (SQLCHAR *)statbuf, (SQLINTEGER)len);
if(ret != SQL_SUCCESS && ret != SQL_SUCCESS_WITH_INFO){
sqlerr((char *)statbuf);
return;
}
attempt = 0;
}
}
attempt = 0;
}
pthread_mutex_unlock(&log_mutex);
}
#endif

199
src/hash.c Normal file
View File

@ -0,0 +1,199 @@
#include "proxy.h"
#include "libs/blake2.h"
static uint32_t hashindex(struct hashtable *ht, const uint8_t* hash){
return (*(unsigned *)hash ) % (ht->tablesize);
}
void destroyhashtable(struct hashtable *ht){
pthread_mutex_lock(&hash_mutex);
if(ht->ihashtable){
myfree(ht->ihashtable);
ht->ihashtable = NULL;
}
if(ht->hashvalues){
myfree(ht->hashvalues);
ht->hashvalues = NULL;
}
ht->hashsize = 0;
ht->tablesize = 0;
pthread_mutex_unlock(&hash_mutex);
}
#define hvalue(ht,I) ((struct hashentry *)(ht->hashvalues + (I-1)*(sizeof(struct hashentry) + ht->recsize - 4)))
int inithashtable(struct hashtable *ht, unsigned nhashsize){
unsigned i;
unsigned tablesize, hashsize;
clock_t c;
#ifdef _WIN32
struct timeb tb;
ftime(&tb);
#else
struct timeval tb;
struct timezone tz;
gettimeofday(&tb, &tz);
#endif
c = clock();
hashsize = tablesize = (nhashsize >> 2);
if(tablesize < 2) return 1;
pthread_mutex_lock(&hash_mutex);
if(ht->ihashtable){
myfree(ht->ihashtable);
ht->ihashtable = NULL;
}
if(ht->hashvalues){
myfree(ht->hashvalues);
ht->hashvalues = NULL;
}
ht->hashsize = 0;
ht->tablesize = 0;
if(!(ht->ihashtable = myalloc(tablesize * sizeof(uint32_t)))){
pthread_mutex_unlock(&hash_mutex);
return 2;
}
if(!(ht->hashvalues = myalloc(hashsize * (sizeof(struct hashentry) + (ht->recsize-4))))){
myfree(ht->ihashtable);
ht->ihashtable = NULL;
pthread_mutex_unlock(&hash_mutex);
return 3;
}
ht->hashsize = hashsize;
ht->tablesize = tablesize;
ht->growlimit = nhashsize;
ht->rnd[0] = myrand(&tb, sizeof(tb));
ht->rnd[1] = myrand(ht->ihashtable, sizeof(ht->ihashtable));
ht->rnd[2] = myrand(&c, sizeof(c));
ht->rnd[3] = myrand(ht->hashvalues,sizeof(ht->hashvalues));
memset(ht->ihashtable, 0, ht->tablesize * sizeof(struct hashentry *));
memset(ht->hashvalues, 0, ht->hashsize * (sizeof(struct hashentry) + ht->recsize - 4));
for(i = 1; i < ht->hashsize; i++) {
hvalue(ht,i)->inext = i+1;
}
ht->ihashempty = 1;
pthread_mutex_unlock(&hash_mutex);
return 0;
}
static void hashgrow(struct hashtable *ht){
unsigned newsize = (ht->hashsize + (ht->hashsize >> 1));
unsigned i;
void * newvalues;
if(!ht->tablesize || !ht->hashsize) return;
if(ht->hashsize >= ht->growlimit) return;
if(ht->hashsize / ht->tablesize > 100) return;
if(newsize > ht->growlimit) newsize = ht->growlimit;
newvalues = myrealloc(ht->hashvalues, newsize * (sizeof(struct hashentry) + ht->recsize - 4));
if(!newvalues) return;
memset(ht->hashvalues + (ht->hashsize * (sizeof(struct hashentry) + ht->recsize - 4)), 0, (newsize - ht->hashsize) * (sizeof(struct hashentry) + ht->recsize - 4));
for(i = ht->hashsize + 1; i < newsize; i++) {
hvalue(ht,i)->inext = i+1;
}
hvalue(ht,newsize)->inext = ht->ihashempty;
ht->ihashempty = ht->hashsize + 1;
ht->hashsize = newsize;
}
/*
static void hashcompact(struct hashtable *ht){
int i;
uint32_t he, *hep;
if((conf.time - ht->compacted) < 60 || !ht->tablesize || !ht->hashsize || ht->ihashempty) return;
if(ht->grow && ht->hashsize/ht->tablesize < 100){
hashgrow(ht);
if(ht->ihashempty) return;
}
if(ht->hashsize/ht->tablesize < 4){
for(i = 0; i < ht->tablesize; i++){
for(hep = ht->ihashtable + i; (he = *hep) != 0; ){
if(hvalue(ht,he)->expires < conf.time ) {
(*hep) = hvalue(ht,he)->inext;
hvalue(ht,he)->expires = 0;
hvalue(ht,he)->inext = ht->ihashempty;
ht->ihashempty = he;
}
else hep=&(hvalue(ht,he)->inext);
}
}
ht->compacted = conf.time;
if(ht->ihashempty) return;
}
}
*/
void hashadd(struct hashtable *ht, const void* name, const void* value, time_t expires){
uint32_t hen, he;
uint32_t *hep;
uint32_t index;
pthread_mutex_lock(&hash_mutex);
if(!ht->ihashempty){
hashgrow(ht);
}
if(!ht||!value||!name||!ht->ihashtable||!ht->ihashempty) {
pthread_mutex_unlock(&hash_mutex);
return;
}
hen = ht->ihashempty;
ht->ihashempty = hvalue(ht,ht->ihashempty)->inext;
ht->index2hash(name, hvalue(ht,hen)->hash, (unsigned char *)ht->rnd);
memcpy(hvalue(ht,hen)->value, value, ht->recsize);
hvalue(ht,hen)->expires = expires;
hvalue(ht,hen)->inext = 0;
index = hashindex(ht, hvalue(ht,hen)->hash);
for(hep = ht->ihashtable + index; (he = *hep)!=0; ){
if(hvalue(ht,he)->expires < conf.time || !memcmp(hvalue(ht,hen)->hash, hvalue(ht,he)->hash, HASH_SIZE)) {
(*hep) = hvalue(ht,he)->inext;
hvalue(ht,he)->expires = 0;
hvalue(ht,he)->inext = ht->ihashempty;
ht->ihashempty = he;
}
else hep=&(hvalue(ht,he)->inext);
}
hvalue(ht,hen)->inext = ht->ihashtable[index];
ht->ihashtable[index] = hen;
pthread_mutex_unlock(&hash_mutex);
}
int hashresolv(struct hashtable *ht, const void* name, void* value, uint32_t *ttl){
uint8_t hash[HASH_SIZE];
uint32_t *hep;
uint32_t he;
uint32_t index;
pthread_mutex_lock(&hash_mutex);
if(!ht || !ht->ihashtable || !name) {
pthread_mutex_unlock(&hash_mutex);
return 0;
}
ht->index2hash(name, hash, (unsigned char *)ht->rnd);
index = hashindex(ht, hash);
for(hep = ht->ihashtable + index; (he = *hep)!=0; ){
if(hvalue(ht, he)->expires < conf.time) {
(*hep) = hvalue(ht,he)->inext;
hvalue(ht,he)->expires = 0;
hvalue(ht,he)->inext = ht->ihashempty;
ht->ihashempty = he;
}
else if(!memcmp(hash, hvalue(ht,he)->hash, HASH_SIZE)){
if(ttl) *ttl = (uint32_t)(hvalue(ht,he)->expires - conf.time);
memcpy(value, hvalue(ht,he)->value, ht->recsize);
pthread_mutex_unlock(&hash_mutex);
return 1;
}
else hep=&(hvalue(ht,he)->inext);
}
pthread_mutex_unlock(&hash_mutex);
return 0;
}

160
src/libs/blake2-impl.h Normal file
View File

@ -0,0 +1,160 @@
/*
BLAKE2 reference source code package - reference C implementations
Copyright 2012, Samuel Neves <sneves@dei.uc.pt>. You may use this under the
terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at
your option. The terms of these licenses can be found at:
- CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
- OpenSSL license : https://www.openssl.org/source/license.html
- Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
More information about the BLAKE2 hash function can be found at
https://blake2.net.
*/
#ifndef BLAKE2_IMPL_H
#define BLAKE2_IMPL_H
#include <stdint.h>
#include <string.h>
#if !defined(__cplusplus) && (!defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L)
#if defined(_MSC_VER)
#define BLAKE2_INLINE __inline
#elif defined(__GNUC__)
#define BLAKE2_INLINE __inline__
#else
#define BLAKE2_INLINE
#endif
#else
#define BLAKE2_INLINE inline
#endif
static BLAKE2_INLINE uint32_t load32( const void *src )
{
#if defined(NATIVE_LITTLE_ENDIAN)
uint32_t w;
memcpy(&w, src, sizeof w);
return w;
#else
const uint8_t *p = ( const uint8_t * )src;
return (( uint32_t )( p[0] ) << 0) |
(( uint32_t )( p[1] ) << 8) |
(( uint32_t )( p[2] ) << 16) |
(( uint32_t )( p[3] ) << 24) ;
#endif
}
static BLAKE2_INLINE uint64_t load64( const void *src )
{
#if defined(NATIVE_LITTLE_ENDIAN)
uint64_t w;
memcpy(&w, src, sizeof w);
return w;
#else
const uint8_t *p = ( const uint8_t * )src;
return (( uint64_t )( p[0] ) << 0) |
(( uint64_t )( p[1] ) << 8) |
(( uint64_t )( p[2] ) << 16) |
(( uint64_t )( p[3] ) << 24) |
(( uint64_t )( p[4] ) << 32) |
(( uint64_t )( p[5] ) << 40) |
(( uint64_t )( p[6] ) << 48) |
(( uint64_t )( p[7] ) << 56) ;
#endif
}
static BLAKE2_INLINE uint16_t load16( const void *src )
{
#if defined(NATIVE_LITTLE_ENDIAN)
uint16_t w;
memcpy(&w, src, sizeof w);
return w;
#else
const uint8_t *p = ( const uint8_t * )src;
return ( uint16_t )((( uint32_t )( p[0] ) << 0) |
(( uint32_t )( p[1] ) << 8));
#endif
}
static BLAKE2_INLINE void store16( void *dst, uint16_t w )
{
#if defined(NATIVE_LITTLE_ENDIAN)
memcpy(dst, &w, sizeof w);
#else
uint8_t *p = ( uint8_t * )dst;
*p++ = ( uint8_t )w; w >>= 8;
*p++ = ( uint8_t )w;
#endif
}
static BLAKE2_INLINE void store32( void *dst, uint32_t w )
{
#if defined(NATIVE_LITTLE_ENDIAN)
memcpy(dst, &w, sizeof w);
#else
uint8_t *p = ( uint8_t * )dst;
p[0] = (uint8_t)(w >> 0);
p[1] = (uint8_t)(w >> 8);
p[2] = (uint8_t)(w >> 16);
p[3] = (uint8_t)(w >> 24);
#endif
}
static BLAKE2_INLINE void store64( void *dst, uint64_t w )
{
#if defined(NATIVE_LITTLE_ENDIAN)
memcpy(dst, &w, sizeof w);
#else
uint8_t *p = ( uint8_t * )dst;
p[0] = (uint8_t)(w >> 0);
p[1] = (uint8_t)(w >> 8);
p[2] = (uint8_t)(w >> 16);
p[3] = (uint8_t)(w >> 24);
p[4] = (uint8_t)(w >> 32);
p[5] = (uint8_t)(w >> 40);
p[6] = (uint8_t)(w >> 48);
p[7] = (uint8_t)(w >> 56);
#endif
}
static BLAKE2_INLINE uint64_t load48( const void *src )
{
const uint8_t *p = ( const uint8_t * )src;
return (( uint64_t )( p[0] ) << 0) |
(( uint64_t )( p[1] ) << 8) |
(( uint64_t )( p[2] ) << 16) |
(( uint64_t )( p[3] ) << 24) |
(( uint64_t )( p[4] ) << 32) |
(( uint64_t )( p[5] ) << 40) ;
}
static BLAKE2_INLINE void store48( void *dst, uint64_t w )
{
uint8_t *p = ( uint8_t * )dst;
p[0] = (uint8_t)(w >> 0);
p[1] = (uint8_t)(w >> 8);
p[2] = (uint8_t)(w >> 16);
p[3] = (uint8_t)(w >> 24);
p[4] = (uint8_t)(w >> 32);
p[5] = (uint8_t)(w >> 40);
}
static BLAKE2_INLINE uint32_t rotr32( const uint32_t w, const unsigned c )
{
return ( w >> c ) | ( w << ( 32 - c ) );
}
static BLAKE2_INLINE uint64_t rotr64( const uint64_t w, const unsigned c )
{
return ( w >> c ) | ( w << ( 64 - c ) );
}
/* prevents compiler optimizing out memset() */
static BLAKE2_INLINE void secure_zero_memory(void *v, size_t n)
{
static void *(*const volatile memset_v)(void *, int, size_t) = &memset;
memset_v(v, 0, n);
}
#endif

195
src/libs/blake2.h Normal file
View File

@ -0,0 +1,195 @@
/*
BLAKE2 reference source code package - reference C implementations
Copyright 2012, Samuel Neves <sneves@dei.uc.pt>. You may use this under the
terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at
your option. The terms of these licenses can be found at:
- CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
- OpenSSL license : https://www.openssl.org/source/license.html
- Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
More information about the BLAKE2 hash function can be found at
https://blake2.net.
*/
#ifndef BLAKE2_H
#define BLAKE2_H
#include <stddef.h>
#include <stdint.h>
#if defined(_MSC_VER)
#define BLAKE2_PACKED(x) __pragma(pack(push, 1)) x __pragma(pack(pop))
#else
#define BLAKE2_PACKED(x) x __attribute__((packed))
#endif
#if defined(__cplusplus)
extern "C" {
#endif
enum blake2s_constant
{
BLAKE2S_BLOCKBYTES = 64,
BLAKE2S_OUTBYTES = 32,
BLAKE2S_KEYBYTES = 32,
BLAKE2S_SALTBYTES = 8,
BLAKE2S_PERSONALBYTES = 8
};
enum blake2b_constant
{
BLAKE2B_BLOCKBYTES = 128,
BLAKE2B_OUTBYTES = 64,
BLAKE2B_KEYBYTES = 64,
BLAKE2B_SALTBYTES = 16,
BLAKE2B_PERSONALBYTES = 16
};
typedef struct blake2s_state__
{
uint32_t h[8];
uint32_t t[2];
uint32_t f[2];
uint8_t buf[BLAKE2S_BLOCKBYTES];
size_t buflen;
size_t outlen;
uint8_t last_node;
} blake2s_state;
typedef struct blake2b_state__
{
uint64_t h[8];
uint64_t t[2];
uint64_t f[2];
uint8_t buf[BLAKE2B_BLOCKBYTES];
size_t buflen;
size_t outlen;
uint8_t last_node;
} blake2b_state;
typedef struct blake2sp_state__
{
blake2s_state S[8][1];
blake2s_state R[1];
uint8_t buf[8 * BLAKE2S_BLOCKBYTES];
size_t buflen;
size_t outlen;
} blake2sp_state;
typedef struct blake2bp_state__
{
blake2b_state S[4][1];
blake2b_state R[1];
uint8_t buf[4 * BLAKE2B_BLOCKBYTES];
size_t buflen;
size_t outlen;
} blake2bp_state;
BLAKE2_PACKED(struct blake2s_param__
{
uint8_t digest_length; /* 1 */
uint8_t key_length; /* 2 */
uint8_t fanout; /* 3 */
uint8_t depth; /* 4 */
uint32_t leaf_length; /* 8 */
uint32_t node_offset; /* 12 */
uint16_t xof_length; /* 14 */
uint8_t node_depth; /* 15 */
uint8_t inner_length; /* 16 */
/* uint8_t reserved[0]; */
uint8_t salt[BLAKE2S_SALTBYTES]; /* 24 */
uint8_t personal[BLAKE2S_PERSONALBYTES]; /* 32 */
});
typedef struct blake2s_param__ blake2s_param;
BLAKE2_PACKED(struct blake2b_param__
{
uint8_t digest_length; /* 1 */
uint8_t key_length; /* 2 */
uint8_t fanout; /* 3 */
uint8_t depth; /* 4 */
uint32_t leaf_length; /* 8 */
uint32_t node_offset; /* 12 */
uint32_t xof_length; /* 16 */
uint8_t node_depth; /* 17 */
uint8_t inner_length; /* 18 */
uint8_t reserved[14]; /* 32 */
uint8_t salt[BLAKE2B_SALTBYTES]; /* 48 */
uint8_t personal[BLAKE2B_PERSONALBYTES]; /* 64 */
});
typedef struct blake2b_param__ blake2b_param;
typedef struct blake2xs_state__
{
blake2s_state S[1];
blake2s_param P[1];
} blake2xs_state;
typedef struct blake2xb_state__
{
blake2b_state S[1];
blake2b_param P[1];
} blake2xb_state;
/* Padded structs result in a compile-time error */
enum {
BLAKE2_DUMMY_1 = 1/(int)(sizeof(blake2s_param) == BLAKE2S_OUTBYTES),
BLAKE2_DUMMY_2 = 1/(int)(sizeof(blake2b_param) == BLAKE2B_OUTBYTES)
};
/* Streaming API */
int blake2s_init( blake2s_state *S, size_t outlen );
int blake2s_init_key( blake2s_state *S, size_t outlen, const void *key, size_t keylen );
int blake2s_init_param( blake2s_state *S, const blake2s_param *P );
int blake2s_update( blake2s_state *S, const void *in, size_t inlen );
int blake2s_final( blake2s_state *S, void *out, size_t outlen );
int blake2b_init( blake2b_state *S, size_t outlen );
int blake2b_init_key( blake2b_state *S, size_t outlen, const void *key, size_t keylen );
int blake2b_init_param( blake2b_state *S, const blake2b_param *P );
int blake2b_update( blake2b_state *S, const void *in, size_t inlen );
int blake2b_final( blake2b_state *S, void *out, size_t outlen );
int blake2sp_init( blake2sp_state *S, size_t outlen );
int blake2sp_init_key( blake2sp_state *S, size_t outlen, const void *key, size_t keylen );
int blake2sp_update( blake2sp_state *S, const void *in, size_t inlen );
int blake2sp_final( blake2sp_state *S, void *out, size_t outlen );
int blake2bp_init( blake2bp_state *S, size_t outlen );
int blake2bp_init_key( blake2bp_state *S, size_t outlen, const void *key, size_t keylen );
int blake2bp_update( blake2bp_state *S, const void *in, size_t inlen );
int blake2bp_final( blake2bp_state *S, void *out, size_t outlen );
/* Variable output length API */
int blake2xs_init( blake2xs_state *S, const size_t outlen );
int blake2xs_init_key( blake2xs_state *S, const size_t outlen, const void *key, size_t keylen );
int blake2xs_update( blake2xs_state *S, const void *in, size_t inlen );
int blake2xs_final(blake2xs_state *S, void *out, size_t outlen);
int blake2xb_init( blake2xb_state *S, const size_t outlen );
int blake2xb_init_key( blake2xb_state *S, const size_t outlen, const void *key, size_t keylen );
int blake2xb_update( blake2xb_state *S, const void *in, size_t inlen );
int blake2xb_final(blake2xb_state *S, void *out, size_t outlen);
/* Simple API */
int blake2s( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
int blake2b( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
int blake2sp( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
int blake2bp( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
int blake2xs( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
int blake2xb( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
/* This is simply an alias for blake2b */
int blake2( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );
#if defined(__cplusplus)
}
#endif
#endif

379
src/libs/blake2b-ref.c Normal file
View File

@ -0,0 +1,379 @@
/*
BLAKE2 reference source code package - reference C implementations
Copyright 2012, Samuel Neves <sneves@dei.uc.pt>. You may use this under the
terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at
your option. The terms of these licenses can be found at:
- CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0
- OpenSSL license : https://www.openssl.org/source/license.html
- Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0
More information about the BLAKE2 hash function can be found at
https://blake2.net.
*/
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include "blake2.h"
#include "blake2-impl.h"
static const uint64_t blake2b_IV[8] =
{
0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL,
0x3c6ef372fe94f82bULL, 0xa54ff53a5f1d36f1ULL,
0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL,
0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL
};
static const uint8_t blake2b_sigma[12][16] =
{
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } ,
{ 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } ,
{ 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 } ,
{ 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 } ,
{ 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 } ,
{ 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 } ,
{ 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 } ,
{ 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 } ,
{ 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 } ,
{ 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0 } ,
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } ,
{ 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 }
};
static void blake2b_set_lastnode( blake2b_state *S )
{
S->f[1] = (uint64_t)-1;
}
/* Some helper functions, not necessarily useful */
static int blake2b_is_lastblock( const blake2b_state *S )
{
return S->f[0] != 0;
}
static void blake2b_set_lastblock( blake2b_state *S )
{
if( S->last_node ) blake2b_set_lastnode( S );
S->f[0] = (uint64_t)-1;
}
static void blake2b_increment_counter( blake2b_state *S, const uint64_t inc )
{
S->t[0] += inc;
S->t[1] += ( S->t[0] < inc );
}
static void blake2b_init0( blake2b_state *S )
{
size_t i;
memset( S, 0, sizeof( blake2b_state ) );
for( i = 0; i < 8; ++i ) S->h[i] = blake2b_IV[i];
}
/* init xors IV with input parameter block */
int blake2b_init_param( blake2b_state *S, const blake2b_param *P )
{
const uint8_t *p = ( const uint8_t * )( P );
size_t i;
blake2b_init0( S );
/* IV XOR ParamBlock */
for( i = 0; i < 8; ++i )
S->h[i] ^= load64( p + sizeof( S->h[i] ) * i );
S->outlen = P->digest_length;
return 0;
}
int blake2b_init( blake2b_state *S, size_t outlen )
{
blake2b_param P[1];
if ( ( !outlen ) || ( outlen > BLAKE2B_OUTBYTES ) ) return -1;
P->digest_length = (uint8_t)outlen;
P->key_length = 0;
P->fanout = 1;
P->depth = 1;
store32( &P->leaf_length, 0 );
store32( &P->node_offset, 0 );
store32( &P->xof_length, 0 );
P->node_depth = 0;
P->inner_length = 0;
memset( P->reserved, 0, sizeof( P->reserved ) );
memset( P->salt, 0, sizeof( P->salt ) );
memset( P->personal, 0, sizeof( P->personal ) );
return blake2b_init_param( S, P );
}
int blake2b_init_key( blake2b_state *S, size_t outlen, const void *key, size_t keylen )
{
blake2b_param P[1];
if ( ( !outlen ) || ( outlen > BLAKE2B_OUTBYTES ) ) return -1;
if ( !key || !keylen || keylen > BLAKE2B_KEYBYTES ) return -1;
P->digest_length = (uint8_t)outlen;
P->key_length = (uint8_t)keylen;
P->fanout = 1;
P->depth = 1;
store32( &P->leaf_length, 0 );
store32( &P->node_offset, 0 );
store32( &P->xof_length, 0 );
P->node_depth = 0;
P->inner_length = 0;
memset( P->reserved, 0, sizeof( P->reserved ) );
memset( P->salt, 0, sizeof( P->salt ) );
memset( P->personal, 0, sizeof( P->personal ) );
if( blake2b_init_param( S, P ) < 0 ) return -1;
{
uint8_t block[BLAKE2B_BLOCKBYTES];
memset( block, 0, BLAKE2B_BLOCKBYTES );
memcpy( block, key, keylen );
blake2b_update( S, block, BLAKE2B_BLOCKBYTES );
secure_zero_memory( block, BLAKE2B_BLOCKBYTES ); /* Burn the key from stack */
}
return 0;
}
#define G(r,i,a,b,c,d) \
do { \
a = a + b + m[blake2b_sigma[r][2*i+0]]; \
d = rotr64(d ^ a, 32); \
c = c + d; \
b = rotr64(b ^ c, 24); \
a = a + b + m[blake2b_sigma[r][2*i+1]]; \
d = rotr64(d ^ a, 16); \
c = c + d; \
b = rotr64(b ^ c, 63); \
} while(0)
#define ROUND(r) \
do { \
G(r,0,v[ 0],v[ 4],v[ 8],v[12]); \
G(r,1,v[ 1],v[ 5],v[ 9],v[13]); \
G(r,2,v[ 2],v[ 6],v[10],v[14]); \
G(r,3,v[ 3],v[ 7],v[11],v[15]); \
G(r,4,v[ 0],v[ 5],v[10],v[15]); \
G(r,5,v[ 1],v[ 6],v[11],v[12]); \
G(r,6,v[ 2],v[ 7],v[ 8],v[13]); \
G(r,7,v[ 3],v[ 4],v[ 9],v[14]); \
} while(0)
static void blake2b_compress( blake2b_state *S, const uint8_t block[BLAKE2B_BLOCKBYTES] )
{
uint64_t m[16];
uint64_t v[16];
size_t i;
for( i = 0; i < 16; ++i ) {
m[i] = load64( block + i * sizeof( m[i] ) );
}
for( i = 0; i < 8; ++i ) {
v[i] = S->h[i];
}
v[ 8] = blake2b_IV[0];
v[ 9] = blake2b_IV[1];
v[10] = blake2b_IV[2];
v[11] = blake2b_IV[3];
v[12] = blake2b_IV[4] ^ S->t[0];
v[13] = blake2b_IV[5] ^ S->t[1];
v[14] = blake2b_IV[6] ^ S->f[0];
v[15] = blake2b_IV[7] ^ S->f[1];
ROUND( 0 );
ROUND( 1 );
ROUND( 2 );
ROUND( 3 );
ROUND( 4 );
ROUND( 5 );
ROUND( 6 );
ROUND( 7 );
ROUND( 8 );
ROUND( 9 );
ROUND( 10 );
ROUND( 11 );
for( i = 0; i < 8; ++i ) {
S->h[i] = S->h[i] ^ v[i] ^ v[i + 8];
}
}
#undef G
#undef ROUND
int blake2b_update( blake2b_state *S, const void *pin, size_t inlen )
{
const unsigned char * in = (const unsigned char *)pin;
if( inlen > 0 )
{
size_t left = S->buflen;
size_t fill = BLAKE2B_BLOCKBYTES - left;
if( inlen > fill )
{
S->buflen = 0;
memcpy( S->buf + left, in, fill ); /* Fill buffer */
blake2b_increment_counter( S, BLAKE2B_BLOCKBYTES );
blake2b_compress( S, S->buf ); /* Compress */
in += fill; inlen -= fill;
while(inlen > BLAKE2B_BLOCKBYTES) {
blake2b_increment_counter(S, BLAKE2B_BLOCKBYTES);
blake2b_compress( S, in );
in += BLAKE2B_BLOCKBYTES;
inlen -= BLAKE2B_BLOCKBYTES;
}
}
memcpy( S->buf + S->buflen, in, inlen );
S->buflen += inlen;
}
return 0;
}
int blake2b_final( blake2b_state *S, void *out, size_t outlen )
{
uint8_t buffer[BLAKE2B_OUTBYTES] = {0};
size_t i;
if( out == NULL || outlen < S->outlen )
return -1;
if( blake2b_is_lastblock( S ) )
return -1;
blake2b_increment_counter( S, S->buflen );
blake2b_set_lastblock( S );
memset( S->buf + S->buflen, 0, BLAKE2B_BLOCKBYTES - S->buflen ); /* Padding */
blake2b_compress( S, S->buf );
for( i = 0; i < 8; ++i ) /* Output full hash to temp buffer */
store64( buffer + sizeof( S->h[i] ) * i, S->h[i] );
memcpy( out, buffer, S->outlen );
secure_zero_memory(buffer, sizeof(buffer));
return 0;
}
/* inlen, at least, should be uint64_t. Others can be size_t. */
int blake2b( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen )
{
blake2b_state S[1];
/* Verify parameters */
if ( NULL == in && inlen > 0 ) return -1;
if ( NULL == out ) return -1;
if( NULL == key && keylen > 0 ) return -1;
if( !outlen || outlen > BLAKE2B_OUTBYTES ) return -1;
if( keylen > BLAKE2B_KEYBYTES ) return -1;
if( keylen > 0 )
{
if( blake2b_init_key( S, outlen, key, keylen ) < 0 ) return -1;
}
else
{
if( blake2b_init( S, outlen ) < 0 ) return -1;
}
blake2b_update( S, ( const uint8_t * )in, inlen );
blake2b_final( S, out, outlen );
return 0;
}
int blake2( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen ) {
return blake2b(out, outlen, in, inlen, key, keylen);
}
#if defined(SUPERCOP)
int crypto_hash( unsigned char *out, unsigned char *in, unsigned long long inlen )
{
return blake2b( out, BLAKE2B_OUTBYTES, in, inlen, NULL, 0 );
}
#endif
#if defined(BLAKE2B_SELFTEST)
#include <string.h>
#include "blake2-kat.h"
int main( void )
{
uint8_t key[BLAKE2B_KEYBYTES];
uint8_t buf[BLAKE2_KAT_LENGTH];
size_t i, step;
for( i = 0; i < BLAKE2B_KEYBYTES; ++i )
key[i] = ( uint8_t )i;
for( i = 0; i < BLAKE2_KAT_LENGTH; ++i )
buf[i] = ( uint8_t )i;
/* Test simple API */
for( i = 0; i < BLAKE2_KAT_LENGTH; ++i )
{
uint8_t hash[BLAKE2B_OUTBYTES];
blake2b( hash, BLAKE2B_OUTBYTES, buf, i, key, BLAKE2B_KEYBYTES );
if( 0 != memcmp( hash, blake2b_keyed_kat[i], BLAKE2B_OUTBYTES ) )
{
goto fail;
}
}
/* Test streaming API */
for(step = 1; step < BLAKE2B_BLOCKBYTES; ++step) {
for (i = 0; i < BLAKE2_KAT_LENGTH; ++i) {
uint8_t hash[BLAKE2B_OUTBYTES];
blake2b_state S;
uint8_t * p = buf;
size_t mlen = i;
int err = 0;
if( (err = blake2b_init_key(&S, BLAKE2B_OUTBYTES, key, BLAKE2B_KEYBYTES)) < 0 ) {
goto fail;
}
while (mlen >= step) {
if ( (err = blake2b_update(&S, p, step)) < 0 ) {
goto fail;
}
mlen -= step;
p += step;
}
if ( (err = blake2b_update(&S, p, mlen)) < 0) {
goto fail;
}
if ( (err = blake2b_final(&S, hash, BLAKE2B_OUTBYTES)) < 0) {
goto fail;
}
if (0 != memcmp(hash, blake2b_keyed_kat[i], BLAKE2B_OUTBYTES)) {
goto fail;
}
}
}
puts( "ok" );
return 0;
fail:
puts("error");
return -1;
}
#endif

View File

@ -11,8 +11,6 @@
unsigned bandlimitfunc(struct clientparam *param, unsigned nbytesin, unsigned nbytesout);
void trafcountfunc(struct clientparam *param);
int checkACL(struct clientparam * param);
void nametohash(const unsigned char * name, unsigned char *hash, unsigned char *rnd);
unsigned hashindex(struct hashtable *ht, const unsigned char* hash);
void decodeurl(unsigned char *s, int allowcr);
int parsestr (unsigned char *str, unsigned char **argm, int nitems, unsigned char ** buff, int *inbuf, int *bufsize);
struct ace * make_ace (int argc, unsigned char ** argv);
@ -45,38 +43,36 @@ struct symbol symbols[] = {
{symbols+18, "ipauth", (void *) ipauth},
{symbols+19, "strongauth", (void *) strongauth},
{symbols+20, "checkACL", (void *) checkACL},
{symbols+21, "nametohash", (void *) nametohash},
{symbols+22, "hashindex", (void *) hashindex},
{symbols+23, "nservers", (void *) nservers},
{symbols+24, "udpresolve", (void *) udpresolve},
{symbols+25, "bandlim_mutex", (void *) &bandlim_mutex},
{symbols+26, "tc_mutex", (void *) &tc_mutex},
{symbols+27, "hash_mutex", (void *) &hash_mutex},
{symbols+28, "pwl_mutex", (void *) &pwl_mutex},
{symbols+29, "linenum", (void *) &linenum},
{symbols+30, "proxy_stringtable", (void *) proxy_stringtable},
{symbols+31, "en64", (void *) en64},
{symbols+32, "de64", (void *) de64},
{symbols+33, "tohex", (void *) tohex},
{symbols+34, "fromhex", (void *) fromhex},
{symbols+35, "dnspr", (void *) dnsprchild},
{symbols+36, "pop3p", (void *) pop3pchild},
{symbols+37, "proxy", (void *) proxychild},
{symbols+38, "socks", (void *) sockschild},
{symbols+39, "tcppm", (void *) tcppmchild},
{symbols+40, "udppm", (void *) udppmchild},
{symbols+41, "admin", (void *) adminchild},
{symbols+42, "ftppr", (void *) ftpprchild},
{symbols+43, "smtpp", (void *) smtppchild},
{symbols+44, "auto", (void *) smtppchild},
{symbols+45, "tlspr", (void *) smtppchild},
{symbols+46, "authfuncs", (void *) &authfuncs},
{symbols+47, "commandhandlers", (void *) &commandhandlers},
{symbols+48, "decodeurl", (void *) decodeurl},
{symbols+49, "parsestr", (void *) parsestr},
{symbols+50, "make_ace", (void *) make_ace},
{symbols+51, "freeacl", (void *) freeacl},
{symbols+52, "handleredirect", (void *) handleredirect},
{symbols+21, "nservers", (void *) nservers},
{symbols+22, "udpresolve", (void *) udpresolve},
{symbols+23, "bandlim_mutex", (void *) &bandlim_mutex},
{symbols+24, "tc_mutex", (void *) &tc_mutex},
{symbols+25, "hash_mutex", (void *) &hash_mutex},
{symbols+26, "pwl_mutex", (void *) &pwl_mutex},
{symbols+27, "linenum", (void *) &linenum},
{symbols+28, "proxy_stringtable", (void *) proxy_stringtable},
{symbols+29, "en64", (void *) en64},
{symbols+30, "de64", (void *) de64},
{symbols+31, "tohex", (void *) tohex},
{symbols+32, "fromhex", (void *) fromhex},
{symbols+33, "dnspr", (void *) dnsprchild},
{symbols+34, "pop3p", (void *) pop3pchild},
{symbols+35, "proxy", (void *) proxychild},
{symbols+36, "socks", (void *) sockschild},
{symbols+37, "tcppm", (void *) tcppmchild},
{symbols+38, "udppm", (void *) udppmchild},
{symbols+39, "admin", (void *) adminchild},
{symbols+40, "ftppr", (void *) ftpprchild},
{symbols+41, "smtpp", (void *) smtppchild},
{symbols+42, "auto", (void *) smtppchild},
{symbols+43, "tlspr", (void *) smtppchild},
{symbols+44, "authfuncs", (void *) &authfuncs},
{symbols+45, "commandhandlers", (void *) &commandhandlers},
{symbols+46, "decodeurl", (void *) decodeurl},
{symbols+47, "parsestr", (void *) parsestr},
{symbols+48, "make_ace", (void *) make_ace},
{symbols+49, "freeacl", (void *) freeacl},
{symbols+50, "handleredirect", (void *) handleredirect},
{NULL, "", NULL}
};
@ -111,8 +107,6 @@ struct pluginlink pluginlink = {
ACLmatches,
alwaysauth,
checkACL,
nametohash,
hashindex,
en64,
de64,
tohex,

View File

@ -204,7 +204,6 @@ uint32_t getip46(int family, unsigned char *name, struct sockaddr *sa);
int afdetect(unsigned char *name);
uint32_t myresolver(int, unsigned char *, unsigned char *);
uint32_t fakeresolver (int, unsigned char *, unsigned char*);
int inithashtable(struct hashtable *hashtable, unsigned nhashsize);
void freeparam(struct clientparam * param);
void clearstat(struct clientparam * param);
void dumpcounters(struct trafcount *tl, int counterd);
@ -244,8 +243,10 @@ void genchallenge(struct clientparam *param, char * challenge, char *buf);
void mschap(const unsigned char *win_password,
const unsigned char *challenge, unsigned char *response);
struct hashtable;
void hashadd(struct hashtable *ht, const unsigned char* name, unsigned char* value, time_t expires);
void destroyhashtable(struct hashtable *ht);
int inithashtable(struct hashtable *ht, unsigned nhashsize);
void hashadd(struct hashtable *ht, const void* name, const void* value, time_t expires);
int hashresolv(struct hashtable *ht, const void* name, void* value, uint32_t *ttl);
int parsehost(int family, unsigned char *host, struct sockaddr *sa);
int parsehostname(char *hostname, struct clientparam *param, uint16_t port);

212
src/resolve.c Normal file
View File

@ -0,0 +1,212 @@
#include "proxy.h"
#include "libs/blake2.h"
void char_index2hash(const void *index, uint8_t *hash, const unsigned char *rnd){
const char* name = index;
blake2b(hash, HASH_SIZE, index, strlen((const char*)index), rnd, 4*sizeof(unsigned) );
}
struct hashtable dns_table = {0, 4, {0,0,0,0}, NULL, NULL, 0, char_index2hash};
struct hashtable dns6_table = {0, 16, {0,0,0,0}, NULL, NULL, 0, char_index2hash};
struct nserver nservers[MAXNSERVERS] = {{{0},0}, {{0},0}, {{0},0}, {{0},0}, {{0},0}};
struct nserver authnserver;
uint32_t udpresolve(int af, unsigned char * name, unsigned char * value, uint32_t *retttl, struct clientparam* param, int makeauth){
int i,n;
uint32_t retval;
if((af == AF_INET) && (retval = hashresolv(&dns_table, name, value, retttl))) {
return retval;
}
if((af == AF_INET6) && (retval = hashresolv(&dns6_table, name, value, retttl))) {
return retval;
}
n = (makeauth && !SAISNULL(&authnserver.addr))? 1 : numservers;
for(i=0; i<n; i++){
unsigned short nq, na;
unsigned char b[4098], *buf, *s1, *s2;
int j, k, len, flen;
SOCKET sock;
uint32_t ttl;
PROXYSOCKADDRTYPE addr;
PROXYSOCKADDRTYPE *sinsr, *sinsl;
int usetcp = 0;
unsigned short serial = 1;
buf = b+2;
sinsl = (param && !makeauth)? &param->sinsl : &addr;
sinsr = (param && !makeauth)? &param->sinsr : &addr;
memset(sinsl, 0, sizeof(addr));
memset(sinsr, 0, sizeof(addr));
if(makeauth && !SAISNULL(&authnserver.addr)){
usetcp = authnserver.usetcp;
*SAFAMILY(sinsl) = *SAFAMILY(&authnserver.addr);
}
else {
usetcp = nservers[i].usetcp;
*SAFAMILY(sinsl) = *SAFAMILY(&nservers[i].addr);
}
if((sock=so._socket(so.state, SASOCK(sinsl), usetcp?SOCK_STREAM:SOCK_DGRAM, usetcp?IPPROTO_TCP:IPPROTO_UDP)) == INVALID_SOCKET) break;
if(so._bind(so.state, sock,(struct sockaddr *)sinsl,SASIZE(sinsl))){
so._shutdown(so.state, sock, SHUT_RDWR);
so._closesocket(so.state, sock);
break;
}
if(makeauth && !SAISNULL(&authnserver.addr)){
*sinsr = authnserver.addr;
}
else {
*sinsr = nservers[i].addr;
}
if(usetcp){
if(connectwithpoll(NULL, sock,(struct sockaddr *)sinsr,SASIZE(sinsr),conf.timeouts[CONNECT_TO])) {
so._shutdown(so.state, sock, SHUT_RDWR);
so._closesocket(so.state, sock);
break;
}
#ifdef TCP_NODELAY
{
int opt = 1;
setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char *)&opt, sizeof(opt));
}
#endif
}
len = (int)strlen((char *)name);
serial = myrand(name,len);
*(unsigned short*)buf = serial; /* query id */
buf[2] = 1; /* recursive */
buf[3] = 0;
buf[4] = 0;
buf[5] = 1; /* 1 request */
buf[6] = buf[7] = 0; /* no replies */
buf[8] = buf[9] = 0; /* no ns count */
buf[10] = buf[11] = 0; /* no additional */
if(len > 255) {
len = 255;
}
memcpy(buf + 13, name, len);
len += 13;
buf[len] = 0;
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;
len++;
buf[len++] = 0;
buf[len++] = (makeauth == 1)? 0x0c : (af==AF_INET6? 0x1c:0x01);/* PTR:host address */
buf[len++] = 0;
buf[len++] = 1; /* INET */
if(usetcp){
buf-=2;
*(unsigned short*)buf = htons(len);
len+=2;
}
if(socksendto(NULL, sock, (struct sockaddr *)sinsr, buf, len, conf.timeouts[SINGLEBYTE_L]*1000) != len){
so._shutdown(so.state, sock, SHUT_RDWR);
so._closesocket(so.state, sock);
continue;
}
if(param) param->statscli64 += len;
len = sockrecvfrom(NULL, sock, (struct sockaddr *)sinsr, buf, 4096, conf.timeouts[DNS_TO]*1000);
so._shutdown(so.state, sock, SHUT_RDWR);
so._closesocket(so.state, sock);
if(len <= 13) {
continue;
}
if(param) param->statssrv64 += len;
if(usetcp){
unsigned short us;
us = ntohs(*(unsigned short*)buf);
len-=2;
buf+=2;
if(us > 4096 || us < len || (us > len && sockrecvfrom(NULL, sock, (struct sockaddr *)sinsr, buf+len, us-len, conf.timeouts[DNS_TO]*1000) != us-len)) {
continue;
}
}
if(*(unsigned short *)buf != serial)continue;
if((na = buf[7] + (((unsigned short)buf[6])<<8)) < 1) {
return 0;
}
nq = buf[5] + (((unsigned short)buf[4])<<8);
if (nq != 1) {
continue; /* we did only 1 request */
}
for(k = 13; k<len && buf[k]; k++) {
}
k++;
if( (k+4) >= len) {
continue;
}
k += 4;
if(na > 255) na = 255; /* somebody is very evil */
for (j = 0; j < na; j++) { /* now there should be answers */
while(buf[k] < 192 && buf[k] !=0 && (k+buf[k]+14) < len) k+= (buf[k] + 1);
if(!buf[k]) k--;
if((k+(af == AF_INET6?28:16)) > len) {
break;
}
flen = buf[k+11] + (((unsigned short)buf[k+10])<<8);
if((k+12+flen) > len) {
break;
}
if(makeauth != 1){
if(buf[k+2] != 0 || buf[k+3] != (af == AF_INET6?0x1c:0x1) || flen != (af == AF_INET6?16:4)) {
k+= (12 + flen);
continue; /* we need A IPv4 */
}
ttl = ntohl(*(uint32_t *)(buf + k + 6));
memcpy(value, buf + k + 12, af == AF_INET6? 16:4);
if(ttl < 0 || ttl > (3600*12)) ttl = 3600*12;
if(!ttl) ttl = 1;
hashadd(af == AF_INET6?&dns6_table:&dns_table, name, value, conf.time+ttl);
if(retttl) *retttl = ttl;
return 1;
}
else {
if(buf[k+2] != 0 || buf[k+3] != 0x0c) {
k+= (12 + flen);
continue; /* we need A PTR */
}
for (s2 = buf + k + 12; s2 < (buf + k + 12 + len) && *s2; ){
s1 = s2 + ((unsigned)*s2) + 1;
*s2 = '.';
s2 = s1;
}
*s2 = 0;
if(param->username)myfree(param->username);
param->username = (unsigned char *)mystrdup ((char *)buf + k + 13);
return udpresolve(af,param->username, value, NULL, NULL, 2);
}
}
}
return 0;
}
uint32_t myresolver(int af, unsigned char * name, unsigned char * value){
return udpresolve(af, name, value, NULL, NULL, 0);
}
uint32_t fakeresolver (int af, unsigned char *name, unsigned char * value){
memset(value, 0, af == AF_INET6? 16 : 4);
if(af == AF_INET6){
memset(value, 0, 16);
value[15] = 2;
}
else {
value[0] = 127;
value[1] = 0;
value[2] = 0;
value[3] = 2;
}
return 1;
}

152
src/sql.c Normal file
View File

@ -0,0 +1,152 @@
#include "proxy.h"
#ifndef NOODBC
SQLHENV henv = NULL;
SQLHSTMT hstmt = NULL;
SQLHDBC hdbc = NULL;
char * sqlstring = NULL;
void close_sql(){
if(hstmt) {
SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
hstmt = NULL;
}
if(hdbc){
SQLDisconnect(hdbc);
SQLFreeHandle(SQL_HANDLE_DBC, hdbc);
hdbc = NULL;
}
if(henv) {
SQLFreeHandle(SQL_HANDLE_ENV, henv);
henv = NULL;
}
}
int attempt = 0;
time_t attempt_time = 0;
int init_sql(char * s){
SQLRETURN retcode;
char * datasource;
char * username;
char * password;
char * string;
if(!s) return 0;
if(!sqlstring || strcmp(sqlstring, s)){
string = sqlstring;
sqlstring=mystrdup(s);
if(string)myfree(string);
}
if(hstmt || hdbc || henv) close_sql();
attempt++;
attempt_time = time(0);
if(!henv){
retcode = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv);
if (!henv || (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO)){
henv = NULL;
return 0;
}
retcode = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0);
if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO) {
return 0;
}
}
if(!hdbc){
retcode = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc);
if (!hdbc || (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO)) {
hdbc = NULL;
SQLFreeHandle(SQL_HANDLE_ENV, henv);
henv = NULL;
return 0;
}
SQLSetConnectAttr(hdbc, SQL_LOGIN_TIMEOUT, (void*)15, 0);
}
string = mystrdup(sqlstring);
if(!string) return 0;
datasource = strtok(string, ",");
username = strtok(NULL, ",");
password = strtok(NULL, ",");
/* Connect to data source */
retcode = SQLConnect(hdbc, (SQLCHAR*) datasource, (SQLSMALLINT)strlen(datasource),
(SQLCHAR*) username, (SQLSMALLINT)((username)?strlen(username):0),
(SQLCHAR*) password, (SQLSMALLINT)((password)?strlen(password):0));
myfree(string);
if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO){
SQLFreeHandle(SQL_HANDLE_DBC, hdbc);
hdbc = NULL;
SQLFreeHandle(SQL_HANDLE_ENV, henv);
henv = NULL;
return 0;
}
retcode = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);
if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO){
close_sql();
return 0;
}
return 1;
}
void sqlerr (char *buf){
if(conf.stdlog){
fprintf(conf.stdlog, "%s\n", buf);
fflush(conf.stdlog);
}
pthread_mutex_unlock(&log_mutex);
}
unsigned char statbuf[8192];
void logsql(struct clientparam * param, const unsigned char *s) {
SQLRETURN ret;
int len;
if(param->nolog) return;
pthread_mutex_lock(&log_mutex);
len = dobuf(param, statbuf, s, (unsigned char *)"\'");
if(attempt > 5){
time_t t;
t = time(0);
if (t - attempt_time < 180){
sqlerr((char *)statbuf);
return;
}
}
if(!hstmt){
if(!init_sql(sqlstring)) {
sqlerr((char *)statbuf);
return;
}
}
if(hstmt){
ret = SQLExecDirect(hstmt, (SQLCHAR *)statbuf, (SQLINTEGER)len);
if(ret != SQL_SUCCESS && ret != SQL_SUCCESS_WITH_INFO){
close_sql();
if(!init_sql(sqlstring)){
sqlerr((char *)statbuf);
return;
}
if(hstmt) {
ret = SQLExecDirect(hstmt, (SQLCHAR *)statbuf, (SQLINTEGER)len);
if(ret != SQL_SUCCESS && ret != SQL_SUCCESS_WITH_INFO){
sqlerr((char *)statbuf);
return;
}
attempt = 0;
}
}
attempt = 0;
}
pthread_mutex_unlock(&log_mutex);
}
#endif

View File

@ -754,10 +754,12 @@ struct child {
unsigned char **argv;
};
#define HASH_SIZE (16)
struct hashentry {
unsigned char hash[sizeof(unsigned)*4];
uint8_t hash[HASH_SIZE];
time_t expires;
struct hashentry *next;
uint32_t inext;
char value[4];
};
@ -765,9 +767,12 @@ struct hashtable {
unsigned hashsize;
unsigned recsize;
unsigned rnd[4];
struct hashentry ** hashtable;
void * hashvalues;
struct hashentry * hashempty;
uint32_t * ihashtable;
uint8_t * hashvalues;
uint32_t ihashempty;
void (*index2hash)(const void *index, unsigned char *hash, const unsigned char *rnd);
unsigned growlimit;
int tablesize;
};
extern struct hashtable dns_table;
@ -795,8 +800,6 @@ struct pluginlink {
int (*ACLMatches)(struct ace* acentry, struct clientparam * param);
int (*alwaysauth)(struct clientparam * param);
int (*checkACL)(struct clientparam * param);
void (*nametohash)(const unsigned char * name, unsigned char *hash, unsigned char *rnd);
unsigned (*hashindex)(struct hashtable *ht, const unsigned char* hash);
unsigned char* (*en64)(const unsigned char *in, unsigned char *out, int inlen);
int (*de64)(const unsigned char *in, unsigned char *out, int maxlen);
void (*tohex)(unsigned char *in, unsigned char *out, int len);