local.in
newserv
modules/
-newserv.local.conf
+newserv.conf
+chanservlog.*
+logs/*
+core/events.c
/* Send hook */
harg[0]=ch[i];
harg[1]=np;
+ harg[2]=NULL;
triggerhook(HOOK_CHANNEL_PART,harg);
delnickfromchannel(ch[i],np->numeric,0);
}
if (newchan) {
delchannel(cp);
}
- } else {
+ } else {
+ chanindex *cip=cp->index;
+
/* If we just created a channel, flag it */
if (newchan) {
triggerhook(HOOK_CHANNEL_NEWCHANNEL,cp);
}
-
- /* send hook */
- harg[0]=cp;
- harg[1]=np;
- triggerhook(HOOK_CHANNEL_JOIN,harg);
+
+ /* Don't send HOOK_CHANNEL_JOIN if the channel doesn't exist any
+ * more (can happen if something destroys it in response to
+ * HOOK_CHANNEL_NEWCHANNEL) */
+ if (cp == cip->channel) {
+ /* send hook */
+ harg[0]=cp;
+ harg[1]=np;
+ triggerhook(HOOK_CHANNEL_JOIN,harg);
+ }
}
}
nextchan=pos;
if (newchan) {
delchannel(cp);
}
- } else {
+ } else {
+ chanindex *cip = cp->index;
+
/* Flag the channel as new if necessary */
if (newchan) {
triggerhook(HOOK_CHANNEL_NEWCHANNEL,cp);
}
- /* Trigger hook */
- harg[0]=cp;
- harg[1]=np;
- triggerhook(HOOK_CHANNEL_CREATE,harg);
+ /* If HOOK_CHANNEL_NEWCHANNEL has caused the channel to be deleted,
+ * don't trigger the CREATE hook. */
+ if (cip->channel == cp) {
+ /* Trigger hook */
+ harg[0]=cp;
+ harg[1]=np;
+ triggerhook(HOOK_CHANNEL_CREATE,harg);
+ }
}
nextchan=pos;
}
--- /dev/null
+
+.PHONY: all
+all: chanprofile.so
+
+chanprofile.so: chanprofile.o
+ ld -shared -Bdynamic -o $@ $^
--- /dev/null
+
+#include "chanprofile.h"
+#include "../channel/channel.h"
+#include "../control/control.h"
+#include "../newsearch/newsearch.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+unsigned int activeprofiles;
+struct chanprofile *cptable[CPHASHSIZE];
+
+struct chanprofile *getcprec(nick *np) {
+ unsigned int hash=0,mhash;
+ unsigned int ccount=0;
+ unsigned int clen=0;
+ unsigned int i;
+ struct chanprofile *cpp;
+
+ struct channel **cs=(np->channels->content);
+
+ ccount=np->channels->cursi;
+
+ for (i=0;i<np->channels->cursi;i++) {
+ clen+=cs[i]->index->name->length;
+ hash ^= (unsigned int )cs[i];
+ }
+
+ mhash=hash%CPHASHSIZE;
+
+ for (cpp=cptable[mhash];cpp;cpp=cpp->next) {
+ if ((cpp->hashval==hash) && (cpp->ccount==ccount) &&
+ (cpp->clen==clen))
+ return cpp;
+ }
+
+ cpp=malloc(sizeof(struct chanprofile));
+
+ cpp->clones=0;
+ cpp->hashval=hash;
+ cpp->ccount=ccount;
+ cpp->clen=clen;
+ cpp->nicks=NULL;
+ cpp->next=cptable[mhash];
+ cptable[mhash]=cpp;
+
+ activeprofiles++;
+
+ return cpp;
+}
+
+void popprofiles() {
+ unsigned int i;
+ struct chanprofile *cpp;
+ nick *np;
+
+ /* Create the chanprofile records and count clones for each profile */
+ for (i=0;i<NICKHASHSIZE;i++) {
+ for (np=nicktable[i];np;np=np->next) {
+ cpp=getcprec(np);
+ cpp->clones++;
+ }
+ }
+
+ /* Allocate space for nick array in each profile */
+ for (i=0;i<CPHASHSIZE;i++) {
+ for (cpp=cptable[i];cpp;cpp=cpp->next) {
+ cpp->nicks=(nick **)malloc(cpp->clones * sizeof(nick *));
+ cpp->clones=0;
+ }
+ }
+
+ /* Populate the nick arrays */
+ for (i=0;i<NICKHASHSIZE;i++) {
+ for (np=nicktable[i];np;np=np->next) {
+ cpp=getcprec(np);
+ cpp->nicks[cpp->clones++]=np;
+ }
+ }
+}
+
+void clearprofiles() {
+ unsigned int i;
+ struct chanprofile *cpp, *ncpp;
+
+ for (i=0;i<CPHASHSIZE;i++) {
+ for (cpp=cptable[i];cpp;cpp=ncpp) {
+ ncpp=cpp->next;
+ free(cpp->nicks);
+ free(cpp);
+ }
+ cptable[i]=NULL;
+ }
+
+ activeprofiles=0;
+}
+
+int cpcompare(const void *a, const void *b) {
+ const struct chanprofile **cpa=a, **cpb=b;
+
+ return (*cpb)->clones - (*cpa)->clones;
+}
+
+void reportprofile(nick *sender, struct chanprofile *cpp) {
+ channel **cps, *cp;
+ unsigned int i;
+ nick *np;
+ char buf[1024];
+ unsigned int repwidth=80;
+ unsigned int bufpos;
+
+ controlreply(sender,"============================================================");
+
+ if (cpp->ccount==0) {
+ controlreply(sender,"(no channels): %u users",cpp->clones);
+ return;
+ }
+
+ controlreply(sender,"Channels (%u):",cpp->ccount);
+
+ np=cpp->nicks[0];
+ cps=np->channels->content;
+ bufpos=0;
+ for (i=0;i<np->channels->cursi;i++) {
+ cp=cps[i];
+ if (bufpos && ((bufpos + cp->index->name->length) > repwidth)) {
+ controlreply(sender," %s",buf);
+ bufpos=0;
+ }
+
+ bufpos += sprintf(buf+bufpos,"%s ",cp->index->name->content);
+ }
+
+ if (bufpos)
+ controlreply(sender," %s",buf);
+
+ controlreply(sender,"Users (%u):",cpp->clones);
+
+ for (i=0;i<cpp->clones;i++) {
+ printnick(sender,cpp->nicks[i]);
+ }
+}
+
+int reportprofiles(void *source, int cargc, char **cargv) {
+ unsigned int i,j;
+ struct chanprofile **cpary, *cpp;
+ unsigned int repnum=20;
+ nick *sender=source;
+
+ if (cargc>0)
+ repnum=strtoul(cargv[0],NULL,10);
+
+ popprofiles();
+
+ /* Make a big fat array */
+ cpary=malloc(activeprofiles*sizeof(struct chanprofile *));
+ for (i=0,j=0;i<CPHASHSIZE;i++)
+ for (cpp=cptable[i];cpp;cpp=cpp->next)
+ cpary[j++]=cpp;
+
+ controlreply(sender,"Populated array, lest number=%u (should be %u)",j,activeprofiles);
+
+ qsort(cpary, activeprofiles, sizeof(struct chanprofile *), cpcompare);
+
+ controlreply(sender,"Top %u channel profiles (%u total):",repnum,activeprofiles);
+
+ for (i=0;i<repnum;i++) {
+ reportprofile(sender,cpary[i]);
+ }
+
+ controlreply(sender,"--- End of list.");
+
+ clearprofiles();
+
+ return CMD_OK;
+}
+
+void _init() {
+ memset(cptable,0,sizeof(cptable));
+ registercontrolhelpcmd("chanprofiles",NO_DEVELOPER,1,reportprofiles,"Usage: chanprofiles [count]\nDisplays the most common channel profiles. count defaults to 20.");
+}
+
+void _fini() {
+ deregistercontrolcmd("chanprofiles",reportprofiles);
+}
+
--- /dev/null
+#ifndef CHANPROFILE_H
+#define CHANPROFILE_H
+
+#include "../nick/nick.h"
+
+#define CPHASHSIZE 50000
+
+struct chanprofile {
+ unsigned int clones;
+ unsigned int hashval;
+ unsigned int ccount;
+ unsigned int clen;
+ nick **nicks;
+ struct chanprofile *next;
+};
+
+struct chanprofile *cptable[CPHASHSIZE];
+
+#endif
-CSDIRS=database chancmds usercmds authcmds authtracker
+CSDIRS=database chancmds usercmds authcmds authtracker newsearch
.PHONY: all dirs clean
all: chanserv.so chanserv_protect.so chanserv_grep.so chanserv_chansearch.so chanserv_authlib.so dirs
--- /dev/null
+
+.PHONY: all
+all: chanserv_newsearch.so
+
+chanserv_newsearch.so: cs-newsearch.o formats.o
+ ld -shared -Bdynamic -o $@ $^
+
--- /dev/null
+#include "../../newsearch/newsearch.h"
+#include "../chanserv.h"
+
+/* formats.c */
+void printnick_auth(nick *, nick *);
+void printnick_authchans(nick *, nick *);
+
+void _init() {
+ regnickdisp("auth", printnick_auth);
+ regnickdisp("authchans", printnick_authchans);
+}
+
+void _fini() {
+ unregnickdisp("auth", printnick_auth);
+ unregnickdisp("authchans", printnick_authchans);
+}
--- /dev/null
+#include "../chanserv.h"
+#include "../../newsearch/newsearch.h"
+#include "../../control/control.h"
+
+void printnick_auth(nick *sender, nick *np) {
+ struct reguser *rup;
+
+ if (!(rup=getreguserfromnick(np))) {
+ controlreply(sender,"%s (not authed)",np->nick);
+ } else {
+ controlreply(sender,"%s (%s/%u) (%s) (%s)",np->nick,rup->username,rup->ID,
+ rup->email ? rup->email->content : "no email",
+ rup->comment ? rup->comment->content : "no comment" );
+ }
+}
+
+void printnick_authchans(nick *sender, nick *np) {
+ struct reguser *rup;
+ struct regchanuser *rcup;
+ char thebuf[1024];
+ char buf2[512];
+ unsigned int bufpos=0, buf2len;
+ unsigned char ch;
+
+ printnick_auth(sender,np);
+
+ if (!(rup=getreguserfromnick(np)))
+ return;
+
+ if (!rup->knownon) {
+ controlreply(sender, " (no channels)");
+ } else {
+ for (rcup=rup->knownon;rcup;rcup=rcup->nextbyuser) {
+ if (CUIsOwner(rcup))
+ ch='*';
+ else if (CUHasMasterPriv(rcup))
+ ch='&';
+ else if (CUHasOpPriv(rcup))
+ ch='@';
+ else if (CUHasVoicePriv(rcup))
+ ch='+';
+ else if (CUKnown(rcup))
+ ch=' ';
+ else
+ ch='!';
+
+ buf2len=sprintf(buf2,"%c%s",ch,rcup->chan->index->name->content);
+
+ if (buf2len+bufpos > 400) {
+ controlreply(sender," %s", thebuf);
+ bufpos=0;
+ }
+ bufpos+=sprintf(thebuf+bufpos,"%s ",buf2);
+ }
+ if (bufpos)
+ controlreply(sender," %s", thebuf);
+ }
+}
myrealname=getcopyconfigitem("control","realname","NewServ Control Service",REALLEN);
myauthname=getcopyconfigitem("control","authname","C",ACCOUNTLEN);
- mynick=registerlocaluser(cnick->content,myident->content,myhost->content,myrealname->content,myauthname->content,UMODE_SERVICE|UMODE_DEAF|UMODE_OPER|UMODE_ACCOUNT,&handlemessages);
+ mynick=registerlocaluser(cnick->content,myident->content,myhost->content,myrealname->content,myauthname->content,UMODE_SERVICE|UMODE_DEAF|UMODE_OPER|UMODE_ACCOUNT|UMODE_INV,&handlemessages);
triggerhook(HOOK_CONTROL_REGISTERED, mynick);
cp=findchannel("#twilightzone");
if (!cp) {
buf[i*18]=' ';
}
}
-
for (cbp=cp->bans;cbp;cbp=cbp->next) {
controlreply((nick *)sender,"Ban : %s",bantostringdebug(cbp));
/*
- * events.c: the event handling core, poll() version
+ * events.c: the event handling core, epoll() version
*/
#include <stdio.h>
}
eventfds=(struct pollfd *)realloc((void *)eventfds,maxfds*sizeof(struct pollfd));
- memset(&eventfds[oldmax],0,maxfds-oldmax);
+ memset(&eventfds[oldmax],0,(maxfds-oldmax)*sizeof(struct pollfd));
eventhandlers=(reghandler *)realloc((void *)eventhandlers,maxfds*sizeof(reghandler));
- memset(&eventhandlers[oldmax],0,maxfds-oldmax);
+ memset(&eventhandlers[oldmax],0,(maxfds-oldmax)*sizeof(reghandler));
}
/*
Error("core",ERR_INFO,"All modules removed. Exiting.");
}
+
+/* very slow, make sure you cache the pointer! */
+void *ndlsym(char *modulename, char *fn) {
+ module *mods=(module *)(modules.content);
+ int i=getindex(modulename);
+
+ if (i<0)
+ return NULL;
+
+ return dlsym(mods[i].handle, fn);
+}
void reloadmarked(void);
void safereload(char *themodule);
void newserv_shutdown();
+void *ndlsym(char *module, char *fn);
extern int newserv_shutdown_pending;
#define POOL_CHANSERVDB 5
#define POOL_SSTRING 6
#define POOL_AUTHTRACKER 7
+#define POOL_PROXYSCAN 8
#include "../control/control.h"
#include "../lib/version.h"
+#include <strings.h>
+
#include "libGeoIP/GeoIP.h"
#include "geoip.h"
-#warning This module is GPL'ed. Load/link at your peril.
+#warning This module is GPLed. Load/link at your peril.
MODULE_VERSION("");
}
}
+int geoip_lookupcode(char *code) {
+ int i;
+ for(i=COUNTRY_MIN;i<COUNTRY_MAX;i++)
+ if(!strcasecmp(code, GeoIP_country_code[i]))
+ return i;
+
+ return -1;
+}
extern int geoip_totals[COUNTRY_MAX + 1];
+int geoip_lookupcode(char *code);
+typedef int (*GeoIP_LookupCode)(char *);
+
if (IsAccount(nck))
authed_count++;
- if (IsOper(nck) && strlen(nck->nick) > 1)
+ if (IsOper(nck) && strlen(nck->nick) > 1 && (IsSecret(chan) || IsPrivate(chan) || IsKey(chan) || IsInviteOnly(chan)))
{
- helpmod_reply(sender, returntype, "Cannot check channel: Permission denied. Channel %s has an oper on it", argv[0]);
+ helpmod_reply(sender, returntype, "Cannot check channel: Permission denied. Channel %s has an oper on it and one or more of +i/+k/+p/+s", argv[0]);
return;
}
}
.PHONY: all
-all: sstring.o array.o splitline.o base64.o flags.o irc_string.o malloc.o strlfunc.o sha1.o helix.o irc_ipv6.o patricia.o
+all: sstring.o array.o splitline.o base64.o flags.o irc_string.o malloc.o strlfunc.o sha1.o irc_ipv6.o patricia.o rijndael.o sha2.o
+++ /dev/null
-/* Cleanroom reference implementation of Helix */
-
-/* HEAVILY modified by Chris Porter to support contexts. */
-
-/* See Ferguson et. al, Fast Software Encryption 2003, or
- * http://www.macfergus.com/helix/helixPreproc.pdf
- */
-
-#include <string.h>
-#include "helix.h"
-
-/* some useful macros -- little-endian */
-#define B(x,i) ((UCHAR)(((x) >> (8*i)) & 0xFF))
-#define BYTE2WORD(b) ( \
- (((WORD)(b)[3] & 0xFF)<<24) | \
- (((WORD)(b)[2] & 0xFF)<<16) | \
- (((WORD)(b)[1] & 0xFF)<<8) | \
- (((WORD)(b)[0] & 0xFF)) \
-)
-#define WORD2BYTE(w, b) { \
- (b)[3] = B(w,3); \
- (b)[2] = B(w,2); \
- (b)[1] = B(w,1); \
- (b)[0] = B(w,0); \
-}
-#define XORWORD(w, b) { \
- (b)[3] ^= B(w,3); \
- (b)[2] ^= B(w,2); \
- (b)[1] ^= B(w,1); \
- (b)[0] ^= B(w,0); \
-}
-#define ROTL(w,x) (((w) << (x))|((w) >> (32 - (x))))
-
-/* 3.2, figure 2, block function */
-WORD
-h_block(struct helix_ctx *ctx, WORD X_i0, WORD P_i, WORD X_i1)
-{
- WORD r;
-
- r = ctx->A; /* for returning later */
- ctx->A += ctx->D; ctx->D = ROTL(ctx->D, 15);
- ctx->B += ctx->E; ctx->E = ROTL(ctx->E, 25);
- ctx->C ^= ctx->A; ctx->A = ROTL(ctx->A, 9);
- ctx->D ^= ctx->B; ctx->B = ROTL(ctx->B, 10);
- ctx->E += ctx->C; ctx->C = ROTL(ctx->C, 17);
- ctx->A ^= ctx->D + X_i0; ctx->D = ROTL(ctx->D, 30);
- ctx->B ^= ctx->E; ctx->E = ROTL(ctx->E, 13);
- ctx->C += ctx->A; ctx->A = ROTL(ctx->A, 20);
- ctx->D += ctx->B; ctx->B = ROTL(ctx->B, 11);
- ctx->E ^= ctx->C; ctx->C = ROTL(ctx->C, 5);
- ctx->A += ctx->D ^ P_i; ctx->D = ROTL(ctx->D, 15);
- ctx->B += ctx->E; ctx->E = ROTL(ctx->E, 25);
- ctx->C ^= ctx->A; ctx->A = ROTL(ctx->A, 9);
- ctx->D ^= ctx->B; ctx->B = ROTL(ctx->B, 10);
- ctx->E += ctx->C; ctx->C = ROTL(ctx->C, 17);
- ctx->A ^= ctx->D + X_i1; ctx->D = ROTL(ctx->D, 30);
- ctx->B ^= ctx->E; ctx->E = ROTL(ctx->E, 13);
- ctx->C += ctx->A; ctx->A = ROTL(ctx->A, 20);
- ctx->D += ctx->B; ctx->B = ROTL(ctx->B, 11);
- ctx->E ^= ctx->C; ctx->C = ROTL(ctx->C, 5);
- /* increment i in funny way */
- if (++ctx->h_iplus8[0] == 0x80000000lu) {
- ++ctx->h_iplus8[1];
- ctx->h_iplus8[0] = 0;
- }
- return r;
-}
-
-/* 3.7 Key schedule.
- * Could do feistel in place, but this follows description in paper.
- */
-void
-h_key(struct helix_ctx *ctx, unsigned char *U, int U_len)
-{
- WORD k[40]; /* room for key schedule */
- int i;
-
- if (U_len > 32)
- U_len = 32; /* limit size of key */
- memset((void *)k, 0, sizeof k);
- memcpy((void *)&k[32], U, U_len);
- ctx->h_iplus8[0] = ctx->h_iplus8[1] = 0;
-
- for (i = 32; i < 40; ++i)
- k[i] = BYTE2WORD(((unsigned char *)&k[i])); /* convert to words */
- for (i = 7; i >= 0; --i) {
- ctx->A = k[4*i+4];
- ctx->B = k[4*i+5];
- ctx->C = k[4*i+6];
- ctx->D = k[4*i+7];
- ctx->E = U_len + 64;
- (void)h_block(ctx, 0, 0, 0);
- k[4*i+0] = ctx->A ^ k[4*i+8];
- k[4*i+1] = ctx->B ^ k[4*i+9];
- k[4*i+2] = ctx->C ^ k[4*i+10];
- k[4*i+3] = ctx->D ^ k[4*i+11];
- }
- /* copy into K */
- for (i = 0; i < 8; ++i)
- ctx->K[i] = k[i];
- /* remember length of key */
- ctx->l_u = U_len;
-}
-
-/* 3.3, nonce setup */
-void
-h_nonce(struct helix_ctx *ctx, UCHAR nonce[16])
-{
- ctx->N[0] = BYTE2WORD(&nonce[0]);
- ctx->N[1] = BYTE2WORD(&nonce[4]);
- ctx->N[2] = BYTE2WORD(&nonce[8]);
- ctx->N[3] = BYTE2WORD(&nonce[12]);
- ctx->N[4] = 0 - ctx->N[0];
- ctx->N[5] = 1 - ctx->N[1];
- ctx->N[6] = 2 - ctx->N[2];
- ctx->N[7] = 3 - ctx->N[3];
-}
-
-/* 3.3, X_i functions */
-WORD
-X(struct helix_ctx *ctx, int one)
-{
- WORD x = 0;
-
- if (one) {
- x = ctx->K[(ctx->h_iplus8[0] + 4) & 0x07] + ctx->N[ctx->h_iplus8[0] & 0x07] + ctx->h_iplus8[0];
- if ((ctx->h_iplus8[0] & 0x03) == 3)
- x += ctx->h_iplus8[1];
- else if ((ctx->h_iplus8[0] & 0x03) == 1)
- x += ctx->l_u << 2;
- }
- else
- x = ctx->K[ctx->h_iplus8[0] & 0x07];
- return x;
-}
-
-/* 3.4 initialisation */
-void
-h_init(struct helix_ctx *ctx)
-{
- int i;
-
- ctx->h_iplus8[0] = ctx->h_iplus8[1] = 0;
- ctx->A = ctx->K[3] ^ ctx->N[0];
- ctx->B = ctx->K[4] ^ ctx->N[1];
- ctx->C = ctx->K[5] ^ ctx->N[2];
- ctx->D = ctx->K[6] ^ ctx->N[3];
- ctx->E = ctx->K[7];
- for (i = 0; i < 8; ++i)
- (void) h_block(ctx, X(ctx, 0), 0, X(ctx, 1));
-}
-
-/* 3.5 encryption, and 3.6 compute MAC */
-void
-h_encrypt(struct helix_ctx *ctx, UCHAR *buf, int n, UCHAR macbuf[16])
-{
- UCHAR b[4];
- WORD w;
- int i;
-
- h_init(ctx);
- while (n >= 4) {
- w = h_block(ctx, X(ctx, 0), BYTE2WORD(buf), X(ctx, 1));
- XORWORD(w, buf);
- buf += 4;
- n -= 4;
- }
- if (n != 0) {
- /* handle an odd bit at the end */
- for (i = 0; i < n; ++i)
- b[i] = buf[i];
- for (/*...*/; i < 4; ++i)
- b[i] = 0;
- w = BYTE2WORD(b);
- w = h_block(ctx, X(ctx,0), w, X(ctx,1));
- XORWORD(w, b);
- for (i = 0; i < n; ++i)
- buf[i] = b[i];
- }
- /* now compute MAC. Note that "n" is currently l(P) mod 4. */
- ctx->A ^= 0x912d94f1;
- for (i = 0; i < 8; ++i)
- (void) h_block(ctx, X(ctx,0), n, X(ctx,1));
- for (i = 0; i < 4; ++i) {
- w = h_block(ctx, X(ctx,0), n, X(ctx,1));
- WORD2BYTE(w, &macbuf[i*4]);
- }
-}
-
-/* 3.8 decryption, and 3.6 compute MAC */
-void
-h_decrypt(struct helix_ctx *ctx, UCHAR *buf, int n, UCHAR macbuf[16])
-{
- UCHAR b[4];
- WORD w;
- int i;
-
- h_init(ctx);
- while (n >= 4) {
- /* rather than muck with h_block, we use knowledge of A */
- w = BYTE2WORD(buf) ^ ctx->A; /* plaintext */
- w = h_block(ctx, X(ctx,0), w, X(ctx,1));
- XORWORD(w, buf);
- buf += 4;
- n -= 4;
- }
- if (n != 0) {
- /* handle an odd bit at the end */
- for (i = 0; i < n; ++i)
- b[i] = buf[i];
- XORWORD(ctx->A, b);
- for (/*...*/; i < 4; ++i)
- b[i] = 0;
- w = BYTE2WORD(b);
- (void) h_block(ctx, X(ctx,0), w, X(ctx,1)); /* note decryption already done */
- for (i = 0; i < n; ++i)
- buf[i] = b[i];
- }
- /* now compute MAC. Note that "n" is currently l(P) mod 4. */
- ctx->A ^= 0x912d94f1;
- for (i = 0; i < 8; ++i)
- (void) h_block(ctx, X(ctx,0), n, X(ctx,1));
- for (i = 0; i < 4; ++i) {
- w = h_block(ctx, X(ctx,0), n, X(ctx,1));
- WORD2BYTE(w, &macbuf[i*4]);
- }
-}
-
-#ifdef TEST
-/*--------------------------------------------------------------------------*/
-/* test harness */
-/*--------------------------------------------------------------------------*/
-
-#include "hexlib.h"
-#include <stdlib.h>
-#include <stdio.h>
-#include <time.h>
-
-/* self test */
-void
-test_helix(int quick)
-{
- extern int keylen;
- UCHAR key[32], nonce[16], buf[32], mac[16];
- struct helix_ctx ctx;
-
- /* basic test */
- printf("Test Vector set 1:\n");
- hexprint("Initial Key", key, 0);
- memset((void *)nonce, 0, 16);
- hexprint("Nonce", nonce, 16);
- h_key(&ctx, key, 0);
- h_nonce(&ctx, nonce);
- hexwprint("Working Key", ctx.K, 32);
- hexwcheck(ctx.K, "a9 3b 6e 32 bc 23 4f 6c 32 6c 0f 82 74 ff a2 41"
- "e3 da 57 7d ef 7c 1b 64 af 78 7c 38 dc ef e3 de", 32);
- hexwprint("Working N", ctx.N, 32);
- memset(buf, 0, 10);
- hexprint("Plaintext", buf, 10);
- h_encrypt(&ctx, buf, 10, mac);
- hexprint("Ciphertext", buf, 10);
- hexcheck(buf, "70 44 c9 be 48 ae 89 22 66 e4", 10);
- hexprint("MAC", mac, 16);
- hexcheck(mac, "65 be 7a 60 fd 3b 8a 5e 31 61 80 80 56 32 d8 10", 16);
- h_decrypt(&ctx, buf, 10, mac);
- hexprint("decrypted", buf, 10);
- hexprint("MAC", mac, 16);
- hexcheck(mac, "65 be 7a 60 fd 3b 8a 5e 31 61 80 80 56 32 d8 10", 16);
-
- /* second vector */
- printf("\nTest Vector set 2:\n");
- hexread(key, "00 00 00 00 01 00 00 00 02 00 00 00 03 00 00 00"
- "04 00 00 00 05 00 00 00 06 00 00 00 07 00 00 00", 32);
- hexprint("Initial Key", key, 32);
- hexread(nonce, "00 00 00 00 01 00 00 00 02 00 00 00 03 00 00 00", 16);
- hexprint("Nonce", nonce, 16);
- h_key(&ctx, key, 32);
- h_nonce(&ctx, nonce);
- hexwprint("Working Key", ctx.K, 32);
- hexwcheck(ctx.K, "6e e9 a7 6c bd 0b f6 20 a6 d9 b7 59 49 d3 39 95"
- "04 f8 4a d6 83 12 f9 06 ed d1 a6 98 9e c8 9d 45", 32);
- hexread(buf, "00 00 00 00 01 00 00 00 02 00 00 00 03 00 00 00"
- "04 00 00 00 05 00 00 00 06 00 00 00 07 00 00 00", 32);
- hexprint("Plaintext", buf, 32);
- h_encrypt(&ctx, buf, 32, mac);
- hexprint("Ciphertext", buf, 32);
- hexcheck(buf, "7a 72 a7 5b 62 50 38 0b 69 75 1c d1 28 30 8d 9a"
- "0c 74 46 a3 bf 3f 99 e6 65 56 b9 c1 18 ca 7d 87", 32);
- hexprint("MAC", mac, 16);
- hexcheck(mac, "e4 e5 49 01 c5 0b 34 e7 80 c0 9c 39 b1 09 a1 17", 16);
- h_decrypt(&ctx, buf, 32, mac);
- hexprint("decrypted", buf, 32);
- hexprint("MAC", mac, 16);
- hexcheck(mac, "e4 e5 49 01 c5 0b 34 e7 80 c0 9c 39 b1 09 a1 17", 16);
-
- /* third vector */
- printf("\nTest Vector set 3:\n");
- hexread(key, "48 65 6c 69 78", 5);
- hexprint("Initial Key", key, 5);
- hexread(nonce, "30 31 32 33 34 35 36 37 38 39 61 62 63 64 65 66", 16);
- hexprint("Nonce", nonce, 16);
- h_key(&ctx, key, 5);
- h_nonce(&ctx, nonce);
- hexwprint("Working Key", ctx.K, 32);
- hexwcheck(ctx.K, "6c 1e d7 7a cb a3 a1 d2 8f 1c d6 20 6d f1 15 da"
- "f4 03 28 4a 73 9b b6 9f 35 7a 85 f5 51 32 11 39", 32);
- hexread(buf, "48 65 6c 6c 6f 2c 20 77 6f 72 6c 64 21", 13);
- hexprint("Plaintext", buf, 13);
- h_encrypt(&ctx, buf, 13, mac);
- hexprint("Ciphertext", buf, 13);
- hexcheck(buf, "6c 4c 27 b9 7a 82 a0 c5 80 2c 23 f2 0d", 13);
- hexprint("MAC", mac, 16);
- hexcheck(mac, "6c 82 d1 aa 3b 90 5f 12 f1 44 3f a7 f6 a1 01 d2", 16);
- h_decrypt(&ctx, buf, 13, mac);
- hexprint("decrypted", buf, 13);
- hexprint("MAC", mac, 16);
- hexcheck(mac, "6c 82 d1 aa 3b 90 5f 12 f1 44 3f a7 f6 a1 01 d2", 16);
-}
-
-#define BLOCKSIZE 1600 /* for MAC-style tests */
-#define MACSIZE 16
-char *testkey = "test key 128bits";
-UCHAR testIV[16];
-UCHAR testframe[BLOCKSIZE];
-UCHAR testmac[16];
-
-/* Perform various timing tests
- */
-UCHAR bigbuf[1024*1024];
-UCHAR macbuf[16];
-int
-main(int ac, char **av)
-{
- int n, i;
- int vflag = 0;
- UCHAR key[32], IV[32];
- int keysz, IVsz;
- extern int keylen;
- extern WORD K[];
-
- if (ac == 2 && strcmp(av[1], "-test") == 0) {
- test_helix(0);
- return nerrors;
- }
- if (ac >= 2 && strcmp(av[1], "-verbose") == 0) {
- vflag = 1;
- ++av, --ac;
- }
- return 0;
-}
-#endif /* TEST */
+++ /dev/null
-#ifndef __helix_H
-#define __helix_H
-
-typedef unsigned long WORD;
-typedef unsigned char UCHAR;
-
-#define NONCE_LEN 16
-#define MAC_LEN 16
-
-/* HELIX variables */
-typedef struct helix_ctx {
-WORD h_iplus8[2]; /* block number maintained in two parts */
-WORD K[8]; /* expanded key */
-WORD N[8]; /* expanded nonce */
-int l_u; /* length of user key */
-WORD A, B, C, D, E; /* Z_0..Z_4 in the paper */
-} helix_ctx;
-
-#undef TEST
-
-void
-h_key(struct helix_ctx *ctx, unsigned char *U, int U_len);
-void
-h_nonce(struct helix_ctx *ctx, UCHAR nonce[16]);
-void
-h_encrypt(struct helix_ctx *ctx, UCHAR *buf, int n, UCHAR macbuf[16]);
-void
-h_decrypt(struct helix_ctx *ctx, UCHAR *buf, int n, UCHAR macbuf[16]);
-
-#endif
#include <netdb.h>
#include "irc_ipv6.h"
-#warning This source file is probably GPL'ed, it needs relicensing.
+#warning This source file is probably GPLed, it needs relicensing.
/*
* this new faster inet_ntoa was ripped from:
#ifndef __irc_ipv6_H
#define __irc_ipv6_H
+#include <limits.h>
+
/* from res.h */
/** Structure to store an IP address. */
"This product includes software developed by the University of Michigan, Merit"
"Network, Inc., and their contributors.";
-#include <malloc.h>
#include <assert.h> /* assert */
#include <ctype.h> /* isdigit */
#include <errno.h> /* errno */
node->prefix = patricia_ref_prefix (prefix);
node->parent = NULL;
node->l = node->r = NULL;
+ node->usercount = 0;
patricia->head = node;
patricia->num_active_node++;
return (node);
new_node->prefix = patricia_ref_prefix (prefix);
new_node->parent = NULL;
new_node->l = new_node->r = NULL;
+ new_node->usercount = 0;
patricia->num_active_node++;
if (node->bit == differ_bit) {
glue->bit = differ_bit;
glue->prefix = NULL;
glue->parent = node->parent;
+ glue->usercount = 0;
patricia->num_active_node++;
if (differ_bit < patricia->maxbits &&
(addr[differ_bit >> 3]) & (0x80 >> (differ_bit & 0x07))) {
--- /dev/null
+#define FULL_UNROLL
+
+#include "rijndael.h"
+
+typedef unsigned long u32;
+typedef unsigned char u8;
+
+static const u32 Te0[256] =
+{
+ 0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU,
+ 0xfff2f20dU, 0xd66b6bbdU, 0xde6f6fb1U, 0x91c5c554U,
+ 0x60303050U, 0x02010103U, 0xce6767a9U, 0x562b2b7dU,
+ 0xe7fefe19U, 0xb5d7d762U, 0x4dababe6U, 0xec76769aU,
+ 0x8fcaca45U, 0x1f82829dU, 0x89c9c940U, 0xfa7d7d87U,
+ 0xeffafa15U, 0xb25959ebU, 0x8e4747c9U, 0xfbf0f00bU,
+ 0x41adadecU, 0xb3d4d467U, 0x5fa2a2fdU, 0x45afafeaU,
+ 0x239c9cbfU, 0x53a4a4f7U, 0xe4727296U, 0x9bc0c05bU,
+ 0x75b7b7c2U, 0xe1fdfd1cU, 0x3d9393aeU, 0x4c26266aU,
+ 0x6c36365aU, 0x7e3f3f41U, 0xf5f7f702U, 0x83cccc4fU,
+ 0x6834345cU, 0x51a5a5f4U, 0xd1e5e534U, 0xf9f1f108U,
+ 0xe2717193U, 0xabd8d873U, 0x62313153U, 0x2a15153fU,
+ 0x0804040cU, 0x95c7c752U, 0x46232365U, 0x9dc3c35eU,
+ 0x30181828U, 0x379696a1U, 0x0a05050fU, 0x2f9a9ab5U,
+ 0x0e070709U, 0x24121236U, 0x1b80809bU, 0xdfe2e23dU,
+ 0xcdebeb26U, 0x4e272769U, 0x7fb2b2cdU, 0xea75759fU,
+ 0x1209091bU, 0x1d83839eU, 0x582c2c74U, 0x341a1a2eU,
+ 0x361b1b2dU, 0xdc6e6eb2U, 0xb45a5aeeU, 0x5ba0a0fbU,
+ 0xa45252f6U, 0x763b3b4dU, 0xb7d6d661U, 0x7db3b3ceU,
+ 0x5229297bU, 0xdde3e33eU, 0x5e2f2f71U, 0x13848497U,
+ 0xa65353f5U, 0xb9d1d168U, 0x00000000U, 0xc1eded2cU,
+ 0x40202060U, 0xe3fcfc1fU, 0x79b1b1c8U, 0xb65b5bedU,
+ 0xd46a6abeU, 0x8dcbcb46U, 0x67bebed9U, 0x7239394bU,
+ 0x944a4adeU, 0x984c4cd4U, 0xb05858e8U, 0x85cfcf4aU,
+ 0xbbd0d06bU, 0xc5efef2aU, 0x4faaaae5U, 0xedfbfb16U,
+ 0x864343c5U, 0x9a4d4dd7U, 0x66333355U, 0x11858594U,
+ 0x8a4545cfU, 0xe9f9f910U, 0x04020206U, 0xfe7f7f81U,
+ 0xa05050f0U, 0x783c3c44U, 0x259f9fbaU, 0x4ba8a8e3U,
+ 0xa25151f3U, 0x5da3a3feU, 0x804040c0U, 0x058f8f8aU,
+ 0x3f9292adU, 0x219d9dbcU, 0x70383848U, 0xf1f5f504U,
+ 0x63bcbcdfU, 0x77b6b6c1U, 0xafdada75U, 0x42212163U,
+ 0x20101030U, 0xe5ffff1aU, 0xfdf3f30eU, 0xbfd2d26dU,
+ 0x81cdcd4cU, 0x180c0c14U, 0x26131335U, 0xc3ecec2fU,
+ 0xbe5f5fe1U, 0x359797a2U, 0x884444ccU, 0x2e171739U,
+ 0x93c4c457U, 0x55a7a7f2U, 0xfc7e7e82U, 0x7a3d3d47U,
+ 0xc86464acU, 0xba5d5de7U, 0x3219192bU, 0xe6737395U,
+ 0xc06060a0U, 0x19818198U, 0x9e4f4fd1U, 0xa3dcdc7fU,
+ 0x44222266U, 0x542a2a7eU, 0x3b9090abU, 0x0b888883U,
+ 0x8c4646caU, 0xc7eeee29U, 0x6bb8b8d3U, 0x2814143cU,
+ 0xa7dede79U, 0xbc5e5ee2U, 0x160b0b1dU, 0xaddbdb76U,
+ 0xdbe0e03bU, 0x64323256U, 0x743a3a4eU, 0x140a0a1eU,
+ 0x924949dbU, 0x0c06060aU, 0x4824246cU, 0xb85c5ce4U,
+ 0x9fc2c25dU, 0xbdd3d36eU, 0x43acacefU, 0xc46262a6U,
+ 0x399191a8U, 0x319595a4U, 0xd3e4e437U, 0xf279798bU,
+ 0xd5e7e732U, 0x8bc8c843U, 0x6e373759U, 0xda6d6db7U,
+ 0x018d8d8cU, 0xb1d5d564U, 0x9c4e4ed2U, 0x49a9a9e0U,
+ 0xd86c6cb4U, 0xac5656faU, 0xf3f4f407U, 0xcfeaea25U,
+ 0xca6565afU, 0xf47a7a8eU, 0x47aeaee9U, 0x10080818U,
+ 0x6fbabad5U, 0xf0787888U, 0x4a25256fU, 0x5c2e2e72U,
+ 0x381c1c24U, 0x57a6a6f1U, 0x73b4b4c7U, 0x97c6c651U,
+ 0xcbe8e823U, 0xa1dddd7cU, 0xe874749cU, 0x3e1f1f21U,
+ 0x964b4bddU, 0x61bdbddcU, 0x0d8b8b86U, 0x0f8a8a85U,
+ 0xe0707090U, 0x7c3e3e42U, 0x71b5b5c4U, 0xcc6666aaU,
+ 0x904848d8U, 0x06030305U, 0xf7f6f601U, 0x1c0e0e12U,
+ 0xc26161a3U, 0x6a35355fU, 0xae5757f9U, 0x69b9b9d0U,
+ 0x17868691U, 0x99c1c158U, 0x3a1d1d27U, 0x279e9eb9U,
+ 0xd9e1e138U, 0xebf8f813U, 0x2b9898b3U, 0x22111133U,
+ 0xd26969bbU, 0xa9d9d970U, 0x078e8e89U, 0x339494a7U,
+ 0x2d9b9bb6U, 0x3c1e1e22U, 0x15878792U, 0xc9e9e920U,
+ 0x87cece49U, 0xaa5555ffU, 0x50282878U, 0xa5dfdf7aU,
+ 0x038c8c8fU, 0x59a1a1f8U, 0x09898980U, 0x1a0d0d17U,
+ 0x65bfbfdaU, 0xd7e6e631U, 0x844242c6U, 0xd06868b8U,
+ 0x824141c3U, 0x299999b0U, 0x5a2d2d77U, 0x1e0f0f11U,
+ 0x7bb0b0cbU, 0xa85454fcU, 0x6dbbbbd6U, 0x2c16163aU,
+};
+
+static const u32 Te1[256] =
+{
+ 0xa5c66363U, 0x84f87c7cU, 0x99ee7777U, 0x8df67b7bU,
+ 0x0dfff2f2U, 0xbdd66b6bU, 0xb1de6f6fU, 0x5491c5c5U,
+ 0x50603030U, 0x03020101U, 0xa9ce6767U, 0x7d562b2bU,
+ 0x19e7fefeU, 0x62b5d7d7U, 0xe64dababU, 0x9aec7676U,
+ 0x458fcacaU, 0x9d1f8282U, 0x4089c9c9U, 0x87fa7d7dU,
+ 0x15effafaU, 0xebb25959U, 0xc98e4747U, 0x0bfbf0f0U,
+ 0xec41adadU, 0x67b3d4d4U, 0xfd5fa2a2U, 0xea45afafU,
+ 0xbf239c9cU, 0xf753a4a4U, 0x96e47272U, 0x5b9bc0c0U,
+ 0xc275b7b7U, 0x1ce1fdfdU, 0xae3d9393U, 0x6a4c2626U,
+ 0x5a6c3636U, 0x417e3f3fU, 0x02f5f7f7U, 0x4f83ccccU,
+ 0x5c683434U, 0xf451a5a5U, 0x34d1e5e5U, 0x08f9f1f1U,
+ 0x93e27171U, 0x73abd8d8U, 0x53623131U, 0x3f2a1515U,
+ 0x0c080404U, 0x5295c7c7U, 0x65462323U, 0x5e9dc3c3U,
+ 0x28301818U, 0xa1379696U, 0x0f0a0505U, 0xb52f9a9aU,
+ 0x090e0707U, 0x36241212U, 0x9b1b8080U, 0x3ddfe2e2U,
+ 0x26cdebebU, 0x694e2727U, 0xcd7fb2b2U, 0x9fea7575U,
+ 0x1b120909U, 0x9e1d8383U, 0x74582c2cU, 0x2e341a1aU,
+ 0x2d361b1bU, 0xb2dc6e6eU, 0xeeb45a5aU, 0xfb5ba0a0U,
+ 0xf6a45252U, 0x4d763b3bU, 0x61b7d6d6U, 0xce7db3b3U,
+ 0x7b522929U, 0x3edde3e3U, 0x715e2f2fU, 0x97138484U,
+ 0xf5a65353U, 0x68b9d1d1U, 0x00000000U, 0x2cc1ededU,
+ 0x60402020U, 0x1fe3fcfcU, 0xc879b1b1U, 0xedb65b5bU,
+ 0xbed46a6aU, 0x468dcbcbU, 0xd967bebeU, 0x4b723939U,
+ 0xde944a4aU, 0xd4984c4cU, 0xe8b05858U, 0x4a85cfcfU,
+ 0x6bbbd0d0U, 0x2ac5efefU, 0xe54faaaaU, 0x16edfbfbU,
+ 0xc5864343U, 0xd79a4d4dU, 0x55663333U, 0x94118585U,
+ 0xcf8a4545U, 0x10e9f9f9U, 0x06040202U, 0x81fe7f7fU,
+ 0xf0a05050U, 0x44783c3cU, 0xba259f9fU, 0xe34ba8a8U,
+ 0xf3a25151U, 0xfe5da3a3U, 0xc0804040U, 0x8a058f8fU,
+ 0xad3f9292U, 0xbc219d9dU, 0x48703838U, 0x04f1f5f5U,
+ 0xdf63bcbcU, 0xc177b6b6U, 0x75afdadaU, 0x63422121U,
+ 0x30201010U, 0x1ae5ffffU, 0x0efdf3f3U, 0x6dbfd2d2U,
+ 0x4c81cdcdU, 0x14180c0cU, 0x35261313U, 0x2fc3ececU,
+ 0xe1be5f5fU, 0xa2359797U, 0xcc884444U, 0x392e1717U,
+ 0x5793c4c4U, 0xf255a7a7U, 0x82fc7e7eU, 0x477a3d3dU,
+ 0xacc86464U, 0xe7ba5d5dU, 0x2b321919U, 0x95e67373U,
+ 0xa0c06060U, 0x98198181U, 0xd19e4f4fU, 0x7fa3dcdcU,
+ 0x66442222U, 0x7e542a2aU, 0xab3b9090U, 0x830b8888U,
+ 0xca8c4646U, 0x29c7eeeeU, 0xd36bb8b8U, 0x3c281414U,
+ 0x79a7dedeU, 0xe2bc5e5eU, 0x1d160b0bU, 0x76addbdbU,
+ 0x3bdbe0e0U, 0x56643232U, 0x4e743a3aU, 0x1e140a0aU,
+ 0xdb924949U, 0x0a0c0606U, 0x6c482424U, 0xe4b85c5cU,
+ 0x5d9fc2c2U, 0x6ebdd3d3U, 0xef43acacU, 0xa6c46262U,
+ 0xa8399191U, 0xa4319595U, 0x37d3e4e4U, 0x8bf27979U,
+ 0x32d5e7e7U, 0x438bc8c8U, 0x596e3737U, 0xb7da6d6dU,
+ 0x8c018d8dU, 0x64b1d5d5U, 0xd29c4e4eU, 0xe049a9a9U,
+ 0xb4d86c6cU, 0xfaac5656U, 0x07f3f4f4U, 0x25cfeaeaU,
+ 0xafca6565U, 0x8ef47a7aU, 0xe947aeaeU, 0x18100808U,
+ 0xd56fbabaU, 0x88f07878U, 0x6f4a2525U, 0x725c2e2eU,
+ 0x24381c1cU, 0xf157a6a6U, 0xc773b4b4U, 0x5197c6c6U,
+ 0x23cbe8e8U, 0x7ca1ddddU, 0x9ce87474U, 0x213e1f1fU,
+ 0xdd964b4bU, 0xdc61bdbdU, 0x860d8b8bU, 0x850f8a8aU,
+ 0x90e07070U, 0x427c3e3eU, 0xc471b5b5U, 0xaacc6666U,
+ 0xd8904848U, 0x05060303U, 0x01f7f6f6U, 0x121c0e0eU,
+ 0xa3c26161U, 0x5f6a3535U, 0xf9ae5757U, 0xd069b9b9U,
+ 0x91178686U, 0x5899c1c1U, 0x273a1d1dU, 0xb9279e9eU,
+ 0x38d9e1e1U, 0x13ebf8f8U, 0xb32b9898U, 0x33221111U,
+ 0xbbd26969U, 0x70a9d9d9U, 0x89078e8eU, 0xa7339494U,
+ 0xb62d9b9bU, 0x223c1e1eU, 0x92158787U, 0x20c9e9e9U,
+ 0x4987ceceU, 0xffaa5555U, 0x78502828U, 0x7aa5dfdfU,
+ 0x8f038c8cU, 0xf859a1a1U, 0x80098989U, 0x171a0d0dU,
+ 0xda65bfbfU, 0x31d7e6e6U, 0xc6844242U, 0xb8d06868U,
+ 0xc3824141U, 0xb0299999U, 0x775a2d2dU, 0x111e0f0fU,
+ 0xcb7bb0b0U, 0xfca85454U, 0xd66dbbbbU, 0x3a2c1616U,
+};
+
+static const u32 Te2[256] =
+{
+ 0x63a5c663U, 0x7c84f87cU, 0x7799ee77U, 0x7b8df67bU,
+ 0xf20dfff2U, 0x6bbdd66bU, 0x6fb1de6fU, 0xc55491c5U,
+ 0x30506030U, 0x01030201U, 0x67a9ce67U, 0x2b7d562bU,
+ 0xfe19e7feU, 0xd762b5d7U, 0xabe64dabU, 0x769aec76U,
+ 0xca458fcaU, 0x829d1f82U, 0xc94089c9U, 0x7d87fa7dU,
+ 0xfa15effaU, 0x59ebb259U, 0x47c98e47U, 0xf00bfbf0U,
+ 0xadec41adU, 0xd467b3d4U, 0xa2fd5fa2U, 0xafea45afU,
+ 0x9cbf239cU, 0xa4f753a4U, 0x7296e472U, 0xc05b9bc0U,
+ 0xb7c275b7U, 0xfd1ce1fdU, 0x93ae3d93U, 0x266a4c26U,
+ 0x365a6c36U, 0x3f417e3fU, 0xf702f5f7U, 0xcc4f83ccU,
+ 0x345c6834U, 0xa5f451a5U, 0xe534d1e5U, 0xf108f9f1U,
+ 0x7193e271U, 0xd873abd8U, 0x31536231U, 0x153f2a15U,
+ 0x040c0804U, 0xc75295c7U, 0x23654623U, 0xc35e9dc3U,
+ 0x18283018U, 0x96a13796U, 0x050f0a05U, 0x9ab52f9aU,
+ 0x07090e07U, 0x12362412U, 0x809b1b80U, 0xe23ddfe2U,
+ 0xeb26cdebU, 0x27694e27U, 0xb2cd7fb2U, 0x759fea75U,
+ 0x091b1209U, 0x839e1d83U, 0x2c74582cU, 0x1a2e341aU,
+ 0x1b2d361bU, 0x6eb2dc6eU, 0x5aeeb45aU, 0xa0fb5ba0U,
+ 0x52f6a452U, 0x3b4d763bU, 0xd661b7d6U, 0xb3ce7db3U,
+ 0x297b5229U, 0xe33edde3U, 0x2f715e2fU, 0x84971384U,
+ 0x53f5a653U, 0xd168b9d1U, 0x00000000U, 0xed2cc1edU,
+ 0x20604020U, 0xfc1fe3fcU, 0xb1c879b1U, 0x5bedb65bU,
+ 0x6abed46aU, 0xcb468dcbU, 0xbed967beU, 0x394b7239U,
+ 0x4ade944aU, 0x4cd4984cU, 0x58e8b058U, 0xcf4a85cfU,
+ 0xd06bbbd0U, 0xef2ac5efU, 0xaae54faaU, 0xfb16edfbU,
+ 0x43c58643U, 0x4dd79a4dU, 0x33556633U, 0x85941185U,
+ 0x45cf8a45U, 0xf910e9f9U, 0x02060402U, 0x7f81fe7fU,
+ 0x50f0a050U, 0x3c44783cU, 0x9fba259fU, 0xa8e34ba8U,
+ 0x51f3a251U, 0xa3fe5da3U, 0x40c08040U, 0x8f8a058fU,
+ 0x92ad3f92U, 0x9dbc219dU, 0x38487038U, 0xf504f1f5U,
+ 0xbcdf63bcU, 0xb6c177b6U, 0xda75afdaU, 0x21634221U,
+ 0x10302010U, 0xff1ae5ffU, 0xf30efdf3U, 0xd26dbfd2U,
+ 0xcd4c81cdU, 0x0c14180cU, 0x13352613U, 0xec2fc3ecU,
+ 0x5fe1be5fU, 0x97a23597U, 0x44cc8844U, 0x17392e17U,
+ 0xc45793c4U, 0xa7f255a7U, 0x7e82fc7eU, 0x3d477a3dU,
+ 0x64acc864U, 0x5de7ba5dU, 0x192b3219U, 0x7395e673U,
+ 0x60a0c060U, 0x81981981U, 0x4fd19e4fU, 0xdc7fa3dcU,
+ 0x22664422U, 0x2a7e542aU, 0x90ab3b90U, 0x88830b88U,
+ 0x46ca8c46U, 0xee29c7eeU, 0xb8d36bb8U, 0x143c2814U,
+ 0xde79a7deU, 0x5ee2bc5eU, 0x0b1d160bU, 0xdb76addbU,
+ 0xe03bdbe0U, 0x32566432U, 0x3a4e743aU, 0x0a1e140aU,
+ 0x49db9249U, 0x060a0c06U, 0x246c4824U, 0x5ce4b85cU,
+ 0xc25d9fc2U, 0xd36ebdd3U, 0xacef43acU, 0x62a6c462U,
+ 0x91a83991U, 0x95a43195U, 0xe437d3e4U, 0x798bf279U,
+ 0xe732d5e7U, 0xc8438bc8U, 0x37596e37U, 0x6db7da6dU,
+ 0x8d8c018dU, 0xd564b1d5U, 0x4ed29c4eU, 0xa9e049a9U,
+ 0x6cb4d86cU, 0x56faac56U, 0xf407f3f4U, 0xea25cfeaU,
+ 0x65afca65U, 0x7a8ef47aU, 0xaee947aeU, 0x08181008U,
+ 0xbad56fbaU, 0x7888f078U, 0x256f4a25U, 0x2e725c2eU,
+ 0x1c24381cU, 0xa6f157a6U, 0xb4c773b4U, 0xc65197c6U,
+ 0xe823cbe8U, 0xdd7ca1ddU, 0x749ce874U, 0x1f213e1fU,
+ 0x4bdd964bU, 0xbddc61bdU, 0x8b860d8bU, 0x8a850f8aU,
+ 0x7090e070U, 0x3e427c3eU, 0xb5c471b5U, 0x66aacc66U,
+ 0x48d89048U, 0x03050603U, 0xf601f7f6U, 0x0e121c0eU,
+ 0x61a3c261U, 0x355f6a35U, 0x57f9ae57U, 0xb9d069b9U,
+ 0x86911786U, 0xc15899c1U, 0x1d273a1dU, 0x9eb9279eU,
+ 0xe138d9e1U, 0xf813ebf8U, 0x98b32b98U, 0x11332211U,
+ 0x69bbd269U, 0xd970a9d9U, 0x8e89078eU, 0x94a73394U,
+ 0x9bb62d9bU, 0x1e223c1eU, 0x87921587U, 0xe920c9e9U,
+ 0xce4987ceU, 0x55ffaa55U, 0x28785028U, 0xdf7aa5dfU,
+ 0x8c8f038cU, 0xa1f859a1U, 0x89800989U, 0x0d171a0dU,
+ 0xbfda65bfU, 0xe631d7e6U, 0x42c68442U, 0x68b8d068U,
+ 0x41c38241U, 0x99b02999U, 0x2d775a2dU, 0x0f111e0fU,
+ 0xb0cb7bb0U, 0x54fca854U, 0xbbd66dbbU, 0x163a2c16U,
+};
+
+static const u32 Te3[256] =
+{
+ 0x6363a5c6U, 0x7c7c84f8U, 0x777799eeU, 0x7b7b8df6U,
+ 0xf2f20dffU, 0x6b6bbdd6U, 0x6f6fb1deU, 0xc5c55491U,
+ 0x30305060U, 0x01010302U, 0x6767a9ceU, 0x2b2b7d56U,
+ 0xfefe19e7U, 0xd7d762b5U, 0xababe64dU, 0x76769aecU,
+ 0xcaca458fU, 0x82829d1fU, 0xc9c94089U, 0x7d7d87faU,
+ 0xfafa15efU, 0x5959ebb2U, 0x4747c98eU, 0xf0f00bfbU,
+ 0xadadec41U, 0xd4d467b3U, 0xa2a2fd5fU, 0xafafea45U,
+ 0x9c9cbf23U, 0xa4a4f753U, 0x727296e4U, 0xc0c05b9bU,
+ 0xb7b7c275U, 0xfdfd1ce1U, 0x9393ae3dU, 0x26266a4cU,
+ 0x36365a6cU, 0x3f3f417eU, 0xf7f702f5U, 0xcccc4f83U,
+ 0x34345c68U, 0xa5a5f451U, 0xe5e534d1U, 0xf1f108f9U,
+ 0x717193e2U, 0xd8d873abU, 0x31315362U, 0x15153f2aU,
+ 0x04040c08U, 0xc7c75295U, 0x23236546U, 0xc3c35e9dU,
+ 0x18182830U, 0x9696a137U, 0x05050f0aU, 0x9a9ab52fU,
+ 0x0707090eU, 0x12123624U, 0x80809b1bU, 0xe2e23ddfU,
+ 0xebeb26cdU, 0x2727694eU, 0xb2b2cd7fU, 0x75759feaU,
+ 0x09091b12U, 0x83839e1dU, 0x2c2c7458U, 0x1a1a2e34U,
+ 0x1b1b2d36U, 0x6e6eb2dcU, 0x5a5aeeb4U, 0xa0a0fb5bU,
+ 0x5252f6a4U, 0x3b3b4d76U, 0xd6d661b7U, 0xb3b3ce7dU,
+ 0x29297b52U, 0xe3e33eddU, 0x2f2f715eU, 0x84849713U,
+ 0x5353f5a6U, 0xd1d168b9U, 0x00000000U, 0xeded2cc1U,
+ 0x20206040U, 0xfcfc1fe3U, 0xb1b1c879U, 0x5b5bedb6U,
+ 0x6a6abed4U, 0xcbcb468dU, 0xbebed967U, 0x39394b72U,
+ 0x4a4ade94U, 0x4c4cd498U, 0x5858e8b0U, 0xcfcf4a85U,
+ 0xd0d06bbbU, 0xefef2ac5U, 0xaaaae54fU, 0xfbfb16edU,
+ 0x4343c586U, 0x4d4dd79aU, 0x33335566U, 0x85859411U,
+ 0x4545cf8aU, 0xf9f910e9U, 0x02020604U, 0x7f7f81feU,
+ 0x5050f0a0U, 0x3c3c4478U, 0x9f9fba25U, 0xa8a8e34bU,
+ 0x5151f3a2U, 0xa3a3fe5dU, 0x4040c080U, 0x8f8f8a05U,
+ 0x9292ad3fU, 0x9d9dbc21U, 0x38384870U, 0xf5f504f1U,
+ 0xbcbcdf63U, 0xb6b6c177U, 0xdada75afU, 0x21216342U,
+ 0x10103020U, 0xffff1ae5U, 0xf3f30efdU, 0xd2d26dbfU,
+ 0xcdcd4c81U, 0x0c0c1418U, 0x13133526U, 0xecec2fc3U,
+ 0x5f5fe1beU, 0x9797a235U, 0x4444cc88U, 0x1717392eU,
+ 0xc4c45793U, 0xa7a7f255U, 0x7e7e82fcU, 0x3d3d477aU,
+ 0x6464acc8U, 0x5d5de7baU, 0x19192b32U, 0x737395e6U,
+ 0x6060a0c0U, 0x81819819U, 0x4f4fd19eU, 0xdcdc7fa3U,
+ 0x22226644U, 0x2a2a7e54U, 0x9090ab3bU, 0x8888830bU,
+ 0x4646ca8cU, 0xeeee29c7U, 0xb8b8d36bU, 0x14143c28U,
+ 0xdede79a7U, 0x5e5ee2bcU, 0x0b0b1d16U, 0xdbdb76adU,
+ 0xe0e03bdbU, 0x32325664U, 0x3a3a4e74U, 0x0a0a1e14U,
+ 0x4949db92U, 0x06060a0cU, 0x24246c48U, 0x5c5ce4b8U,
+ 0xc2c25d9fU, 0xd3d36ebdU, 0xacacef43U, 0x6262a6c4U,
+ 0x9191a839U, 0x9595a431U, 0xe4e437d3U, 0x79798bf2U,
+ 0xe7e732d5U, 0xc8c8438bU, 0x3737596eU, 0x6d6db7daU,
+ 0x8d8d8c01U, 0xd5d564b1U, 0x4e4ed29cU, 0xa9a9e049U,
+ 0x6c6cb4d8U, 0x5656faacU, 0xf4f407f3U, 0xeaea25cfU,
+ 0x6565afcaU, 0x7a7a8ef4U, 0xaeaee947U, 0x08081810U,
+ 0xbabad56fU, 0x787888f0U, 0x25256f4aU, 0x2e2e725cU,
+ 0x1c1c2438U, 0xa6a6f157U, 0xb4b4c773U, 0xc6c65197U,
+ 0xe8e823cbU, 0xdddd7ca1U, 0x74749ce8U, 0x1f1f213eU,
+ 0x4b4bdd96U, 0xbdbddc61U, 0x8b8b860dU, 0x8a8a850fU,
+ 0x707090e0U, 0x3e3e427cU, 0xb5b5c471U, 0x6666aaccU,
+ 0x4848d890U, 0x03030506U, 0xf6f601f7U, 0x0e0e121cU,
+ 0x6161a3c2U, 0x35355f6aU, 0x5757f9aeU, 0xb9b9d069U,
+ 0x86869117U, 0xc1c15899U, 0x1d1d273aU, 0x9e9eb927U,
+ 0xe1e138d9U, 0xf8f813ebU, 0x9898b32bU, 0x11113322U,
+ 0x6969bbd2U, 0xd9d970a9U, 0x8e8e8907U, 0x9494a733U,
+ 0x9b9bb62dU, 0x1e1e223cU, 0x87879215U, 0xe9e920c9U,
+ 0xcece4987U, 0x5555ffaaU, 0x28287850U, 0xdfdf7aa5U,
+ 0x8c8c8f03U, 0xa1a1f859U, 0x89898009U, 0x0d0d171aU,
+ 0xbfbfda65U, 0xe6e631d7U, 0x4242c684U, 0x6868b8d0U,
+ 0x4141c382U, 0x9999b029U, 0x2d2d775aU, 0x0f0f111eU,
+ 0xb0b0cb7bU, 0x5454fca8U, 0xbbbbd66dU, 0x16163a2cU,
+};
+
+static const u32 Te4[256] =
+{
+ 0x63636363U, 0x7c7c7c7cU, 0x77777777U, 0x7b7b7b7bU,
+ 0xf2f2f2f2U, 0x6b6b6b6bU, 0x6f6f6f6fU, 0xc5c5c5c5U,
+ 0x30303030U, 0x01010101U, 0x67676767U, 0x2b2b2b2bU,
+ 0xfefefefeU, 0xd7d7d7d7U, 0xababababU, 0x76767676U,
+ 0xcacacacaU, 0x82828282U, 0xc9c9c9c9U, 0x7d7d7d7dU,
+ 0xfafafafaU, 0x59595959U, 0x47474747U, 0xf0f0f0f0U,
+ 0xadadadadU, 0xd4d4d4d4U, 0xa2a2a2a2U, 0xafafafafU,
+ 0x9c9c9c9cU, 0xa4a4a4a4U, 0x72727272U, 0xc0c0c0c0U,
+ 0xb7b7b7b7U, 0xfdfdfdfdU, 0x93939393U, 0x26262626U,
+ 0x36363636U, 0x3f3f3f3fU, 0xf7f7f7f7U, 0xccccccccU,
+ 0x34343434U, 0xa5a5a5a5U, 0xe5e5e5e5U, 0xf1f1f1f1U,
+ 0x71717171U, 0xd8d8d8d8U, 0x31313131U, 0x15151515U,
+ 0x04040404U, 0xc7c7c7c7U, 0x23232323U, 0xc3c3c3c3U,
+ 0x18181818U, 0x96969696U, 0x05050505U, 0x9a9a9a9aU,
+ 0x07070707U, 0x12121212U, 0x80808080U, 0xe2e2e2e2U,
+ 0xebebebebU, 0x27272727U, 0xb2b2b2b2U, 0x75757575U,
+ 0x09090909U, 0x83838383U, 0x2c2c2c2cU, 0x1a1a1a1aU,
+ 0x1b1b1b1bU, 0x6e6e6e6eU, 0x5a5a5a5aU, 0xa0a0a0a0U,
+ 0x52525252U, 0x3b3b3b3bU, 0xd6d6d6d6U, 0xb3b3b3b3U,
+ 0x29292929U, 0xe3e3e3e3U, 0x2f2f2f2fU, 0x84848484U,
+ 0x53535353U, 0xd1d1d1d1U, 0x00000000U, 0xededededU,
+ 0x20202020U, 0xfcfcfcfcU, 0xb1b1b1b1U, 0x5b5b5b5bU,
+ 0x6a6a6a6aU, 0xcbcbcbcbU, 0xbebebebeU, 0x39393939U,
+ 0x4a4a4a4aU, 0x4c4c4c4cU, 0x58585858U, 0xcfcfcfcfU,
+ 0xd0d0d0d0U, 0xefefefefU, 0xaaaaaaaaU, 0xfbfbfbfbU,
+ 0x43434343U, 0x4d4d4d4dU, 0x33333333U, 0x85858585U,
+ 0x45454545U, 0xf9f9f9f9U, 0x02020202U, 0x7f7f7f7fU,
+ 0x50505050U, 0x3c3c3c3cU, 0x9f9f9f9fU, 0xa8a8a8a8U,
+ 0x51515151U, 0xa3a3a3a3U, 0x40404040U, 0x8f8f8f8fU,
+ 0x92929292U, 0x9d9d9d9dU, 0x38383838U, 0xf5f5f5f5U,
+ 0xbcbcbcbcU, 0xb6b6b6b6U, 0xdadadadaU, 0x21212121U,
+ 0x10101010U, 0xffffffffU, 0xf3f3f3f3U, 0xd2d2d2d2U,
+ 0xcdcdcdcdU, 0x0c0c0c0cU, 0x13131313U, 0xececececU,
+ 0x5f5f5f5fU, 0x97979797U, 0x44444444U, 0x17171717U,
+ 0xc4c4c4c4U, 0xa7a7a7a7U, 0x7e7e7e7eU, 0x3d3d3d3dU,
+ 0x64646464U, 0x5d5d5d5dU, 0x19191919U, 0x73737373U,
+ 0x60606060U, 0x81818181U, 0x4f4f4f4fU, 0xdcdcdcdcU,
+ 0x22222222U, 0x2a2a2a2aU, 0x90909090U, 0x88888888U,
+ 0x46464646U, 0xeeeeeeeeU, 0xb8b8b8b8U, 0x14141414U,
+ 0xdedededeU, 0x5e5e5e5eU, 0x0b0b0b0bU, 0xdbdbdbdbU,
+ 0xe0e0e0e0U, 0x32323232U, 0x3a3a3a3aU, 0x0a0a0a0aU,
+ 0x49494949U, 0x06060606U, 0x24242424U, 0x5c5c5c5cU,
+ 0xc2c2c2c2U, 0xd3d3d3d3U, 0xacacacacU, 0x62626262U,
+ 0x91919191U, 0x95959595U, 0xe4e4e4e4U, 0x79797979U,
+ 0xe7e7e7e7U, 0xc8c8c8c8U, 0x37373737U, 0x6d6d6d6dU,
+ 0x8d8d8d8dU, 0xd5d5d5d5U, 0x4e4e4e4eU, 0xa9a9a9a9U,
+ 0x6c6c6c6cU, 0x56565656U, 0xf4f4f4f4U, 0xeaeaeaeaU,
+ 0x65656565U, 0x7a7a7a7aU, 0xaeaeaeaeU, 0x08080808U,
+ 0xbabababaU, 0x78787878U, 0x25252525U, 0x2e2e2e2eU,
+ 0x1c1c1c1cU, 0xa6a6a6a6U, 0xb4b4b4b4U, 0xc6c6c6c6U,
+ 0xe8e8e8e8U, 0xddddddddU, 0x74747474U, 0x1f1f1f1fU,
+ 0x4b4b4b4bU, 0xbdbdbdbdU, 0x8b8b8b8bU, 0x8a8a8a8aU,
+ 0x70707070U, 0x3e3e3e3eU, 0xb5b5b5b5U, 0x66666666U,
+ 0x48484848U, 0x03030303U, 0xf6f6f6f6U, 0x0e0e0e0eU,
+ 0x61616161U, 0x35353535U, 0x57575757U, 0xb9b9b9b9U,
+ 0x86868686U, 0xc1c1c1c1U, 0x1d1d1d1dU, 0x9e9e9e9eU,
+ 0xe1e1e1e1U, 0xf8f8f8f8U, 0x98989898U, 0x11111111U,
+ 0x69696969U, 0xd9d9d9d9U, 0x8e8e8e8eU, 0x94949494U,
+ 0x9b9b9b9bU, 0x1e1e1e1eU, 0x87878787U, 0xe9e9e9e9U,
+ 0xcecececeU, 0x55555555U, 0x28282828U, 0xdfdfdfdfU,
+ 0x8c8c8c8cU, 0xa1a1a1a1U, 0x89898989U, 0x0d0d0d0dU,
+ 0xbfbfbfbfU, 0xe6e6e6e6U, 0x42424242U, 0x68686868U,
+ 0x41414141U, 0x99999999U, 0x2d2d2d2dU, 0x0f0f0f0fU,
+ 0xb0b0b0b0U, 0x54545454U, 0xbbbbbbbbU, 0x16161616U,
+};
+
+static const u32 Td0[256] =
+{
+ 0x51f4a750U, 0x7e416553U, 0x1a17a4c3U, 0x3a275e96U,
+ 0x3bab6bcbU, 0x1f9d45f1U, 0xacfa58abU, 0x4be30393U,
+ 0x2030fa55U, 0xad766df6U, 0x88cc7691U, 0xf5024c25U,
+ 0x4fe5d7fcU, 0xc52acbd7U, 0x26354480U, 0xb562a38fU,
+ 0xdeb15a49U, 0x25ba1b67U, 0x45ea0e98U, 0x5dfec0e1U,
+ 0xc32f7502U, 0x814cf012U, 0x8d4697a3U, 0x6bd3f9c6U,
+ 0x038f5fe7U, 0x15929c95U, 0xbf6d7aebU, 0x955259daU,
+ 0xd4be832dU, 0x587421d3U, 0x49e06929U, 0x8ec9c844U,
+ 0x75c2896aU, 0xf48e7978U, 0x99583e6bU, 0x27b971ddU,
+ 0xbee14fb6U, 0xf088ad17U, 0xc920ac66U, 0x7dce3ab4U,
+ 0x63df4a18U, 0xe51a3182U, 0x97513360U, 0x62537f45U,
+ 0xb16477e0U, 0xbb6bae84U, 0xfe81a01cU, 0xf9082b94U,
+ 0x70486858U, 0x8f45fd19U, 0x94de6c87U, 0x527bf8b7U,
+ 0xab73d323U, 0x724b02e2U, 0xe31f8f57U, 0x6655ab2aU,
+ 0xb2eb2807U, 0x2fb5c203U, 0x86c57b9aU, 0xd33708a5U,
+ 0x302887f2U, 0x23bfa5b2U, 0x02036abaU, 0xed16825cU,
+ 0x8acf1c2bU, 0xa779b492U, 0xf307f2f0U, 0x4e69e2a1U,
+ 0x65daf4cdU, 0x0605bed5U, 0xd134621fU, 0xc4a6fe8aU,
+ 0x342e539dU, 0xa2f355a0U, 0x058ae132U, 0xa4f6eb75U,
+ 0x0b83ec39U, 0x4060efaaU, 0x5e719f06U, 0xbd6e1051U,
+ 0x3e218af9U, 0x96dd063dU, 0xdd3e05aeU, 0x4de6bd46U,
+ 0x91548db5U, 0x71c45d05U, 0x0406d46fU, 0x605015ffU,
+ 0x1998fb24U, 0xd6bde997U, 0x894043ccU, 0x67d99e77U,
+ 0xb0e842bdU, 0x07898b88U, 0xe7195b38U, 0x79c8eedbU,
+ 0xa17c0a47U, 0x7c420fe9U, 0xf8841ec9U, 0x00000000U,
+ 0x09808683U, 0x322bed48U, 0x1e1170acU, 0x6c5a724eU,
+ 0xfd0efffbU, 0x0f853856U, 0x3daed51eU, 0x362d3927U,
+ 0x0a0fd964U, 0x685ca621U, 0x9b5b54d1U, 0x24362e3aU,
+ 0x0c0a67b1U, 0x9357e70fU, 0xb4ee96d2U, 0x1b9b919eU,
+ 0x80c0c54fU, 0x61dc20a2U, 0x5a774b69U, 0x1c121a16U,
+ 0xe293ba0aU, 0xc0a02ae5U, 0x3c22e043U, 0x121b171dU,
+ 0x0e090d0bU, 0xf28bc7adU, 0x2db6a8b9U, 0x141ea9c8U,
+ 0x57f11985U, 0xaf75074cU, 0xee99ddbbU, 0xa37f60fdU,
+ 0xf701269fU, 0x5c72f5bcU, 0x44663bc5U, 0x5bfb7e34U,
+ 0x8b432976U, 0xcb23c6dcU, 0xb6edfc68U, 0xb8e4f163U,
+ 0xd731dccaU, 0x42638510U, 0x13972240U, 0x84c61120U,
+ 0x854a247dU, 0xd2bb3df8U, 0xaef93211U, 0xc729a16dU,
+ 0x1d9e2f4bU, 0xdcb230f3U, 0x0d8652ecU, 0x77c1e3d0U,
+ 0x2bb3166cU, 0xa970b999U, 0x119448faU, 0x47e96422U,
+ 0xa8fc8cc4U, 0xa0f03f1aU, 0x567d2cd8U, 0x223390efU,
+ 0x87494ec7U, 0xd938d1c1U, 0x8ccaa2feU, 0x98d40b36U,
+ 0xa6f581cfU, 0xa57ade28U, 0xdab78e26U, 0x3fadbfa4U,
+ 0x2c3a9de4U, 0x5078920dU, 0x6a5fcc9bU, 0x547e4662U,
+ 0xf68d13c2U, 0x90d8b8e8U, 0x2e39f75eU, 0x82c3aff5U,
+ 0x9f5d80beU, 0x69d0937cU, 0x6fd52da9U, 0xcf2512b3U,
+ 0xc8ac993bU, 0x10187da7U, 0xe89c636eU, 0xdb3bbb7bU,
+ 0xcd267809U, 0x6e5918f4U, 0xec9ab701U, 0x834f9aa8U,
+ 0xe6956e65U, 0xaaffe67eU, 0x21bccf08U, 0xef15e8e6U,
+ 0xbae79bd9U, 0x4a6f36ceU, 0xea9f09d4U, 0x29b07cd6U,
+ 0x31a4b2afU, 0x2a3f2331U, 0xc6a59430U, 0x35a266c0U,
+ 0x744ebc37U, 0xfc82caa6U, 0xe090d0b0U, 0x33a7d815U,
+ 0xf104984aU, 0x41ecdaf7U, 0x7fcd500eU, 0x1791f62fU,
+ 0x764dd68dU, 0x43efb04dU, 0xccaa4d54U, 0xe49604dfU,
+ 0x9ed1b5e3U, 0x4c6a881bU, 0xc12c1fb8U, 0x4665517fU,
+ 0x9d5eea04U, 0x018c355dU, 0xfa877473U, 0xfb0b412eU,
+ 0xb3671d5aU, 0x92dbd252U, 0xe9105633U, 0x6dd64713U,
+ 0x9ad7618cU, 0x37a10c7aU, 0x59f8148eU, 0xeb133c89U,
+ 0xcea927eeU, 0xb761c935U, 0xe11ce5edU, 0x7a47b13cU,
+ 0x9cd2df59U, 0x55f2733fU, 0x1814ce79U, 0x73c737bfU,
+ 0x53f7cdeaU, 0x5ffdaa5bU, 0xdf3d6f14U, 0x7844db86U,
+ 0xcaaff381U, 0xb968c43eU, 0x3824342cU, 0xc2a3405fU,
+ 0x161dc372U, 0xbce2250cU, 0x283c498bU, 0xff0d9541U,
+ 0x39a80171U, 0x080cb3deU, 0xd8b4e49cU, 0x6456c190U,
+ 0x7bcb8461U, 0xd532b670U, 0x486c5c74U, 0xd0b85742U,
+};
+
+static const u32 Td1[256] =
+{
+ 0x5051f4a7U, 0x537e4165U, 0xc31a17a4U, 0x963a275eU,
+ 0xcb3bab6bU, 0xf11f9d45U, 0xabacfa58U, 0x934be303U,
+ 0x552030faU, 0xf6ad766dU, 0x9188cc76U, 0x25f5024cU,
+ 0xfc4fe5d7U, 0xd7c52acbU, 0x80263544U, 0x8fb562a3U,
+ 0x49deb15aU, 0x6725ba1bU, 0x9845ea0eU, 0xe15dfec0U,
+ 0x02c32f75U, 0x12814cf0U, 0xa38d4697U, 0xc66bd3f9U,
+ 0xe7038f5fU, 0x9515929cU, 0xebbf6d7aU, 0xda955259U,
+ 0x2dd4be83U, 0xd3587421U, 0x2949e069U, 0x448ec9c8U,
+ 0x6a75c289U, 0x78f48e79U, 0x6b99583eU, 0xdd27b971U,
+ 0xb6bee14fU, 0x17f088adU, 0x66c920acU, 0xb47dce3aU,
+ 0x1863df4aU, 0x82e51a31U, 0x60975133U, 0x4562537fU,
+ 0xe0b16477U, 0x84bb6baeU, 0x1cfe81a0U, 0x94f9082bU,
+ 0x58704868U, 0x198f45fdU, 0x8794de6cU, 0xb7527bf8U,
+ 0x23ab73d3U, 0xe2724b02U, 0x57e31f8fU, 0x2a6655abU,
+ 0x07b2eb28U, 0x032fb5c2U, 0x9a86c57bU, 0xa5d33708U,
+ 0xf2302887U, 0xb223bfa5U, 0xba02036aU, 0x5ced1682U,
+ 0x2b8acf1cU, 0x92a779b4U, 0xf0f307f2U, 0xa14e69e2U,
+ 0xcd65daf4U, 0xd50605beU, 0x1fd13462U, 0x8ac4a6feU,
+ 0x9d342e53U, 0xa0a2f355U, 0x32058ae1U, 0x75a4f6ebU,
+ 0x390b83ecU, 0xaa4060efU, 0x065e719fU, 0x51bd6e10U,
+ 0xf93e218aU, 0x3d96dd06U, 0xaedd3e05U, 0x464de6bdU,
+ 0xb591548dU, 0x0571c45dU, 0x6f0406d4U, 0xff605015U,
+ 0x241998fbU, 0x97d6bde9U, 0xcc894043U, 0x7767d99eU,
+ 0xbdb0e842U, 0x8807898bU, 0x38e7195bU, 0xdb79c8eeU,
+ 0x47a17c0aU, 0xe97c420fU, 0xc9f8841eU, 0x00000000U,
+ 0x83098086U, 0x48322bedU, 0xac1e1170U, 0x4e6c5a72U,
+ 0xfbfd0effU, 0x560f8538U, 0x1e3daed5U, 0x27362d39U,
+ 0x640a0fd9U, 0x21685ca6U, 0xd19b5b54U, 0x3a24362eU,
+ 0xb10c0a67U, 0x0f9357e7U, 0xd2b4ee96U, 0x9e1b9b91U,
+ 0x4f80c0c5U, 0xa261dc20U, 0x695a774bU, 0x161c121aU,
+ 0x0ae293baU, 0xe5c0a02aU, 0x433c22e0U, 0x1d121b17U,
+ 0x0b0e090dU, 0xadf28bc7U, 0xb92db6a8U, 0xc8141ea9U,
+ 0x8557f119U, 0x4caf7507U, 0xbbee99ddU, 0xfda37f60U,
+ 0x9ff70126U, 0xbc5c72f5U, 0xc544663bU, 0x345bfb7eU,
+ 0x768b4329U, 0xdccb23c6U, 0x68b6edfcU, 0x63b8e4f1U,
+ 0xcad731dcU, 0x10426385U, 0x40139722U, 0x2084c611U,
+ 0x7d854a24U, 0xf8d2bb3dU, 0x11aef932U, 0x6dc729a1U,
+ 0x4b1d9e2fU, 0xf3dcb230U, 0xec0d8652U, 0xd077c1e3U,
+ 0x6c2bb316U, 0x99a970b9U, 0xfa119448U, 0x2247e964U,
+ 0xc4a8fc8cU, 0x1aa0f03fU, 0xd8567d2cU, 0xef223390U,
+ 0xc787494eU, 0xc1d938d1U, 0xfe8ccaa2U, 0x3698d40bU,
+ 0xcfa6f581U, 0x28a57adeU, 0x26dab78eU, 0xa43fadbfU,
+ 0xe42c3a9dU, 0x0d507892U, 0x9b6a5fccU, 0x62547e46U,
+ 0xc2f68d13U, 0xe890d8b8U, 0x5e2e39f7U, 0xf582c3afU,
+ 0xbe9f5d80U, 0x7c69d093U, 0xa96fd52dU, 0xb3cf2512U,
+ 0x3bc8ac99U, 0xa710187dU, 0x6ee89c63U, 0x7bdb3bbbU,
+ 0x09cd2678U, 0xf46e5918U, 0x01ec9ab7U, 0xa8834f9aU,
+ 0x65e6956eU, 0x7eaaffe6U, 0x0821bccfU, 0xe6ef15e8U,
+ 0xd9bae79bU, 0xce4a6f36U, 0xd4ea9f09U, 0xd629b07cU,
+ 0xaf31a4b2U, 0x312a3f23U, 0x30c6a594U, 0xc035a266U,
+ 0x37744ebcU, 0xa6fc82caU, 0xb0e090d0U, 0x1533a7d8U,
+ 0x4af10498U, 0xf741ecdaU, 0x0e7fcd50U, 0x2f1791f6U,
+ 0x8d764dd6U, 0x4d43efb0U, 0x54ccaa4dU, 0xdfe49604U,
+ 0xe39ed1b5U, 0x1b4c6a88U, 0xb8c12c1fU, 0x7f466551U,
+ 0x049d5eeaU, 0x5d018c35U, 0x73fa8774U, 0x2efb0b41U,
+ 0x5ab3671dU, 0x5292dbd2U, 0x33e91056U, 0x136dd647U,
+ 0x8c9ad761U, 0x7a37a10cU, 0x8e59f814U, 0x89eb133cU,
+ 0xeecea927U, 0x35b761c9U, 0xede11ce5U, 0x3c7a47b1U,
+ 0x599cd2dfU, 0x3f55f273U, 0x791814ceU, 0xbf73c737U,
+ 0xea53f7cdU, 0x5b5ffdaaU, 0x14df3d6fU, 0x867844dbU,
+ 0x81caaff3U, 0x3eb968c4U, 0x2c382434U, 0x5fc2a340U,
+ 0x72161dc3U, 0x0cbce225U, 0x8b283c49U, 0x41ff0d95U,
+ 0x7139a801U, 0xde080cb3U, 0x9cd8b4e4U, 0x906456c1U,
+ 0x617bcb84U, 0x70d532b6U, 0x74486c5cU, 0x42d0b857U,
+};
+
+static const u32 Td2[256] =
+{
+ 0xa75051f4U, 0x65537e41U, 0xa4c31a17U, 0x5e963a27U,
+ 0x6bcb3babU, 0x45f11f9dU, 0x58abacfaU, 0x03934be3U,
+ 0xfa552030U, 0x6df6ad76U, 0x769188ccU, 0x4c25f502U,
+ 0xd7fc4fe5U, 0xcbd7c52aU, 0x44802635U, 0xa38fb562U,
+ 0x5a49deb1U, 0x1b6725baU, 0x0e9845eaU, 0xc0e15dfeU,
+ 0x7502c32fU, 0xf012814cU, 0x97a38d46U, 0xf9c66bd3U,
+ 0x5fe7038fU, 0x9c951592U, 0x7aebbf6dU, 0x59da9552U,
+ 0x832dd4beU, 0x21d35874U, 0x692949e0U, 0xc8448ec9U,
+ 0x896a75c2U, 0x7978f48eU, 0x3e6b9958U, 0x71dd27b9U,
+ 0x4fb6bee1U, 0xad17f088U, 0xac66c920U, 0x3ab47dceU,
+ 0x4a1863dfU, 0x3182e51aU, 0x33609751U, 0x7f456253U,
+ 0x77e0b164U, 0xae84bb6bU, 0xa01cfe81U, 0x2b94f908U,
+ 0x68587048U, 0xfd198f45U, 0x6c8794deU, 0xf8b7527bU,
+ 0xd323ab73U, 0x02e2724bU, 0x8f57e31fU, 0xab2a6655U,
+ 0x2807b2ebU, 0xc2032fb5U, 0x7b9a86c5U, 0x08a5d337U,
+ 0x87f23028U, 0xa5b223bfU, 0x6aba0203U, 0x825ced16U,
+ 0x1c2b8acfU, 0xb492a779U, 0xf2f0f307U, 0xe2a14e69U,
+ 0xf4cd65daU, 0xbed50605U, 0x621fd134U, 0xfe8ac4a6U,
+ 0x539d342eU, 0x55a0a2f3U, 0xe132058aU, 0xeb75a4f6U,
+ 0xec390b83U, 0xefaa4060U, 0x9f065e71U, 0x1051bd6eU,
+ 0x8af93e21U, 0x063d96ddU, 0x05aedd3eU, 0xbd464de6U,
+ 0x8db59154U, 0x5d0571c4U, 0xd46f0406U, 0x15ff6050U,
+ 0xfb241998U, 0xe997d6bdU, 0x43cc8940U, 0x9e7767d9U,
+ 0x42bdb0e8U, 0x8b880789U, 0x5b38e719U, 0xeedb79c8U,
+ 0x0a47a17cU, 0x0fe97c42U, 0x1ec9f884U, 0x00000000U,
+ 0x86830980U, 0xed48322bU, 0x70ac1e11U, 0x724e6c5aU,
+ 0xfffbfd0eU, 0x38560f85U, 0xd51e3daeU, 0x3927362dU,
+ 0xd9640a0fU, 0xa621685cU, 0x54d19b5bU, 0x2e3a2436U,
+ 0x67b10c0aU, 0xe70f9357U, 0x96d2b4eeU, 0x919e1b9bU,
+ 0xc54f80c0U, 0x20a261dcU, 0x4b695a77U, 0x1a161c12U,
+ 0xba0ae293U, 0x2ae5c0a0U, 0xe0433c22U, 0x171d121bU,
+ 0x0d0b0e09U, 0xc7adf28bU, 0xa8b92db6U, 0xa9c8141eU,
+ 0x198557f1U, 0x074caf75U, 0xddbbee99U, 0x60fda37fU,
+ 0x269ff701U, 0xf5bc5c72U, 0x3bc54466U, 0x7e345bfbU,
+ 0x29768b43U, 0xc6dccb23U, 0xfc68b6edU, 0xf163b8e4U,
+ 0xdccad731U, 0x85104263U, 0x22401397U, 0x112084c6U,
+ 0x247d854aU, 0x3df8d2bbU, 0x3211aef9U, 0xa16dc729U,
+ 0x2f4b1d9eU, 0x30f3dcb2U, 0x52ec0d86U, 0xe3d077c1U,
+ 0x166c2bb3U, 0xb999a970U, 0x48fa1194U, 0x642247e9U,
+ 0x8cc4a8fcU, 0x3f1aa0f0U, 0x2cd8567dU, 0x90ef2233U,
+ 0x4ec78749U, 0xd1c1d938U, 0xa2fe8ccaU, 0x0b3698d4U,
+ 0x81cfa6f5U, 0xde28a57aU, 0x8e26dab7U, 0xbfa43fadU,
+ 0x9de42c3aU, 0x920d5078U, 0xcc9b6a5fU, 0x4662547eU,
+ 0x13c2f68dU, 0xb8e890d8U, 0xf75e2e39U, 0xaff582c3U,
+ 0x80be9f5dU, 0x937c69d0U, 0x2da96fd5U, 0x12b3cf25U,
+ 0x993bc8acU, 0x7da71018U, 0x636ee89cU, 0xbb7bdb3bU,
+ 0x7809cd26U, 0x18f46e59U, 0xb701ec9aU, 0x9aa8834fU,
+ 0x6e65e695U, 0xe67eaaffU, 0xcf0821bcU, 0xe8e6ef15U,
+ 0x9bd9bae7U, 0x36ce4a6fU, 0x09d4ea9fU, 0x7cd629b0U,
+ 0xb2af31a4U, 0x23312a3fU, 0x9430c6a5U, 0x66c035a2U,
+ 0xbc37744eU, 0xcaa6fc82U, 0xd0b0e090U, 0xd81533a7U,
+ 0x984af104U, 0xdaf741ecU, 0x500e7fcdU, 0xf62f1791U,
+ 0xd68d764dU, 0xb04d43efU, 0x4d54ccaaU, 0x04dfe496U,
+ 0xb5e39ed1U, 0x881b4c6aU, 0x1fb8c12cU, 0x517f4665U,
+ 0xea049d5eU, 0x355d018cU, 0x7473fa87U, 0x412efb0bU,
+ 0x1d5ab367U, 0xd25292dbU, 0x5633e910U, 0x47136dd6U,
+ 0x618c9ad7U, 0x0c7a37a1U, 0x148e59f8U, 0x3c89eb13U,
+ 0x27eecea9U, 0xc935b761U, 0xe5ede11cU, 0xb13c7a47U,
+ 0xdf599cd2U, 0x733f55f2U, 0xce791814U, 0x37bf73c7U,
+ 0xcdea53f7U, 0xaa5b5ffdU, 0x6f14df3dU, 0xdb867844U,
+ 0xf381caafU, 0xc43eb968U, 0x342c3824U, 0x405fc2a3U,
+ 0xc372161dU, 0x250cbce2U, 0x498b283cU, 0x9541ff0dU,
+ 0x017139a8U, 0xb3de080cU, 0xe49cd8b4U, 0xc1906456U,
+ 0x84617bcbU, 0xb670d532U, 0x5c74486cU, 0x5742d0b8U,
+};
+
+static const u32 Td3[256] =
+{
+ 0xf4a75051U, 0x4165537eU, 0x17a4c31aU, 0x275e963aU,
+ 0xab6bcb3bU, 0x9d45f11fU, 0xfa58abacU, 0xe303934bU,
+ 0x30fa5520U, 0x766df6adU, 0xcc769188U, 0x024c25f5U,
+ 0xe5d7fc4fU, 0x2acbd7c5U, 0x35448026U, 0x62a38fb5U,
+ 0xb15a49deU, 0xba1b6725U, 0xea0e9845U, 0xfec0e15dU,
+ 0x2f7502c3U, 0x4cf01281U, 0x4697a38dU, 0xd3f9c66bU,
+ 0x8f5fe703U, 0x929c9515U, 0x6d7aebbfU, 0x5259da95U,
+ 0xbe832dd4U, 0x7421d358U, 0xe0692949U, 0xc9c8448eU,
+ 0xc2896a75U, 0x8e7978f4U, 0x583e6b99U, 0xb971dd27U,
+ 0xe14fb6beU, 0x88ad17f0U, 0x20ac66c9U, 0xce3ab47dU,
+ 0xdf4a1863U, 0x1a3182e5U, 0x51336097U, 0x537f4562U,
+ 0x6477e0b1U, 0x6bae84bbU, 0x81a01cfeU, 0x082b94f9U,
+ 0x48685870U, 0x45fd198fU, 0xde6c8794U, 0x7bf8b752U,
+ 0x73d323abU, 0x4b02e272U, 0x1f8f57e3U, 0x55ab2a66U,
+ 0xeb2807b2U, 0xb5c2032fU, 0xc57b9a86U, 0x3708a5d3U,
+ 0x2887f230U, 0xbfa5b223U, 0x036aba02U, 0x16825cedU,
+ 0xcf1c2b8aU, 0x79b492a7U, 0x07f2f0f3U, 0x69e2a14eU,
+ 0xdaf4cd65U, 0x05bed506U, 0x34621fd1U, 0xa6fe8ac4U,
+ 0x2e539d34U, 0xf355a0a2U, 0x8ae13205U, 0xf6eb75a4U,
+ 0x83ec390bU, 0x60efaa40U, 0x719f065eU, 0x6e1051bdU,
+ 0x218af93eU, 0xdd063d96U, 0x3e05aeddU, 0xe6bd464dU,
+ 0x548db591U, 0xc45d0571U, 0x06d46f04U, 0x5015ff60U,
+ 0x98fb2419U, 0xbde997d6U, 0x4043cc89U, 0xd99e7767U,
+ 0xe842bdb0U, 0x898b8807U, 0x195b38e7U, 0xc8eedb79U,
+ 0x7c0a47a1U, 0x420fe97cU, 0x841ec9f8U, 0x00000000U,
+ 0x80868309U, 0x2bed4832U, 0x1170ac1eU, 0x5a724e6cU,
+ 0x0efffbfdU, 0x8538560fU, 0xaed51e3dU, 0x2d392736U,
+ 0x0fd9640aU, 0x5ca62168U, 0x5b54d19bU, 0x362e3a24U,
+ 0x0a67b10cU, 0x57e70f93U, 0xee96d2b4U, 0x9b919e1bU,
+ 0xc0c54f80U, 0xdc20a261U, 0x774b695aU, 0x121a161cU,
+ 0x93ba0ae2U, 0xa02ae5c0U, 0x22e0433cU, 0x1b171d12U,
+ 0x090d0b0eU, 0x8bc7adf2U, 0xb6a8b92dU, 0x1ea9c814U,
+ 0xf1198557U, 0x75074cafU, 0x99ddbbeeU, 0x7f60fda3U,
+ 0x01269ff7U, 0x72f5bc5cU, 0x663bc544U, 0xfb7e345bU,
+ 0x4329768bU, 0x23c6dccbU, 0xedfc68b6U, 0xe4f163b8U,
+ 0x31dccad7U, 0x63851042U, 0x97224013U, 0xc6112084U,
+ 0x4a247d85U, 0xbb3df8d2U, 0xf93211aeU, 0x29a16dc7U,
+ 0x9e2f4b1dU, 0xb230f3dcU, 0x8652ec0dU, 0xc1e3d077U,
+ 0xb3166c2bU, 0x70b999a9U, 0x9448fa11U, 0xe9642247U,
+ 0xfc8cc4a8U, 0xf03f1aa0U, 0x7d2cd856U, 0x3390ef22U,
+ 0x494ec787U, 0x38d1c1d9U, 0xcaa2fe8cU, 0xd40b3698U,
+ 0xf581cfa6U, 0x7ade28a5U, 0xb78e26daU, 0xadbfa43fU,
+ 0x3a9de42cU, 0x78920d50U, 0x5fcc9b6aU, 0x7e466254U,
+ 0x8d13c2f6U, 0xd8b8e890U, 0x39f75e2eU, 0xc3aff582U,
+ 0x5d80be9fU, 0xd0937c69U, 0xd52da96fU, 0x2512b3cfU,
+ 0xac993bc8U, 0x187da710U, 0x9c636ee8U, 0x3bbb7bdbU,
+ 0x267809cdU, 0x5918f46eU, 0x9ab701ecU, 0x4f9aa883U,
+ 0x956e65e6U, 0xffe67eaaU, 0xbccf0821U, 0x15e8e6efU,
+ 0xe79bd9baU, 0x6f36ce4aU, 0x9f09d4eaU, 0xb07cd629U,
+ 0xa4b2af31U, 0x3f23312aU, 0xa59430c6U, 0xa266c035U,
+ 0x4ebc3774U, 0x82caa6fcU, 0x90d0b0e0U, 0xa7d81533U,
+ 0x04984af1U, 0xecdaf741U, 0xcd500e7fU, 0x91f62f17U,
+ 0x4dd68d76U, 0xefb04d43U, 0xaa4d54ccU, 0x9604dfe4U,
+ 0xd1b5e39eU, 0x6a881b4cU, 0x2c1fb8c1U, 0x65517f46U,
+ 0x5eea049dU, 0x8c355d01U, 0x877473faU, 0x0b412efbU,
+ 0x671d5ab3U, 0xdbd25292U, 0x105633e9U, 0xd647136dU,
+ 0xd7618c9aU, 0xa10c7a37U, 0xf8148e59U, 0x133c89ebU,
+ 0xa927eeceU, 0x61c935b7U, 0x1ce5ede1U, 0x47b13c7aU,
+ 0xd2df599cU, 0xf2733f55U, 0x14ce7918U, 0xc737bf73U,
+ 0xf7cdea53U, 0xfdaa5b5fU, 0x3d6f14dfU, 0x44db8678U,
+ 0xaff381caU, 0x68c43eb9U, 0x24342c38U, 0xa3405fc2U,
+ 0x1dc37216U, 0xe2250cbcU, 0x3c498b28U, 0x0d9541ffU,
+ 0xa8017139U, 0x0cb3de08U, 0xb4e49cd8U, 0x56c19064U,
+ 0xcb84617bU, 0x32b670d5U, 0x6c5c7448U, 0xb85742d0U,
+};
+
+static const u32 Td4[256] =
+{
+ 0x52525252U, 0x09090909U, 0x6a6a6a6aU, 0xd5d5d5d5U,
+ 0x30303030U, 0x36363636U, 0xa5a5a5a5U, 0x38383838U,
+ 0xbfbfbfbfU, 0x40404040U, 0xa3a3a3a3U, 0x9e9e9e9eU,
+ 0x81818181U, 0xf3f3f3f3U, 0xd7d7d7d7U, 0xfbfbfbfbU,
+ 0x7c7c7c7cU, 0xe3e3e3e3U, 0x39393939U, 0x82828282U,
+ 0x9b9b9b9bU, 0x2f2f2f2fU, 0xffffffffU, 0x87878787U,
+ 0x34343434U, 0x8e8e8e8eU, 0x43434343U, 0x44444444U,
+ 0xc4c4c4c4U, 0xdedededeU, 0xe9e9e9e9U, 0xcbcbcbcbU,
+ 0x54545454U, 0x7b7b7b7bU, 0x94949494U, 0x32323232U,
+ 0xa6a6a6a6U, 0xc2c2c2c2U, 0x23232323U, 0x3d3d3d3dU,
+ 0xeeeeeeeeU, 0x4c4c4c4cU, 0x95959595U, 0x0b0b0b0bU,
+ 0x42424242U, 0xfafafafaU, 0xc3c3c3c3U, 0x4e4e4e4eU,
+ 0x08080808U, 0x2e2e2e2eU, 0xa1a1a1a1U, 0x66666666U,
+ 0x28282828U, 0xd9d9d9d9U, 0x24242424U, 0xb2b2b2b2U,
+ 0x76767676U, 0x5b5b5b5bU, 0xa2a2a2a2U, 0x49494949U,
+ 0x6d6d6d6dU, 0x8b8b8b8bU, 0xd1d1d1d1U, 0x25252525U,
+ 0x72727272U, 0xf8f8f8f8U, 0xf6f6f6f6U, 0x64646464U,
+ 0x86868686U, 0x68686868U, 0x98989898U, 0x16161616U,
+ 0xd4d4d4d4U, 0xa4a4a4a4U, 0x5c5c5c5cU, 0xccccccccU,
+ 0x5d5d5d5dU, 0x65656565U, 0xb6b6b6b6U, 0x92929292U,
+ 0x6c6c6c6cU, 0x70707070U, 0x48484848U, 0x50505050U,
+ 0xfdfdfdfdU, 0xededededU, 0xb9b9b9b9U, 0xdadadadaU,
+ 0x5e5e5e5eU, 0x15151515U, 0x46464646U, 0x57575757U,
+ 0xa7a7a7a7U, 0x8d8d8d8dU, 0x9d9d9d9dU, 0x84848484U,
+ 0x90909090U, 0xd8d8d8d8U, 0xababababU, 0x00000000U,
+ 0x8c8c8c8cU, 0xbcbcbcbcU, 0xd3d3d3d3U, 0x0a0a0a0aU,
+ 0xf7f7f7f7U, 0xe4e4e4e4U, 0x58585858U, 0x05050505U,
+ 0xb8b8b8b8U, 0xb3b3b3b3U, 0x45454545U, 0x06060606U,
+ 0xd0d0d0d0U, 0x2c2c2c2cU, 0x1e1e1e1eU, 0x8f8f8f8fU,
+ 0xcacacacaU, 0x3f3f3f3fU, 0x0f0f0f0fU, 0x02020202U,
+ 0xc1c1c1c1U, 0xafafafafU, 0xbdbdbdbdU, 0x03030303U,
+ 0x01010101U, 0x13131313U, 0x8a8a8a8aU, 0x6b6b6b6bU,
+ 0x3a3a3a3aU, 0x91919191U, 0x11111111U, 0x41414141U,
+ 0x4f4f4f4fU, 0x67676767U, 0xdcdcdcdcU, 0xeaeaeaeaU,
+ 0x97979797U, 0xf2f2f2f2U, 0xcfcfcfcfU, 0xcecececeU,
+ 0xf0f0f0f0U, 0xb4b4b4b4U, 0xe6e6e6e6U, 0x73737373U,
+ 0x96969696U, 0xacacacacU, 0x74747474U, 0x22222222U,
+ 0xe7e7e7e7U, 0xadadadadU, 0x35353535U, 0x85858585U,
+ 0xe2e2e2e2U, 0xf9f9f9f9U, 0x37373737U, 0xe8e8e8e8U,
+ 0x1c1c1c1cU, 0x75757575U, 0xdfdfdfdfU, 0x6e6e6e6eU,
+ 0x47474747U, 0xf1f1f1f1U, 0x1a1a1a1aU, 0x71717171U,
+ 0x1d1d1d1dU, 0x29292929U, 0xc5c5c5c5U, 0x89898989U,
+ 0x6f6f6f6fU, 0xb7b7b7b7U, 0x62626262U, 0x0e0e0e0eU,
+ 0xaaaaaaaaU, 0x18181818U, 0xbebebebeU, 0x1b1b1b1bU,
+ 0xfcfcfcfcU, 0x56565656U, 0x3e3e3e3eU, 0x4b4b4b4bU,
+ 0xc6c6c6c6U, 0xd2d2d2d2U, 0x79797979U, 0x20202020U,
+ 0x9a9a9a9aU, 0xdbdbdbdbU, 0xc0c0c0c0U, 0xfefefefeU,
+ 0x78787878U, 0xcdcdcdcdU, 0x5a5a5a5aU, 0xf4f4f4f4U,
+ 0x1f1f1f1fU, 0xddddddddU, 0xa8a8a8a8U, 0x33333333U,
+ 0x88888888U, 0x07070707U, 0xc7c7c7c7U, 0x31313131U,
+ 0xb1b1b1b1U, 0x12121212U, 0x10101010U, 0x59595959U,
+ 0x27272727U, 0x80808080U, 0xececececU, 0x5f5f5f5fU,
+ 0x60606060U, 0x51515151U, 0x7f7f7f7fU, 0xa9a9a9a9U,
+ 0x19191919U, 0xb5b5b5b5U, 0x4a4a4a4aU, 0x0d0d0d0dU,
+ 0x2d2d2d2dU, 0xe5e5e5e5U, 0x7a7a7a7aU, 0x9f9f9f9fU,
+ 0x93939393U, 0xc9c9c9c9U, 0x9c9c9c9cU, 0xefefefefU,
+ 0xa0a0a0a0U, 0xe0e0e0e0U, 0x3b3b3b3bU, 0x4d4d4d4dU,
+ 0xaeaeaeaeU, 0x2a2a2a2aU, 0xf5f5f5f5U, 0xb0b0b0b0U,
+ 0xc8c8c8c8U, 0xebebebebU, 0xbbbbbbbbU, 0x3c3c3c3cU,
+ 0x83838383U, 0x53535353U, 0x99999999U, 0x61616161U,
+ 0x17171717U, 0x2b2b2b2bU, 0x04040404U, 0x7e7e7e7eU,
+ 0xbabababaU, 0x77777777U, 0xd6d6d6d6U, 0x26262626U,
+ 0xe1e1e1e1U, 0x69696969U, 0x14141414U, 0x63636363U,
+ 0x55555555U, 0x21212121U, 0x0c0c0c0cU, 0x7d7d7d7dU,
+};
+
+static const u32 rcon[] =
+{
+ 0x01000000, 0x02000000, 0x04000000, 0x08000000,
+ 0x10000000, 0x20000000, 0x40000000, 0x80000000,
+ 0x1B000000, 0x36000000,
+ /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */
+};
+
+#define GETU32(plaintext) (((u32)(plaintext)[0] << 24) ^ \
+ ((u32)(plaintext)[1] << 16) ^ \
+ ((u32)(plaintext)[2] << 8) ^ \
+ ((u32)(plaintext)[3]))
+
+#define PUTU32(ciphertext, st) { (ciphertext)[0] = (u8)((st) >> 24); \
+ (ciphertext)[1] = (u8)((st) >> 16); \
+ (ciphertext)[2] = (u8)((st) >> 8); \
+ (ciphertext)[3] = (u8)(st); }
+
+/**
+ * Expand the cipher key into the encryption key schedule.
+ *
+ * @return the number of rounds for the given cipher key size.
+ */
+int rijndaelSetupEncrypt(u32 *rk, const u8 *key, int keybits)
+{
+ int i = 0;
+ u32 temp;
+
+ rk[0] = GETU32(key );
+ rk[1] = GETU32(key + 4);
+ rk[2] = GETU32(key + 8);
+ rk[3] = GETU32(key + 12);
+ if (keybits == 128)
+ {
+ for (;;)
+ {
+ temp = rk[3];
+ rk[4] = rk[0] ^
+ (Te4[(temp >> 16) & 0xff] & 0xff000000) ^
+ (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^
+ (Te4[(temp ) & 0xff] & 0x0000ff00) ^
+ (Te4[(temp >> 24) ] & 0x000000ff) ^
+ rcon[i];
+ rk[5] = rk[1] ^ rk[4];
+ rk[6] = rk[2] ^ rk[5];
+ rk[7] = rk[3] ^ rk[6];
+ if (++i == 10)
+ return 10;
+ rk += 4;
+ }
+ }
+ rk[4] = GETU32(key + 16);
+ rk[5] = GETU32(key + 20);
+ if (keybits == 192)
+ {
+ for (;;)
+ {
+ temp = rk[ 5];
+ rk[ 6] = rk[ 0] ^
+ (Te4[(temp >> 16) & 0xff] & 0xff000000) ^
+ (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^
+ (Te4[(temp ) & 0xff] & 0x0000ff00) ^
+ (Te4[(temp >> 24) ] & 0x000000ff) ^
+ rcon[i];
+ rk[ 7] = rk[ 1] ^ rk[ 6];
+ rk[ 8] = rk[ 2] ^ rk[ 7];
+ rk[ 9] = rk[ 3] ^ rk[ 8];
+ if (++i == 8)
+ return 12;
+ rk[10] = rk[ 4] ^ rk[ 9];
+ rk[11] = rk[ 5] ^ rk[10];
+ rk += 6;
+ }
+ }
+ rk[6] = GETU32(key + 24);
+ rk[7] = GETU32(key + 28);
+ if (keybits == 256)
+ {
+ for (;;)
+ {
+ temp = rk[ 7];
+ rk[ 8] = rk[ 0] ^
+ (Te4[(temp >> 16) & 0xff] & 0xff000000) ^
+ (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^
+ (Te4[(temp ) & 0xff] & 0x0000ff00) ^
+ (Te4[(temp >> 24) ] & 0x000000ff) ^
+ rcon[i];
+ rk[ 9] = rk[ 1] ^ rk[ 8];
+ rk[10] = rk[ 2] ^ rk[ 9];
+ rk[11] = rk[ 3] ^ rk[10];
+ if (++i == 7)
+ return 14;
+ temp = rk[11];
+ rk[12] = rk[ 4] ^
+ (Te4[(temp >> 24) ] & 0xff000000) ^
+ (Te4[(temp >> 16) & 0xff] & 0x00ff0000) ^
+ (Te4[(temp >> 8) & 0xff] & 0x0000ff00) ^
+ (Te4[(temp ) & 0xff] & 0x000000ff);
+ rk[13] = rk[ 5] ^ rk[12];
+ rk[14] = rk[ 6] ^ rk[13];
+ rk[15] = rk[ 7] ^ rk[14];
+ rk += 8;
+ }
+ }
+ return 0;
+}
+
+/**
+ * Expand the cipher key into the decryption key schedule.
+ *
+ * @return the number of rounds for the given cipher key size.
+ */
+int rijndaelSetupDecrypt(u32 *rk, const u8 *key, int keybits)
+{
+ int nrounds, i, j;
+ u32 temp;
+
+ /* expand the cipher key: */
+ nrounds = rijndaelSetupEncrypt(rk, key, keybits);
+ /* invert the order of the round keys: */
+ for (i = 0, j = 4*nrounds; i < j; i += 4, j -= 4)
+ {
+ temp = rk[i ]; rk[i ] = rk[j ]; rk[j ] = temp;
+ temp = rk[i + 1]; rk[i + 1] = rk[j + 1]; rk[j + 1] = temp;
+ temp = rk[i + 2]; rk[i + 2] = rk[j + 2]; rk[j + 2] = temp;
+ temp = rk[i + 3]; rk[i + 3] = rk[j + 3]; rk[j + 3] = temp;
+ }
+ /* apply the inverse MixColumn transform to all round keys but the first and the last: */
+ for (i = 1; i < nrounds; i++)
+ {
+ rk += 4;
+ rk[0] =
+ Td0[Te4[(rk[0] >> 24) ] & 0xff] ^
+ Td1[Te4[(rk[0] >> 16) & 0xff] & 0xff] ^
+ Td2[Te4[(rk[0] >> 8) & 0xff] & 0xff] ^
+ Td3[Te4[(rk[0] ) & 0xff] & 0xff];
+ rk[1] =
+ Td0[Te4[(rk[1] >> 24) ] & 0xff] ^
+ Td1[Te4[(rk[1] >> 16) & 0xff] & 0xff] ^
+ Td2[Te4[(rk[1] >> 8) & 0xff] & 0xff] ^
+ Td3[Te4[(rk[1] ) & 0xff] & 0xff];
+ rk[2] =
+ Td0[Te4[(rk[2] >> 24) ] & 0xff] ^
+ Td1[Te4[(rk[2] >> 16) & 0xff] & 0xff] ^
+ Td2[Te4[(rk[2] >> 8) & 0xff] & 0xff] ^
+ Td3[Te4[(rk[2] ) & 0xff] & 0xff];
+ rk[3] =
+ Td0[Te4[(rk[3] >> 24) ] & 0xff] ^
+ Td1[Te4[(rk[3] >> 16) & 0xff] & 0xff] ^
+ Td2[Te4[(rk[3] >> 8) & 0xff] & 0xff] ^
+ Td3[Te4[(rk[3] ) & 0xff] & 0xff];
+ }
+ return nrounds;
+}
+
+void rijndaelEncrypt(const u32 *rk, int nrounds, const u8 plaintext[16],
+ u8 ciphertext[16])
+{
+ u32 s0, s1, s2, s3, t0, t1, t2, t3;
+ #ifndef FULL_UNROLL
+ int r;
+ #endif /* ?FULL_UNROLL */
+ /*
+ * map byte array block to cipher state
+ * and add initial round key:
+ */
+ s0 = GETU32(plaintext ) ^ rk[0];
+ s1 = GETU32(plaintext + 4) ^ rk[1];
+ s2 = GETU32(plaintext + 8) ^ rk[2];
+ s3 = GETU32(plaintext + 12) ^ rk[3];
+ #ifdef FULL_UNROLL
+ /* round 1: */
+ t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[ 4];
+ t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[ 5];
+ t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[ 6];
+ t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[ 7];
+ /* round 2: */
+ s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[ 8];
+ s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[ 9];
+ s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[10];
+ s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[11];
+ /* round 3: */
+ t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[12];
+ t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[13];
+ t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[14];
+ t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[15];
+ /* round 4: */
+ s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[16];
+ s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[17];
+ s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[18];
+ s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[19];
+ /* round 5: */
+ t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[20];
+ t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[21];
+ t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[22];
+ t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[23];
+ /* round 6: */
+ s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[24];
+ s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[25];
+ s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[26];
+ s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[27];
+ /* round 7: */
+ t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[28];
+ t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[29];
+ t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[30];
+ t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[31];
+ /* round 8: */
+ s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[32];
+ s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[33];
+ s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[34];
+ s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[35];
+ /* round 9: */
+ t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[36];
+ t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[37];
+ t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[38];
+ t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[39];
+ if (nrounds > 10)
+ {
+ /* round 10: */
+ s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[40];
+ s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[41];
+ s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[42];
+ s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[43];
+ /* round 11: */
+ t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[44];
+ t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[45];
+ t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[46];
+ t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[47];
+ if (nrounds > 12)
+ {
+ /* round 12: */
+ s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[48];
+ s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[49];
+ s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[50];
+ s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[51];
+ /* round 13: */
+ t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[52];
+ t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[53];
+ t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[54];
+ t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[55];
+ }
+ }
+ rk += nrounds << 2;
+ #else /* !FULL_UNROLL */
+ /*
+ * nrounds - 1 full rounds:
+ */
+ r = nrounds >> 1;
+ for (;;)
+ {
+ t0 =
+ Te0[(s0 >> 24) ] ^
+ Te1[(s1 >> 16) & 0xff] ^
+ Te2[(s2 >> 8) & 0xff] ^
+ Te3[(s3 ) & 0xff] ^
+ rk[4];
+ t1 =
+ Te0[(s1 >> 24) ] ^
+ Te1[(s2 >> 16) & 0xff] ^
+ Te2[(s3 >> 8) & 0xff] ^
+ Te3[(s0 ) & 0xff] ^
+ rk[5];
+ t2 =
+ Te0[(s2 >> 24) ] ^
+ Te1[(s3 >> 16) & 0xff] ^
+ Te2[(s0 >> 8) & 0xff] ^
+ Te3[(s1 ) & 0xff] ^
+ rk[6];
+ t3 =
+ Te0[(s3 >> 24) ] ^
+ Te1[(s0 >> 16) & 0xff] ^
+ Te2[(s1 >> 8) & 0xff] ^
+ Te3[(s2 ) & 0xff] ^
+ rk[7];
+ rk += 8;
+ if (--r == 0)
+ break;
+ s0 =
+ Te0[(t0 >> 24) ] ^
+ Te1[(t1 >> 16) & 0xff] ^
+ Te2[(t2 >> 8) & 0xff] ^
+ Te3[(t3 ) & 0xff] ^
+ rk[0];
+ s1 =
+ Te0[(t1 >> 24) ] ^
+ Te1[(t2 >> 16) & 0xff] ^
+ Te2[(t3 >> 8) & 0xff] ^
+ Te3[(t0 ) & 0xff] ^
+ rk[1];
+ s2 =
+ Te0[(t2 >> 24) ] ^
+ Te1[(t3 >> 16) & 0xff] ^
+ Te2[(t0 >> 8) & 0xff] ^
+ Te3[(t1 ) & 0xff] ^
+ rk[2];
+ s3 =
+ Te0[(t3 >> 24) ] ^
+ Te1[(t0 >> 16) & 0xff] ^
+ Te2[(t1 >> 8) & 0xff] ^
+ Te3[(t2 ) & 0xff] ^
+ rk[3];
+ }
+ #endif /* ?FULL_UNROLL */
+ /*
+ * apply last round and
+ * map cipher state to byte array block:
+ */
+ s0 =
+ (Te4[(t0 >> 24) ] & 0xff000000) ^
+ (Te4[(t1 >> 16) & 0xff] & 0x00ff0000) ^
+ (Te4[(t2 >> 8) & 0xff] & 0x0000ff00) ^
+ (Te4[(t3 ) & 0xff] & 0x000000ff) ^
+ rk[0];
+ PUTU32(ciphertext , s0);
+ s1 =
+ (Te4[(t1 >> 24) ] & 0xff000000) ^
+ (Te4[(t2 >> 16) & 0xff] & 0x00ff0000) ^
+ (Te4[(t3 >> 8) & 0xff] & 0x0000ff00) ^
+ (Te4[(t0 ) & 0xff] & 0x000000ff) ^
+ rk[1];
+ PUTU32(ciphertext + 4, s1);
+ s2 =
+ (Te4[(t2 >> 24) ] & 0xff000000) ^
+ (Te4[(t3 >> 16) & 0xff] & 0x00ff0000) ^
+ (Te4[(t0 >> 8) & 0xff] & 0x0000ff00) ^
+ (Te4[(t1 ) & 0xff] & 0x000000ff) ^
+ rk[2];
+ PUTU32(ciphertext + 8, s2);
+ s3 =
+ (Te4[(t3 >> 24) ] & 0xff000000) ^
+ (Te4[(t0 >> 16) & 0xff] & 0x00ff0000) ^
+ (Te4[(t1 >> 8) & 0xff] & 0x0000ff00) ^
+ (Te4[(t2 ) & 0xff] & 0x000000ff) ^
+ rk[3];
+ PUTU32(ciphertext + 12, s3);
+}
+
+void rijndaelDecrypt(const u32 *rk, int nrounds, const u8 ciphertext[16],
+ u8 plaintext[16])
+{
+ u32 s0, s1, s2, s3, t0, t1, t2, t3;
+ #ifndef FULL_UNROLL
+ int r;
+ #endif /* ?FULL_UNROLL */
+
+ /*
+ * map byte array block to cipher state
+ * and add initial round key:
+ */
+ s0 = GETU32(ciphertext ) ^ rk[0];
+ s1 = GETU32(ciphertext + 4) ^ rk[1];
+ s2 = GETU32(ciphertext + 8) ^ rk[2];
+ s3 = GETU32(ciphertext + 12) ^ rk[3];
+ #ifdef FULL_UNROLL
+ /* round 1: */
+ t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[ 4];
+ t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[ 5];
+ t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[ 6];
+ t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[ 7];
+ /* round 2: */
+ s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[ 8];
+ s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[ 9];
+ s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[10];
+ s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[11];
+ /* round 3: */
+ t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[12];
+ t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[13];
+ t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[14];
+ t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[15];
+ /* round 4: */
+ s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[16];
+ s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[17];
+ s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[18];
+ s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[19];
+ /* round 5: */
+ t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[20];
+ t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[21];
+ t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[22];
+ t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[23];
+ /* round 6: */
+ s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[24];
+ s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[25];
+ s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[26];
+ s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[27];
+ /* round 7: */
+ t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[28];
+ t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[29];
+ t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[30];
+ t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[31];
+ /* round 8: */
+ s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[32];
+ s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[33];
+ s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[34];
+ s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[35];
+ /* round 9: */
+ t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[36];
+ t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[37];
+ t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[38];
+ t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[39];
+ if (nrounds > 10)
+ {
+ /* round 10: */
+ s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[40];
+ s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[41];
+ s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[42];
+ s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[43];
+ /* round 11: */
+ t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[44];
+ t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[45];
+ t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[46];
+ t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[47];
+ if (nrounds > 12)
+ {
+ /* round 12: */
+ s0 = Td0[t0 >> 24] ^ Td1[(t3 >> 16) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^ Td3[t1 & 0xff] ^ rk[48];
+ s1 = Td0[t1 >> 24] ^ Td1[(t0 >> 16) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^ Td3[t2 & 0xff] ^ rk[49];
+ s2 = Td0[t2 >> 24] ^ Td1[(t1 >> 16) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^ Td3[t3 & 0xff] ^ rk[50];
+ s3 = Td0[t3 >> 24] ^ Td1[(t2 >> 16) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^ Td3[t0 & 0xff] ^ rk[51];
+ /* round 13: */
+ t0 = Td0[s0 >> 24] ^ Td1[(s3 >> 16) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^ Td3[s1 & 0xff] ^ rk[52];
+ t1 = Td0[s1 >> 24] ^ Td1[(s0 >> 16) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^ Td3[s2 & 0xff] ^ rk[53];
+ t2 = Td0[s2 >> 24] ^ Td1[(s1 >> 16) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^ Td3[s3 & 0xff] ^ rk[54];
+ t3 = Td0[s3 >> 24] ^ Td1[(s2 >> 16) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^ Td3[s0 & 0xff] ^ rk[55];
+ }
+ }
+ rk += nrounds << 2;
+ #else /* !FULL_UNROLL */
+ /*
+ * nrounds - 1 full rounds:
+ */
+ r = nrounds >> 1;
+ for (;;)
+ {
+ t0 =
+ Td0[(s0 >> 24) ] ^
+ Td1[(s3 >> 16) & 0xff] ^
+ Td2[(s2 >> 8) & 0xff] ^
+ Td3[(s1 ) & 0xff] ^
+ rk[4];
+ t1 =
+ Td0[(s1 >> 24) ] ^
+ Td1[(s0 >> 16) & 0xff] ^
+ Td2[(s3 >> 8) & 0xff] ^
+ Td3[(s2 ) & 0xff] ^
+ rk[5];
+ t2 =
+ Td0[(s2 >> 24) ] ^
+ Td1[(s1 >> 16) & 0xff] ^
+ Td2[(s0 >> 8) & 0xff] ^
+ Td3[(s3 ) & 0xff] ^
+ rk[6];
+ t3 =
+ Td0[(s3 >> 24) ] ^
+ Td1[(s2 >> 16) & 0xff] ^
+ Td2[(s1 >> 8) & 0xff] ^
+ Td3[(s0 ) & 0xff] ^
+ rk[7];
+ rk += 8;
+ if (--r == 0)
+ break;
+ s0 =
+ Td0[(t0 >> 24) ] ^
+ Td1[(t3 >> 16) & 0xff] ^
+ Td2[(t2 >> 8) & 0xff] ^
+ Td3[(t1 ) & 0xff] ^
+ rk[0];
+ s1 =
+ Td0[(t1 >> 24) ] ^
+ Td1[(t0 >> 16) & 0xff] ^
+ Td2[(t3 >> 8) & 0xff] ^
+ Td3[(t2 ) & 0xff] ^
+ rk[1];
+ s2 =
+ Td0[(t2 >> 24) ] ^
+ Td1[(t1 >> 16) & 0xff] ^
+ Td2[(t0 >> 8) & 0xff] ^
+ Td3[(t3 ) & 0xff] ^
+ rk[2];
+ s3 =
+ Td0[(t3 >> 24) ] ^
+ Td1[(t2 >> 16) & 0xff] ^
+ Td2[(t1 >> 8) & 0xff] ^
+ Td3[(t0 ) & 0xff] ^
+ rk[3];
+ }
+ #endif /* ?FULL_UNROLL */
+ /*
+ * apply last round and
+ * map cipher state to byte array block:
+ */
+ s0 =
+ (Td4[(t0 >> 24) ] & 0xff000000) ^
+ (Td4[(t3 >> 16) & 0xff] & 0x00ff0000) ^
+ (Td4[(t2 >> 8) & 0xff] & 0x0000ff00) ^
+ (Td4[(t1 ) & 0xff] & 0x000000ff) ^
+ rk[0];
+ PUTU32(plaintext , s0);
+ s1 =
+ (Td4[(t1 >> 24) ] & 0xff000000) ^
+ (Td4[(t0 >> 16) & 0xff] & 0x00ff0000) ^
+ (Td4[(t3 >> 8) & 0xff] & 0x0000ff00) ^
+ (Td4[(t2 ) & 0xff] & 0x000000ff) ^
+ rk[1];
+ PUTU32(plaintext + 4, s1);
+ s2 =
+ (Td4[(t2 >> 24) ] & 0xff000000) ^
+ (Td4[(t1 >> 16) & 0xff] & 0x00ff0000) ^
+ (Td4[(t0 >> 8) & 0xff] & 0x0000ff00) ^
+ (Td4[(t3 ) & 0xff] & 0x000000ff) ^
+ rk[2];
+ PUTU32(plaintext + 8, s2);
+ s3 =
+ (Td4[(t3 >> 24) ] & 0xff000000) ^
+ (Td4[(t2 >> 16) & 0xff] & 0x00ff0000) ^
+ (Td4[(t1 >> 8) & 0xff] & 0x0000ff00) ^
+ (Td4[(t0 ) & 0xff] & 0x000000ff) ^
+ rk[3];
+ PUTU32(plaintext + 12, s3);
+}
--- /dev/null
+#ifndef H__RIJNDAEL
+#define H__RIJNDAEL
+
+int rijndaelSetupEncrypt(unsigned long *rk, const unsigned char *key,
+ int keybits);
+int rijndaelSetupDecrypt(unsigned long *rk, const unsigned char *key,
+ int keybits);
+void rijndaelEncrypt(const unsigned long *rk, int nrounds,
+ const unsigned char plaintext[16], unsigned char ciphertext[16]);
+void rijndaelDecrypt(const unsigned long *rk, int nrounds,
+ const unsigned char ciphertext[16], unsigned char plaintext[16]);
+
+#define KEYLENGTH(keybits) ((keybits)/8)
+#define RKLENGTH(keybits) ((keybits)/8+28)
+#define NROUNDS(keybits) ((keybits)/32+6)
+
+#endif
--- /dev/null
+/*
+ * FILE: sha2.c
+ * AUTHOR: Aaron D. Gifford <me@aarongifford.com>
+ *
+ * Copyright (c) 2000-2001, Aaron D. Gifford
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the names of contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTOR(S) BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: sha2.c,v 1.1 2001/11/08 00:01:51 adg Exp adg $
+ */
+
+#include <string.h> /* memcpy()/memset() or bcopy()/bzero() */
+#include <assert.h> /* assert() */
+#include "sha2.h"
+
+/*
+ * ASSERT NOTE:
+ * Some sanity checking code is included using assert(). On my FreeBSD
+ * system, this additional code can be removed by compiling with NDEBUG
+ * defined. Check your own systems manpage on assert() to see how to
+ * compile WITHOUT the sanity checking code on your system.
+ *
+ * UNROLLED TRANSFORM LOOP NOTE:
+ * You can define SHA2_UNROLL_TRANSFORM to use the unrolled transform
+ * loop version for the hash transform rounds (defined using macros
+ * later in this file). Either define on the command line, for example:
+ *
+ * cc -DSHA2_UNROLL_TRANSFORM -o sha2 sha2.c sha2prog.c
+ *
+ * or define below:
+ *
+ * #define SHA2_UNROLL_TRANSFORM
+ *
+ */
+
+
+/*** SHA-256/384/512 Machine Architecture Definitions *****************/
+/*
+ * BYTE_ORDER NOTE:
+ *
+ * Please make sure that your system defines BYTE_ORDER. If your
+ * architecture is little-endian, make sure it also defines
+ * LITTLE_ENDIAN and that the two (BYTE_ORDER and LITTLE_ENDIAN) are
+ * equivilent.
+ *
+ * If your system does not define the above, then you can do so by
+ * hand like this:
+ *
+ * #define LITTLE_ENDIAN 1234
+ * #define BIG_ENDIAN 4321
+ *
+ * And for little-endian machines, add:
+ *
+ * #define BYTE_ORDER LITTLE_ENDIAN
+ *
+ * Or for big-endian machines:
+ *
+ * #define BYTE_ORDER BIG_ENDIAN
+ *
+ * The FreeBSD machine this was written on defines BYTE_ORDER
+ * appropriately by including <sys/types.h> (which in turn includes
+ * <machine/endian.h> where the appropriate definitions are actually
+ * made).
+ */
+#if !defined(BYTE_ORDER)
+#define BYTE_ORDER __BYTE_ORDER
+#endif
+
+#if !defined(BYTE_ORDER) || (BYTE_ORDER != LITTLE_ENDIAN && BYTE_ORDER != BIG_ENDIAN)
+#error Define BYTE_ORDER to be equal to either LITTLE_ENDIAN or BIG_ENDIAN
+#endif
+
+/*
+ * Define the followingsha2_* types to types of the correct length on
+ * the native archtecture. Most BSD systems and Linux define u_intXX_t
+ * types. Machines with very recent ANSI C headers, can use the
+ * uintXX_t definintions from inttypes.h by defining SHA2_USE_INTTYPES_H
+ * during compile or in the sha.h header file.
+ *
+ * Machines that support neither u_intXX_t nor inttypes.h's uintXX_t
+ * will need to define these three typedefs below (and the appropriate
+ * ones in sha.h too) by hand according to their system architecture.
+ *
+ * Thank you, Jun-ichiro itojun Hagino, for suggesting using u_intXX_t
+ * types and pointing out recent ANSI C support for uintXX_t in inttypes.h.
+ */
+#ifdef SHA2_USE_INTTYPES_H
+
+typedef uint8_t sha2_byte; /* Exactly 1 byte */
+typedef uint32_t sha2_word32; /* Exactly 4 bytes */
+typedef uint64_t sha2_word64; /* Exactly 8 bytes */
+
+#else /* SHA2_USE_INTTYPES_H */
+
+typedef u_int8_t sha2_byte; /* Exactly 1 byte */
+typedef u_int32_t sha2_word32; /* Exactly 4 bytes */
+typedef u_int64_t sha2_word64; /* Exactly 8 bytes */
+
+#endif /* SHA2_USE_INTTYPES_H */
+
+
+/*** SHA-256/384/512 Various Length Definitions ***********************/
+/* NOTE: Most of these are in sha2.h */
+#define SHA256_SHORT_BLOCK_LENGTH (SHA256_BLOCK_LENGTH - 8)
+#define SHA384_SHORT_BLOCK_LENGTH (SHA384_BLOCK_LENGTH - 16)
+#define SHA512_SHORT_BLOCK_LENGTH (SHA512_BLOCK_LENGTH - 16)
+
+
+/*** ENDIAN REVERSAL MACROS *******************************************/
+#if BYTE_ORDER == LITTLE_ENDIAN
+#define REVERSE32(w,x) { \
+ sha2_word32 tmp = (w); \
+ tmp = (tmp >> 16) | (tmp << 16); \
+ (x) = ((tmp & 0xff00ff00UL) >> 8) | ((tmp & 0x00ff00ffUL) << 8); \
+}
+#define REVERSE64(w,x) { \
+ sha2_word64 tmp = (w); \
+ tmp = (tmp >> 32) | (tmp << 32); \
+ tmp = ((tmp & 0xff00ff00ff00ff00ULL) >> 8) | \
+ ((tmp & 0x00ff00ff00ff00ffULL) << 8); \
+ (x) = ((tmp & 0xffff0000ffff0000ULL) >> 16) | \
+ ((tmp & 0x0000ffff0000ffffULL) << 16); \
+}
+#endif /* BYTE_ORDER == LITTLE_ENDIAN */
+
+/*
+ * Macro for incrementally adding the unsigned 64-bit integer n to the
+ * unsigned 128-bit integer (represented using a two-element array of
+ * 64-bit words):
+ */
+#define ADDINC128(w,n) { \
+ (w)[0] += (sha2_word64)(n); \
+ if ((w)[0] < (n)) { \
+ (w)[1]++; \
+ } \
+}
+
+/*
+ * Macros for copying blocks of memory and for zeroing out ranges
+ * of memory. Using these macros makes it easy to switch from
+ * using memset()/memcpy() and using bzero()/bcopy().
+ *
+ * Please define either SHA2_USE_MEMSET_MEMCPY or define
+ * SHA2_USE_BZERO_BCOPY depending on which function set you
+ * choose to use:
+ */
+#if !defined(SHA2_USE_MEMSET_MEMCPY) && !defined(SHA2_USE_BZERO_BCOPY)
+/* Default to memset()/memcpy() if no option is specified */
+#define SHA2_USE_MEMSET_MEMCPY 1
+#endif
+#if defined(SHA2_USE_MEMSET_MEMCPY) && defined(SHA2_USE_BZERO_BCOPY)
+/* Abort with an error if BOTH options are defined */
+#error Define either SHA2_USE_MEMSET_MEMCPY or SHA2_USE_BZERO_BCOPY, not both!
+#endif
+
+#ifdef SHA2_USE_MEMSET_MEMCPY
+#define MEMSET_BZERO(p,l) memset((p), 0, (l))
+#define MEMCPY_BCOPY(d,s,l) memcpy((d), (s), (l))
+#endif
+#ifdef SHA2_USE_BZERO_BCOPY
+#define MEMSET_BZERO(p,l) bzero((p), (l))
+#define MEMCPY_BCOPY(d,s,l) bcopy((s), (d), (l))
+#endif
+
+
+/*** THE SIX LOGICAL FUNCTIONS ****************************************/
+/*
+ * Bit shifting and rotation (used by the six SHA-XYZ logical functions:
+ *
+ * NOTE: The naming of R and S appears backwards here (R is a SHIFT and
+ * S is a ROTATION) because the SHA-256/384/512 description document
+ * (see http://csrc.nist.gov/cryptval/shs/sha256-384-512.pdf) uses this
+ * same "backwards" definition.
+ */
+/* Shift-right (used in SHA-256, SHA-384, and SHA-512): */
+#define R(b,x) ((x) >> (b))
+/* 32-bit Rotate-right (used in SHA-256): */
+#define S32(b,x) (((x) >> (b)) | ((x) << (32 - (b))))
+/* 64-bit Rotate-right (used in SHA-384 and SHA-512): */
+#define S64(b,x) (((x) >> (b)) | ((x) << (64 - (b))))
+
+/* Two of six logical functions used in SHA-256, SHA-384, and SHA-512: */
+#define Ch(x,y,z) (((x) & (y)) ^ ((~(x)) & (z)))
+#define Maj(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
+
+/* Four of six logical functions used in SHA-256: */
+#define Sigma0_256(x) (S32(2, (x)) ^ S32(13, (x)) ^ S32(22, (x)))
+#define Sigma1_256(x) (S32(6, (x)) ^ S32(11, (x)) ^ S32(25, (x)))
+#define sigma0_256(x) (S32(7, (x)) ^ S32(18, (x)) ^ R(3 , (x)))
+#define sigma1_256(x) (S32(17, (x)) ^ S32(19, (x)) ^ R(10, (x)))
+
+/* Four of six logical functions used in SHA-384 and SHA-512: */
+#define Sigma0_512(x) (S64(28, (x)) ^ S64(34, (x)) ^ S64(39, (x)))
+#define Sigma1_512(x) (S64(14, (x)) ^ S64(18, (x)) ^ S64(41, (x)))
+#define sigma0_512(x) (S64( 1, (x)) ^ S64( 8, (x)) ^ R( 7, (x)))
+#define sigma1_512(x) (S64(19, (x)) ^ S64(61, (x)) ^ R( 6, (x)))
+
+/*** INTERNAL FUNCTION PROTOTYPES *************************************/
+/* NOTE: These should not be accessed directly from outside this
+ * library -- they are intended for private internal visibility/use
+ * only.
+ */
+void SHA512_Last(SHA512_CTX*);
+void SHA256_Transform(SHA256_CTX*, const sha2_word32*);
+void SHA512_Transform(SHA512_CTX*, const sha2_word64*);
+
+
+/*** SHA-XYZ INITIAL HASH VALUES AND CONSTANTS ************************/
+/* Hash constant words K for SHA-256: */
+const static sha2_word32 K256[64] = {
+ 0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL,
+ 0x3956c25bUL, 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL,
+ 0xd807aa98UL, 0x12835b01UL, 0x243185beUL, 0x550c7dc3UL,
+ 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 0xc19bf174UL,
+ 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL,
+ 0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL,
+ 0x983e5152UL, 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL,
+ 0xc6e00bf3UL, 0xd5a79147UL, 0x06ca6351UL, 0x14292967UL,
+ 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 0x53380d13UL,
+ 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL,
+ 0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL,
+ 0xd192e819UL, 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL,
+ 0x19a4c116UL, 0x1e376c08UL, 0x2748774cUL, 0x34b0bcb5UL,
+ 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, 0x682e6ff3UL,
+ 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL,
+ 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL
+};
+
+/* Initial hash value H for SHA-256: */
+const static sha2_word32 sha256_initial_hash_value[8] = {
+ 0x6a09e667UL,
+ 0xbb67ae85UL,
+ 0x3c6ef372UL,
+ 0xa54ff53aUL,
+ 0x510e527fUL,
+ 0x9b05688cUL,
+ 0x1f83d9abUL,
+ 0x5be0cd19UL
+};
+
+/* Hash constant words K for SHA-384 and SHA-512: */
+const static sha2_word64 K512[80] = {
+ 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL,
+ 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL,
+ 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
+ 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL,
+ 0xd807aa98a3030242ULL, 0x12835b0145706fbeULL,
+ 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
+ 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL,
+ 0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL,
+ 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,
+ 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL,
+ 0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL,
+ 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
+ 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL,
+ 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL,
+ 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
+ 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL,
+ 0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL,
+ 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
+ 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL,
+ 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL,
+ 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,
+ 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL,
+ 0xd192e819d6ef5218ULL, 0xd69906245565a910ULL,
+ 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
+ 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL,
+ 0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL,
+ 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,
+ 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL,
+ 0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL,
+ 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
+ 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL,
+ 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL,
+ 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL,
+ 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL,
+ 0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL,
+ 0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
+ 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL,
+ 0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL,
+ 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
+ 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL
+};
+
+/* Initial hash value H for SHA-384 */
+const static sha2_word64 sha384_initial_hash_value[8] = {
+ 0xcbbb9d5dc1059ed8ULL,
+ 0x629a292a367cd507ULL,
+ 0x9159015a3070dd17ULL,
+ 0x152fecd8f70e5939ULL,
+ 0x67332667ffc00b31ULL,
+ 0x8eb44a8768581511ULL,
+ 0xdb0c2e0d64f98fa7ULL,
+ 0x47b5481dbefa4fa4ULL
+};
+
+/* Initial hash value H for SHA-512 */
+const static sha2_word64 sha512_initial_hash_value[8] = {
+ 0x6a09e667f3bcc908ULL,
+ 0xbb67ae8584caa73bULL,
+ 0x3c6ef372fe94f82bULL,
+ 0xa54ff53a5f1d36f1ULL,
+ 0x510e527fade682d1ULL,
+ 0x9b05688c2b3e6c1fULL,
+ 0x1f83d9abfb41bd6bULL,
+ 0x5be0cd19137e2179ULL
+};
+
+/*
+ * Constant used by SHA256/384/512_End() functions for converting the
+ * digest to a readable hexadecimal character string:
+ */
+static const char *sha2_hex_digits = "0123456789abcdef";
+
+
+/*** SHA-256: *********************************************************/
+void SHA256_Init(SHA256_CTX* context) {
+ if (context == (SHA256_CTX*)0) {
+ return;
+ }
+ MEMCPY_BCOPY(context->state, sha256_initial_hash_value, SHA256_DIGEST_LENGTH);
+ MEMSET_BZERO(context->buffer, SHA256_BLOCK_LENGTH);
+ context->bitcount = 0;
+}
+
+#ifdef SHA2_UNROLL_TRANSFORM
+
+/* Unrolled SHA-256 round macros: */
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+
+#define ROUND256_0_TO_15(a,b,c,d,e,f,g,h) \
+ REVERSE32(*data++, W256[j]); \
+ T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + \
+ K256[j] + W256[j]; \
+ (d) += T1; \
+ (h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \
+ j++
+
+
+#else /* BYTE_ORDER == LITTLE_ENDIAN */
+
+#define ROUND256_0_TO_15(a,b,c,d,e,f,g,h) \
+ T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + \
+ K256[j] + (W256[j] = *data++); \
+ (d) += T1; \
+ (h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \
+ j++
+
+#endif /* BYTE_ORDER == LITTLE_ENDIAN */
+
+#define ROUND256(a,b,c,d,e,f,g,h) \
+ s0 = W256[(j+1)&0x0f]; \
+ s0 = sigma0_256(s0); \
+ s1 = W256[(j+14)&0x0f]; \
+ s1 = sigma1_256(s1); \
+ T1 = (h) + Sigma1_256(e) + Ch((e), (f), (g)) + K256[j] + \
+ (W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0); \
+ (d) += T1; \
+ (h) = T1 + Sigma0_256(a) + Maj((a), (b), (c)); \
+ j++
+
+void SHA256_Transform(SHA256_CTX* context, const sha2_word32* data) {
+ sha2_word32 a, b, c, d, e, f, g, h, s0, s1;
+ sha2_word32 T1, *W256;
+ int j;
+
+ W256 = (sha2_word32*)context->buffer;
+
+ /* Initialize registers with the prev. intermediate value */
+ a = context->state[0];
+ b = context->state[1];
+ c = context->state[2];
+ d = context->state[3];
+ e = context->state[4];
+ f = context->state[5];
+ g = context->state[6];
+ h = context->state[7];
+
+ j = 0;
+ do {
+ /* Rounds 0 to 15 (unrolled): */
+ ROUND256_0_TO_15(a,b,c,d,e,f,g,h);
+ ROUND256_0_TO_15(h,a,b,c,d,e,f,g);
+ ROUND256_0_TO_15(g,h,a,b,c,d,e,f);
+ ROUND256_0_TO_15(f,g,h,a,b,c,d,e);
+ ROUND256_0_TO_15(e,f,g,h,a,b,c,d);
+ ROUND256_0_TO_15(d,e,f,g,h,a,b,c);
+ ROUND256_0_TO_15(c,d,e,f,g,h,a,b);
+ ROUND256_0_TO_15(b,c,d,e,f,g,h,a);
+ } while (j < 16);
+
+ /* Now for the remaining rounds to 64: */
+ do {
+ ROUND256(a,b,c,d,e,f,g,h);
+ ROUND256(h,a,b,c,d,e,f,g);
+ ROUND256(g,h,a,b,c,d,e,f);
+ ROUND256(f,g,h,a,b,c,d,e);
+ ROUND256(e,f,g,h,a,b,c,d);
+ ROUND256(d,e,f,g,h,a,b,c);
+ ROUND256(c,d,e,f,g,h,a,b);
+ ROUND256(b,c,d,e,f,g,h,a);
+ } while (j < 64);
+
+ /* Compute the current intermediate hash value */
+ context->state[0] += a;
+ context->state[1] += b;
+ context->state[2] += c;
+ context->state[3] += d;
+ context->state[4] += e;
+ context->state[5] += f;
+ context->state[6] += g;
+ context->state[7] += h;
+
+ /* Clean up */
+ a = b = c = d = e = f = g = h = T1 = 0;
+}
+
+#else /* SHA2_UNROLL_TRANSFORM */
+
+void SHA256_Transform(SHA256_CTX* context, const sha2_word32* data) {
+ sha2_word32 a, b, c, d, e, f, g, h, s0, s1;
+ sha2_word32 T1, T2, *W256;
+ int j;
+
+ W256 = (sha2_word32*)context->buffer;
+
+ /* Initialize registers with the prev. intermediate value */
+ a = context->state[0];
+ b = context->state[1];
+ c = context->state[2];
+ d = context->state[3];
+ e = context->state[4];
+ f = context->state[5];
+ g = context->state[6];
+ h = context->state[7];
+
+ j = 0;
+ do {
+#if BYTE_ORDER == LITTLE_ENDIAN
+ /* Copy data while converting to host byte order */
+ REVERSE32(*data++,W256[j]);
+ /* Apply the SHA-256 compression function to update a..h */
+ T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + W256[j];
+#else /* BYTE_ORDER == LITTLE_ENDIAN */
+ /* Apply the SHA-256 compression function to update a..h with copy */
+ T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] + (W256[j] = *data++);
+#endif /* BYTE_ORDER == LITTLE_ENDIAN */
+ T2 = Sigma0_256(a) + Maj(a, b, c);
+ h = g;
+ g = f;
+ f = e;
+ e = d + T1;
+ d = c;
+ c = b;
+ b = a;
+ a = T1 + T2;
+
+ j++;
+ } while (j < 16);
+
+ do {
+ /* Part of the message block expansion: */
+ s0 = W256[(j+1)&0x0f];
+ s0 = sigma0_256(s0);
+ s1 = W256[(j+14)&0x0f];
+ s1 = sigma1_256(s1);
+
+ /* Apply the SHA-256 compression function to update a..h */
+ T1 = h + Sigma1_256(e) + Ch(e, f, g) + K256[j] +
+ (W256[j&0x0f] += s1 + W256[(j+9)&0x0f] + s0);
+ T2 = Sigma0_256(a) + Maj(a, b, c);
+ h = g;
+ g = f;
+ f = e;
+ e = d + T1;
+ d = c;
+ c = b;
+ b = a;
+ a = T1 + T2;
+
+ j++;
+ } while (j < 64);
+
+ /* Compute the current intermediate hash value */
+ context->state[0] += a;
+ context->state[1] += b;
+ context->state[2] += c;
+ context->state[3] += d;
+ context->state[4] += e;
+ context->state[5] += f;
+ context->state[6] += g;
+ context->state[7] += h;
+
+ /* Clean up */
+ a = b = c = d = e = f = g = h = T1 = T2 = 0;
+}
+
+#endif /* SHA2_UNROLL_TRANSFORM */
+
+void SHA256_Update(SHA256_CTX* context, const sha2_byte *data, size_t len) {
+ unsigned int freespace, usedspace;
+
+ if (len == 0) {
+ /* Calling with no data is valid - we do nothing */
+ return;
+ }
+
+ /* Sanity check: */
+ assert(context != (SHA256_CTX*)0 && data != (sha2_byte*)0);
+
+ usedspace = (context->bitcount >> 3) % SHA256_BLOCK_LENGTH;
+ if (usedspace > 0) {
+ /* Calculate how much free space is available in the buffer */
+ freespace = SHA256_BLOCK_LENGTH - usedspace;
+
+ if (len >= freespace) {
+ /* Fill the buffer completely and process it */
+ MEMCPY_BCOPY(&context->buffer[usedspace], data, freespace);
+ context->bitcount += freespace << 3;
+ len -= freespace;
+ data += freespace;
+ SHA256_Transform(context, (sha2_word32*)context->buffer);
+ } else {
+ /* The buffer is not yet full */
+ MEMCPY_BCOPY(&context->buffer[usedspace], data, len);
+ context->bitcount += len << 3;
+ /* Clean up: */
+ usedspace = freespace = 0;
+ return;
+ }
+ }
+ while (len >= SHA256_BLOCK_LENGTH) {
+ /* Process as many complete blocks as we can */
+ SHA256_Transform(context, (sha2_word32*)data);
+ context->bitcount += SHA256_BLOCK_LENGTH << 3;
+ len -= SHA256_BLOCK_LENGTH;
+ data += SHA256_BLOCK_LENGTH;
+ }
+ if (len > 0) {
+ /* There's left-overs, so save 'em */
+ MEMCPY_BCOPY(context->buffer, data, len);
+ context->bitcount += len << 3;
+ }
+ /* Clean up: */
+ usedspace = freespace = 0;
+}
+
+void SHA256_Final(sha2_byte digest[], SHA256_CTX* context) {
+ sha2_word32 *d = (sha2_word32*)digest;
+ unsigned int usedspace;
+
+ /* Sanity check: */
+ assert(context != (SHA256_CTX*)0);
+
+ /* If no digest buffer is passed, we don't bother doing this: */
+ if (digest != (sha2_byte*)0) {
+ usedspace = (context->bitcount >> 3) % SHA256_BLOCK_LENGTH;
+#if BYTE_ORDER == LITTLE_ENDIAN
+ /* Convert FROM host byte order */
+ REVERSE64(context->bitcount,context->bitcount);
+#endif
+ if (usedspace > 0) {
+ /* Begin padding with a 1 bit: */
+ context->buffer[usedspace++] = 0x80;
+
+ if (usedspace <= SHA256_SHORT_BLOCK_LENGTH) {
+ /* Set-up for the last transform: */
+ MEMSET_BZERO(&context->buffer[usedspace], SHA256_SHORT_BLOCK_LENGTH - usedspace);
+ } else {
+ if (usedspace < SHA256_BLOCK_LENGTH) {
+ MEMSET_BZERO(&context->buffer[usedspace], SHA256_BLOCK_LENGTH - usedspace);
+ }
+ /* Do second-to-last transform: */
+ SHA256_Transform(context, (sha2_word32*)context->buffer);
+
+ /* And set-up for the last transform: */
+ MEMSET_BZERO(context->buffer, SHA256_SHORT_BLOCK_LENGTH);
+ }
+ } else {
+ /* Set-up for the last transform: */
+ MEMSET_BZERO(context->buffer, SHA256_SHORT_BLOCK_LENGTH);
+
+ /* Begin padding with a 1 bit: */
+ *context->buffer = 0x80;
+ }
+ /* Set the bit count: */
+ *(sha2_word64*)&context->buffer[SHA256_SHORT_BLOCK_LENGTH] = context->bitcount;
+
+ /* Final transform: */
+ SHA256_Transform(context, (sha2_word32*)context->buffer);
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+ {
+ /* Convert TO host byte order */
+ int j;
+ for (j = 0; j < 8; j++) {
+ REVERSE32(context->state[j],context->state[j]);
+ *d++ = context->state[j];
+ }
+ }
+#else
+ MEMCPY_BCOPY(d, context->state, SHA256_DIGEST_LENGTH);
+#endif
+ }
+
+ /* Clean up state data: */
+ MEMSET_BZERO(context, sizeof(context));
+ usedspace = 0;
+}
+
+char *SHA256_End(SHA256_CTX* context, char buffer[]) {
+ sha2_byte digest[SHA256_DIGEST_LENGTH], *d = digest;
+ int i;
+
+ /* Sanity check: */
+ assert(context != (SHA256_CTX*)0);
+
+ if (buffer != (char*)0) {
+ SHA256_Final(digest, context);
+
+ for (i = 0; i < SHA256_DIGEST_LENGTH; i++) {
+ *buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4];
+ *buffer++ = sha2_hex_digits[*d & 0x0f];
+ d++;
+ }
+ *buffer = (char)0;
+ } else {
+ MEMSET_BZERO(context, sizeof(context));
+ }
+ MEMSET_BZERO(digest, SHA256_DIGEST_LENGTH);
+ return buffer;
+}
+
+char* SHA256_Data(const sha2_byte* data, size_t len, char digest[SHA256_DIGEST_STRING_LENGTH]) {
+ SHA256_CTX context;
+
+ SHA256_Init(&context);
+ SHA256_Update(&context, data, len);
+ return SHA256_End(&context, digest);
+}
+
+
+/*** SHA-512: *********************************************************/
+void SHA512_Init(SHA512_CTX* context) {
+ if (context == (SHA512_CTX*)0) {
+ return;
+ }
+ MEMCPY_BCOPY(context->state, sha512_initial_hash_value, SHA512_DIGEST_LENGTH);
+ MEMSET_BZERO(context->buffer, SHA512_BLOCK_LENGTH);
+ context->bitcount[0] = context->bitcount[1] = 0;
+}
+
+#ifdef SHA2_UNROLL_TRANSFORM
+
+/* Unrolled SHA-512 round macros: */
+#if BYTE_ORDER == LITTLE_ENDIAN
+
+#define ROUND512_0_TO_15(a,b,c,d,e,f,g,h) \
+ REVERSE64(*data++, W512[j]); \
+ T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + \
+ K512[j] + W512[j]; \
+ (d) += T1, \
+ (h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)), \
+ j++
+
+
+#else /* BYTE_ORDER == LITTLE_ENDIAN */
+
+#define ROUND512_0_TO_15(a,b,c,d,e,f,g,h) \
+ T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + \
+ K512[j] + (W512[j] = *data++); \
+ (d) += T1; \
+ (h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)); \
+ j++
+
+#endif /* BYTE_ORDER == LITTLE_ENDIAN */
+
+#define ROUND512(a,b,c,d,e,f,g,h) \
+ s0 = W512[(j+1)&0x0f]; \
+ s0 = sigma0_512(s0); \
+ s1 = W512[(j+14)&0x0f]; \
+ s1 = sigma1_512(s1); \
+ T1 = (h) + Sigma1_512(e) + Ch((e), (f), (g)) + K512[j] + \
+ (W512[j&0x0f] += s1 + W512[(j+9)&0x0f] + s0); \
+ (d) += T1; \
+ (h) = T1 + Sigma0_512(a) + Maj((a), (b), (c)); \
+ j++
+
+void SHA512_Transform(SHA512_CTX* context, const sha2_word64* data) {
+ sha2_word64 a, b, c, d, e, f, g, h, s0, s1;
+ sha2_word64 T1, *W512 = (sha2_word64*)context->buffer;
+ int j;
+
+ /* Initialize registers with the prev. intermediate value */
+ a = context->state[0];
+ b = context->state[1];
+ c = context->state[2];
+ d = context->state[3];
+ e = context->state[4];
+ f = context->state[5];
+ g = context->state[6];
+ h = context->state[7];
+
+ j = 0;
+ do {
+ ROUND512_0_TO_15(a,b,c,d,e,f,g,h);
+ ROUND512_0_TO_15(h,a,b,c,d,e,f,g);
+ ROUND512_0_TO_15(g,h,a,b,c,d,e,f);
+ ROUND512_0_TO_15(f,g,h,a,b,c,d,e);
+ ROUND512_0_TO_15(e,f,g,h,a,b,c,d);
+ ROUND512_0_TO_15(d,e,f,g,h,a,b,c);
+ ROUND512_0_TO_15(c,d,e,f,g,h,a,b);
+ ROUND512_0_TO_15(b,c,d,e,f,g,h,a);
+ } while (j < 16);
+
+ /* Now for the remaining rounds up to 79: */
+ do {
+ ROUND512(a,b,c,d,e,f,g,h);
+ ROUND512(h,a,b,c,d,e,f,g);
+ ROUND512(g,h,a,b,c,d,e,f);
+ ROUND512(f,g,h,a,b,c,d,e);
+ ROUND512(e,f,g,h,a,b,c,d);
+ ROUND512(d,e,f,g,h,a,b,c);
+ ROUND512(c,d,e,f,g,h,a,b);
+ ROUND512(b,c,d,e,f,g,h,a);
+ } while (j < 80);
+
+ /* Compute the current intermediate hash value */
+ context->state[0] += a;
+ context->state[1] += b;
+ context->state[2] += c;
+ context->state[3] += d;
+ context->state[4] += e;
+ context->state[5] += f;
+ context->state[6] += g;
+ context->state[7] += h;
+
+ /* Clean up */
+ a = b = c = d = e = f = g = h = T1 = 0;
+}
+
+#else /* SHA2_UNROLL_TRANSFORM */
+
+void SHA512_Transform(SHA512_CTX* context, const sha2_word64* data) {
+ sha2_word64 a, b, c, d, e, f, g, h, s0, s1;
+ sha2_word64 T1, T2, *W512 = (sha2_word64*)context->buffer;
+ int j;
+
+ /* Initialize registers with the prev. intermediate value */
+ a = context->state[0];
+ b = context->state[1];
+ c = context->state[2];
+ d = context->state[3];
+ e = context->state[4];
+ f = context->state[5];
+ g = context->state[6];
+ h = context->state[7];
+
+ j = 0;
+ do {
+#if BYTE_ORDER == LITTLE_ENDIAN
+ /* Convert TO host byte order */
+ REVERSE64(*data++, W512[j]);
+ /* Apply the SHA-512 compression function to update a..h */
+ T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + W512[j];
+#else /* BYTE_ORDER == LITTLE_ENDIAN */
+ /* Apply the SHA-512 compression function to update a..h with copy */
+ T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] + (W512[j] = *data++);
+#endif /* BYTE_ORDER == LITTLE_ENDIAN */
+ T2 = Sigma0_512(a) + Maj(a, b, c);
+ h = g;
+ g = f;
+ f = e;
+ e = d + T1;
+ d = c;
+ c = b;
+ b = a;
+ a = T1 + T2;
+
+ j++;
+ } while (j < 16);
+
+ do {
+ /* Part of the message block expansion: */
+ s0 = W512[(j+1)&0x0f];
+ s0 = sigma0_512(s0);
+ s1 = W512[(j+14)&0x0f];
+ s1 = sigma1_512(s1);
+
+ /* Apply the SHA-512 compression function to update a..h */
+ T1 = h + Sigma1_512(e) + Ch(e, f, g) + K512[j] +
+ (W512[j&0x0f] += s1 + W512[(j+9)&0x0f] + s0);
+ T2 = Sigma0_512(a) + Maj(a, b, c);
+ h = g;
+ g = f;
+ f = e;
+ e = d + T1;
+ d = c;
+ c = b;
+ b = a;
+ a = T1 + T2;
+
+ j++;
+ } while (j < 80);
+
+ /* Compute the current intermediate hash value */
+ context->state[0] += a;
+ context->state[1] += b;
+ context->state[2] += c;
+ context->state[3] += d;
+ context->state[4] += e;
+ context->state[5] += f;
+ context->state[6] += g;
+ context->state[7] += h;
+
+ /* Clean up */
+ a = b = c = d = e = f = g = h = T1 = T2 = 0;
+}
+
+#endif /* SHA2_UNROLL_TRANSFORM */
+
+void SHA512_Update(SHA512_CTX* context, const sha2_byte *data, size_t len) {
+ unsigned int freespace, usedspace;
+
+ if (len == 0) {
+ /* Calling with no data is valid - we do nothing */
+ return;
+ }
+
+ /* Sanity check: */
+ assert(context != (SHA512_CTX*)0 && data != (sha2_byte*)0);
+
+ usedspace = (context->bitcount[0] >> 3) % SHA512_BLOCK_LENGTH;
+ if (usedspace > 0) {
+ /* Calculate how much free space is available in the buffer */
+ freespace = SHA512_BLOCK_LENGTH - usedspace;
+
+ if (len >= freespace) {
+ /* Fill the buffer completely and process it */
+ MEMCPY_BCOPY(&context->buffer[usedspace], data, freespace);
+ ADDINC128(context->bitcount, freespace << 3);
+ len -= freespace;
+ data += freespace;
+ SHA512_Transform(context, (sha2_word64*)context->buffer);
+ } else {
+ /* The buffer is not yet full */
+ MEMCPY_BCOPY(&context->buffer[usedspace], data, len);
+ ADDINC128(context->bitcount, len << 3);
+ /* Clean up: */
+ usedspace = freespace = 0;
+ return;
+ }
+ }
+ while (len >= SHA512_BLOCK_LENGTH) {
+ /* Process as many complete blocks as we can */
+ SHA512_Transform(context, (sha2_word64*)data);
+ ADDINC128(context->bitcount, SHA512_BLOCK_LENGTH << 3);
+ len -= SHA512_BLOCK_LENGTH;
+ data += SHA512_BLOCK_LENGTH;
+ }
+ if (len > 0) {
+ /* There's left-overs, so save 'em */
+ MEMCPY_BCOPY(context->buffer, data, len);
+ ADDINC128(context->bitcount, len << 3);
+ }
+ /* Clean up: */
+ usedspace = freespace = 0;
+}
+
+void SHA512_Last(SHA512_CTX* context) {
+ unsigned int usedspace;
+
+ usedspace = (context->bitcount[0] >> 3) % SHA512_BLOCK_LENGTH;
+#if BYTE_ORDER == LITTLE_ENDIAN
+ /* Convert FROM host byte order */
+ REVERSE64(context->bitcount[0],context->bitcount[0]);
+ REVERSE64(context->bitcount[1],context->bitcount[1]);
+#endif
+ if (usedspace > 0) {
+ /* Begin padding with a 1 bit: */
+ context->buffer[usedspace++] = 0x80;
+
+ if (usedspace <= SHA512_SHORT_BLOCK_LENGTH) {
+ /* Set-up for the last transform: */
+ MEMSET_BZERO(&context->buffer[usedspace], SHA512_SHORT_BLOCK_LENGTH - usedspace);
+ } else {
+ if (usedspace < SHA512_BLOCK_LENGTH) {
+ MEMSET_BZERO(&context->buffer[usedspace], SHA512_BLOCK_LENGTH - usedspace);
+ }
+ /* Do second-to-last transform: */
+ SHA512_Transform(context, (sha2_word64*)context->buffer);
+
+ /* And set-up for the last transform: */
+ MEMSET_BZERO(context->buffer, SHA512_BLOCK_LENGTH - 2);
+ }
+ } else {
+ /* Prepare for final transform: */
+ MEMSET_BZERO(context->buffer, SHA512_SHORT_BLOCK_LENGTH);
+
+ /* Begin padding with a 1 bit: */
+ *context->buffer = 0x80;
+ }
+ /* Store the length of input data (in bits): */
+ *(sha2_word64*)&context->buffer[SHA512_SHORT_BLOCK_LENGTH] = context->bitcount[1];
+ *(sha2_word64*)&context->buffer[SHA512_SHORT_BLOCK_LENGTH+8] = context->bitcount[0];
+
+ /* Final transform: */
+ SHA512_Transform(context, (sha2_word64*)context->buffer);
+}
+
+void SHA512_Final(sha2_byte digest[], SHA512_CTX* context) {
+ sha2_word64 *d = (sha2_word64*)digest;
+
+ /* Sanity check: */
+ assert(context != (SHA512_CTX*)0);
+
+ /* If no digest buffer is passed, we don't bother doing this: */
+ if (digest != (sha2_byte*)0) {
+ SHA512_Last(context);
+
+ /* Save the hash data for output: */
+#if BYTE_ORDER == LITTLE_ENDIAN
+ {
+ /* Convert TO host byte order */
+ int j;
+ for (j = 0; j < 8; j++) {
+ REVERSE64(context->state[j],context->state[j]);
+ *d++ = context->state[j];
+ }
+ }
+#else
+ MEMCPY_BCOPY(d, context->state, SHA512_DIGEST_LENGTH);
+#endif
+ }
+
+ /* Zero out state data */
+ MEMSET_BZERO(context, sizeof(context));
+}
+
+char *SHA512_End(SHA512_CTX* context, char buffer[]) {
+ sha2_byte digest[SHA512_DIGEST_LENGTH], *d = digest;
+ int i;
+
+ /* Sanity check: */
+ assert(context != (SHA512_CTX*)0);
+
+ if (buffer != (char*)0) {
+ SHA512_Final(digest, context);
+
+ for (i = 0; i < SHA512_DIGEST_LENGTH; i++) {
+ *buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4];
+ *buffer++ = sha2_hex_digits[*d & 0x0f];
+ d++;
+ }
+ *buffer = (char)0;
+ } else {
+ MEMSET_BZERO(context, sizeof(context));
+ }
+ MEMSET_BZERO(digest, SHA512_DIGEST_LENGTH);
+ return buffer;
+}
+
+char* SHA512_Data(const sha2_byte* data, size_t len, char digest[SHA512_DIGEST_STRING_LENGTH]) {
+ SHA512_CTX context;
+
+ SHA512_Init(&context);
+ SHA512_Update(&context, data, len);
+ return SHA512_End(&context, digest);
+}
+
+
+/*** SHA-384: *********************************************************/
+void SHA384_Init(SHA384_CTX* context) {
+ if (context == (SHA384_CTX*)0) {
+ return;
+ }
+ MEMCPY_BCOPY(context->state, sha384_initial_hash_value, SHA512_DIGEST_LENGTH);
+ MEMSET_BZERO(context->buffer, SHA384_BLOCK_LENGTH);
+ context->bitcount[0] = context->bitcount[1] = 0;
+}
+
+void SHA384_Update(SHA384_CTX* context, const sha2_byte* data, size_t len) {
+ SHA512_Update((SHA512_CTX*)context, data, len);
+}
+
+void SHA384_Final(sha2_byte digest[], SHA384_CTX* context) {
+ sha2_word64 *d = (sha2_word64*)digest;
+
+ /* Sanity check: */
+ assert(context != (SHA384_CTX*)0);
+
+ /* If no digest buffer is passed, we don't bother doing this: */
+ if (digest != (sha2_byte*)0) {
+ SHA512_Last((SHA512_CTX*)context);
+
+ /* Save the hash data for output: */
+#if BYTE_ORDER == LITTLE_ENDIAN
+ {
+ /* Convert TO host byte order */
+ int j;
+ for (j = 0; j < 6; j++) {
+ REVERSE64(context->state[j],context->state[j]);
+ *d++ = context->state[j];
+ }
+ }
+#else
+ MEMCPY_BCOPY(d, context->state, SHA384_DIGEST_LENGTH);
+#endif
+ }
+
+ /* Zero out state data */
+ MEMSET_BZERO(context, sizeof(context));
+}
+
+char *SHA384_End(SHA384_CTX* context, char buffer[]) {
+ sha2_byte digest[SHA384_DIGEST_LENGTH], *d = digest;
+ int i;
+
+ /* Sanity check: */
+ assert(context != (SHA384_CTX*)0);
+
+ if (buffer != (char*)0) {
+ SHA384_Final(digest, context);
+
+ for (i = 0; i < SHA384_DIGEST_LENGTH; i++) {
+ *buffer++ = sha2_hex_digits[(*d & 0xf0) >> 4];
+ *buffer++ = sha2_hex_digits[*d & 0x0f];
+ d++;
+ }
+ *buffer = (char)0;
+ } else {
+ MEMSET_BZERO(context, sizeof(context));
+ }
+ MEMSET_BZERO(digest, SHA384_DIGEST_LENGTH);
+ return buffer;
+}
+
+char* SHA384_Data(const sha2_byte* data, size_t len, char digest[SHA384_DIGEST_STRING_LENGTH]) {
+ SHA384_CTX context;
+
+ SHA384_Init(&context);
+ SHA384_Update(&context, data, len);
+ return SHA384_End(&context, digest);
+}
+
--- /dev/null
+/*
+ * FILE: sha2.h
+ * AUTHOR: Aaron D. Gifford <me@aarongifford.com>
+ *
+ * Copyright (c) 2000-2001, Aaron D. Gifford
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holder nor the names of contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTOR(S) ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTOR(S) BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: sha2.h,v 1.1 2001/11/08 00:02:01 adg Exp adg $
+ */
+
+#ifndef __SHA2_H__
+#define __SHA2_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/*
+ * Import u_intXX_t size_t type definitions from system headers. You
+ * may need to change this, or define these things yourself in this
+ * file.
+ */
+#include <sys/types.h>
+
+#ifdef SHA2_USE_INTTYPES_H
+
+#include <inttypes.h>
+
+#endif /* SHA2_USE_INTTYPES_H */
+
+
+/*** SHA-256/384/512 Various Length Definitions ***********************/
+#define SHA256_BLOCK_LENGTH 64
+#define SHA256_DIGEST_LENGTH 32
+#define SHA256_DIGEST_STRING_LENGTH (SHA256_DIGEST_LENGTH * 2 + 1)
+#define SHA384_BLOCK_LENGTH 128
+#define SHA384_DIGEST_LENGTH 48
+#define SHA384_DIGEST_STRING_LENGTH (SHA384_DIGEST_LENGTH * 2 + 1)
+#define SHA512_BLOCK_LENGTH 128
+#define SHA512_DIGEST_LENGTH 64
+#define SHA512_DIGEST_STRING_LENGTH (SHA512_DIGEST_LENGTH * 2 + 1)
+
+
+/*** SHA-256/384/512 Context Structures *******************************/
+/* NOTE: If your architecture does not define either u_intXX_t types or
+ * uintXX_t (from inttypes.h), you may need to define things by hand
+ * for your system:
+ */
+#if 0
+typedef unsigned char u_int8_t; /* 1-byte (8-bits) */
+typedef unsigned int u_int32_t; /* 4-bytes (32-bits) */
+typedef unsigned long long u_int64_t; /* 8-bytes (64-bits) */
+#endif
+/*
+ * Most BSD systems already define u_intXX_t types, as does Linux.
+ * Some systems, however, like Compaq's Tru64 Unix instead can use
+ * uintXX_t types defined by very recent ANSI C standards and included
+ * in the file:
+ *
+ * #include <inttypes.h>
+ *
+ * If you choose to use <inttypes.h> then please define:
+ *
+ * #define SHA2_USE_INTTYPES_H
+ *
+ * Or on the command line during compile:
+ *
+ * cc -DSHA2_USE_INTTYPES_H ...
+ */
+#ifdef SHA2_USE_INTTYPES_H
+
+typedef struct _SHA256_CTX {
+ uint32_t state[8];
+ uint64_t bitcount;
+ uint8_t buffer[SHA256_BLOCK_LENGTH];
+} SHA256_CTX;
+typedef struct _SHA512_CTX {
+ uint64_t state[8];
+ uint64_t bitcount[2];
+ uint8_t buffer[SHA512_BLOCK_LENGTH];
+} SHA512_CTX;
+
+#else /* SHA2_USE_INTTYPES_H */
+
+typedef struct _SHA256_CTX {
+ u_int32_t state[8];
+ u_int64_t bitcount;
+ u_int8_t buffer[SHA256_BLOCK_LENGTH];
+} SHA256_CTX;
+typedef struct _SHA512_CTX {
+ u_int64_t state[8];
+ u_int64_t bitcount[2];
+ u_int8_t buffer[SHA512_BLOCK_LENGTH];
+} SHA512_CTX;
+
+#endif /* SHA2_USE_INTTYPES_H */
+
+typedef SHA512_CTX SHA384_CTX;
+
+
+/*** SHA-256/384/512 Function Prototypes ******************************/
+#ifndef NOPROTO
+#ifdef SHA2_USE_INTTYPES_H
+
+void SHA256_Init(SHA256_CTX *);
+void SHA256_Update(SHA256_CTX*, const uint8_t*, size_t);
+void SHA256_Final(uint8_t[SHA256_DIGEST_LENGTH], SHA256_CTX*);
+char* SHA256_End(SHA256_CTX*, char[SHA256_DIGEST_STRING_LENGTH]);
+char* SHA256_Data(const uint8_t*, size_t, char[SHA256_DIGEST_STRING_LENGTH]);
+
+void SHA384_Init(SHA384_CTX*);
+void SHA384_Update(SHA384_CTX*, const uint8_t*, size_t);
+void SHA384_Final(uint8_t[SHA384_DIGEST_LENGTH], SHA384_CTX*);
+char* SHA384_End(SHA384_CTX*, char[SHA384_DIGEST_STRING_LENGTH]);
+char* SHA384_Data(const uint8_t*, size_t, char[SHA384_DIGEST_STRING_LENGTH]);
+
+void SHA512_Init(SHA512_CTX*);
+void SHA512_Update(SHA512_CTX*, const uint8_t*, size_t);
+void SHA512_Final(uint8_t[SHA512_DIGEST_LENGTH], SHA512_CTX*);
+char* SHA512_End(SHA512_CTX*, char[SHA512_DIGEST_STRING_LENGTH]);
+char* SHA512_Data(const uint8_t*, size_t, char[SHA512_DIGEST_STRING_LENGTH]);
+
+#else /* SHA2_USE_INTTYPES_H */
+
+void SHA256_Init(SHA256_CTX *);
+void SHA256_Update(SHA256_CTX*, const u_int8_t*, size_t);
+void SHA256_Final(u_int8_t[SHA256_DIGEST_LENGTH], SHA256_CTX*);
+char* SHA256_End(SHA256_CTX*, char[SHA256_DIGEST_STRING_LENGTH]);
+char* SHA256_Data(const u_int8_t*, size_t, char[SHA256_DIGEST_STRING_LENGTH]);
+
+void SHA384_Init(SHA384_CTX*);
+void SHA384_Update(SHA384_CTX*, const u_int8_t*, size_t);
+void SHA384_Final(u_int8_t[SHA384_DIGEST_LENGTH], SHA384_CTX*);
+char* SHA384_End(SHA384_CTX*, char[SHA384_DIGEST_STRING_LENGTH]);
+char* SHA384_Data(const u_int8_t*, size_t, char[SHA384_DIGEST_STRING_LENGTH]);
+
+void SHA512_Init(SHA512_CTX*);
+void SHA512_Update(SHA512_CTX*, const u_int8_t*, size_t);
+void SHA512_Final(u_int8_t[SHA512_DIGEST_LENGTH], SHA512_CTX*);
+char* SHA512_End(SHA512_CTX*, char[SHA512_DIGEST_STRING_LENGTH]);
+char* SHA512_Data(const u_int8_t*, size_t, char[SHA512_DIGEST_STRING_LENGTH]);
+
+#endif /* SHA2_USE_INTTYPES_H */
+
+#else /* NOPROTO */
+
+void SHA256_Init();
+void SHA256_Update();
+void SHA256_Final();
+char* SHA256_End();
+char* SHA256_Data();
+
+void SHA384_Init();
+void SHA384_Update();
+void SHA384_Final();
+char* SHA384_End();
+char* SHA384_Data();
+
+void SHA512_Init();
+void SHA512_Update();
+void SHA512_Final();
+char* SHA512_End();
+char* SHA512_Data();
+
+#endif /* NOPROTO */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __SHA2_H__ */
+
.PHONY: all
all: lua.so nterfacer_lua.so
-lua.so: lua.o luacommands.o luacontrol.o luabot.o lualocal.o luadebug.o
+lua.so: lua.o luacommands.o luacontrol.o luabot.o lualocal.o luadebug.o luadb.o luasocket.o
ld -shared -Bdynamic -o $@ $^ ${LIBLUA} ${ADDLIB}
nterfacer_lua.so: nterfacer_lua.o
void lua_startup(void *arg);
void lua_loadscripts(void);
void lua_registercommands(lua_State *l);
+void lua_registerdbcommands(lua_State *l);
void lua_initnickpusher(void);
void lua_initchanpusher(void);
void lua_loadlibs(lua_State *l);
void lua_deregisternicks(lua_list *l);
void lua_registerlocalcommands(lua_State *ps);
void lua_registerdebug(lua_State *ps);
+void lua_socket_closeall(lua_list *l);
+void lua_registersocketcommands(lua_State *ps);
#ifdef LUA_DEBUGSOCKET
lua_registerdebug(l);
lua_registercommands(l);
lua_registerlocalcommands(l);
+ lua_registerdbcommands(l);
+ lua_registersocketcommands(l);
lua_setpath(l);
return NULL;
}
- top = lua_gettop(l);
-
- if(lua_pcall(l, 0, 0, 0)) {
- Error("lua", ERR_ERROR, "Error pcalling: %s.", file);
- lua_close(l);
- freesstring(n->name);
- free(n);
- return NULL;
- }
-
- lua_settop(l, top);
-
- Error("lua", ERR_INFO, "Loaded %s.", file);
n->l = l;
n->next = NULL;
n->prev = lua_tail;
n->nicks = NULL;
+ n->sockets = NULL;
if(!lua_head) {
lua_head = n;
lua_tail = n;
+ top = lua_gettop(l);
+
+ if(lua_pcall(l, 0, 0, 0)) {
+ Error("lua", ERR_ERROR, "Error pcalling: %s.", file);
+ lua_close(l);
+ freesstring(n->name);
+ free(n);
+ return NULL;
+ }
+
+ lua_settop(l, top);
+
+ Error("lua", ERR_INFO, "Loaded %s.", file);
lua_onload(l);
return l;
void lua_unloadscript(lua_list *l) {
lua_onunload(l->l);
lua_deregisternicks(l);
+ lua_socket_closeall(l);
lua_close(l->l);
freesstring(l->name);
return &dummy;
}
+int lua_listexists(lua_list *l) {
+ lua_list *i;
+
+ for(i=lua_head;i;i=i->next)
+ if(i == l)
+ return 1;
+
+ return 0;
+}
+
int lua_lineok(const char *data) {
if(strchr(data, '\r') || strchr(data, '\n'))
return 0;
#include "../lib/sstring.h"
#include "lualocal.h"
+#include "luasocket.h"
/*** defines ************************************/
-#define LUA_BOTVERSION "1.75"
+#define LUA_BOTVERSION "1.83"
#define LUA_CHANFIXBOT "Z"
#define LUA_OPERCHAN "#twilightzone"
struct lua_list *next;
struct lua_list *prev;
lua_localnick *nicks;
+ lua_socket *sockets;
} lua_list;
#define LUA_STARTLOOP(l) { lua_list *ll; for(ll=lua_head;ll;ll=ll->next) { l = ll->l
void lua_unloadscript(lua_list *l);
lua_list *lua_scriptloaded(char *name);
lua_list *lua_listfromstate(lua_State *l);
+int lua_listexists(lua_list *l);
int lua_lineok(const char *data);
#define lua_toint(l, n) (int)lua_tonumber(l, n)
#include "../localuser/localuserchannel.h"
#include "../core/schedule.h"
#include "../lib/irc_string.h"
+#include "../core/config.h"
#include "lua.h"
#include "luabot.h"
void lua_startbot(void *arg) {
channel *cp;
+ sstring *n;
myureconnect = NULL;
- lua_nick = registerlocaluser("U", "lua", "quakenet.department.of.corrections", LUA_FULLVERSION, "U", UMODE_ACCOUNT | UMODE_DEAF | UMODE_OPER | UMODE_SERVICE, &lua_bothandler);
+ n = getcopyconfigitem("lua", "botnick", "U", NICKLEN);
+ lua_nick = registerlocaluser(n->content, "lua", "quakenet.department.of.corrections", LUA_FULLVERSION, "U", UMODE_ACCOUNT | UMODE_DEAF | UMODE_OPER | UMODE_SERVICE, &lua_bothandler);
if(!lua_nick) {
myureconnect = scheduleoneshot(time(NULL) + 1, &lua_startbot, NULL);
return;
case 'S':
lua_pushstring(l, ((sstring *)(va_arg(va, sstring *)))->content);
break;
+ case 'L':
+ {
+ char *p = va_arg(va, char *);
+ long len = va_arg(va, long);
+ lua_pushlstring(l, p, len);
+ }
+ break;
case 'N':
{
nick *np = va_arg(va, nick *);
case '0':
lua_pushnil(l);
break;
+ case 'R':
+ lua_rawgeti(l, LUA_REGISTRYINDEX, va_arg(va, long));
+ break;
+ case 'b':
+ lua_pushboolean(l, va_arg(va, int));
+ break;
case '>':
goto endwhile;
nick *kicked = arglist[1];
nick *kicker = arglist[2];
char *message = (char *)arglist[3];
+ int mode = 1;
if(!kicker || IsOper(kicker) || IsService(kicker) || IsXOper(kicker)) /* bloody Cruicky */
- return;
+ mode = 0;
- if(kicker) {
+ if(mode) {
lua_avpcall("irc_onkick", "Slls", ci->name, kicked->numeric, kicker->numeric, message);
+ } else if(kicker) {
+ lua_avpcall("irc_onkickall", "Slls", ci->name, kicked->numeric, kicker->numeric, message);
} else {
- lua_avpcall("irc_onkick", "Sl0s", ci->name, kicked->numeric, message);
+ lua_avpcall("irc_onkickall", "Sl0s", ci->name, kicked->numeric, message);
}
}
int hashindex;
nick *lasthashnick;
+static int geoipext;
struct lua_pusher *nickhashpusher[MAX_PUSHER];
lasthashnick = NULL;
lua_setupnickpusher(l, 1, nickhashpusher, MAX_PUSHER);
+ geoipext = findnickext("geoip");
return lua_getnextnick(l);
}
#define PUSHER_SSTRING 6
#define PUSHER_TOTALUSERS 7
#define PUSHER_TOPIC 8
+#define PUSHER_UMODES 9
+#define PUSHER_COUNTRY 10
void lua_initnickpusher(void) {
int i = 0;
#define PUSH_NICKPUSHER(F2, O2) nickpusher[i].argtype = F2; nickpusher[i].structname = #O2; nickpusher[i].offset = offsetof(nick, O2); i++;
+#define PUSH_NICKPUSHER_CUSTOM(F2, custom) nickpusher[i].argtype = F2; nickpusher[i].structname = custom; nickpusher[i].offset = 0; i++;
PUSH_NICKPUSHER(PUSHER_STRING, nick);
PUSH_NICKPUSHER(PUSHER_STRING, ident);
PUSH_NICKPUSHER(PUSHER_STRING, authname);
PUSH_NICKPUSHER(PUSHER_IP, ipnode);
PUSH_NICKPUSHER(PUSHER_LONG, numeric);
+ PUSH_NICKPUSHER(PUSHER_LONG, timestamp);
+ PUSH_NICKPUSHER(PUSHER_LONG, accountts);
+ PUSH_NICKPUSHER(PUSHER_UMODES, umodes);
+ PUSH_NICKPUSHER_CUSTOM(PUSHER_COUNTRY, "country");
nickpushercount = i;
nickpusher[i].argtype = 0;
lua_pushlong(l, *((long *)offset));
break;
case PUSHER_IP:
- lua_pushstring(l, IPtostr((((patricia_node_t *)offset)->prefix->sin)));
+ lua_pushstring(l, IPtostr((*((patricia_node_t **)offset))->prefix->sin));
break;
case PUSHER_TOTALUSERS:
lua_pushint(l, (*((channel **)offset))->users->totalusers);
break;
+ case PUSHER_UMODES:
+ lua_pushstring(l, printflags(*((flag_t *)offset), umodeflags));
+ break;
case PUSHER_TOPIC:
if((*((channel **)offset))->topic) {
lua_pushstring(l, (*((channel **)offset))->topic->content);
lua_pushnil(l);
}
break;
+ case PUSHER_COUNTRY:
+ if(geoipext < 0) {
+ lua_pushint(l, -1);
+ } else {
+ lua_pushint(l, (long)((nick *)offset)->exts[geoipext]);
+ }
+ break;
}
i++;
--- /dev/null
+#include "../pqsql/pqsql.h"
+#include "lua.h"
+#include "luabot.h"
+
+static int lua_dbcreatequery(lua_State *ps) {
+ char *s = (char *)lua_tostring(ps, 1);
+
+ if(!s)
+ LUA_RETURN(ps, LUA_FAIL);
+
+ pqcreatequery(s);
+ LUA_RETURN(ps, LUA_OK);
+}
+
+/* TODO */
+/*
+static int lua_dbloadtable(lua_State *ps) {
+ lua_list *l = lua_listfromstate(ps);
+ if(!l)
+ LUA_RETURN(ps, LUA_FAIL);
+
+}
+*/
+
+typedef struct lua_callback {
+ lua_list *l;
+ long handler, args;
+} lua_callback;
+
+/* hack */
+PGresult *pgres;
+
+static int lua_dbnumfields(lua_State *ps) {
+ lua_pushint(ps, PQnfields(pgres));
+
+ return 1;
+}
+
+static int lua_dbnumrows(lua_State *ps) {
+ lua_pushint(ps, PQntuples(pgres));
+
+ return 1;
+}
+
+static int lua_dbgetvalue(lua_State *ps) {
+ char *r;
+ int tuple, field, len;
+
+ if(!lua_isint(ps, 1) || !lua_isint(ps, 2))
+ return 0;
+
+ tuple = lua_toint(ps, 1);
+ field = lua_toint(ps, 2);
+
+ r = PQgetvalue(pgres, lua_toint(ps, 1), lua_toint(ps, 2));
+ len = PQgetlength(pgres, tuple, field);
+
+ lua_pushlstring(ps, r, len); /* safe?! */
+
+ return 1;
+}
+
+void lua_dbcallback(PGconn *dbconn, void *arg) {
+ pgres = PQgetResult(dbconn);
+ lua_callback *c = (lua_callback *)arg;
+
+ if(!lua_listexists(c->l)) {
+ free(c);
+ return;
+ }
+
+ if(PQresultStatus(pgres) != PGRES_TUPLES_OK) {
+ _lua_vpcall(c->l->l, (void *)c->handler, LUA_POINTERMODE, "bR", 0, c->args);
+
+ luaL_unref(c->l->l, LUA_REGISTRYINDEX, c->handler);
+ luaL_unref(c->l->l, LUA_REGISTRYINDEX, c->args);
+ free(c);
+ return;
+ }
+
+ _lua_vpcall(c->l->l, (void *)c->handler, LUA_POINTERMODE, "bR", 1, c->args);
+
+ luaL_unref(c->l->l, LUA_REGISTRYINDEX, c->handler);
+ luaL_unref(c->l->l, LUA_REGISTRYINDEX, c->args);
+ free(c);
+ PQclear(pgres);
+ pgres = NULL;
+}
+
+static int lua_dbquery(lua_State *ps) {
+ lua_list *l = lua_listfromstate(ps);
+ char *q = (char *)lua_tostring(ps, 1);
+ lua_callback *cb;
+
+ /* what happens if 3 isn't there? */
+ if(!l || !q)
+ LUA_RETURN(ps, LUA_FAIL);
+
+ if(!lua_isfunction(ps, 2)) {
+ pqquery(q);
+ LUA_RETURN(ps, LUA_OK);
+ }
+
+ cb = (lua_callback *)malloc(sizeof(lua_callback));
+ if(!cb)
+ LUA_RETURN(ps, LUA_FAIL);
+
+ cb->l = l;
+ cb->args = luaL_ref(ps, LUA_REGISTRYINDEX);
+ cb->handler = luaL_ref(ps, LUA_REGISTRYINDEX);
+
+ pqasyncquery(lua_dbcallback, cb, q);
+
+ LUA_RETURN(ps, LUA_OK);
+}
+
+static int lua_dbescape(lua_State *ps) {
+ char ebuf[8192 * 2];
+ char *s = (char *)lua_tostring(ps, 1);
+ int len;
+ size_t elen;
+
+ if(!s)
+ return 0;
+
+ len = lua_strlen(ps, 1);
+ if(len > sizeof(ebuf) / 2 - 5)
+ return 0;
+
+ elen = PQescapeString(ebuf, s, len);
+ lua_pushlstring(ps, ebuf, elen);
+
+ return 1;
+}
+
+void lua_registerdbcommands(lua_State *l) {
+ lua_register(l, "db_createquery", lua_dbcreatequery);
+
+/* lua_register(l, "db_loadtable", lua_dbloadtable); */
+
+ lua_register(l, "db_query", lua_dbquery);
+ lua_register(l, "db_escape", lua_dbescape);
+ lua_register(l, "db_numfields", lua_dbnumfields);
+ lua_register(l, "db_numrows", lua_dbnumrows);
+ lua_register(l, "db_getvalue", lua_dbgetvalue);
+}
--- /dev/null
+/* Copyright (C) Chris Porter 2007 */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/poll.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <errno.h>
+#include <fcntl.h>
+#include "../lib/strlfunc.h"
+#include "../core/events.h"
+
+#include "lua.h"
+#include "luabot.h"
+
+#define lua_vnpcall(F2, N2, S2, ...) _lua_vpcall(F2->l->l, (void *)F2->handler, LUA_POINTERMODE, "lsR" S2 , F2->identifier, N2, F2->tag , ##__VA_ARGS__)
+
+/*
+ * instead of these identifiers I could just use the file descriptor...
+ * BUT I can't remember the exact semantics of the fd table WRT reuse...
+ */
+static long nextidentifier = 0;
+static void lua_socket_poll_event(int fd, short events);
+
+static int lua_socket_unix_connect(lua_State *l) {
+ int len, ret;
+ struct sockaddr_un r;
+ char *path;
+ lua_socket *ls;
+ lua_list *ll;
+
+ ll = lua_listfromstate(l);
+ if(!ll)
+ return 0;
+
+ if(!lua_isfunction(l, 2))
+ return 0;
+
+ path = (char *)lua_tostring(l, 1);
+ if(!path)
+ return 0;
+
+ ls = (lua_socket *)malloc(sizeof(lua_socket));
+ if(!ls)
+ return 0;
+
+ ls->fd = socket(AF_UNIX, SOCK_STREAM, 0);
+ if(ls->fd <= -1) {
+ free(ls);
+ return 0;
+ }
+
+ memset(&r, 0, sizeof(r));
+ r.sun_family = AF_UNIX;
+ strlcpy(r.sun_path, path, sizeof(r.sun_path));
+
+ /* don't really like this, there's a macro in sys/un.h but it's not there under FreeBSD */
+ len = sizeof(r.sun_family) + strlen(r.sun_path) + 1;
+
+ /* WTB exceptions */
+ ret = fcntl(ls->fd, F_GETFL, 0);
+ if(ret < 0) {
+ free(ls);
+ close(ls->fd);
+ return 0;
+ }
+
+ ret = fcntl(ls->fd, F_SETFL, ret | O_NONBLOCK);
+ if(ret < 0) {
+ free(ls);
+ close(ls->fd);
+ return 0;
+ }
+
+ ret = connect(ls->fd, (struct sockaddr *)&r, len);
+ if(ret == 0) {
+ ls->state = SOCKET_CONNECTED;
+ } else if(ret == -1 && (errno == EINPROGRESS)) {
+ ls->state = SOCKET_CONNECTING;
+ } else {
+ free(ls);
+ close(ls->fd);
+ return 0;
+ }
+
+ /* this whole identifier thing should probably use userdata stuff */
+ ls->identifier = nextidentifier++;
+ ls->tag = luaL_ref(l, LUA_REGISTRYINDEX);
+ ls->handler = luaL_ref(l, LUA_REGISTRYINDEX);
+
+ ls->l = ll;
+
+ ls->next = ll->sockets;
+ ll->sockets = ls;
+
+ registerhandler(ls->fd, (ls->state==SOCKET_CONNECTED?POLLIN:POLLOUT) | POLLERR | POLLHUP, lua_socket_poll_event);
+
+ lua_pushboolean(l, ls->state==SOCKET_CONNECTED?1:0);
+ lua_pushlong(l, ls->identifier);
+ return 2;
+}
+
+static lua_socket *socketbyfd(int fd) {
+ lua_list *l;
+ lua_socket *ls;
+
+ for(l=lua_head;l;l=l->next)
+ for(ls=l->sockets;ls;ls=ls->next)
+ if(ls->fd == fd)
+ return ls;
+
+ return NULL;
+}
+
+static lua_socket *socketbyidentifier(long identifier) {
+ lua_list *l;
+ lua_socket *ls;
+
+ for(l=lua_head;l;l=l->next)
+ for(ls=l->sockets;ls;ls=ls->next)
+ if(ls->identifier == identifier)
+ return ls;
+
+ return NULL;
+}
+
+static void lua_socket_call_close(lua_socket *ls) {
+ lua_socket *p, *c;
+
+ for(c=ls->l->sockets,p=NULL;c;p=c,c=c->next) {
+ if(c == ls) {
+ if(ls->state == SOCKET_CLOSED)
+ return;
+
+ ls->state = SOCKET_CLOSED;
+ deregisterhandler(ls->fd, 1);
+
+ lua_vnpcall(ls, "close", "");
+
+ if(!p) {
+ ls->l->sockets = ls->next;
+ } else {
+ p->next = ls->next;
+ }
+
+ luaL_unref(ls->l->l, LUA_REGISTRYINDEX, ls->tag);
+ luaL_unref(ls->l->l, LUA_REGISTRYINDEX, ls->handler);
+
+ free(ls);
+ return;
+ }
+ }
+
+}
+
+static int lua_socket_write(lua_State *l) {
+ char *buf;
+ long len;
+ lua_socket *ls;
+ int ret;
+
+ buf = (char *)lua_tostring(l, 2);
+
+ if(!lua_islong(l, 1) || !buf) {
+ lua_pushint(l, -1);
+ return 1;
+ }
+ len = lua_strlen(l, 2);
+
+ ls = socketbyidentifier(lua_tolong(l, 1));
+ if(!ls || (ls->state != SOCKET_CONNECTED)) {
+ lua_pushint(l, -1);
+ return 1;
+ }
+
+ ret = write(ls->fd, buf, len);
+ if(ret == -1 && (errno == EAGAIN)) {
+ deregisterhandler(ls->fd, 0);
+ registerhandler(ls->fd, POLLIN | POLLOUT | POLLERR | POLLHUP, lua_socket_poll_event);
+
+ lua_pushint(l, 0);
+ return 1;
+ }
+
+ if(ret == -1)
+ lua_socket_call_close(ls);
+
+ if(ret < len) {
+ deregisterhandler(ls->fd, 0);
+ registerhandler(ls->fd, POLLIN | POLLOUT | POLLERR | POLLHUP, lua_socket_poll_event);
+ }
+
+ lua_pushint(l, ret);
+ return 1;
+}
+
+static int lua_socket_close(lua_State *l) {
+ lua_socket *ls;
+
+ if(!lua_islong(l, 1))
+ LUA_RETURN(l, LUA_FAIL);
+
+ ls = socketbyidentifier(lua_tolong(l, 1));
+ if(!ls || (ls->state == SOCKET_CLOSED))
+ LUA_RETURN(l, LUA_FAIL);
+
+ lua_socket_call_close(ls);
+
+ LUA_RETURN(l, LUA_OK);
+}
+
+static void lua_socket_poll_event(int fd, short events) {
+ lua_socket *ls = socketbyfd(fd);
+ if(!ls || (ls->state == SOCKET_CLOSED))
+ return;
+
+ if(events & (POLLERR | POLLHUP)) {
+ lua_socket_call_close(ls);
+ return;
+ }
+
+ switch(ls->state) {
+ case SOCKET_CONNECTING:
+ if(events & POLLOUT) {
+ deregisterhandler(fd, 0);
+ registerhandler(fd, POLLIN | POLLERR | POLLHUP, lua_socket_poll_event);
+ ls->state = SOCKET_CONNECTED;
+
+ lua_vnpcall(ls, "connect", "");
+ }
+ break;
+ case SOCKET_CONNECTED:
+ if(events & POLLOUT) {
+ deregisterhandler(fd, 0);
+ registerhandler(fd, POLLIN | POLLERR | POLLHUP, lua_socket_poll_event);
+
+ lua_vnpcall(ls, "flush", "");
+ }
+ if(events & POLLIN) {
+ char buf[8192 * 2];
+ int bytesread;
+
+ bytesread = read(fd, buf, sizeof(buf));
+ if((bytesread == -1) && (errno == EAGAIN))
+ return;
+
+ if(bytesread <= 0) {
+ lua_socket_call_close(ls);
+ return;
+ }
+
+ lua_vnpcall(ls, "read", "L", buf, bytesread);
+ }
+ break;
+ }
+}
+
+void lua_socket_closeall(lua_list *l) {
+ while(l->sockets)
+ lua_socket_call_close(l->sockets);
+}
+
+void lua_registersocketcommands(lua_State *l) {
+ lua_register(l, "socket_unix_connect", lua_socket_unix_connect);
+ lua_register(l, "socket_close", lua_socket_close);
+ lua_register(l, "socket_write", lua_socket_write);
+}
--- /dev/null
+/* Copyright (C) Chris Porter 2007 */
+
+#ifndef _LUA_SOCKET_H
+#define _LUA_SOCKET_H
+
+#include "lua.h"
+
+typedef struct lua_socket {
+ int fd;
+ int state;
+ long handler;
+ long tag;
+ unsigned long identifier;
+ struct lua_list *l;
+ struct lua_socket *next;
+} lua_socket;
+
+#define SOCKET_CONNECTING 0x00
+#define SOCKET_CONNECTED 0x01
+#define SOCKET_CLOSED 0x02
+
+#endif
+
.PHONY: all
all: newsearch.so
-newsearch.so: newsearch.o ns-not.o ns-and.o ns-or.o ns-eq.o ns-match.o ns-hostmask.o ns-realname.o ns-modes.o ns-nick.o ns-ident.o ns-regex.o ns-host.o ns-channel.o ns-lt.o ns-gt.o ns-timestamp.o ns-country.o ns-authname.o ns-ip.o ns-kill.o ns-gline.o ns-exists.o ns-services.o ns-size.o ns-name.o ns-topic.o ns-oppct.o ns-hostpct.o ns-authedpct.o ns-length.o
+newsearch.so: newsearch.o formats.o ns-not.o ns-and.o ns-or.o ns-eq.o ns-match.o ns-hostmask.o ns-realname.o ns-modes.o ns-nick.o ns-ident.o ns-regex.o ns-host.o ns-channel.o ns-lt.o ns-gt.o ns-timestamp.o ns-country.o ns-authname.o ns-ip.o ns-kill.o ns-gline.o ns-exists.o ns-services.o ns-size.o ns-name.o ns-topic.o ns-oppct.o ns-hostpct.o ns-authedpct.o ns-length.o ns-kick.o ns-authts.o ns-channels.o ns-server.o
ld -shared -Bdynamic $(LIBPCRE) -o $@ $^
--- /dev/null
+
+#include <stdio.h>
+#include "newsearch.h"
+
+#include "../irc/irc_config.h"
+#include "../lib/irc_string.h"
+#include "../parser/parser.h"
+#include "../control/control.h"
+#include "../lib/splitline.h"
+#include "../lib/version.h"
+
+void printnick(nick *sender, nick *np) {
+ char hostbuf[HOSTLEN+NICKLEN+USERLEN+4];
+
+ controlreply(sender,"%s [%s] (%s) (%s)",visiblehostmask(np,hostbuf),
+ IPtostr(np->p_ipaddr), printflags(np->umodes, umodeflags), np->realname->name->content);
+}
+
+void printnick_channels(nick *sender, nick *np) {
+ char hostbuf[HOSTLEN+NICKLEN+USERLEN+4];
+ char chanlistbuf[512];
+ unsigned int bufpos=0, overflow=0;
+ channel **cs, *cp;
+ unsigned int i;
+ unsigned long *lp;
+
+ /* Include the default format too */
+ printnick(sender,np);
+
+ /* Now add the channels.. */
+ cs=(channel **)(np->channels->content);
+ for (i=0;i<np->channels->cursi;i++) {
+ cp=cs[i];
+
+ if (!(lp=getnumerichandlefromchanhash(cp->users,np->numeric)))
+ /* "Impossible" error case - nick not on this channel */
+ continue;
+
+ if (bufpos + cp->index->name->length > 400) {
+ overflow=1;
+ break;
+ }
+
+ if (*lp & CUMODE_OP) {
+ chanlistbuf[bufpos++]='@';
+ } else if (*lp & CUMODE_VOICE) {
+ chanlistbuf[bufpos++]='+';
+ }
+
+ bufpos+=sprintf(chanlistbuf+bufpos,"%s ",cp->index->name->content);
+ }
+
+ if (!bufpos) {
+ controlreply(sender," Not an any channels.");
+ } else {
+ controlreply(sender," On channel%s: %s%s",np->channels->cursi>1?"s":"", chanlistbuf, overflow?"[...]":"");
+ }
+}
+
+void printchannel(nick *sender, chanindex *cip) {
+ /* shamelessly stolen from (now defunct) chansearch.c */
+ int i;
+ int op,voice,peon;
+ int oper,service,hosts;
+ nick *np;
+ chanuserhash *cuhp;
+ unsigned int marker;
+
+ op=voice=peon=oper=service=hosts=0;
+ marker=nexthostmarker();
+
+ if (cip->channel==NULL) {
+ controlreply(sender,"[ Channel currently empty ] %s",cip->name->content);
+ } else {
+ cuhp=cip->channel->users;
+ for (i=0;i<cuhp->hashsize;i++) {
+ if (cuhp->content[i]!=nouser) {
+ if (cuhp->content[i]&CUMODE_OP) {
+ op++;
+ } else if (cuhp->content[i]&CUMODE_VOICE) {
+ voice++;
+ } else {
+ peon++;
+ }
+ if ((np=getnickbynumeric(cuhp->content[i]&CU_NUMERICMASK))!=NULL) {
+ if (IsOper(np)) {
+ oper++;
+ }
+ if (IsService(np)) {
+ service++;
+ }
+ if (np->host->marker!=marker) {
+ np->host->marker=marker;
+ hosts++;
+ }
+ }
+ }
+ }
+ controlreply(sender,"[ %4dU %4d@ %4d+ %4d %4d* %4dk %4dH ] %s (%s)",cuhp->totalusers,op,voice,peon,oper,
+ service,hosts,cip->name->content, printflags(cip->channel->flags, cmodeflags));
+ }
+}
+
+
+void printchannel_topic(nick *sender, chanindex *cip) {
+ if (cip->channel==NULL) {
+ controlreply(sender,"[ empty ] %-30s",cip->name->content);
+ } else {
+ controlreply(sender,"[%4u users] %s (%s)",cip->channel->users->totalusers,cip->name->content,cip->channel->topic?cip->channel->topic->content:"no topic");
+ }
+}
+
+void printchannel_services(nick *sender, chanindex *cip) {
+ int i;
+ chanuserhash *cuhp;
+ char servlist[300];
+ int slpos=0,slfull=0;
+ nick *np;
+ int servs=0;
+
+ if (cip->channel==NULL) {
+ controlreply(sender,"%-30s empty",cip->name->content);
+ } else {
+ cuhp=cip->channel->users;
+ for (i=0;i<cuhp->hashsize;i++) {
+ if (cuhp->content[i]!=nouser) {
+ if ((np=getnickbynumeric(cuhp->content[i]&CU_NUMERICMASK))) {
+ if (IsService(np)) {
+ servs++;
+ if (!slfull) {
+ if (slpos) {
+ slpos+=sprintf(&servlist[slpos],", ");
+ }
+ slpos+=sprintf(&servlist[slpos],"%s",np->nick);
+ if (slpos>280) {
+ sprintf(&servlist[slpos],", ...");
+ slfull=1;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ controlreply(sender,"%-30s %5d user%c %2d service%c %s%s%s",cip->name->content,cuhp->totalusers,
+ cuhp->totalusers>1?'s':' ',servs,(servs==1)?' ':'s',servs?"(":"",slpos?servlist:"",servs?")":"");
+ }
+}
+
MODULE_VERSION("");
CommandTree *searchTree;
+CommandTree *chanOutputTree;
+CommandTree *nickOutputTree;
int do_nicksearch(void *source, int cargc, char **cargv);
int do_chansearch(void *source, int cargc, char **cargv);
struct searchNode *search_parse(int type, char *input);
+void printnick(nick *, nick *);
+void printnick_channels(nick *, nick *);
+void printchannel(nick *, chanindex *);
+void printchannel_topic(nick *, chanindex *);
+void printchannel_services(nick *, chanindex *);
+
void registersearchterm(char *term, parseFunc parsefunc);
void deregistersearchterm(char *term, parseFunc parsefunc);
-void *trueval(int type);
-void *falseval(int type);
+void regchandisp(const char *name, ChanDisplayFunc handler) {
+ addcommandtotree(chanOutputTree, name, 0, 0, (CommandHandler)handler);
+}
+
+void unregchandisp(const char *name, ChanDisplayFunc handler) {
+ deletecommandfromtree(chanOutputTree, name, (CommandHandler)handler);
+}
+
+void regnickdisp(const char *name, NickDisplayFunc handler) {
+ addcommandtotree(nickOutputTree, name, 0, 0, (CommandHandler)handler);
+}
+
+void unregnickdisp(const char *name, NickDisplayFunc handler) {
+ deletecommandfromtree(nickOutputTree, name, (CommandHandler)handler);
+}
const char *parseError;
/* used for *_free functions that need to warn users of certain things
void _init() {
searchTree=newcommandtree();
+ chanOutputTree=newcommandtree();
+ nickOutputTree=newcommandtree();
/* Boolean operations */
registersearchterm("and",and_parse);
registersearchterm("hostmask",hostmask_parse);
registersearchterm("realname",realname_parse);
registersearchterm("authname",authname_parse);
+ registersearchterm("authts",authts_parse);
registersearchterm("ident",ident_parse);
registersearchterm("host",host_parse);
registersearchterm("channel",channel_parse);
registersearchterm("timestamp",timestamp_parse);
registersearchterm("country",country_parse);
registersearchterm("ip",ip_parse);
+ registersearchterm("channels",channels_parse);
+ registersearchterm("server",server_parse);
/* Channel operations */
registersearchterm("exists",exists_parse);
registersearchterm("oppct",oppct_parse);
registersearchterm("uniquehostpct",hostpct_parse);
registersearchterm("authedpct",authedpct_parse);
+ registersearchterm("kick",kick_parse);
/* Nickname / channel operations */
registersearchterm("modes",modes_parse);
/* Kill / gline parameters */
registersearchterm("kill",kill_parse);
registersearchterm("gline",gline_parse);
+
+ /* Nick output filters */
+ regnickdisp("default",printnick);
+ regnickdisp("channels",printnick_channels);
+
+ /* Channel output filters */
+ regchandisp("default",printchannel);
+ regchandisp("topic",printchannel_topic);
+ regchandisp("services",printchannel_services);
registercontrolhelpcmd("nicksearch",NO_OPER,4,do_nicksearch, "Usage: nicksearch <criteria>\nSearches for nicknames with the given criteria.");
registercontrolhelpcmd("chansearch",NO_OPER,4,do_chansearch, "Usage: chansearch <criteria>\nSearches for channels with the given criteria.");
void _fini() {
destroycommandtree(searchTree);
+ destroycommandtree(chanOutputTree);
+ destroycommandtree(nickOutputTree);
deregistercontrolcmd("nicksearch", do_nicksearch);
deregistercontrolcmd("chansearch", do_chansearch);
}
deletecommandfromtree(searchTree, term, (CommandHandler) parsefunc);
}
-void printnick(nick *sender, nick *np) {
- char hostbuf[HOSTLEN+NICKLEN+USERLEN+4];
-
- controlreply(sender,"%s [%s] (%s) (%s)",visiblehostmask(np,hostbuf),
- IPtostr(np->p_ipaddr), printflags(np->umodes, umodeflags), np->realname->name->content);
-}
-
-void printchannel(nick *sender, chanindex *cip) {
- /* shamelessly stolen from (now defunct) chansearch.c */
- int i;
- int op,voice,peon;
- int oper,service,hosts;
- nick *np;
- chanuserhash *cuhp;
- unsigned int marker;
-
- op=voice=peon=oper=service=hosts=0;
- marker=nexthostmarker();
-
- if (cip->channel==NULL) {
- controlreply(sender,"[ Channel currently empty ] %s",cip->name->content);
- } else {
- cuhp=cip->channel->users;
- for (i=0;i<cuhp->hashsize;i++) {
- if (cuhp->content[i]!=nouser) {
- if (cuhp->content[i]&CUMODE_OP) {
- op++;
- } else if (cuhp->content[i]&CUMODE_VOICE) {
- voice++;
- } else {
- peon++;
- }
- if ((np=getnickbynumeric(cuhp->content[i]&CU_NUMERICMASK))!=NULL) {
- if (IsOper(np)) {
- oper++;
- }
- if (IsService(np)) {
- service++;
- }
- if (np->host->marker!=marker) {
- np->host->marker=marker;
- hosts++;
- }
- }
- }
- }
- controlreply(sender,"[ %4dU %4d@ %4d+ %4d %4d* %4dk %4dH ] %s (%s)",cuhp->totalusers,op,voice,peon,oper,
- service,hosts,cip->name->content, printflags(cip->channel->flags, cmodeflags));
- }
-}
-
int do_nicksearch(void *source, int cargc, char **cargv) {
nick *sender = senderNSExtern = source, *np;
- int i;
+ int i,j;
struct searchNode *search;
int limit=500,matches=0;
char *ch;
int arg=0;
-
+ struct Command *cmd;
+ NickDisplayFunc display=printnick;
+ unsigned int cmarker;
+ unsigned int tchans=0,uchans=0;
+ struct channel **cs;
+
if (cargc<1)
return CMD_USAGE;
limit=strtoul(cargv[arg++],NULL,10);
break;
+ case 'd':
+ if (cargc<arg) {
+ controlreply(sender,"Error: -d switch requires an argument");
+ return CMD_USAGE;
+ }
+ cmd=findcommandintree(nickOutputTree, cargv[arg], 1);
+ if (!cmd) {
+ controlreply(sender,"Error: unknown output format %s",cargv[arg]);
+ return CMD_USAGE;
+ }
+ display=(NickDisplayFunc)cmd->handler;
+ arg++;
+ break;
+
default:
controlreply(sender,"Unrecognised flag -%c.",*ch);
}
return CMD_ERROR;
}
+ /* Get a marker value to mark "seen" channels for unique count */
+ cmarker=nextchanmarker();
+
/* The top-level node needs to return a BOOL */
search=coerceNode(search, RETURNTYPE_BOOL);
for (i=0;i<NICKHASHSIZE;i++) {
for (np=nicktable[i];np;np=np->next) {
if ((search->exe)(search, np)) {
+ /* Add total channels */
+ tchans += np->channels->cursi;
+
+ /* Check channels for uniqueness */
+ cs=(channel **)np->channels->content;
+ for (j=0;j<np->channels->cursi;j++) {
+ if (cs[j]->index->marker != cmarker) {
+ cs[j]->index->marker=cmarker;
+ uchans++;
+ }
+ }
+
if (matches<limit)
- printnick(sender, np);
+ display(sender, np);
+
if (matches==limit)
controlreply(sender, "--- More than %d matches, skipping the rest",limit);
matches++;
(search->free)(search);
- controlreply(sender,"--- End of list: %d matches", matches);
-
+ controlreply(sender,"--- End of list: %d matches; users were on %u channels (%u unique, %.1f average clones)",
+ matches, tchans, uchans, (float)tchans/uchans);
+
return CMD_OK;
}
int limit=500,matches=0;
char *ch;
int arg=0;
+ struct Command *cmd;
+ ChanDisplayFunc display=printchannel;
if (cargc<1)
return CMD_USAGE;
}
limit=strtoul(cargv[arg++],NULL,10);
break;
+
+ case 'd':
+ if (cargc<arg) {
+ controlreply(sender,"Error: -d switch requires an argument");
+ return CMD_USAGE;
+ }
+ cmd=findcommandintree(chanOutputTree, cargv[arg], 1);
+ if (!cmd) {
+ controlreply(sender,"Error: unknown output format %s",cargv[arg]);
+ return CMD_USAGE;
+ }
+ display=(ChanDisplayFunc)cmd->handler;
+ arg++;
+ break;
default:
controlreply(sender,"Unrecognised flag -%c.",*ch);
for (cip=chantable[i];cip;cip=cip->next) {
if ((search->exe)(search, cip)) {
if (matches<limit)
- printchannel(sender, cip);
+ display(sender, cip);
if (matches==limit)
controlreply(sender, "--- More than %d matches, skipping the rest",limit);
matches++;
return CMD_OK;
}
-void *trueval(int type) {
- switch(type) {
- default:
- case RETURNTYPE_INT:
- case RETURNTYPE_BOOL:
- return (void *)1;
-
- case RETURNTYPE_STRING:
- return "1";
- }
-}
-
-void *falseval(int type) {
- switch (type) {
- default:
- case RETURNTYPE_INT:
- case RETURNTYPE_BOOL:
- return NULL;
-
- case RETURNTYPE_STRING:
- return "";
- }
-}
-
struct coercedata {
struct searchNode *child;
union {
return thenode;
}
}
+
+struct bufs {
+ char *buf;
+ int capacity;
+ int len;
+};
+
+static int addchar(struct bufs *buf, char c) {
+ if(buf->len >= buf->capacity - 1)
+ return 0;
+
+ buf->buf[buf->len++] = c;
+
+ return 1;
+}
+
+static int addstr(struct bufs *buf, char *c) {
+ int remaining = buf->capacity - buf->len - 1;
+ char *p;
+
+ for(p=c;*p;p++) {
+ if(remaining-- <= 0)
+ return 0;
+
+ buf->buf[buf->len++] = *p;
+ }
+
+ return 1;
+}
+
+void nssnprintf(char *buf, size_t size, const char *format, nick *np) {
+ struct bufs b;
+ const char *p;
+ char *c;
+ char hostbuf[512];
+
+ if(size == 0)
+ return;
+
+ b.buf = buf;
+ b.capacity = size;
+ b.len = 0;
+
+ for(p=format;*p;p++) {
+ if(*p != '%') {
+ if(!addchar(&b, *p))
+ break;
+ continue;
+ }
+ p++;
+ if(*p == '\0')
+ break;
+ if(*p == '%') {
+ if(!addchar(&b, *p))
+ break;
+ continue;
+ }
+
+ c = NULL;
+ switch(*p) {
+ case 'n':
+ c = np->nick; break;
+ case 'i':
+ c = np->ident; break;
+ case 'h':
+ c = np->host->name->content; break;
+ case 'I':
+ snprintf(hostbuf, sizeof(hostbuf), "%s", IPtostr(np->p_ipaddr));
+ c = hostbuf;
+ break;
+ case 'u':
+ snprintf(hostbuf, sizeof(hostbuf), "%s!%s@%s", np->nick, np->ident, IPtostr(np->p_ipaddr));
+ c = hostbuf;
+ break;
+ default:
+ c = "(bad format specifier)";
+ }
+ if(c)
+ if(!addstr(&b, c))
+ break;
+ }
+
+ buf[b.len] = '\0';
+
+ /* not required */
+ /*
+ buf[size-1] = '\0';
+ */
+}
+
typedef struct searchNode *(*parseFunc)(int, int, char **);
typedef void (*freeFunc)(struct searchNode *);
typedef void *(*exeFunc)(struct searchNode *, void *);
+typedef void (*ChanDisplayFunc)(nick *, chanindex *);
+typedef void (*NickDisplayFunc)(nick *, nick *);
/* Core functions */
/* Logical (BOOL -> BOOL)*/
struct searchNode *hostmask_parse(int type, int argc, char **argv);
struct searchNode *realname_parse(int type, int argc, char **argv);
struct searchNode *authname_parse(int type, int argc, char **argv);
+struct searchNode *authts_parse(int type, int argc, char **argv);
struct searchNode *ident_parse(int type, int argc, char **argv);
struct searchNode *host_parse(int type, int argc, char **argv);
struct searchNode *channel_parse(int type, int argc, char **argv);
struct searchNode *timestamp_parse(int type, int argc, char **argv);
struct searchNode *country_parse(int type, int argc, char **argv);
struct searchNode *ip_parse(int type, int argc, char **argv);
+struct searchNode *channels_parse(int type, int argc, char **argv);
+struct searchNode *server_parse(int type, int argc, char **argv);
/* Channel functions (various types) */
struct searchNode *exists_parse(int type, int argc, char **argv);
struct searchNode *oppct_parse(int type, int argc, char **argv);
struct searchNode *hostpct_parse(int type, int argc, char **argv);
struct searchNode *authedpct_parse(int type, int argc, char **argv);
+struct searchNode *kick_parse(int type, int argc, char **argv);
/* Interpret a string to give a node */
struct searchNode *search_parse(int type, char *input);
/* Registration functions */
void registersearchterm(char *term, parseFunc parsefunc);
void deregistersearchterm(char *term, parseFunc parsefunc);
+void regchandisp(const char *name, ChanDisplayFunc handler);
+void unregchandisp(const char *name, ChanDisplayFunc handler);
+void regnickdisp(const char *name, NickDisplayFunc handler);
+void unregnickdisp(const char *name, NickDisplayFunc handler);
-void *trueval(int type);
-void *falseval(int type);
+/* Special nick* printf */
+void nssnprintf(char *, size_t, const char *, nick *);
typedef struct searchNode {
int returntype;
--- /dev/null
+/*
+ * AUTHTS functionality
+ */
+
+#include "newsearch.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+void *authts_exe(struct searchNode *thenode, void *theinput);
+void authts_free(struct searchNode *thenode);
+
+struct searchNode *authts_parse(int type, int argc, char **argv) {
+ struct searchNode *thenode;
+
+ if (type != SEARCHTYPE_NICK) {
+ parseError = "authts: this function is only valid for nick searches.";
+ return NULL;
+ }
+
+ if (!(thenode=(struct searchNode *)malloc(sizeof (struct searchNode)))) {
+ parseError = "malloc: could not allocate memory for this search.";
+ return NULL;
+ }
+
+ thenode->returntype = RETURNTYPE_INT;
+ thenode->localdata = NULL;
+ thenode->exe = authts_exe;
+ thenode->free = authts_free;
+
+ return thenode;
+}
+
+void *authts_exe(struct searchNode *thenode, void *theinput) {
+ nick *np = (nick *)theinput;
+
+ if (IsAccount(np))
+ return (void *)(np->accountts);
+ else
+ return (void *)0; /* will cast to a FALSE */
+
+}
+
+void authts_free(struct searchNode *thenode) {
+ free(thenode);
+}
--- /dev/null
+/*
+ * CHANNELS functionality
+ */
+
+#include "newsearch.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "../irc/irc_config.h"
+#include "../lib/irc_string.h"
+
+void *channels_exe(struct searchNode *thenode, void *theinput);
+void channels_free(struct searchNode *thenode);
+
+struct searchNode *channels_parse(int type, int argc, char **argv) {
+ struct searchNode *thenode;
+
+ if (type != SEARCHTYPE_NICK) {
+ parseError = "channels: this function is only valid for nick searches.";
+ return NULL;
+ }
+
+ if (!(thenode=(struct searchNode *)malloc(sizeof (struct searchNode)))) {
+ parseError = "malloc: could not allocate memory for this search.";
+ return NULL;
+ }
+
+ thenode->returntype = RETURNTYPE_INT;
+ thenode->localdata = NULL;
+ thenode->exe = channels_exe;
+ thenode->free = channels_free;
+
+ return thenode;
+}
+
+void *channels_exe(struct searchNode *thenode, void *theinput) {
+ nick *np = (nick *)theinput;
+
+ return (void *)np->channels->cursi;
+}
+
+void channels_free(struct searchNode *thenode) {
+ free(thenode);
+}
#include "../irc/irc_config.h"
#include "../lib/irc_string.h"
+#include "../geoip/geoip.h"
+#include "../core/modules.h"
void *country_exe(struct searchNode *thenode, void *theinput);
void country_free(struct searchNode *thenode);
struct searchNode *country_parse(int type, int argc, char **argv) {
struct searchNode *thenode;
+ GeoIP_LookupCode l;
+ int target;
if (type != SEARCHTYPE_NICK) {
parseError = "country: this function is only valid for nick searches.";
return NULL;
}
+ if (argc<1) {
+ parseError = "country: usage: country <country 2 character ISO code>";
+ return NULL;
+ }
+
ext = findnickext("geoip");
if(ext == -1) {
parseError = "country: Geoip module not loaded.";
return NULL;
}
+ l = ndlsym("geoip", "geoip_lookupcode");
+ target = l(argv[0]);
+ if(target == -1) {
+ parseError = "country: invalid country.";
+ return NULL;
+ }
if (!(thenode=(struct searchNode *)malloc(sizeof (struct searchNode)))) {
parseError = "malloc: could not allocate memory for this search.";
return NULL;
}
- thenode->returntype = RETURNTYPE_INT;
- thenode->localdata = NULL;
+ thenode->returntype = RETURNTYPE_BOOL;
+ thenode->localdata = (void *)target;
thenode->exe = country_exe;
thenode->free = country_free;
void *country_exe(struct searchNode *thenode, void *theinput) {
nick *np = (nick *)theinput;
+ int country = (int)thenode->localdata, rc = (int)np->exts[ext];
+
+ if(country == rc)
+ return (void *)1;
- return (void *)np->exts[ext];
+ return (void *)0;
}
void country_free(struct searchNode *thenode) {
#include "../control/control.h" /* controlreply() */
#include "../irc/irc.h" /* irc_send() */
#include "../lib/irc_string.h" /* IPtostr(), longtoduration(), durationtolong() */
+#include "../lib/strlfunc.h"
/* used for *_free functions that need to warn users of certain things
i.e. hitting too many users in a (kill) or (gline) - declared in newsearch.c */
extern nick *senderNSExtern;
+static const char *defaultreason = "You (%u) have been g-lined for violating our terms of service";
void *gline_exe(struct searchNode *thenode, void *theinput);
void gline_free(struct searchNode *thenode);
struct gline_localdata *localdata;
struct searchNode *thenode;
int len;
+ char *p;
if (!(localdata = (struct gline_localdata *) malloc(sizeof(struct gline_localdata)))) {
parseError = "malloc: could not allocate memory for this search.";
switch (argc) {
case 0:
localdata->duration = NSGLINE_DURATION;
- snprintf(localdata->reason, NSMAX_REASON_LEN, ".");
+ strlcpy(localdata->reason, defaultreason, sizeof(localdata->reason));
break;
case 1:
/* error checking on gline duration */
if (localdata->duration == 0)
localdata->duration = NSGLINE_DURATION;
- snprintf(localdata->reason, NSMAX_REASON_LEN, ".");
+ strlcpy(localdata->reason, defaultreason, sizeof(localdata->reason));
}
else { /* reason specified */
localdata->duration = NSGLINE_DURATION;
- len = snprintf(localdata->reason, NSMAX_REASON_LEN, ":%s", argv[0]);
- /* strip leading and trailing '"'s */
- localdata->reason[1] = ' ';
- localdata->reason[len-1] = '\0';
+
+ p = argv[0];
+ if(*p == '\"')
+ *p++;
+ len = strlcpy(localdata->reason, p, sizeof(localdata->reason));
+ if(len >= sizeof(localdata->reason)) {
+ localdata->reason[sizeof(localdata->reason)-1] = '\0';
+ } else {
+ localdata->reason[len-1] = '\0';
+ }
}
break;
/* error checking on gline duration */
if (localdata->duration == 0)
localdata->duration = NSGLINE_DURATION;
- len = snprintf(localdata->reason, NSMAX_REASON_LEN, ":%s", argv[1]);
- /* strip leading and trailing '"'s */
- localdata->reason[1] = ' ';
- localdata->reason[len-1] = '\0';
- break;
+ p = argv[1];
+ if(*p == '\"')
+ *p++;
+ len = strlcpy(localdata->reason, p, sizeof(localdata->reason));
+ if(len >= sizeof(localdata->reason)) {
+ localdata->reason[sizeof(localdata->reason)-1] = '\0';
+ } else {
+ localdata->reason[len-1] = '\0';
+ }
+
+ break;
default:
free(localdata);
parseError = "gline: invalid number of arguments";
nick *np, *nnp;
chanindex *cip, *ncip;
int i, j, safe=0;
+ char msgbuf[512];
localdata = thenode->localdata;
if ((np=getnickbynumeric(cip->channel->users->content[j]))) {
if (!IsOper(np) && !IsService(np) && !IsXOper(np)) {
+ nssnprintf(msgbuf, sizeof(msgbuf), localdata->reason, np);
if (np->host->clonecount <= NSMAX_GLINE_CLONES)
- irc_send("%s GL * +*@%s %u :You (%s!%s@%s) have been glined for violating our terms of service%s",
- mynumeric->content, IPtostr(np->p_ipaddr), localdata->duration, np->nick, np->ident, IPtostr(np->p_ipaddr), localdata->reason);
- else
- irc_send("%s GL * +%s@%s %u :You (%s!%s@%s) have been glined for violating our terms of service%s",
- mynumeric->content, np->ident, IPtostr(np->p_ipaddr), localdata->duration, np->nick, np->ident, IPtostr(np->p_ipaddr), localdata->reason);
- }
+ irc_send("%s GL * +*@%s %u :%s", mynumeric->content, IPtostr(np->p_ipaddr), localdata->duration, msgbuf);
else
- safe++;
+ irc_send("%s GL * +%s@%s %u :%s", mynumeric->content, np->ident, IPtostr(np->p_ipaddr), localdata->duration, msgbuf);
+ }
+ else
+ safe++;
}
}
}
nnp = np->next;
if (np->marker == localdata->marker) {
if (!IsOper(np) && !IsService(np) && !IsXOper(np)) {
+ nssnprintf(msgbuf, sizeof(msgbuf), localdata->reason, np);
if (np->host->clonecount <= NSMAX_GLINE_CLONES)
- irc_send("%s GL * +*@%s %u :You (%s!%s@%s) have been glined for violating our terms of service%s",
- mynumeric->content, IPtostr(np->p_ipaddr), localdata->duration, np->nick, np->ident, IPtostr(np->p_ipaddr), localdata->reason);
+ irc_send("%s GL * +*@%s %u :%s", mynumeric->content, IPtostr(np->p_ipaddr), localdata->duration, msgbuf);
else
- irc_send("%s GL * +%s@%s %u :You (%s!%s@%s) have been glined for violating our terms of service%s",
- mynumeric->content, np->ident, IPtostr(np->p_ipaddr), localdata->duration, np->nick, np->ident, IPtostr(np->p_ipaddr), localdata->reason);
+ irc_send("%s GL * +%s@%s %u :%s", mynumeric->content, np->ident, IPtostr(np->p_ipaddr), localdata->duration, msgbuf);
}
else
safe++;
--- /dev/null
+/*
+ * KICK functionality
+ */
+
+#include "newsearch.h"
+#include "../localuser/localuserchannel.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+void *kick_exe(struct searchNode *thenode, void *theinput);
+void kick_free(struct searchNode *thenode);
+
+struct searchNode *kick_parse(int type, int argc, char **argv) {
+ struct searchNode *thenode;
+ nick *np;
+
+ if (type!=SEARCHTYPE_CHANNEL) {
+ parseError="kick: only channel searches are supported";
+ return NULL;
+ }
+
+ if (argc!=1) {
+ parseError="kick: usage: (kick target)";
+ return NULL;
+ }
+
+ if ((np=getnickbynick(argv[0]))==NULL) {
+ parseError="kick: unknown nickname";
+ return NULL;
+ }
+
+ if (IsOper(np) || IsService(np)) {
+ parseError="kick: can't kick opers or services";
+ return NULL;
+ }
+
+ if (!(thenode=(struct searchNode *)malloc(sizeof(struct searchNode)))) {
+ parseError = "malloc: could not allocate memory for this search.";
+ return NULL;
+ }
+
+ thenode->returntype = RETURNTYPE_BOOL;
+ thenode->localdata = np;
+ thenode->exe = kick_exe;
+ thenode->free = kick_free;
+
+ return thenode;
+}
+
+void *kick_exe(struct searchNode *thenode, void *theinput) {
+ nick *np;
+ chanindex *cip;
+
+ np=thenode->localdata;
+ cip=(chanindex *)theinput;
+
+ if (cip->channel==NULL || getnumerichandlefromchanhash(cip->channel->users, np->numeric)==NULL)
+ return (void *)0;
+
+ localkickuser(NULL, cip->channel, np, "");
+ return (void *)1;
+}
+
+void kick_free(struct searchNode *thenode) {
+ free(thenode);
+}
#include "../control/control.h" /* controlreply() */
#include "../localuser/localuser.h" /* killuser() */
#include "../lib/irc_string.h" /* IPtostr() */
+#include "../lib/strlfunc.h"
/* used for *_free functions that need to warn users of certain things
i.e. hitting too many users in a (kill) or (gline) - declared in newsearch.c */
void *kill_exe(struct searchNode *thenode, void *theinput);
void kill_free(struct searchNode *thenode);
+static const char *defaultreason = "You (%u) have been disconnected for violating our terms of service";
struct kill_localdata {
unsigned int marker;
localdata->marker = nextnickmarker();
if (argc==1) {
- len = snprintf(localdata->reason, NSMAX_REASON_LEN, ":%s", argv[0]);
- /* strip leading and trailing '"'s */
- localdata->reason[1] = ' ';
- localdata->reason[len-1] = '\0';
+ char *p = argv[0];
+ if(*p == '\"')
+ *p++;
+ len = strlcpy(localdata->reason, p, sizeof(localdata->reason));
+ if(len >= sizeof(localdata->reason)) {
+ localdata->reason[sizeof(localdata->reason)-1] = '\0';
+ } else {
+ localdata->reason[len-1] = '\0';
+ }
}
else
- snprintf(localdata->reason, NSMAX_REASON_LEN, ".");
+ strlcpy(localdata->reason, defaultreason, sizeof(localdata->reason));
if (!(thenode=(struct searchNode *)malloc(sizeof (struct searchNode)))) {
/* couldn't malloc() memory for thenode, so free localdata to avoid leakage */
chanindex *cip, *ncip;
int i, j, safe=0;
unsigned int nickmarker;
+ char msgbuf[512];
localdata = thenode->localdata;
for (i=0;i<NICKHASHSIZE;i++) {
for(np=nicktable[i];np;np=nnp) {
nnp = np->next;
- if (np->marker == nickmarker)
- killuser(NULL, np, "You (%s!%s@%s) have been disconnected for violating our terms of service%s",
- np->nick,np->ident, IPtostr(np->p_ipaddr), localdata->reason);
+ if (np->marker == nickmarker) {
+ nssnprintf(msgbuf, sizeof(msgbuf), localdata->reason, np);
+ killuser(NULL, np, "%s", msgbuf);
+ }
}
}
}
nnp = np->next;
if (np->marker == localdata->marker) {
if (!IsOper(np) && !IsService(np) && !IsXOper(np)) {
- killuser(NULL, np, "You (%s!%s@%s) have been disconnected for violating our terms of service%s", np->nick,
- np->ident, IPtostr(np->p_ipaddr), localdata->reason);
+ nssnprintf(msgbuf, sizeof(msgbuf), localdata->reason, np);
+ killuser(NULL, np, "%s", msgbuf);
}
else
safe++;
}
/* Our subnode needs to return a BOOL */
- subnode=coerceNode(thenode, RETURNTYPE_BOOL);
+ subnode=coerceNode(subnode, RETURNTYPE_BOOL);
thenode->localdata=(void *)subnode;
--- /dev/null
+/*
+ * SERVER functionality
+ */
+
+#include "newsearch.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../irc/irc_config.h"
+#include "../lib/irc_string.h"
+#include "../core/modules.h"
+#include "../server/server.h"
+
+void *server_exe_bool(struct searchNode *thenode, void *theinput);
+void *server_exe_str(struct searchNode *thenode, void *theinput);
+void server_free(struct searchNode *thenode);
+
+int ext;
+
+struct searchNode *server_parse(int type, int argc, char **argv) {
+ struct searchNode *thenode;
+ int i;
+ long numeric;
+
+ if (type != SEARCHTYPE_NICK) {
+ parseError = "server: this function is only valid for nick searches.";
+ return NULL;
+ }
+
+ if (argc>0) {
+ numeric = -1;
+ for(i=0;i<MAXSERVERS;i++) {
+ sstring *n = serverlist[i].name;
+ if(n && !strcmp(n->content, argv[0])) {
+ numeric = i;
+ break;
+ }
+ }
+
+ if(numeric == -1) {
+ parseError = "server: server not found.";
+ return NULL;
+ }
+
+ thenode->returntype = RETURNTYPE_BOOL;
+ thenode->localdata = (void *)numeric;
+
+ thenode->exe = server_exe_bool;
+ } else {
+ thenode->returntype = RETURNTYPE_STRING;
+ thenode->localdata = NULL;
+
+ thenode->exe = server_exe_str;
+ }
+
+ thenode->free = server_free;
+
+ return thenode;
+}
+
+void *server_exe_bool(struct searchNode *thenode, void *theinput) {
+ nick *np = (nick *)theinput;
+ long server = (long)thenode->localdata;
+
+ if(homeserver(np->numeric) == server)
+ return (void *)1;
+
+ return (void *)0;
+}
+
+void *server_exe_str(struct searchNode *thenode, void *theinput) {
+ nick *np = (nick *)theinput;
+ sstring *n = serverlist[homeserver(np->numeric)].name;
+
+ if(!n)
+ return NULL;
+
+ return n->content;
+}
+
+void server_free(struct searchNode *thenode) {
+ free(thenode);
+}
{ 'h', UMODE_SETHOST },
{ 'R', UMODE_REGPRIV },
{ 'I', UMODE_HIDEIDLE },
+ { 'P', UMODE_PARANOID },
{ '\0', 0 } };
#define nickhash(x) ((crc32i(x))%NICKHASHSIZE)
#include <time.h>
+#ifndef MAXNICKEXTS
#define MAXNICKEXTS 6
+#endif
#define UMODE_INV 0x0001
#define UMODE_WALLOPS 0x0002
#include "../localuser/localuserchannel.h"
#include "../geoip/geoip.h"
#include "../lib/version.h"
+#include "../core/modules.h"
MODULE_VERSION("");
return CMD_OK;
}
-const char GeoIP_country_code[247][3] = { "--","AP","EU","AD","AE","AF","AG","AI","AL","AM","AN","AO","AQ","AR","AS","AT","AU","AW","AZ","BA","BB","BD","BE","BF","BG","BH","BI","BJ","BM","BN","BO","BR","BS","BT","BV","BW","BY","BZ","CA","CC","CD","CF","CG","CH","CI","CK","CL","CM","CN","CO","CR","CU","CV","CX","CY","CZ","DE","DJ","DK","DM","DO","DZ","EC","EE","EG","EH","ER","ES","ET","FI","FJ","FK","FM","FO","FR","FX","GA","GB","GD","GE","GF","GH","GI","GL","GM","GN","GP","GQ","GR","GS","GT","GU","GW","GY","HK","HM","HN","HR","HT","HU","ID","IE","IL","IN","IO","IQ","IR","IS","IT","JM","JO","JP","KE","KG","KH","KI","KM","KN","KP","KR","KW","KY","KZ","LA","LB","LC","LI","LK","LR","LS","LT","LU","LV","LY","MA","MC","MD","MG","MH","MK","ML","MM","MN","MO","MP","MQ","MR","MS","MT","MU","MV","MW","MX","MY","MZ","NA","NC","NE","NF","NG","NI","NL","NO","NP","NR","NU","NZ","OM","PA","PE","PF","PG","PH","PK","PL","PM","PN","PR","PS","PT","PW","PY","QA","RE","RO","RU","RW","SA","SB","SC","SD","SE","SG","SH","SI","SJ","SK","SL","SM","SN","SO","SR","ST","SV","SY","SZ","TC","TD","TF","TG","TH","TJ","TK","TM","TN","TO","TP","TR","TT","TV","TW","TZ","UA","UG","UM","US","UY","UZ","VA","VC","VE","VG","VI","VN","VU","WF","WS","YE","YT","YU","ZA","ZM","ZR","ZW","A1","A2","O1"};
-
int controlcbroadcast(void *sender, int cargc, char **cargv) {
nick *np = (nick *)sender, *nip;
int i, ext, target;
+ GeoIP_LookupCode l;
if(cargc < 2)
return CMD_USAGE;
return CMD_ERROR;
}
- target = COUNTRY_MIN - 1;
- for(i=COUNTRY_MIN;i<COUNTRY_MAX;i++) {
- if(!strcasecmp(cargv[0], GeoIP_country_code[i])) {
- target = i;
- break;
- }
- }
+ l = ndlsym("geoip", "geoip_lookupcode");
+ target = l(cargv[0]);
if(target == -1) {
controlreply(np, "Invalid country.");
void _init() {
if (!fakeuser_loaddb())
{
- Error("noperserv_fakeuser", ERR_ERROR, "Cannot load database");
+ Error("noperserv_fakeuser", ERR_FATAL, "Cannot load database");
return;
}
registercontrolhelpcmd("fakeuser", NO_OPER, 4, &fakeadd, "Usage: FAKEUSER nick <ident> <host> <realname>\nCreates a fake user.");
free(killed);
}
fakeusercount = 0;
+ killedusercount = 0;
fakeuserlist = NULL;
killeduserlist = NULL;
}
int fakeuser_loaddb()
+// Called from _init
{
if (!pqconnected())
return 0;
}
void fakeusers_load(PGconn *dbconn, void *tag)
+// Called automatically when the async database query finishes
{
PGresult *pgres = PQgetResult(dbconn);
user_details details;
int i, rowcount;
if (PQresultStatus(pgres) != PGRES_TUPLES_OK) {
- Error("noperserv_fakeuser", ERR_ERROR, "Error loading fakeuser list (%d)", PQresultStatus(pgres));
+ Error("noperserv_fakeuser", ERR_FATAL, "Error loading fakeuser list (%d)", PQresultStatus(pgres));
return;
}
- details.schedule = NULL;
rowcount = PQntuples(pgres);
Error("noperserv_fakeuser", ERR_INFO, "Loading %d users", rowcount);
details.lastkill = 0;
-
+ details.schedule = NULL;
for (i = 0; i < rowcount; i++)
{
strlcpy(details.nick, PQgetvalue(pgres, i, 0), NICKLEN + 1);
details = malloc(sizeof(user_details));
if (!details)
return NULL;
- details->schedule = NULL;
strlcpy(details->nick, user->nick, NICKLEN + 1);
strlcpy(details->ident, user->ident, USERLEN + 1);
strlcpy(details->host, user->host->name->content, HOSTLEN + 1);
strlcpy(details->realname, user->realname->name->content, REALLEN + 1);
+ details->schedule = NULL;
details->lastkill = 0;
return details;
}
nick *register_fakeuser(user_details *details)
{
nick *user;
- if((user = getnickbynick(details->nick)) && (IsOper(user) || IsService(user) || IsXOper(user))) {
+ if ((user = getnickbynick(details->nick)) && (IsOper(user) || IsService(user) || IsXOper(user))) {
err_code = ERR_WONTKILL;
return NULL;
}
NULL, UMODE_INV | UMODE_DEAF, &fakeuser_handler);
}
-fakeuser *ll_add(user_details *details) //Adds to the (sorted) linked list
+fakeuser *ll_add(user_details *details)
+// Adds to the (sorted) linked list
{
fakeuser *fake, *newfake;
int cmp;
err_code = ERR_MEM;
return NULL;
}
-
newfake->user = register_fakeuser(details);
if (!newfake->user)
{
free(newfake);
- /* errcode already set by register_fakeuser */
- return NULL;
+ return NULL; //errcode already set by register_fakeuser
}
newfake->lastkill = details->lastkill;
newfake->next = fakeuserlist;
if (!newfake->user)
{
free(newfake);
- /* errcode already set by register_fakeuser */
- return NULL;
+ return NULL; //errcode already set by register_fakeuser
}
newfake->lastkill = details->lastkill;
newfake->next = fake->next;
if (!newfake->user)
{
free(newfake);
- /* errcode already set by register_fakeuser */
- return NULL;
+ return NULL; //errcode already set by register_fakeuser
}
newfake->lastkill = details->lastkill;
newfake->next = NULL;
return newfake;
}
-void kll_add(user_details *details) //Adds to the (sorted) linked list of killed users
+void kll_add(user_details *details)
+//Adds to the (sorted) linked list of killed users
{
int cmp;
user_details *killed;
return;
}
-fakeuser *ll_remove(char *nickname) //Removes from the linked list
+fakeuser *ll_remove(char *nickname)
+//Removes from the linked list
{
fakeuser *fake, *rmfake;
int cmp;
details = getdetails(user);
item = ll_remove(details->nick);
- if(!item)
+ if (!item)
+ {
+ controlwall(NO_OPER, NL_FAKEUSERS, "Error: A fakeuser was killed, but wasn't found in the list");
+ Error("noperserv_fakeuser", ERR_ERROR, "A fakeuser was killed, but wasn't found in the list");
return;
+ }
details->lastkill = item->lastkill;
free(item);
- if(timenow - item->lastkill < KILL_TIME) {
+ if (timenow - details->lastkill < KILL_TIME) {
char escnick[NICKLEN * 2 + 1];
controlwall(NO_OPER, NL_FAKEUSERS, "Fake user %s!%s@%s (%s) KILL'ed twice under in %d seconds. Removing.", details->nick, details->ident, details->host, details->realname, KILL_TIME);
- item = ll_remove(details->nick);
- free(item);
-
PQescapeString(escnick, details->nick, strlen(details->nick));
pqquery("DELETE FROM noperserv.fakeusers WHERE nick = '%s'", escnick);
return;
if (err_code == ERR_EXISTS)
controlreply(sender, "Error: fakeuser already exists");
else if (err_code == ERR_MEM)
+ {
controlreply(sender, "Error: memory error!!");
+ Error("noperserv_fakeuser", ERR_STOP, "malloc error");
+ }
else if (err_code == ERR_WONTKILL)
controlreply(sender, "Nick already exists and I won't kill it");
else
+ {
controlreply(sender, "Unknown error when adding fakeuser");
+ Error("noperserv_fakeuser", ERR_ERROR, "Unknown error when adding fakeuser");
+ }
return CMD_ERROR;
}
newnick = newfake->user;
}
void reconnectfake(void *details)
+//Called after the timeout period has expired since a fakeuser was killed, or on load
{
fakeuser *fake;
user_details *u_details = details;
/*
- Easy async socket library with HELIX encryption and authentication
- Copyright (C) 2004-2005 Chris Porter.
-
- v1.03
- - changed nonce logic
- v1.02
- - added some \n stripping in crypto code
- v1.01
- - noticed small problem in _read, if ret == -1 && errno != EAGAIN then it would mess up
- - now disconnects on write buffer filling up
- - increased buffer size and maximum queue size
+ Easy async socket library
+ Copyright (C) 2004-2007 Chris Porter.
*/
#include "esockets.h"
#include <stdarg.h>
#include <netinet/in.h>
-#include "../lib/sha1.h"
#include "../core/events.h"
struct esocket *socklist = NULL;
newsock->fd = fd;
newsock->next = socklist;
- newsock->in.on_parse = buffer_parse_ascii;
- newsock->in.startpos = newsock->in.curpos = newsock->in.writepos = newsock->in.data;
- newsock->in.buffer_size = MAX_ASCII_LINE_SIZE;
- newsock->in.packet_length = 0;
+ newsock->in.mode = PARSE_ASCII;
+ newsock->in.data = NULL;
+ newsock->in.size = 0;
+ newsock->in.cryptobuf = NULL;
+ newsock->in.cryptobufsize = 0;
+ newsock->in.mac = 0;
+
newsock->out.head = NULL;
newsock->out.end = NULL;
newsock->out.count = 0;
pkt = npkt;
}
+ if(p->in.data)
+ free(p->in.data);
+ if(p->in.cryptobuf)
+ free(p->in.cryptobuf);
+
free(p);
break;
}
}
}
+int parse_ascii(struct esocket *sock, int *bytes_to_strip) {
+ struct esocket_in_buffer *buf = &sock->in;
+ char *p;
+ int i, ret;
+
+ for(p=buf->data,i=0;i<buf->size;i++,p++) {
+ if(*p == '\0' || *p == '\n') {
+ *p = '\0';
+
+ *bytes_to_strip = i + 1;
+ ret = sock->events.on_line(sock, buf->data);
+ if(ret)
+ return ret;
+
+ return 0;
+ }
+ }
+
+ *bytes_to_strip = 0;
+ return 0;
+}
+
+void seqno_update(hmacsha256 *h, u_int64_t value) {
+ u_int64_t v2 = htonq(value);
+ hmacsha256_update(h, (unsigned char *)&v2, 8);
+}
+
+int crypto_newblock(struct esocket *sock, unsigned char *block) {
+ unsigned char *p, *p2;
+ int i;
+ struct esocket_in_buffer *buf = &sock->in;
+
+ if(buf->mac) {
+ unsigned char digest[32];
+ int ret;
+ hmacsha256_final(&sock->clienthmac, digest);
+
+ if(memcmp(block, digest, 16)) /* mac error */
+ return 1;
+
+ hmacsha256_init(&sock->clienthmac, sock->clientkey, 32);
+ seqno_update(&sock->clienthmac, sock->clientseqno);
+ sock->clientseqno++;
+
+ ret = sock->events.on_line(sock, (char *)buf->cryptobuf);
+ free(buf->cryptobuf);
+ buf->cryptobuf = NULL;
+ buf->cryptobufsize = 0;
+ buf->mac = 0;
+
+ return ret;
+ }
+
+ hmacsha256_update(&sock->clienthmac, block, 16);
+ p = rijndaelcbc_decrypt(sock->clientcrypto, block);
+ for(p2=p,i=0;i<16;i++,p2++) { /* locate terminator */
+ if(*p2 == '\n' || *p2 == '\0') {
+ *p2 = '\0';
+ buf->mac = 1;
+ }
+ }
+
+ p2 = realloc(buf->cryptobuf, buf->cryptobufsize + 16);
+ if(!p2)
+ Error("nterface", ERR_STOP, "realloc() failed in crypto_newblock (esockets.c)");
+ buf->cryptobuf = p2;
+
+ memcpy(p2 + buf->cryptobufsize, p, 16);
+ buf->cryptobufsize+=16;
+
+ return 0;
+}
+
+int parse_crypt(struct esocket *sock, int *bytes_to_strip) {
+ struct esocket_in_buffer *buf = &sock->in;
+ int remaining = buf->size, ret;
+
+ *bytes_to_strip = 0;
+ if(remaining < 16)
+ return 0;
+
+ ret = crypto_newblock(sock, (unsigned char *)buf->data);
+ *bytes_to_strip = 16;
+
+ return ret;
+}
+
int esocket_read(struct esocket *sock) {
struct esocket_in_buffer *buf = &sock->in;
- int ret, bytesread = read(sock->fd, buf->writepos, buf->buffer_size - (buf->writepos - buf->data));
+ char bufd[16384], *p;
+ int bytesread, ret, strip;
+ bytesread = read(sock->fd, bufd, sizeof(bufd));
if(!bytesread || ((bytesread == -1) && (errno != EAGAIN)))
return 1;
if((bytesread == -1) && (errno == EAGAIN))
return 0;
- buf->writepos+=bytesread;
+ p = realloc(buf->data, buf->size + bytesread);
+ if(!p)
+ Error("nterface", ERR_STOP, "realloc() failed in esocket_read (esockets.c)");
+
+ buf->data = p;
+ memcpy(buf->data + buf->size, bufd, bytesread);
+ buf->size+=bytesread;
do {
- ret = buf->on_parse(sock);
- if((ret != BUF_CONT) && ret)
- return ret;
- } while(ret);
+ if(buf->mode == PARSE_ASCII) {
+ ret = parse_ascii(sock, &strip);
+ } else {
+ ret = parse_crypt(sock, &strip);
+ }
- if((buf->curpos == (buf->data + buf->buffer_size)) && (buf->startpos == buf->data))
- return 1;
+ if(strip > 0) {
+ if(buf->size - strip == 0) {
+ free(buf->data);
+ buf->data = NULL;
+ } else {
+ memmove(buf->data, buf->data + strip, buf->size - strip);
+ p = realloc(buf->data, buf->size - strip);
+ if(!p)
+ Error("nterface", ERR_STOP, "realloc() failed in esocket_read (esockets.c)");
- if(buf->startpos != buf->curpos) {
- int moveback = buf->writepos - buf->startpos;
- memmove(buf->data, buf->startpos, moveback);
- buf->writepos = buf->data + moveback;
- } else {
- buf->writepos = buf->data;
- }
+ buf->data = p;
+ }
- buf->curpos = buf->writepos;
- buf->startpos = buf->data;
+ buf->size-=strip;
+ }
+
+ if(ret)
+ return ret;
+ } while(strip && buf->data);
return 0;
}
return 1;
}
-unsigned char *increase_nonce(unsigned char *nonce) {
- u_int64_t *inonce = (u_int64_t *)(nonce + 8);
- *inonce = htonq(ntohq(*inonce) + 1);
- return nonce;
-}
-
int esocket_write(struct esocket *sock, char *buffer, int bytes) {
int ret;
- if(sock->in.on_parse == buffer_parse_ascii) {
+ if(sock->in.mode == PARSE_ASCII) {
ret = esocket_raw_write(sock, buffer, bytes);
} else {
- unsigned char mac[MAC_LEN];
- char newbuf[MAX_BUFSIZE + USED_MAC_LEN + sizeof(packet_t)];
- packet_t packetlength;
- if(bytes > MAX_BUFSIZE)
- return 1;
- packetlength = htons(bytes + USED_MAC_LEN);
-
- memcpy(newbuf, &packetlength, sizeof(packet_t));
- h_nonce(&sock->keysend, increase_nonce(sock->sendnonce));
- h_encrypt(&sock->keysend, (unsigned char *)buffer, bytes, mac);
+ unsigned char newbuf[MAX_BUFSIZE + USED_MAC_LEN], *p = newbuf, hmacdigest[32];
+ hmacsha256 hmac;
+ int padding = 16 - bytes % 16, i;
+
+ if(padding == 16)
+ padding = 0;
+
+ memcpy(newbuf, buffer, bytes);
+ for(i=0;i<padding;i++)
+ newbuf[bytes + i] = i;
+ bytes+=padding;
+
+ hmacsha256_init(&hmac, sock->serverkey, 32);
+ seqno_update(&hmac, sock->serverseqno);
+ sock->serverseqno++;
+
+ i = bytes;
+ while(i) {
+ unsigned char *ct = rijndaelcbc_encrypt(sock->servercrypto, p);
+ hmacsha256_update(&hmac, ct, 16);
+ memcpy(p, ct, 16);
+
+ buffer+=16;
+ p+=16;
+ i-=16;
+ }
- memcpy(newbuf + sizeof(packet_t), buffer, bytes);
- memcpy(newbuf + sizeof(packet_t) + bytes, mac, USED_MAC_LEN);
+ hmacsha256_final(&hmac, hmacdigest);
+ memcpy(p, hmacdigest, USED_MAC_LEN);
- ret = esocket_raw_write(sock, newbuf, bytes + sizeof(packet_t) + USED_MAC_LEN);
+ ret = esocket_raw_write(sock, (char *)newbuf, bytes + USED_MAC_LEN);
}
/* AWOOGA!! */
va_start(va, format);
- if(sock->in.on_parse == buffer_parse_ascii) {
- vsnprintf(nbuf, sizeof(nbuf) - 1, format, va); /* snprintf() and vsnprintf() will write at most size-1 of the characters, one for \n */
- } else {
- vsnprintf(nbuf, sizeof(nbuf), format, va);
- }
+ vsnprintf(nbuf, sizeof(nbuf) - 1, format, va); /* snprintf() and vsnprintf() will write at most size-1 of the characters, one for \n */
va_end(va);
len = strlen(nbuf);
- if(sock->in.on_parse == buffer_parse_ascii)
- nbuf[len++] = '\n';
-
+ nbuf[len++] = '\n';
nbuf[len] = '\0';
return esocket_write(sock, nbuf, len);
}
-int buffer_parse_ascii(struct esocket *sock) {
- struct esocket_in_buffer *buf = &sock->in;
-
- for(;buf->curpos<buf->writepos;buf->curpos++) {
- if((*buf->curpos == '\n') || !*buf->curpos) {
- int ret;
- char *newline = buf->startpos;
-
- *buf->curpos = '\0';
-
- buf->startpos = buf->curpos + 1;
-
- ret = sock->events.on_line(sock, newline);
- if(ret)
- return ret;
-
- if(buf->curpos + 1 < buf->writepos) {
- buf->curpos++;
- return BUF_CONT;
- }
- }
- }
-
- return 0;
-}
-
-int buffer_parse_crypt(struct esocket *sock) {
- struct esocket_in_buffer *buf = &sock->in;
- unsigned char mac[MAC_LEN];
+void switch_buffer_mode(struct esocket *sock, unsigned char *serverkey, unsigned char *serveriv, unsigned char *clientkey, unsigned char *clientiv) {
+ memcpy(sock->serverkey, serverkey, 32);
+ memcpy(sock->clientkey, clientkey, 32);
- if(!buf->packet_length) {
- if(buf->writepos - buf->startpos > sizeof(packet_t)) {
- memcpy(&buf->packet_length, buf->startpos, sizeof(packet_t));
- buf->startpos = buf->startpos + sizeof(packet_t);
- buf->curpos = buf->startpos;
+ sock->in.mode = PARSE_CRYPTO;
- buf->packet_length = ntohs(buf->packet_length);
- if((buf->packet_length > buf->buffer_size - sizeof(packet_t)) || (buf->packet_length <= 0))
- return 1;
+ sock->clientseqno = 0;
+ sock->serverseqno = 0;
- } else {
- buf->curpos = buf->writepos;
- return 0;
- }
- }
-
- if(buf->packet_length <= buf->writepos - buf->startpos) {
- int ret;
- char *newline, *p;
- h_nonce(&sock->keyreceive, increase_nonce(sock->recvnonce));
- h_decrypt(&sock->keyreceive, (unsigned char *)buf->startpos, buf->packet_length - USED_MAC_LEN, mac);
-
- if(memcmp(mac, buf->startpos + buf->packet_length - USED_MAC_LEN, USED_MAC_LEN))
- return 1;
-
- p = newline = buf->startpos;
- newline[buf->packet_length - USED_MAC_LEN] = '\0';
-
- for(;*p;p++) /* shouldn't happen */
- if(*p == '\n')
- *p = '\0';
-
- buf->startpos = buf->startpos + buf->packet_length;
- buf->packet_length = 0;
-
- ret = sock->events.on_line(sock, newline);
- if(ret)
- return ret;
-
- return BUF_CONT;
- }
-
- buf->curpos = buf->writepos;
- return 0;
-}
-
-void switch_buffer_mode(struct esocket *sock, char *key, unsigned char *ournonce, unsigned char *theirnonce) {
- unsigned char ukey[20];
- SHA1_CTX context;
-
- memcpy(sock->sendnonce, ournonce, sizeof(sock->sendnonce));
- memcpy(sock->recvnonce, theirnonce, sizeof(sock->recvnonce));
-
- SHA1Init(&context);
- SHA1Update(&context, (unsigned char *)key, strlen(key));
- SHA1Update(&context, (unsigned char *)" ", 1);
- /* not sure if this is cryptographically secure! */
- SHA1Update(&context, (unsigned char *)ournonce, NONCE_LEN);
- SHA1Final(ukey, &context);
-
- sock->in.on_parse = buffer_parse_crypt;
- sock->in.buffer_size = MAX_BINARY_LINE_SIZE;
-
- h_key(&sock->keysend, ukey, sizeof(ukey));
+ sock->servercrypto = rijndaelcbc_init(serverkey, 256, serveriv, 0);
+ sock->clientcrypto = rijndaelcbc_init(clientkey, 256, clientiv, 1);
- SHA1Init(&context);
- SHA1Update(&context, (unsigned char *)key, strlen(key));
- SHA1Update(&context, (unsigned char *)" ", 1);
- SHA1Update(&context, (unsigned char *)theirnonce, NONCE_LEN);
- SHA1Final(ukey, &context);
+ hmacsha256_init(&sock->clienthmac, sock->clientkey, 32);
+ seqno_update(&sock->clienthmac, sock->clientseqno);
- h_key(&sock->keyreceive, ukey, sizeof(ukey));
+ sock->clientseqno++;
}
/*
- Easy async socket library with HELIX encryption and authentication
- Copyright (C) 2004 Chris Porter.
+ Easy async socket library
+ Copyright (C) 2004-2007 Chris Porter.
*/
#ifndef __esockets_H
#define __esockets_H
-#include "../lib/helix.h"
+#include "../lib/rijndael.h"
+#include "../lib/sha2.h"
+#include "library.h"
#include <sys/types.h>
#include <ctype.h>
#define BUF_CONT -1
#define BUF_OVERFLOW -2
#define BUF_ERROR -3
+#define BUF_RESET -4
+
+#define PARSE_ASCII 0
+#define PARSE_CRYPTO 1
#define MAX_BUFSIZE 50000
-#define USED_MAC_LEN 3
+#define USED_MAC_LEN 16
typedef unsigned short packet_t;
#define MAX_BINARY_LINE_SIZE MAX_BUFSIZE
-#define MAX_ASCII_LINE_SIZE MAX_BINARY_LINE_SIZE - sizeof(packet_t) - USED_MAC_LEN
+#define MAX_ASCII_LINE_SIZE MAX_BINARY_LINE_SIZE - 10 - USED_MAC_LEN
#define MAX_OUT_QUEUE_SIZE 5000
typedef int (*line_event)(struct esocket *sock, char *newline);
typedef struct esocket_in_buffer {
- char data[MAX_BUFSIZE];
- char *writepos;
- char *curpos;
- char *startpos;
- unsigned short buffer_size;
- parse_event on_parse;
- packet_t packet_length;
+ char *data;
+ int size;
+ short mode;
+ unsigned char *cryptobuf;
+ int cryptobufsize;
+ short mac;
} in_buffer;
typedef struct esocket_packet {
struct esocket *next;
unsigned short token;
void *tag;
- helix_ctx keysend;
- helix_ctx keyreceive;
- unsigned char sendnonce[NONCE_LEN];
- unsigned char recvnonce[NONCE_LEN];
+
+ unsigned char clientkey[32];
+ unsigned char serverkey[32];
+ u_int64_t clientseqno;
+ u_int64_t serverseqno;
+ hmacsha256 clienthmac;
+ rijndaelcbc *clientcrypto;
+ rijndaelcbc *servercrypto;
} esocket;
struct esocket *esocket_add(int fd, char socket_type, struct esocket_events *events, unsigned short token);
unsigned short esocket_token(void);
struct esocket *find_esocket_from_fd(int fd);
void esocket_clean_by_token(unsigned short token);
-void switch_buffer_mode(struct esocket *sock, char *key, unsigned char *ournonce, unsigned char *theirnonce);
+void switch_buffer_mode(struct esocket *sock, unsigned char *serverkey, unsigned char *serveriv, unsigned char *clientkey, unsigned char *clientiv);
void esocket_disconnect_when_complete(struct esocket *active);
int esocket_raw_write(struct esocket *sock, char *buffer, int bytes);
#include "../core/config.h"
#include "../lib/irc_string.h"
-#include "../lib/sha1.h"
-#include "../lib/helix.h"
+#include "../lib/sha2.h"
+#include "../lib/rijndael.h"
#include "library.h"
0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};
-FILE *challenge_random_fd = NULL;
-
-unsigned char entropybuffer[CHALLENGE_ENTROPYLEN * CHALLENGE_ENTROPYBUF];
-int entropy_remaining = 0;
+FILE *random_fd = NULL;
int getcopyconfigitemint(char *section, char *key, int def, int *value) {
char buf[50];
}
char *challenge_response(char *challenge, char *password) {
- unsigned char buf[20];
+ unsigned char buf[32];
static char output[sizeof(buf) * 2 + 1];
- SHA1_CTX context;
+ SHA256_CTX context;
+
+ SHA256_Init(&context);
+ SHA256_Update(&context, (unsigned char *)challenge, strlen(challenge));
+ SHA256_Update(&context, (unsigned char *)":", 1);
+ SHA256_Update(&context, (unsigned char *)password, strlen(password));
+ SHA256_Final(buf, &context);
- SHA1Init(&context);
- SHA1Update(&context, (unsigned char *)password, strlen(password));
- SHA1Update(&context, (unsigned char *)" ", 1);
- SHA1Update(&context, (unsigned char *)challenge, strlen(challenge));
- SHA1Final(buf, &context);
+ SHA256_Init(&context);
+ SHA256_Update(&context, (unsigned char *)buf, 32);
+ SHA256_Final(buf, &context);
- TwentyByteHex(output, buf);
+ ThirtyTwoByteHex(output, buf);
return output;
}
-/* my entropy function from Q */
-int get_challenge_entropy(unsigned char *data) {
- if (!challenge_random_fd) {
- challenge_random_fd = fopen(CHALLENGE_RANDOM_LOCATION, "rb");
- if(!challenge_random_fd)
- return 0;
- }
-
- if(!entropy_remaining) {
- if(fread(entropybuffer, 1, sizeof(entropybuffer), challenge_random_fd) != sizeof(entropybuffer))
+int get_entropy(unsigned char *buf, int bytes) {
+ if (!random_fd) {
+ random_fd = fopen(RANDOM_LOCATION, "rb");
+ if(!random_fd)
return 0;
- entropy_remaining = CHALLENGE_ENTROPYBUF;
}
- memcpy(data, entropybuffer + (CHALLENGE_ENTROPYBUF - entropy_remaining) * CHALLENGE_ENTROPYLEN, CHALLENGE_ENTROPYLEN);
- entropy_remaining--;
+ fread(buf, 1, bytes, random_fd);
return 1;
}
int generate_nonce(unsigned char *nonce, int nterfacer) {
- unsigned char entropy[CHALLENGE_ENTROPYLEN];
+ unsigned char entropy[20], output[32];
struct timeval tvv;
- if(!get_challenge_entropy(entropy))
+ SHA256_CTX c;
+
+ if(!get_entropy(entropy, 20))
return 0;
gettimeofday(&tvv, NULL);
- memcpy(nonce, &tvv, sizeof(struct timeval));
- memcpy(nonce + sizeof(struct timeval) - 2, entropy, NONCE_LEN - sizeof(struct timeval) + 2);
+ SHA256_Init(&c);
+ SHA256_Update(&c, entropy, 20);
+ SHA256_Update(&c, (unsigned char *)&tvv, sizeof(struct timeval));
+ SHA256_Final(output, &c);
+ memcpy(nonce, output, 16);
if(nterfacer) {
nonce[7]&=128;
return 1;
}
-char *get_random_hex(void) {
- static char output[CHALLENGE_ENTROPYLEN * 2 + 1];
- unsigned char stored[CHALLENGE_ENTROPYLEN];
- if(get_challenge_entropy(stored)) {
- TwentyByteHex(output, stored);
- } else {
- return NULL;
- }
- return output;
-}
-
char *int_to_hex(unsigned char *input, char *buf, int len) {
int i;
for(i=0;i<len;i++)
return err;
}
+
+rijndaelcbc *rijndaelcbc_init(unsigned char *key, int keybits, unsigned char *iv, int decrypt) {
+ rijndaelcbc *ret = (rijndaelcbc *)malloc(sizeof(rijndaelcbc) + RKLENGTH(keybits) * sizeof(unsigned long));
+ if(!ret)
+ return NULL;
+
+ ret->rk = (unsigned long *)(ret + 1);
+
+ memcpy(ret->prevblock, iv, 16);
+
+ if(decrypt) {
+ ret->nrounds = rijndaelSetupDecrypt(ret->rk, key, keybits);
+ } else {
+ ret->nrounds = rijndaelSetupEncrypt(ret->rk, key, keybits);
+ }
+ return ret;
+}
+
+void rijndaelcbc_free(rijndaelcbc *c) {
+ free(c);
+}
+
+unsigned char *rijndaelcbc_encrypt(rijndaelcbc *c, unsigned char *ptblock) {
+ int i;
+ unsigned char *p = c->prevblock, *p2 = c->scratch;
+ for(i=0;i<16;i++)
+ *p2++ = *p++ ^ *ptblock++;
+
+ rijndaelEncrypt(c->rk, c->nrounds, c->scratch, c->prevblock);
+ return c->prevblock;
+}
+
+unsigned char *rijndaelcbc_decrypt(rijndaelcbc *c, unsigned char *ctblock) {
+ int i;
+ unsigned char *p = c->prevblock, *p2 = c->scratch;
+
+ rijndaelDecrypt(c->rk, c->nrounds, ctblock, c->scratch);
+
+ for(i=0;i<16;i++)
+ *p2++^=*p++;
+
+ memcpy(c->prevblock, ctblock, 16);
+ return c->scratch;
+}
+
+void hmacsha256_init(hmacsha256 *c, unsigned char *key, int keylen) {
+ unsigned char realkey[64], outerkey[64], innerkey[64];
+ SHA256_CTX keyc;
+ int i;
+
+ memset(realkey, 0, sizeof(realkey));
+ if(keylen > 64) {
+ SHA256_Init(&keyc);
+ SHA256_Update(&keyc, key, keylen);
+ SHA256_Final(realkey, &keyc);
+ keylen = 32;
+ } else {
+ memcpy(realkey, key, keylen);
+ }
+
+ /* abusing the cache here, if we do sha256 in between that'll erase it */
+ for(i=0;i<64;i++) {
+ int r = realkey[i];
+ innerkey[i] = r ^ 0x36;
+ outerkey[i] = r ^ 0x5c;
+ }
+
+ SHA256_Init(&c->outer);
+ SHA256_Init(&c->inner);
+ SHA256_Update(&c->outer, outerkey, 64);
+ SHA256_Update(&c->inner, innerkey, 64);
+}
+
+void hmacsha256_update(hmacsha256 *c, unsigned char *message, int messagelen) {
+ SHA256_Update(&c->inner, message, messagelen);
+}
+
+/* digest must be 32 bytes */
+void hmacsha256_final(hmacsha256 *c, unsigned char *digest) {
+ SHA256_Final(digest, &c->inner);
+ SHA256_Update(&c->outer, digest, 32);
+ SHA256_Final(digest, &c->outer);
+}
+
#include "../core/error.h"
+#include "../lib/sha2.h"
+
#define RE_OK 0x00
#define RE_MEM_ERROR 0x01
#define RE_BAD_LINE 0x02
#define snc(err, f) strncpy(err, f, sizeof(err) - 1)
#define TwentyByteHex(output, buf) snprintf(output, sizeof(output), "%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7], buf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15], buf[16], buf[17], buf[18], buf[19]);
+#define SixteenByteHex(output, buf) snprintf(output, sizeof(output), "%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7], buf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15]);
+#define ThirtyTwoByteHex(output, buf) snprintf(output, sizeof(output), "%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7], buf[8], buf[9], buf[10], buf[11], buf[12], buf[13], buf[14], buf[15], buf[16], buf[17], buf[18], buf[19], buf[20], buf[21], buf[22], buf[23], buf[24], buf[25], buf[26], buf[27], buf[28], buf[29], buf[30], buf[31]);
#define MemError() Error("nterface", ERR_FATAL, "Memory allocation error, file: %s line: %d", __FILE__, __LINE__);
-#define CHALLENGE_ENTROPYLEN 20
-#define CHALLENGE_ENTROPYBUF 10
-#define CHALLENGE_RANDOM_LOCATION "/dev/urandom"
+#define RANDOM_LOCATION "/dev/urandom"
#define MemCheck(x) \
if(!x) { \
int protected_atoi(char *buf, int *value);
int positive_atoi(char *data);
char *challenge_response(char *challenge, char *password);
-char *get_random_hex(void);
char *request_error(int errn);
-int get_challenge_entropy(unsigned char *data);
+int get_entropy(unsigned char *data, int bytes);
int generate_nonce(unsigned char *nonce, int nterfacer);
char *int_to_hex(unsigned char *input, char *buf, int len);
int hex_to_int(char *input, unsigned char *buf, int buflen);
+typedef struct {
+ unsigned char prevblock[16];
+ unsigned char scratch[16];
+ int nrounds;
+ unsigned long *rk;
+} rijndaelcbc;
+
+typedef struct {
+ SHA256_CTX outer, inner;
+} hmacsha256;
+
+void hmacsha256_final(hmacsha256 *c, unsigned char *digest);
+void hmacsha256_update(hmacsha256 *c, unsigned char *message, int messagelen);
+void hmacsha256_init(hmacsha256 *c, unsigned char *key, int keylen);
+unsigned char *rijndaelcbc_decrypt(rijndaelcbc *c, unsigned char *ctblock);
+unsigned char *rijndaelcbc_encrypt(rijndaelcbc *c, unsigned char *ptblock);
+void rijndaelcbc_free(rijndaelcbc *c);
+rijndaelcbc *rijndaelcbc_init(unsigned char *key, int keybits, unsigned char *iv, int decrypt);
+
#endif
/*
nterfacer
- Copyright (C) 2004-2006 Chris Porter.
-
- v1.07a
- - dumb config bug
- v1.07
- - made sure buf[0] = '\0'
- v1.06
- - tidy up
- v1.05
- - added application level ping support
- v1.04
- - modified for new logging system
- v1.03
- - newserv seems to unload this module before the ones that depend on us,
- so deregister_service now checks to see if it's been freed already
- v1.02
- - moronic bug in linked lists fixed
- v1.01
- - logging
+ Copyright (C) 2004-2007 Chris Porter.
*/
#include <stdio.h>
#include "nterfacer.h"
#include "logging.h"
-MODULE_VERSION("");
+MODULE_VERSION("1.1");
struct service_node *tree = NULL;
struct esocket_events nterfacer_events;
struct nterface_auto_log *nrl;
struct service_node *ping = NULL;
+int accept_fd = -1;
+struct permitted *permits;
+int permit_count = 0;
int ping_handler(struct rline *ri, int argc, char **argv);
}
int load_permits(void) {
- int lines, loaded_lines = 0, i, j;
+ int loaded_lines = 0, i, j;
struct permitted *new_permits, *resized, *item;
struct hostent *host;
- char buf[50];
+ array *hostnamesa, *passwordsa;
+ sstring **hostnames, **passwords;
- lines = getcopyconfigitemintpositive("nterfacer", "permits", 0);
- if(lines < 1) {
- nterface_log(nrl, NL_ERROR, "No permits found in config file.");
+ hostnamesa = getconfigitems("nterfacer", "hostname");
+ passwordsa = getconfigitems("nterfacer", "password");
+ if(!hostnamesa || !passwordsa) {
+ nterface_log(nrl, NL_ERROR, "Unable to load hostnames/passwords.");
+ return 0;
+ }
+ if(hostnamesa->cursi != passwordsa->cursi) {
+ nterface_log(nrl, NL_ERROR, "Different number of hostnames/passwords in config file.");
return 0;
}
- nterface_log(nrl, NL_INFO, "Loading %d permit%s from config file", lines, lines==1?"":"s");
- new_permits = calloc(lines, sizeof(struct permitted));
+ hostnames = (sstring **)hostnamesa->content;
+ passwords = (sstring **)passwordsa->content;
+
+ new_permits = calloc(hostnamesa->cursi, sizeof(struct permitted));
item = new_permits;
- for(i=1;i<=lines;i++) {
- snprintf(buf, sizeof(buf), "hostname%d", i);
- item->hostname = getcopyconfigitem("nterfacer", buf, "", 100);
- if(!item->hostname) {
- nterface_log(nrl, NL_ERROR, "No hostname found for item %d.", i);
- continue;
- }
+ for(i=0;i<hostnamesa->cursi;i++) {
+ item->hostname = getsstring(hostnames[i]->content, hostnames[i]->length);
host = gethostbyname(item->hostname->content);
if (!host) {
- nterface_log(nrl, NL_WARNING, "Couldn't resolve hostname: %s (item %d).", item->hostname->content, i);
+ nterface_log(nrl, NL_WARNING, "Couldn't resolve hostname: %s (item %d).", item->hostname->content, i + 1);
freesstring(item->hostname);
continue;
}
item->ihost = (*(struct in_addr *)host->h_addr).s_addr;
for(j=0;j<loaded_lines;j++) {
if(new_permits[j].ihost == item->ihost) {
- nterface_log(nrl, NL_WARNING, "Host with items %d and %d is identical, dropping item %d.", j + 1, i, i);
+ nterface_log(nrl, NL_WARNING, "Host with items %d and %d is identical, dropping item %d.", j + 1, i + 1, i + 1);
host = NULL;
}
}
continue;
}
- snprintf(buf, sizeof(buf), "password%d", i);
- item->password = getcopyconfigitem("nterfacer", buf, "", 100);
- if(!item->password) {
- nterface_log(nrl, NL_ERROR, "No password found for item %d.", item->hostname->content, i);
- freesstring(item->hostname);
- continue;
- }
-
+ item->password = getsstring(passwords[i]->content, passwords[i]->length);
nterface_log(nrl, NL_DEBUG, "Loaded permit, hostname: %s.", item->hostname->content);
item++;
esocket_write_line(newsocket, "nterfacer " PROTOCOL_VERSION);
}
+void derive_key(unsigned char *out, char *password, char *segment, unsigned char *noncea, unsigned char *nonceb) {
+ SHA256_CTX c;
+ SHA256_Init(&c);
+ SHA256_Update(&c, (unsigned char *)password, strlen(password));
+ SHA256_Update(&c, (unsigned char *)":", 1);
+ SHA256_Update(&c, (unsigned char *)segment, strlen(segment));
+ SHA256_Update(&c, (unsigned char *)":", 1);
+ SHA256_Update(&c, noncea, 16);
+ SHA256_Update(&c, (unsigned char *)":", 1);
+ SHA256_Update(&c, nonceb, 16);
+ SHA256_Final(out, &c);
+
+ SHA256_Init(&c);
+ SHA256_Update(&c, out, 32);
+ SHA256_Final(out, &c);
+}
+
int nterfacer_line_event(struct esocket *sock, char *newline) {
struct sconnect *socket = sock->tag;
- char *response, *theirnonceh = NULL;
- unsigned char theirnonce[NONCE_LEN];
+ char *response, *theirnonceh = NULL, *theirivh = NULL;
+ unsigned char theirnonce[16], theiriv[16];
int number, reason;
switch(socket->status) {
nterface_log(nrl, NL_INFO, "Protocol mismatch from %s: %s", socket->permit->hostname->content, newline);
return 1;
} else {
- char *hex, hexbuf[NONCE_LEN * 2 + 1]; /* Vekoma mAD HoUSe */
+ unsigned char challenge[32];
+ char ivhex[16 * 2 + 1], noncehex[16 * 2 + 1];
- hex = get_random_hex();
- if(!hex) {
- nterface_log(nrl, NL_ERROR, "Unable to open challenge entropy bin!");
+ if(!get_entropy(challenge, 32) || !get_entropy(socket->iv, 16)) {
+ nterface_log(nrl, NL_ERROR, "Unable to open challenge/IV entropy bin!");
return 1;
}
- memcpy(socket->response, challenge_response(hex, socket->permit->password->content), sizeof(socket->response));
+ int_to_hex(challenge, socket->challenge, 32);
+ int_to_hex(socket->iv, ivhex, 16);
+
+ memcpy(socket->response, challenge_response(socket->challenge, socket->permit->password->content), sizeof(socket->response));
socket->response[sizeof(socket->response) - 1] = '\0'; /* just in case */
socket->status = SS_VERSIONED;
nterface_log(nrl, NL_ERROR, "Unable to generate nonce!");
return 1;
}
+ int_to_hex(socket->ournonce, noncehex, 16);
- if(esocket_write_line(sock, "%s %s", hex, int_to_hex(socket->ournonce, hexbuf, NONCE_LEN)))
+ if(esocket_write_line(sock, "%s %s %s", socket->challenge, ivhex, noncehex))
return BUF_ERROR;
return 0;
}
for(response=newline;*response;response++) {
if((*response == ' ') && (*(response + 1))) {
*response = '\0';
- theirnonceh = response + 1;
+ theirivh = response + 1;
break;
}
}
- if(!theirnonceh || (strlen(theirnonceh) != 32) || !hex_to_int(theirnonceh, theirnonce, sizeof(theirnonce))) {
+ if(theirivh) {
+ for(response=theirivh;*response;response++) {
+ if((*response == ' ') && (*(response + 1))) {
+ *response = '\0';
+ theirnonceh = response + 1;
+ break;
+ }
+ }
+ }
+
+ if(!theirivh || (strlen(theirivh) != 32) || !hex_to_int(theirivh, theiriv, sizeof(theiriv)) ||
+ !theirnonceh || (strlen(theirnonceh) != 32) || !hex_to_int(theirnonceh, theirnonce, sizeof(theirnonce))) {
nterface_log(nrl, NL_INFO, "Protocol error drop: %s", socket->permit->hostname->content);
return 1;
}
socket->status = SS_AUTHENTICATED;
ret = esocket_write_line(sock, "Oauth");
if(!ret) {
- switch_buffer_mode(sock, socket->permit->password->content, socket->ournonce, theirnonce);
+ unsigned char theirkey[32], ourkey[32];
+ derive_key(ourkey, socket->permit->password->content, socket->challenge, socket->ournonce, theirnonce);
+ derive_key(theirkey, socket->permit->password->content, socket->response, theirnonce, socket->ournonce);
+
+ switch_buffer_mode(sock, ourkey, socket->iv, theirkey, theiriv);
} else {
return BUF_ERROR;
}
#define MAX_ARGS 100
-#define PROTOCOL_VERSION "2"
+#define PROTOCOL_VERSION "3"
#define ANTI_FULL_VERSION "service_link " PROTOCOL_VERSION
struct rline;
typedef struct sconnect {
int status;
- char response[20 * 2 + 1]; /* could store this in binary form but I really can't be assed */
+ char response[32 * 2 + 1], challenge[32 * 2 + 1];
+ unsigned char iv[16];
struct permitted *permit;
- unsigned char ournonce[NONCE_LEN];
+ unsigned char ournonce[16];
} sconnect;
extern struct nterface_auto_log *nrl;
-int accept_fd = -1;
-struct permitted *permits;
-int permit_count = 0;
-
struct service_node *register_service(char *name);
struct handler *register_handler(struct service_node *service, char *command, int args, handler_function fp);
void deregister_service(struct service_node *service);
MODULE_VERSION("");
int handle_chanstats(struct rline *li, int argc, char **argv);
-struct handler *hl = NULL;
+static struct handler *hl = NULL;
void _init(void) {
if(!n_node) {
int handle_counthost(struct rline *li, int argc, char **argv);
struct rline *grli; /* used inline for status */
+struct service_node *n_node;
void _init(void) {
n_node = register_service("N");
return;
register_handler(n_node, "ison", 1, handle_ison);
- register_handler(n_node, "isaccounton", 1, handle_isaccounton);
+/* register_handler(n_node, "isaccounton", 1, handle_isaccounton); */
register_handler(n_node, "whois", 1, handle_whois);
register_handler(n_node, "msg", 2, handle_message);
register_handler(n_node, "notice", 2, handle_notice);
return ri_final(li);
}
-
+/*
int handle_isaccounton(struct rline *li, int argc, char **argv) {
int i;
for(i=0;i<argc;i++)
return ri_final(li);
}
-
+*/
int handle_whois(struct rline *li, int argc, char **argv) {
nick *np = getnickbynick(argv[0]);
channel **channels;
#define ERR_CHANSTATS_STATS_NOT_FOUND 0x02
#define ERR_TOO_MANY_ARGS 0x03
-struct service_node *n_node;
+extern struct service_node *n_node;
#endif
int country_nickext = -1;
-struct handler *hl = NULL, *hl2 = NULL;
+static struct handler *hl = NULL, *hl2 = NULL;
int handle_countrytotals(struct rline *li, int argc, char **argv);
int handle_countrywhois(struct rline *li, int argc, char **argv);
#include "../core/hooks.h"
#include "../lib/irc_string.h"
#include "../lib/version.h"
+#include "../lib/strlfunc.h"
#include "pqsql.h"
#include <stdlib.h>
return;
/* stolen from chanserv as I'm lazy */
- dbhost = getcopyconfigitem("pqsql", "host", "localhost", HOSTLEN);
+ dbhost = getcopyconfigitem("pqsql", "host", "UNIX", HOSTLEN);
dbusername = getcopyconfigitem("pqsql", "username", "newserv", 20);
dbpassword = getcopyconfigitem("pqsql", "password", "moo", 20);
dbdatabase = getcopyconfigitem("pqsql", "database", "newserv", 20);
freesstring(dbport);
return;
}
-
- snprintf(connectstr, sizeof(connectstr), "dbname=%s user=%s password=%s", dbdatabase->content, dbusername->content, dbpassword->content);
+ if (!strcmp(dbhost->content,"UNIX")) {
+ snprintf(connectstr, sizeof(connectstr), "dbname=%s user=%s password=%s", dbdatabase->content, dbusername->content, dbpassword->content);
+ } else {
+ snprintf(connectstr, sizeof(connectstr), "host=%s port=%s dbname=%s user=%s password=%s", dbhost->content, dbport->content, dbdatabase->content, dbusername->content, dbpassword->content);
+ }
+
freesstring(dbhost);
freesstring(dbusername);
freesstring(dbpassword);
dbconn = PQconnectdb(connectstr);
if (!dbconn || (PQstatus(dbconn) != CONNECTION_OK)) {
- Error("pqsql", ERR_ERROR, "Unable to connect to db.");
+ Error("pqsql", ERR_ERROR, "Unable to connect to db: %s", pqlasterror(dbconn));
return;
}
Error("pqsql", ERR_INFO, "Connected!");
int pqconnected(void) {
return dbconnected;
}
+
+char* pqlasterror(PGconn * pgconn) {
+ static char errormsg[PQ_ERRORMSG_LENGTH + 1];
+ int i;
+ if(!pgconn)
+ return "PGCONN NULL";
+ strlcpy(errormsg, PQerrorMessage(pgconn), PQ_ERRORMSG_LENGTH);
+ for(i=0;i<errormsg[i];i++) {
+ if((errormsg[i] == '\r') || (errormsg[i] == '\n'))
+ errormsg[i] = ' ';
+
+ }
+ return errormsg;
+}
#include <libpq-fe.h>
#define QH_CREATE 0x01
+#define PQ_ERRORMSG_LENGTH 1024
typedef void (*PQQueryHandler)(PGconn *, void *);
#define pqquery(format, ...) pqasyncqueryf(NULL, NULL, 0, format , ##__VA_ARGS__)
int pqconnected(void);
+char* pqlasterror(PGconn * pgconn);
#endif
all: proxyscan.so
proxyscan.so: proxyscan.o proxyscanalloc.o proxyscanconnect.o proxyscancache.o proxyscanqueue.o proxyscanhandlers.o proxyscandb.o
- ld -shared -Bdynamic ${LIBMYSQL} -o $@ $^
+ ld -shared -Bdynamic ${LIBPGSQL} -o $@ $^
#include <string.h>
#include "../irc/irc.h"
#include "../lib/irc_string.h"
+#include "../lib/version.h"
+#include "../channel/channel.h"
+#include "../localuser/localuserchannel.h"
+#include "../core/nsmalloc.h"
+
+MODULE_VERSION("")
#define SCANTIMEOUT 60
proxyscan_addscantype(STYPE_HTTP, 808);
proxyscan_addscantype(STYPE_HTTP, 3332);
proxyscan_addscantype(STYPE_HTTP, 2282);
+ proxyscan_addscantype(STYPE_SOCKS4, 559);
proxyscan_addscantype(STYPE_SOCKS4, 1080);
proxyscan_addscantype(STYPE_SOCKS5, 1080);
proxyscan_addscantype(STYPE_SOCKS4, 1075);
proxyscan_addscantype(STYPE_SOCKS5, 2280);
proxyscan_addscantype(STYPE_SOCKS4, 1180);
proxyscan_addscantype(STYPE_SOCKS5, 1180);
+ proxyscan_addscantype(STYPE_SOCKS4, 9999);
+ proxyscan_addscantype(STYPE_SOCKS5, 9999);
proxyscan_addscantype(STYPE_WINGATE, 23);
proxyscan_addscantype(STYPE_CISCO, 23);
proxyscan_addscantype(STYPE_WINGATE, 1181);
proxyscan_addscantype(STYPE_HTTP, 65506);
proxyscan_addscantype(STYPE_HTTP, 63809);
proxyscan_addscantype(STYPE_HTTP, 63000);
- proxyscan_addscantype(STYPE_SOCKS4, 559);
proxyscan_addscantype(STYPE_SOCKS4, 29992);
/* Schedule saves */
void registerproxyscannick(void *arg) {
sstring *psnick,*psuser,*pshost,*psrealname;
/* Set up our nick on the network */
+ channel *cp;
psnick=getcopyconfigitem("proxyscan","nick","P",NICKLEN);
psuser=getcopyconfigitem("proxyscan","user","proxyscan",USERLEN);
freesstring(psuser);
freesstring(pshost);
freesstring(psrealname);
+
+ cp=findchannel("#twilightzone");
+ if (!cp) {
+ localcreatechannel(proxyscannick,"#twilightzone");
+ } else {
+ localjoinchannel(proxyscannick,cp);
+ localgetops(proxyscannick,cp);
+ }
}
void _fini(void) {
dumpcachehosts(NULL);
/* free() all our structures */
- sfreeall();
+ nsfreeall(POOL_PROXYSCAN);
freesstring(ps_mailname);
#if defined(PROXYSCAN_MAIL)
/* proxyscanalloc.c */
#include "proxyscan.h"
+#include "../core/nsmalloc.h"
#include <stdlib.h>
pendingscan *freependingscans;
foundproxy *freefoundproxies;
-void *mallocs=NULL;
-
-void *smalloc(size_t size) {
- void **mem;
-
- /* Get the memory we want, with an extra four bytes for our pointer */
- mem=(void **)malloc(size+sizeof(void *));
-
- /* Set the first word to point at the last chunk we got */
- *mem=mallocs;
-
- /* Now set the "last chunk" pointer to the address of this one */
- mallocs=(void *)mem;
-
- /* Return the rest of the memory to the caller */
- return (void *)(mem+1);
-}
-
-void sfreeall() {
- void *vp,**vp2;
-
- vp=mallocs;
-
- while (vp!=NULL) {
- vp2=(void **)vp;
- vp=*vp2;
- free((void *)vp2);
- }
-}
-
scan *getscan() {
int i;
scan *sp;
if (freescans==NULL) {
/* Eep. Allocate more. */
- freescans=(scan *)smalloc(ALLOCUNIT*sizeof(scan));
+ freescans=(scan *)nsmalloc(POOL_PROXYSCAN,ALLOCUNIT*sizeof(scan));
for (i=0;i<(ALLOCUNIT-1);i++) {
freescans[i].next=&(freescans[i+1]);
}
cachehost *chp;
if (freecachehosts==NULL) {
- freecachehosts=(cachehost *)smalloc(ALLOCUNIT*sizeof(cachehost));
+ freecachehosts=(cachehost *)nsmalloc(POOL_PROXYSCAN,ALLOCUNIT*sizeof(cachehost));
for (i=0;i<(ALLOCUNIT-1);i++) {
freecachehosts[i].next=&(freecachehosts[i+1]);
}
pendingscan *psp;
if (!freependingscans) {
- freependingscans=(pendingscan *)smalloc(ALLOCUNIT * sizeof(pendingscan));
+ freependingscans=(pendingscan *)nsmalloc(POOL_PROXYSCAN,ALLOCUNIT * sizeof(pendingscan));
for (i=0;i<(ALLOCUNIT-1);i++)
freependingscans[i].next = freependingscans+i+1;
freependingscans[ALLOCUNIT-1].next=NULL;
foundproxy *fpp;
if (!freefoundproxies) {
- freefoundproxies=(foundproxy *)smalloc(ALLOCUNIT * sizeof(foundproxy));
+ freefoundproxies=(foundproxy *)nsmalloc(POOL_PROXYSCAN,ALLOCUNIT * sizeof(foundproxy));
for (i=0;i<(ALLOCUNIT-1);i++)
freefoundproxies[i].next = freefoundproxies+i+1;
freefoundproxies[ALLOCUNIT-1].next=NULL;
#include "proxyscan.h"
-#include <mysql/mysql.h>
+#include "../pqsql/pqsql.h"
#include "../core/config.h"
#include "../lib/sstring.h"
#include "../irc/irc_config.h"
#include "../localuser/localuser.h"
#include <string.h>
#include <stdio.h>
+#include <libpq-fe.h>
-MYSQL proxyscansql;
unsigned int lastid;
-int sqlconnected;
+int sqlconnected = 0;
+extern nick *proxyscannick;
+
+void proxyscan_get_last_id(PGconn *dbconn, void *arg);
/*
* proxyscandbinit():
*/
int proxyscandbinit() {
- sstring *dbhost,*dbusername,*dbpassword,*dbdatabase,*dbport;
- MYSQL_RES *myres;
- MYSQL_ROW myrow;
-
- sqlconnected=0;
-
- dbhost=getcopyconfigitem("proxyscan","dbhost","localhost",HOSTLEN);
- dbusername=getcopyconfigitem("proxyscan","dbusername","proxyscan",20);
- dbpassword=getcopyconfigitem("proxyscan","dbpassword","moo",20);
- dbdatabase=getcopyconfigitem("proxyscan","dbdatabase","proxyscan",20);
- dbport=getcopyconfigitem("proxyscan","dbport","3306",8);
-
- mysql_init(&proxyscansql);
- if (!mysql_real_connect(&proxyscansql,dbhost->content,dbusername->content,
- dbpassword->content,dbdatabase->content,
- strtol(dbport->content,NULL,10), NULL, 0)) {
- Error("proxyscan",ERR_ERROR,"Unable to connect to database");
+ if(!pqconnected())
return 1;
- }
- freesstring(dbhost);
- freesstring(dbusername);
- freesstring(dbpassword);
- freesstring(dbdatabase);
- freesstring(dbport);
-
sqlconnected=1;
/* Set up the table */
- mysql_query(&proxyscansql,"CREATE TABLE openproxies (ID BIGINT not null, IP VARCHAR (20) not null, PM INT not null, TS DATETIME not null, RH TEXT not null, PRIMARY KEY (ID), INDEX (ID), UNIQUE (ID))");
+ pqcreatequery("CREATE TABLE openproxies ("
+ "ID int8 not null,"
+ "IP inet not null,"
+ "PM int4 not null,"
+ "TS int4 not null,"
+ "RH varchar not null,"
+ "PRIMARY KEY (ID))");
- /* Get max ID */
- if ((mysql_query(&proxyscansql,"SELECT max(ID) FROM openproxies"))!=0) {
- Error("proxyscan",ERR_ERROR,"Unable to retrieve max ID from database");
- return 1;
- }
-
- myres=mysql_store_result(&proxyscansql);
- if (mysql_num_fields(myres)!=1) {
- Error("proxyscan",ERR_ERROR,"Weird format retrieving max ID");
- mysql_free_result(myres);
- return 1;
- }
+ pqcreatequery("CREATE INDEX openproxies_id_index ON openproxies (ID)");
+
+ pqasyncquery(proxyscan_get_last_id, NULL,
+ "SELECT ID FROM openproxies ORDER BY id DESC LIMIT 1");
- lastid=0;
- if ((myrow=mysql_fetch_row(myres))) {
- if (myrow[0]==NULL) {
- lastid=0;
- } else {
- lastid=strtol(myrow[0],NULL,10);
- }
- Error("proxyscan",ERR_INFO,"Retrieved lastid %d from database.",lastid);
- }
-
- mysql_free_result(myres);
return 0;
}
+void proxyscan_get_last_id(PGconn *dbconn, void *arg) {
+ PGresult *pgres = PQgetResult(dbconn);
+ unsigned int numrows;
+
+ if(PQresultStatus(pgres) != PGRES_TUPLES_OK) {
+ Error("proxyscan", ERR_ERROR, "Error loading last id.");
+ }
+
+ numrows = PQntuples(pgres);
+ if ( numrows )
+ lastid = atoi(PQgetvalue(pgres, 0, 0));
+ else
+ lastid = 0;
+
+ PQclear(pgres);
+ Error("proxyscan",ERR_INFO,"Retrieved lastid %d from database.",lastid);
+}
/*
* scantostr:
* Given a scan number, returns the string associated.
void loggline(cachehost *chp) {
char reasonlist[100];
- char reasonesc[100];
- char sqlquery[4000];
+ char reasonesc[200 + 1]; /* reasonlist*2+1 */
int reasonmask=0;
int reasonpos=0;
foundproxy *fpp;
if (chp->glineid==0) {
chp->glineid=++lastid;
- mysql_escape_string(reasonesc,reasonlist,strlen(reasonlist));
- sprintf(sqlquery,"INSERT INTO openproxies VALUES(%u,'%s',%d,NOW(),'%s')",chp->glineid,
- IPlongtostr(chp->IP),reasonmask,reasonesc);
- mysql_query(&proxyscansql,sqlquery);
+ PQescapeString(reasonesc,reasonlist,strlen(reasonlist));
+ pqquery("INSERT INTO openproxies VALUES(%u,'%s',%d,%ld,'%s')",chp->glineid,
+ IPlongtostr(chp->IP),reasonmask,getnettime(),reasonesc);
} else {
- mysql_escape_string(reasonesc,reasonlist,strlen(reasonlist));
- sprintf(sqlquery,"UPDATE openproxies SET PM=%d,RH='%s' where ID=%u",
+ PQescapeString(reasonesc,reasonlist,strlen(reasonlist));
+ pqquery("UPDATE openproxies SET PM=%d,RH='%s' where ID=%u",
reasonmask,reasonesc,chp->glineid);
- mysql_query(&proxyscansql,sqlquery);
}
}
*/
void proxyscandbclose() {
- if (sqlconnected==1) {
- mysql_close(&proxyscansql);
- }
}
/*
* Lists all the open proxies found since <since> to user usernick.
*/
-void proxyscandolistopen(nick *mynick, nick *usernick, time_t snce) {
- char mysqlquery[2000];
- char timestmp[30];
- MYSQL_RES *myres;
- MYSQL_ROW myrow;
-
- strftime(timestmp,30,"%Y-%m-%d %H:%M:%S",localtime(&snce));
- sprintf(mysqlquery,"SELECT IP,TS,RH FROM openproxies WHERE TS>'%s' ORDER BY TS",timestmp);
+void proxyscandolistopen_real(PGconn *dbconn, void *arg) {
+ nick *np=getnickbynumeric((unsigned int)arg);
+ PGresult *pgres;
+ int i, num;
- if ((mysql_query(&proxyscansql,mysqlquery))!=0) {
- sendnoticetouser(mynick,usernick,"Error performing database query!");
- Error("proxyscan",ERR_ERROR,"Error performing listopen query");
+ pgres=PQgetResult(dbconn);
+ if (PQresultStatus(pgres) != PGRES_TUPLES_OK) {
+ Error("proxyscan", ERR_ERROR, "Error loading data.");
return;
}
+
+ if (PQnfields(pgres) != 3) {
+ Error("proxyscan", ERR_ERROR, "data format error.");
+ }
- myres=mysql_use_result(&proxyscansql);
- if (mysql_num_fields(myres)!=3) {
- sendnoticetouser(mynick,usernick,"Error performing database query!");
- Error("proxyscan",ERR_ERROR,"Error performing listopen query");
+ num=PQntuples(pgres);
+
+ if (!np) {
+ PQclear(pgres);
return;
}
- sendnoticetouser(mynick,usernick,"%-20s %-22s %s","IP","Found at","What was open");
- while ((myrow=mysql_fetch_row(myres))) {
- sendnoticetouser(mynick,usernick,"%-20s %-22s %s",myrow[0],myrow[1],myrow[2]);
+ sendnoticetouser(proxyscannick,np,"%-20s %-22s %s","IP","Found at","What was open");
+ for (i=0; i<num; i++) {
+ sendnoticetouser(proxyscannick,np, "%-20s %-22s %s",PQgetvalue(pgres, i, 0),
+ PQgetvalue(pgres, i, 1),
+ PQgetvalue(pgres, i, 2));
}
- sendnoticetouser(mynick,usernick,"--- End of list ---");
- mysql_free_result(myres);
+ sendnoticetouser(proxyscannick,np,"--- End of list ---");
+}
+
+void proxyscandolistopen(nick *mynick, nick *usernick, time_t snce) {
+
+ pqasyncquery(proxyscandolistopen_real,(void *)usernick->numeric,
+ "SELECT IP,TS,RH FROM openproxies WHERE TS>'%lu' ORDER BY TS",snce);
}
/*
* Check db for open proxies matching the given IP, send to user usernick.
*/
-void proxyscanspewip(nick *mynick, nick *usernick, unsigned long a, unsigned long b, unsigned long c, unsigned long d) {
- char mysqlquery[2000];
- MYSQL_RES *myres;
- MYSQL_ROW myrow;
-
- sprintf(mysqlquery, "SELECT ID,IP,TS,RH FROM openproxies WHERE IP='%lu.%lu.%lu.%lu' ORDER BY TS DESC LIMIT 10",a,b,c,d);
+void proxyscanspewip_real(PGconn *dbconn, void *arg) {
+ nick *np=getnickbynumeric((unsigned int)arg);
+ PGresult *pgres;
+ int i, num;
- if ((mysql_query(&proxyscansql,mysqlquery))!=0) {
- sendnoticetouser(mynick,usernick,"Error performing database query!");
- Error("proxyscan",ERR_ERROR,"Error performing spew query");
+ pgres=PQgetResult(dbconn);
+ if (PQresultStatus(pgres) != PGRES_TUPLES_OK) {
+ Error("proxyscan", ERR_ERROR, "Error loading data.");
return;
}
- myres=mysql_use_result(&proxyscansql);
- if (mysql_num_fields(myres)!=4) {
- sendnoticetouser(mynick,usernick,"Error performing database query!");
- Error("proxyscan",ERR_ERROR,"Error performing spew query");
+ if (PQnfields(pgres) != 4) {
+ Error("proxyscan", ERR_ERROR, "data format error.");
+ }
+
+ num=PQntuples(pgres);
+
+ if (!np) {
+ PQclear(pgres);
return;
}
- sendnoticetouser(mynick,usernick,"%-5s %-20s %-22s %s","ID","IP","Found at","What was open");
- while ((myrow=mysql_fetch_row(myres))) {
- sendnoticetouser(mynick,usernick,"%-5s %-20s %-22s %s",myrow[0],myrow[1],myrow[2],myrow[3]);
+ sendnoticetouser(proxyscannick,np,"%-5s %-20s %-22s %s","ID","IP","Found at","What was open");
+ for (i=0; i<num; i++) {
+ sendnoticetouser(proxyscannick,np, "%-5s %-20s %-22s %s",PQgetvalue(pgres, i, 0),
+ PQgetvalue(pgres, i, 1),
+ PQgetvalue(pgres, i, 2),
+ PQgetvalue(pgres, i, 3));
}
- sendnoticetouser(mynick,usernick,"--- End of list ---");
- mysql_free_result(myres);
+ sendnoticetouser(proxyscannick,np,"--- End of list ---");
+}
+
+void proxyscanspewip(nick *mynick, nick *usernick, unsigned long a, unsigned long b, unsigned long c, unsigned long d) {
+ pqasyncquery(proxyscanspewip_real,(void *)usernick->numeric,
+ "SELECT ID,IP,TS,RH FROM openproxies WHERE IP='%lu.%lu.%lu.%lu' ORDER BY TS DESC LIMIT 10",a,b,c,d);
+
}
/*
* Check db for open proxies matching the given kill/gline ID, send to user usernick.
*/
-void proxyscanshowkill(nick *mynick, nick *usernick, unsigned long a) {
- char mysqlquery[2000];
- MYSQL_RES *myres;
- MYSQL_ROW myrow;
-
- sprintf(mysqlquery, "SELECT ID,IP,TS,RH FROM openproxies WHERE ID='%lu'",a);
+void proxyscanshowkill_real(PGconn *dbconn, void *arg) {
+ nick *np=getnickbynumeric((unsigned int)arg);
+ PGresult *pgres;
+ int i, num;
- if ((mysql_query(&proxyscansql,mysqlquery))!=0) {
- sendnoticetouser(mynick,usernick,"Error performing database query!");
- Error("proxyscan",ERR_ERROR,"Error performing showkill query");
+ pgres=PQgetResult(dbconn);
+ if (PQresultStatus(pgres) != PGRES_TUPLES_OK) {
+ Error("proxyscan", ERR_ERROR, "Error loading data.");
return;
}
- myres=mysql_use_result(&proxyscansql);
- if (mysql_num_fields(myres)!=4) {
- sendnoticetouser(mynick,usernick,"Error performing database query!");
- Error("proxyscan",ERR_ERROR,"Error performing showkill query");
+ if (PQnfields(pgres) != 4) {
+ Error("proxyscan", ERR_ERROR, "data format error.");
+ }
+
+ num=PQntuples(pgres);
+
+ if (!np) {
+ PQclear(pgres);
return;
}
- sendnoticetouser(mynick,usernick,"%-5s %-20s %-22s %s","ID","IP","Found at","What was open");
- /* even though we should only ever have 1 result, still loop below - who knows eh? */
- while ((myrow=mysql_fetch_row(myres))) {
- sendnoticetouser(mynick,usernick,"%-5s %-20s %-22s %s",myrow[0],myrow[1],myrow[2],myrow[3]);
+ sendnoticetouser(proxyscannick,np,"%-5s %-20s %-22s %s","ID","IP","Found at","What was open");
+ for (i=0; i<num; i++) {
+ sendnoticetouser(proxyscannick,np, "%-5s %-20s %-22s %s",PQgetvalue(pgres, i, 0),
+ PQgetvalue(pgres, i, 1),
+ PQgetvalue(pgres, i, 2),
+ PQgetvalue(pgres, i, 3));
}
- sendnoticetouser(mynick,usernick,"--- End of list ---");
- mysql_free_result(myres);
+ sendnoticetouser(proxyscannick,np,"--- End of list ---");
+}
+
+
+void proxyscanshowkill(nick *mynick, nick *usernick, unsigned long a) {
+ pqasyncquery(proxyscanspewip_real,(void *)usernick->numeric,
+ "SELECT ID,IP,TS,RH FROM openproxies WHERE ID='%lu'",a);
}
if (irc_in_addr_is_loopback(&np->p_ipaddr) || !irc_in_addr_is_ipv4(&np->p_ipaddr))
return;
+
+ /* ignore newnick for first 120s */
+ if (ps_start_ts+120 > time(NULL))
+ return;
+
unsigned int ip = irc_in_addr_v4_to_int(&np->p_ipaddr);
/*
#include "proxyscan.h"
#include "../irc/irc.h"
+#include "../core/error.h"
pendingscan *ps_normalqueue=NULL;
pendingscan *ps_prioqueue=NULL;
}
/* We have to queue it */
- psp = (struct pendingscan *) malloc(sizeof(pendingscan));
- if (!psp)
- {
- /* shutdown due to no memory */
- irc_send("%s SQ %s 0 :Out of memory - exiting.",mynumeric->content,myserver->content);
- irc_disconnected();
- exit(0);
- } else {
- countpendingscan++;
- }
+ if (!(psp=(struct pendingscan *)malloc(sizeof(pendingscan))))
+ Error("proxyscan",ERR_STOP,"Unable to allocate memory");
+
+ countpendingscan++;
+
psp->IP=IP;
psp->type=scantype;
psp->port=port;
return NULL;
}
-void rg_dogline(struct rg_glinelist *gll, nick *np, struct rg_struct *rp, char *matched) { /* PPA: if multiple users match the same user@host or *@host it'll send multiple glines?! */
+int __rg_dogline(struct rg_glinelist *gll, nick *np, struct rg_struct *rp, char *matched) { /* PPA: if multiple users match the same user@host or *@host it'll send multiple glines?! */
char hostname[RG_MASKLEN];
int usercount = 0;
nn->punish = rp->type;
}
}
- return;
+ return usercount;
}
if ((rp->type <= 0) || (rp->type >= 3))
- return;
+ return 0;
if (rp->type == 1) {
if (IsAccount(np)) {
}
irc_send("%s GL * +%s %d :AUTO: %s (ID: %08lx)\r\n", mynumeric->content, hostname, rg_expiry_time, rp->reason->content, rp->glineid);
+ return usercount;
+}
+
+int floodprotection = 0;
+
+void rg_dogline(struct rg_glinelist *gll, nick *np, struct rg_struct *rp, char *matched) {
+ int t = time(NULL);
+
+ if(t > floodprotection) {
+ floodprotection = t;
+ } else if((floodprotection - t) / 8 > RG_NETWORK_WIDE_MAX_GLINES_PER_8_SEC) {
+ channel *cp = findchannel("#twilightzone");
+ if(cp)
+ controlchanmsg(cp, "WARNING! REGEXGLINE DISABLED FOR AN HOUR DUE TO NETWORK WIDE LOOKING GLINE!");
+ controlwall(NO_OPER, NL_MANAGEMENT, "WARNING! REGEXGLINE DISABLED FOR AN HOUR DUE TO NETWORK WIDE LOOKING GLINE!");
+ floodprotection = t + RG_NETWORK_WIDE_MAX_GLINES_PER_8_SEC * 3600 * 8;
+ }
+
+ floodprotection+=__rg_dogline(gll, np, rp, matched);
}
void rg_logevent(nick *np, char *event, char *details, ...) {
#define RG_MINIMUM_DELAY_TIME 5
#define RG_MAXIMUM_RAND_TIME 15
#define RG_EXPIRY_TIME_DEFAULT 1800
+#define RG_NETWORK_WIDE_MAX_GLINES_PER_8_SEC 625 /* 5000 / 8 */
#define RGStringise(x) #x
#define RGBuildHostname(buf, np) snprintf(buf, sizeof(buf), "%s!%s@%s\r%s", np->nick, np->ident, np->host->name->content, np->realname->name->content);
/* log fd */
FILE *rq_logfd;
+static int extloaded = 0;
+
void _init(void) {
+ if(!rq_initblocks())
+ return;
+
+ extloaded = 1;
+
rqcommands = newcommandtree();
addcommandtotree(rqcommands, "showcommands", RQU_ANY, 1, &rqcmd_showcommands);
addcommandtotree(rqcommands, "changelev", RQU_OPER, 2, &rqcmd_changelev);
addcommandtotree(rqcommands, "userlist", RQU_OPER, 1, &rqcmd_userlist);
- rq_initblocks();
qr_initrequest();
ru_load();
}
void _fini(void) {
+ if(!extloaded)
+ return;
+
deregisterlocaluser(rqnick, NULL);
deletecommandfromtree(rqcommands, "showcommands", &rqcmd_showcommands);
break;
case LU_PRIVNOTICE:
- qr_handlenotice(params[0], params[1]);
+ qr_handle_notice(params[0], params[1]);
break;
}
block = rq_findblock(channelname);
if (block != NULL) {
- sendnoticetouser(rqnick, np, "Error: You are not allowed to request a "
+ /* only say when block expires if <7 days */
+ if ( block->expires < getnettime() + 3600 * 24 * 7) {
+ sendnoticetouser(rqnick, np, "Error: You are not allowed to request a "
+ "service to this channel. Keep waiting for at least %s before you try again.",
+ rq_longtoduration(block->expires - getnettime()));
+ /* give them another 5 minutes to think about it */
+ block->expires += 300;
+ rq_saveblocks();
+ } else {
+ sendnoticetouser(rqnick, np, "Error: You are not allowed to request a "
"service to this channel.");
+ }
sendnoticetouser(rqnick, np, "Reason: %s", block->reason->content);
rq_blocked++;
void rqhook_lostnick(int hook, void *arg);
-void rq_initblocks(void) {
+int rq_initblocks(void) {
+ rqnext = registernickext("request");
+ if(rqnext < 0)
+ return 0;
+
array_init(&rqblocks, sizeof(rq_block));
array_setlim1(&rqblocks, 5);
array_setlim2(&rqblocks, 20);
registerhook(HOOK_NICK_LOSTNICK, &rqhook_lostnick);
- rqnext = registernickext("request");
+ return 1;
}
void rq_finiblocks(void) {
#define RQ_SPAMCOUNT 5
#define RQ_SPAMBLOCK 3600
-void rq_initblocks(void);
+int rq_initblocks(void);
void rq_finiblocks(void);
int rq_loadblocks(void);
requestrec *nextreqq, *lastreqq;
-requestrec *nextqreq, *lastqreq;
+static requestrec *nextqreq, *lastqreq;
extern nick *rqnick;
int rlstate;
* as part of the process.
*/
-void qr_result(requestrec *req, int outcome, char failcode, char *message, ...) {
+static void qr_result(requestrec *req, int outcome, char failcode, char *message, ...) {
sstring *user, *password;
requestrec **rh;
char msgbuf[512];
* Checks that a channel is beeeeg enough for teh Q
*/
-int qr_checksize(chanindex *cip, int what, char *failcode) {
+static int qr_checksize(chanindex *cip, int what, char *failcode) {
chanstats *csp;
channel *cp;
nick *np, *qbot;
* 11:12 -L(TheLBot@lightweight.quakenet.org)- End of chanlev for #twilightzone.
*/
-void qr_handlenotice(nick *sender, char *message) {
+void qr_handle_notice(nick *sender, char *message) {
char *ch, *chop;
chanindex *cip;
requestrec *rrp1, *rrp2;
int qr_instantrequestq(nick *sender, channel *cp);
int qr_requests(nick *rqnick, nick *sender, channel *cp, nick *lnick, nick *qnick);
void qr_requeststats(nick *rqnick, nick *np);
-void qr_handlenotice(nick *sender, char *message);
+void qr_handle_notice(nick *sender, char *message);
}
}
-void printnick(int hook, void *vp) {
+static void printnick(int hook, void *vp) {
/*
// nick *np=(nick *)vp;
/*
* Trojanscan version 2
*
- * Trojanscan copyright (C) Chris Porter 2002-2005
+ * Trojanscan copyright (C) Chris Porter 2002-2007
* Newserv bits copyright (C) David Mansell 2002-2003
*
* TODO: CHECK::
#include "../lib/strlfunc.h"
#include "../lib/version.h"
-MODULE_VERSION("");
+MODULE_VERSION(TROJANSCAN_VERSION);
+
+void trojanscan_phrasematch(channel *chp, nick *sender, trojanscan_phrases *phrase, char messagetype, char *matchbuf);
+char *trojanscan_sanitise(char *input);
+void trojanscan_refresh_settings(void);
+static void trojanscan_part_watch(int hook, void *arg);
+
+#define TROJANSCAN_SETTING_SIZE 256
+#define TROJANSCAN_MAX_SETTINGS 50
+
+static struct {
+ char setting[TROJANSCAN_SETTING_SIZE];
+ char value[TROJANSCAN_SETTING_SIZE];
+} trojanscan_settings[TROJANSCAN_MAX_SETTINGS];
+
+static int settingcount = 0;
+static char *versionreply;
+static int hooksregistered = 0;
void _init() {
trojanscan_cmds = newcommandtree();
if(trojanscan_cloneschedule)
deleteschedule(trojanscan_poolschedule, &trojanscan_registerclones, NULL);
+ if(hooksregistered)
+ deregisterhook(HOOK_CHANNEL_PART, trojanscan_part_watch);
+
while(rp) {
deleteschedule(rp->schedule, &trojanscan_dopart, (void *)rp);
oldrp = rp;
trojanscan_database_query("CREATE TABLE channels (id INT(10) PRIMARY KEY AUTO_INCREMENT, channel VARCHAR(%d) NOT NULL, exempt BOOL DEFAULT 0)", CHANNELLEN);
trojanscan_database_query("CREATE TABLE users (id INT(10) PRIMARY KEY AUTO_INCREMENT, authname VARCHAR(%d) NOT NULL, authlevel TINYINT(4) NOT NULL)", ACCOUNTLEN);
trojanscan_database_query("CREATE TABLE hits (id INT(10) PRIMARY KEY AUTO_INCREMENT, nickname VARCHAR(%d) NOT NULL, ident VARCHAR(%d) NOT NULL, host VARCHAR(%d) NOT NULL, phrase INT(10) NOT NULL, ts TIMESTAMP, messagetype VARCHAR(1) NOT NULL DEFAULT 'm', glined BOOL DEFAULT 1)", NICKLEN, USERLEN, HOSTLEN);
- trojanscan_database_query("CREATE TABLE settings (id INT(10) PRIMARY KEY AUTO_INCREMENT, setting VARCHAR(15) NOT NULL, value VARCHAR(15) NOT NULL)");
+ trojanscan_database_query("CREATE TABLE settings (id INT(10) PRIMARY KEY AUTO_INCREMENT, setting VARCHAR(255) NOT NULL UNIQUE, value VARCHAR(255) NOT NULL)");
trojanscan_database_query("CREATE TABLE wwwlogs (id INT(10) PRIMARY KEY AUTO_INCREMENT, authid INT(10) NOT NULL, ip VARCHAR(15), action TEXT, ts TIMESTAMP)");
trojanscan_database_query("CREATE TABLE unknownlog (id INT(10) PRIMARY KEY AUTO_INCREMENT, data TEXT, user VARCHAR(%d) NOT NULL, ts TIMESTAMP)", NICKLEN+USERLEN+HOSTLEN+3);
- trojanscan_database_query("DELETE FROM settings");
+ trojanscan_database_query("DELETE FROM settings WHERE setting = 'rehash' OR setting = 'changed'");
trojanscan_database_query("INSERT INTO settings (setting, value) VALUES ('rehash','0')");
trojanscan_database_query("INSERT INTO settings (setting, value) VALUES ('changed','0')");
+
+ /* assumption: constants aren't supplied by someone evil */
+ trojanscan_database_query("INSERT INTO settings (setting, value) VALUES ('versionreply','" TROJANSCAN_DEFAULT_VERSION_REPLY "')");
+ trojanscan_refresh_settings();
trojanscan_read_database(1);
cp = findchannel(TROJANSCAN_OPERCHANNEL);
trojanscan_rehashschedule = scheduleoneshot(time(NULL) + 60, &trojanscan_rehash_schedule, NULL);
+ registerhook(HOOK_CHANNEL_PART, trojanscan_part_watch);
+ hooksregistered = 1;
+}
+
+char *trojanscan_get_setting(char *setting) {
+ int i;
+
+ for(i=0;i<settingcount;i++)
+ if(!strcmp(trojanscan_settings[i].setting, setting))
+ return trojanscan_settings[i].value;
+
+ return NULL;
+}
+
+void trojanscan_refresh_settings(void) {
+ trojanscan_database_res *res;
+ trojanscan_database_row sqlrow;
+ int i = 0;
+
+ if(trojanscan_database_query("SELECT setting, value FROM settings"))
+ return;
+
+ if(!(res = trojanscan_database_store_result(&trojanscan_sql)))
+ return;
+
+ if (trojanscan_database_num_rows(res) <= 0)
+ return;
+
+ while((sqlrow = trojanscan_database_fetch_row(res))) {
+ strlcpy(trojanscan_settings[i].setting, sqlrow[0], TROJANSCAN_SETTING_SIZE);
+ strlcpy(trojanscan_settings[i].value, sqlrow[1], TROJANSCAN_SETTING_SIZE);
+
+ trojanscan_sanitise(trojanscan_settings[i].value);
+
+ if(++i == TROJANSCAN_MAX_SETTINGS)
+ break;
+ }
+
+ settingcount = i;
+
+ trojanscan_database_free_result(res);
+
+ /* optimisation hack */
+ versionreply = trojanscan_get_setting("versionreply");
}
void trojanscan_rehash_schedule(void *arg) {
+ char *v;
trojanscan_rehashschedule = scheduleoneshot(time(NULL) + 60, &trojanscan_rehash_schedule, NULL);
- if (!(trojanscan_database_query("SELECT value FROM settings WHERE setting = 'rehash'"))) {
- trojanscan_database_res *res;
- if ((res = trojanscan_database_store_result(&trojanscan_sql))) {
- if (trojanscan_database_num_rows(res) > 0) {
- trojanscan_database_row sqlrow = trojanscan_database_fetch_row(res);
- if (sqlrow && (sqlrow[0][0] == '1')) {
- trojanscan_mainchanmsg("n: rehash initiated by website. . .");
- trojanscan_read_database(0);
- }
- }
- trojanscan_database_free_result(res);
- }
- }
-
+
+ trojanscan_refresh_settings();
+
+ v = trojanscan_get_setting("rehash");
+ if(v && v[0] == '1') {
+ trojanscan_mainchanmsg("n: rehash initiated by website. . .");
+ trojanscan_read_database(0);
+ }
}
void trojanscan_free_database(void) {
}
+char *trojanscan_sanitise(char *input) {
+ char *p;
+
+ for(p=input;*p;p++)
+ if(*p == '\r' || *p == '\n')
+ *p = '!';
+
+ return input;
+}
+
sstring *trojanscan_getsstring(char *string, int length) {
int i;
if ((trojanscan_database.total_channels>0) && trojanscan_database.channels) {
i = 0;
while((sqlrow = trojanscan_database_fetch_row(res))) {
- trojanscan_database.channels[i].name = trojanscan_getsstring(sqlrow[0], strlen(sqlrow[0]));
+ trojanscan_database.channels[i].name = trojanscan_getsstring(trojanscan_sanitise(sqlrow[0]), strlen(sqlrow[0]));
trojanscan_database.channels[i].exempt = (sqlrow[1][0] == '1');
i++;
}
i = 0;
while((sqlrow = trojanscan_database_fetch_row(res))) {
trojanscan_database.worms[i].id = atoi(sqlrow[0]);
- trojanscan_database.worms[i].name = trojanscan_getsstring(sqlrow[1], strlen(sqlrow[1]));
+ trojanscan_database.worms[i].name = trojanscan_getsstring(trojanscan_sanitise(sqlrow[1]), strlen(sqlrow[1]));
tempresult = atoi(sqlrow[2]);
trojanscan_database.worms[i].glineuser = (tempresult == 0);
trojanscan_database.worms[i].glinehost = (tempresult == 1);
}
trojanscan_database_query("UPDATE settings SET value = '0' where setting = 'rehash'");
-
}
void trojanscan_log(nick *np, char *event, char *details, ...) {
int trojanscan_rehash(void *sender, int cargc, char **cargv) {
nick *np = (void *)sender;
+ trojanscan_refresh_settings();
trojanscan_read_database(0);
trojanscan_log(np, "rehash", "");
trojanscan_reply(np, "Done.");
} else {
trojanscan_gennick(c_nick, trojanscan_minmaxrand(7, TROJANSCAN_MMIN(13, NICKLEN)));
}
- } while (c_nick && (getnickbynick(c_nick) != NULL));
+ } while (c_nick[0] && (getnickbynick(c_nick) != NULL));
renamelocaluser(clone->clone, c_nick);
}
/* Split the line into params */
cargc = splitline((char *)args[1], cargv, 50, 0);
- if(cargc == 0 || !cargv || !cargv[0])
+ if(cargc == 0 || !cargv[0])
return;
cmd=findcommandintree(trojanscan_cmds, cargv[0], 1);
}
}
+static char trojanscan_getmtfromhooktype(int input) {
+ switch(input) {
+ case HOOK_CHANNEL_PART: return 'P';
+ default: return '?';
+ }
+}
+
char trojanscan_getmtfrommessagetype(int input) {
switch(input) {
case LU_PRIVMSG: return 'm';
}
}
+static void trojanscan_process(nick *sender, channel *cp, char mt, char *pretext) {
+ char text[513];
+ unsigned int len;
+ unsigned int i;
+ struct trojanscan_worms *worm;
+ int vector[30], detected = 0;
+
+ trojanscan_strip_codes(text, sizeof(text) - 1, pretext);
+
+ len = strlen(text);
+
+ for(i=0;i<trojanscan_database.total_phrases;i++) {
+ if (
+ (
+ (worm = trojanscan_database.phrases[i].worm)
+ ) &&
+ (
+ (
+ (
+ (mt == 'm') || (mt == 's') || (mt == 'n')
+ ) &&
+ (
+ (trojanscan_database.phrases[i].worm->hitpriv)
+ )
+ ) ||
+ (
+ (
+ (mt == 'M') || (mt == 'N') || (mt == 'P')
+ ) &&
+ (
+ (trojanscan_database.phrases[i].worm->hitchans)
+ )
+ )
+ ) &&
+ (trojanscan_database.phrases[i].phrase)
+ ) {
+ int pre = pcre_exec(trojanscan_database.phrases[i].phrase, trojanscan_database.phrases[i].hint, text, len, 0, 0, vector, 30);
+ if(pre >= 0) {
+ char matchbuf[513];
+ matchbuf[0] = 0;
+ matchbuf[512] = 0; /* hmm */
+
+ if(pre > 1)
+ if(pcre_copy_substring(text, vector, pre, 1, matchbuf, sizeof(matchbuf) - 1) <= 0)
+ matchbuf[0] = 0;
+
+ trojanscan_phrasematch(cp, sender, &trojanscan_database.phrases[i], mt, matchbuf);
+
+ detected = 1;
+ break;
+ }
+ }
+ }
+ if (!detected && (mt != 'N') && (mt != 'M')) {
+ char etext[TROJANSCAN_QUERY_TEMP_BUF_SIZE], enick[TROJANSCAN_QUERY_TEMP_BUF_SIZE], eident[TROJANSCAN_QUERY_TEMP_BUF_SIZE], ehost[TROJANSCAN_QUERY_TEMP_BUF_SIZE];
+ trojanscan_database_escape_string(etext, text, len);
+ trojanscan_database_escape_string(enick, sender->nick, strlen(sender->nick));
+ trojanscan_database_escape_string(eident, sender->ident, strlen(sender->ident));
+ trojanscan_database_escape_string(ehost, sender->host->name->content, sender->host->name->length);
+ trojanscan_database_query("INSERT INTO unknownlog (data, user) VALUES ('%s','%s!%s@%s')", etext, enick, eident, ehost);
+ }
+}
+
void trojanscan_clonehandlemessages(nick *target, int messagetype, void **args) {
- char *pretext = NULL, etext[TROJANSCAN_QUERY_TEMP_BUF_SIZE], enick[TROJANSCAN_QUERY_TEMP_BUF_SIZE], eident[TROJANSCAN_QUERY_TEMP_BUF_SIZE], ehost[TROJANSCAN_QUERY_TEMP_BUF_SIZE], text[513], detected = 0;
+ char *pretext = NULL;
nick *sender;
struct trojanscan_realchannels *rp;
struct trojanscan_rejoinlist *rj;
- unsigned int i, len;
- struct trojanscan_worms *worm;
- int vector[30];
char mt = trojanscan_getmtfrommessagetype(messagetype);
char *channel_name;
+ channel *cp = NULL;
+ int i;
switch(messagetype) {
case LU_PRIVMSG:
case LU_CHANMSG:
case LU_CHANNOTICE:
-
sender = (nick *)args[0];
+
if (strlen(sender->nick) < 2)
break;
- if (!pretext)
+ if (!pretext) {
pretext = (char *)args[2];
+ cp = args[1];
+ }
if(strncmp(TROJANSCAN_VERSION_DETECT, pretext, sizeof(TROJANSCAN_VERSION_DETECT)-1)==0) {
char p = pretext[sizeof(TROJANSCAN_VERSION_DETECT)-1];
sendnoticetouser(target, sender, "\001VERSION T clone, though since T is currently gone you'll have to version me again in a minute for confirmation.\001");
}
} else {
- sendnoticetouser(target, sender, "\001VERSION " TROJANSCAN_CLONE_VERSION_REPLY "\001");
+ sendnoticetouser(target, sender, "\001VERSION %s\001", versionreply);
}
return;
}
}
- trojanscan_strip_codes(text, sizeof(text) - 1, pretext);
-
- len = strlen(text);
-
- for(i=0;i<trojanscan_database.total_phrases;i++) {
- if (
- (
- (worm = trojanscan_database.phrases[i].worm)
- ) &&
- (
- (
- (
- (messagetype == LU_PRIVMSG) || (messagetype == LU_SECUREMSG) || (messagetype == LU_PRIVNOTICE)
- ) &&
- (
- (trojanscan_database.phrases[i].worm->hitpriv)
- )
- ) ||
- (
- (
- (messagetype == LU_CHANMSG) || (messagetype == LU_CHANNOTICE)
- ) &&
- (
- (trojanscan_database.phrases[i].worm->hitchans)
- )
- )
- ) &&
- (trojanscan_database.phrases[i].phrase)
- ) {
- int pre = pcre_exec(trojanscan_database.phrases[i].phrase, trojanscan_database.phrases[i].hint, text, len, 0, 0, vector, 30);
- if(pre >= 0) {
- char glinemask[HOSTLEN + USERLEN + NICKLEN + 4];
- char *userbit;
- host *hp;
- unsigned int j, usercount, frequency;
- int glining = 1;
- channel *chp = (channel *)args[1];
-
- nick *np = NULL; /* sigh at warnings */
-
- detected = 1;
-
- trojanscan_database.detections++;
-
- if (!(hp=findhost(sender->host->name->content))) {
- trojanscan_mainchanmsg("w: user %s!%s@%s triggered infection monitor, yet no hosts found at stage 1 -- worm: %s", sender->nick, sender->ident, sender->host->name->content, worm->name->content);
- break;
- }
-
- usercount = 0; /* stupid warnings */
- if (worm->monitor) {
- glining = 0;
- usercount = -1;
- } else if (worm->glinehost && (hp->clonecount <= TROJANSCAN_MAX_HOST_GLINE)) {
- snprintf(glinemask, sizeof(glinemask) - 1, "*@%s", IPtostr(sender->p_ipaddr));
- usercount = hp->clonecount;
- }
- else if (worm->glineuser || (worm->glinehost && hp->clonecount > TROJANSCAN_MAX_HOST_GLINE)) {
- userbit = sender->ident;
- if(userbit[0] == '~')
- userbit++;
- snprintf(glinemask, sizeof(glinemask) - 1, "*%s@%s", userbit, IPtostr(sender->p_ipaddr));
- for (j=0;j<NICKHASHSIZE;j++) {
- for (np=nicktable[j];np;np=np->next) {
- if ((np->host==hp) && (!ircd_strcmp(np->ident,sender->ident)))
- usercount++;
- }
- }
- }
-
- if (!usercount) {
- trojanscan_mainchanmsg("w: user %s!%s@%s triggered infection monitor, yet no hosts found at stage 2 -- worm: %s", sender->nick, sender->ident, sender->host->name->content, worm->name->content);
- break;
- }
-
- if (glining && (usercount > trojanscan_maxusers)) {
- trojanscan_mainchanmsg("w: not glining %s!%s@%s due to too many users (%d) with mask: *!%s -- worm: %s)", sender->nick, sender->ident, sender->host->name->content, usercount, glinemask, worm->name->content);
- break;
- }
-
- if (glining && !worm->datalen) {
- trojanscan_mainchanmsg("w: not glining %s!%s@%s due to too lack of removal data with mask: *!%s (%d users) -- worm: %s)", sender->nick, sender->ident, sender->host->name->content, glinemask, usercount, worm->name->content);
- break;
- }
-
- trojanscan_database_escape_string(enick, sender->nick, strlen(sender->nick));
- trojanscan_database_escape_string(eident, sender->ident, strlen(sender->ident));
- trojanscan_database_escape_string(ehost, sender->host->name->content, sender->host->name->length);
-
- frequency = 1;
-
- if (!(trojanscan_database_query("SELECT COUNT(*) FROM hits WHERE glined = %d AND host = '%s'", glining, ehost))) {
- trojanscan_database_res *res;
- if ((res = trojanscan_database_store_result(&trojanscan_sql))) {
- trojanscan_database_row sqlrow;
- if ((trojanscan_database_num_rows(res) > 0) && (sqlrow = trojanscan_database_fetch_row(res)))
- frequency = atoi(sqlrow[0]) + 1;
- trojanscan_database_free_result(res);
- }
- }
-
- if (!glining) {
- char matchbuf[513];
- matchbuf[0] = 0;
- matchbuf[512] = 0; /* hmm */
-
- if(pre > 1)
- if (pcre_copy_substring(text, vector, pre, 1, matchbuf, sizeof(matchbuf) - 1) <= 0)
- matchbuf[0] = 0;
-
- trojanscan_mainchanmsg("m: t: %c u: %s!%s@%s%s%s w: %s p: %d %s%s", mt, sender->nick, sender->ident, sender->host->name->content, mt=='N'||mt=='M'?" #: ":"", mt=='N'||mt=='M'?chp->index->name->content:"", worm->name->content, trojanscan_database.phrases[i].id, matchbuf[0]?" --: ":"", matchbuf[0]?matchbuf:"");
-#ifdef TROJANSCAN_PEONCHANNEL
- trojanscan_peonchanmsg("m: t: %c u: %s!%s@%s%s%s%s w: %s %s%s", mt, sender->nick, sender->ident, (IsHideHost(sender)&&IsAccount(sender))?sender->authname:sender->host->name->content, (IsHideHost(sender)&&IsAccount(sender))?"."HIS_HIDDENHOST:"", mt=='N'||mt=='M'?" #: ":"", mt=='N'||mt=='M'?chp->index->name->content:"", worm->name->content, matchbuf[0]?" --: ":"", matchbuf[0]?matchbuf:"");
-#endif
- } else {
- int glinetime = TROJANSCAN_FIRST_OFFENSE * frequency * (worm->epidemic?TROJANSCAN_EPIDEMIC_MULTIPLIER:1);
- if(glinetime > 7 * 24)
- glinetime = 7 * 24; /* can't set glines over 7 days with normal non U:lined glines */
-
- trojanscan_database_query("INSERT INTO hits (nickname, ident, host, phrase, messagetype, glined) VALUES ('%s', '%s', '%s', %d, '%c', %d)", enick, eident, ehost, trojanscan_database.phrases[i].id, mt, glining);
- trojanscan_database.glines++;
-
- irc_send("%s GL * +%s %d :You (%s!%s@%s) are infected with a trojan (%s/%d), see %s%d for details - banned for %d hours\r\n", mynumeric->content, glinemask, glinetime * 3600, sender->nick, sender->ident, sender->host->name->content, worm->name->content, trojanscan_database.phrases[i].id, TROJANSCAN_URL_PREFIX, worm->id, glinetime);
-
- trojanscan_mainchanmsg("g: *!%s t: %c u: %s!%s@%s%s%s c: %d w: %s%s p: %d f: %d", glinemask, mt, sender->nick, sender->ident, sender->host->name->content, mt=='N'||mt=='M'?" #: ":"", mt=='N'||mt=='M'?chp->index->name->content:"", usercount, worm->name->content, worm->epidemic?"(E)":"", trojanscan_database.phrases[i].id, frequency);
- }
-
- break;
- }
- }
- }
- if (!detected && (mt != 'N') && (mt != 'M')) {
- trojanscan_database_escape_string(etext, text, len);
- trojanscan_database_escape_string(enick, sender->nick, strlen(sender->nick));
- trojanscan_database_escape_string(eident, sender->ident, strlen(sender->ident));
- trojanscan_database_escape_string(ehost, sender->host->name->content, sender->host->name->length);
- trojanscan_database_query("INSERT INTO unknownlog (data, user) VALUES ('%s','%s!%s@%s')", etext, enick, eident, ehost);
- }
+ trojanscan_process(sender, cp, mt, pretext);
break;
case LU_KILLED:
/* someone killed me? Bastards */
}
}
+static void trojanscan_part_watch(int hook, void *arg) {
+ void **arglist = (void **)arg;
+ channel *cp = (channel *)arglist[0];
+ nick *np = arglist[1];
+ char *reason = arglist[2];
+
+ if(!cp || !np || !reason || (*reason == '\0'))
+ return;
+
+ trojanscan_process(np, cp, trojanscan_getmtfromhooktype(hook), reason);
+}
+
+void trojanscan_phrasematch(channel *chp, nick *sender, trojanscan_phrases *phrase, char messagetype, char *matchbuf) {
+ char glinemask[HOSTLEN + USERLEN + NICKLEN + 4], enick[TROJANSCAN_QUERY_TEMP_BUF_SIZE], eident[TROJANSCAN_QUERY_TEMP_BUF_SIZE], ehost[TROJANSCAN_QUERY_TEMP_BUF_SIZE];
+ char *userbit;
+ unsigned int j, usercount, frequency;
+ int glining = 1;
+ struct trojanscan_worms *worm = phrase->worm;
+
+ nick *np = NULL; /* sigh at warnings */
+
+ trojanscan_database.detections++;
+
+ usercount = 0;
+ if (worm->monitor) {
+ glining = 0;
+ usercount = -1;
+ } else if (worm->glinehost) {
+ snprintf(glinemask, sizeof(glinemask) - 1, "*@%s", IPtostr(sender->p_ipaddr));
+ for (j=0;j<NICKHASHSIZE;j++)
+ for (np=nicktable[j];np;np=np->next)
+ if (np->ipnode==sender->ipnode)
+ usercount++;
+ }
+ if (worm->glineuser || (worm->glinehost && usercount > TROJANSCAN_MAX_HOST_GLINE)) {
+ userbit = sender->ident;
+/*
+ if(userbit[0] == '~')
+ userbit++;
+*/
+ snprintf(glinemask, sizeof(glinemask) - 1, "%s@%s", userbit, IPtostr(sender->p_ipaddr));
+ for (j=0;j<NICKHASHSIZE;j++)
+ for (np=nicktable[j];np;np=np->next)
+ if ((np->ipnode==sender->ipnode) && (!ircd_strcmp(np->ident,sender->ident)))
+ usercount++;
+ }
+
+ if (!usercount) {
+ trojanscan_mainchanmsg("w: user %s!%s@%s triggered infection monitor, yet no hosts found at stage 2 -- worm: %s", sender->nick, sender->ident, sender->host->name->content, worm->name->content);
+ return;
+ }
+
+ if (glining && (usercount > trojanscan_maxusers)) {
+ trojanscan_mainchanmsg("w: not glining %s!%s@%s due to too many users (%d) with mask: *!%s -- worm: %s)", sender->nick, sender->ident, sender->host->name->content, usercount, glinemask, worm->name->content);
+ return;
+ }
+
+ if (glining && !worm->datalen) {
+ trojanscan_mainchanmsg("w: not glining %s!%s@%s due to too lack of removal data with mask: *!%s (%d users) -- worm: %s)", sender->nick, sender->ident, sender->host->name->content, glinemask, usercount, worm->name->content);
+ return;
+ }
+
+ trojanscan_database_escape_string(enick, sender->nick, strlen(sender->nick));
+ trojanscan_database_escape_string(eident, sender->ident, strlen(sender->ident));
+ trojanscan_database_escape_string(ehost, sender->host->name->content, sender->host->name->length);
+
+ frequency = 1;
+
+ if (!(trojanscan_database_query("SELECT COUNT(*) FROM hits WHERE glined = %d AND host = '%s'", glining, ehost))) {
+ trojanscan_database_res *res;
+ if ((res = trojanscan_database_store_result(&trojanscan_sql))) {
+ trojanscan_database_row sqlrow;
+ if ((trojanscan_database_num_rows(res) > 0) && (sqlrow = trojanscan_database_fetch_row(res)))
+ frequency = atoi(sqlrow[0]) + 1;
+ trojanscan_database_free_result(res);
+ }
+ }
+
+ if (!glining) {
+ trojanscan_mainchanmsg("m: t: %c u: %s!%s@%s%s%s w: %s p: %d %s%s", messagetype, sender->nick, sender->ident, sender->host->name->content, messagetype=='N'||messagetype=='M'||messagetype=='P'?" #: ":"", messagetype=='N'||messagetype=='M'||messagetype=='P'?chp->index->name->content:"", worm->name->content, phrase->id, matchbuf[0]?" --: ":"", matchbuf[0]?matchbuf:"");
+#ifdef TROJANSCAN_PEONCHANNEL
+ trojanscan_peonchanmsg("m: t: %c u: %s!%s@%s%s%s%s w: %s %s%s", messagetype, sender->nick, sender->ident, (IsHideHost(sender)&&IsAccount(sender))?sender->authname:sender->host->name->content, (IsHideHost(sender)&&IsAccount(sender))?"."HIS_HIDDENHOST:"", messagetype=='N'||messagetype=='M'||messagetype=='P'?" #: ":"", messagetype=='N'||messagetype=='M'||messagetype=='P'?chp->index->name->content:"", worm->name->content, matchbuf[0]?" --: ":"", matchbuf[0]?matchbuf:"");
+#endif
+ } else {
+ int glinetime = TROJANSCAN_FIRST_OFFENSE * frequency * (worm->epidemic?TROJANSCAN_EPIDEMIC_MULTIPLIER:1);
+ if(glinetime > 7 * 24)
+ glinetime = 7 * 24; /* can't set glines over 7 days with normal non U:lined glines */
+
+ trojanscan_database_query("INSERT INTO hits (nickname, ident, host, phrase, messagetype, glined) VALUES ('%s', '%s', '%s', %d, '%c', %d)", enick, eident, ehost, phrase->id, messagetype, glining);
+ trojanscan_database.glines++;
+
+ irc_send("%s GL * +%s %d :You (%s!%s@%s) are infected with a trojan (%s/%d), see %s%d for details - banned for %d hours\r\n", mynumeric->content, glinemask, glinetime * 3600, sender->nick, sender->ident, sender->host->name->content, worm->name->content, phrase->id, TROJANSCAN_URL_PREFIX, worm->id, glinetime);
+
+ trojanscan_mainchanmsg("g: *!%s t: %c u: %s!%s@%s%s%s c: %d w: %s%s p: %d f: %d", glinemask, messagetype, sender->nick, sender->ident, sender->host->name->content, messagetype=='N'||messagetype=='M'||messagetype=='P'?" #: ":"", messagetype=='N'||messagetype=='M'||messagetype=='P'?chp->index->name->content:"", usercount, worm->name->content, worm->epidemic?"(E)":"", phrase->id, frequency);
+ }
+}
+
void trojanscan_rejoin_channel(void *arg) {
struct trojanscan_rejoinlist *rj2, *lrj, *rj = (struct trojanscan_rejoinlist *)arg;
#include <ctype.h>
#include <strings.h>
-#define TROJANSCAN_VERSION "2.64"
+#define TROJANSCAN_VERSION "2.68"
#define TROJANSCAN_MAX_HOST_GLINE 5
-#define TROJANSCAN_CLONE_MAX 150
-#define TROJANSCAN_WATCHCLONE_MAX 100
+#define TROJANSCAN_CLONE_MAX 75
+#define TROJANSCAN_WATCHCLONE_MAX 75
#define TROJANSCAN_CLONE_TOTAL TROJANSCAN_CLONE_MAX + TROJANSCAN_WATCHCLONE_MAX
#define TROJANSCAN_POOLSIZE 1000
#define TROJANSCAN_MINIMUM_HOSTS_BEFORE_POOL 5000 /* 5000 */
#define TROJANSCAN_DEFAULT_MAXCHANS 750
-#define TROJANSCAN_DEFAULT_CYCLETIME 800
+#define TROJANSCAN_DEFAULT_CYCLETIME 1600
#define TROJANSCAN_DEFAULT_MINIMUM_CHANNEL_SIZE 100 /* 100 */
#define TROJANSCAN_NICKCHANGE_ODDS 8
#define TROJANSCAN_INVISIBLE_ODDS 8
-#define TROJANSCAN_DEFAULT_PARTTIME 100
+#define TROJANSCAN_DEFAULT_PARTTIME 150
#define TROJANSCAN_DEFAULT_MAXUSERS 20
#define TROJANSCAN_POOL_REGENERATION 3600
#define TROJANSCAN_IPLEN 20
#define TROJANSCAN_VERSION_DETECT "\001VERSION"
-#define TROJANSCAN_CLONE_VERSION_REPLY "mIRC v6.17 Khaled Mardam-Bey"
+#define TROJANSCAN_DEFAULT_VERSION_REPLY "mIRC v6.31 Khaled Mardam-Bey"
typedef struct trojanscan_clones {
int remaining, sitting, index;