// Output string must be 41 bytes minimum. out is returned as a convenience. char* GetHashString(const char* in, char* out) { WDL_SHA1 sha; sha.add(in, (int)strlen(in)); char hash[20]; sha.result(hash); for (int i = 0; i < 20; i++) sprintf(out + i*2, "%02X", (unsigned char)(hash[i] & 0xFF)); out[40] = 0; return out; }
int WDL_RNG_int32() { WDL_SHA1 tmp; tmp.add(state,sizeof(state)); rngcycle(); union { char buf[WDL_SHA1SIZE]; int a; } b; tmp.result(b.buf); return b.a; }
void WDL_RNG_bytes(void *buf, int buflen) { char *b=(char *)buf; while (buflen > 0) { char tb[WDL_SHA1SIZE]; WDL_SHA1 tmp; tmp.add(state,sizeof(state)); rngcycle(); tmp.result(tb); int l=min(buflen,WDL_SHA1SIZE); memcpy(b,tb,l); buflen-=l; b+=l; } }
void WDL_RNG_addentropy(void *buf, int buflen) { WDL_SHA1 tmp; tmp.add(state,sizeof(state)); tmp.result(state); tmp.reset(); tmp.add((unsigned char *)buf,buflen); tmp.result(state+sizeof(state) - WDL_SHA1SIZE); }
int Run() { // perform lookup here user_valid=0; if (!strncmp(username.Get(),"anonymous",9) && (!username.Get()[9] || username.Get()[9] == ':')) { logText("got anonymous request (%s)\n",g_config_allowanonymous?"allowing":"denying"); if (!g_config_allowanonymous) return 1; user_valid=1; reqpass=0; WDL_String tmp(username.Get()); if (tmp.Get()[9] == ':' && tmp.Get()[10]) { username.Set(tmp.Get()+10); int cnt=16; char *p=username.Get(); while (*p) { if (!cnt--) { *p=0; break; } if (*p == '@' || *p == '.') *p='_'; p++; } } else username.Set("anon"); username.Append("@"); username.Append(hostmask.Get()); if (g_config_anonymous_mask_ip) { char *p=username.Get(); while (*p) p++; while (p > username.Get() && *p != '.' && *p != '@') p--; if (*p == '.' && p[1]) { p[1]='x'; p[2]=0; } } privs=(g_config_allow_anonchat?PRIV_CHATSEND:0) | (g_config_allowanonymous_multi?PRIV_ALLOWMULTI:0) | PRIV_VOTE; max_channels=g_config_maxch_anon; } else { int x; logText("got login request for '%s'\n",username.Get()); if (g_status_user.Get()[0] && !strcmp(username.Get(),g_status_user.Get())) { user_valid=1; reqpass=1; is_status=1; privs=0; max_channels=0; WDL_SHA1 shatmp; shatmp.add(username.Get(),strlen(username.Get())); shatmp.add(":",1); shatmp.add(g_status_pass.Get(),strlen(g_status_pass.Get())); shatmp.result(sha1buf_user); } else for (x = 0; x < g_userlist.GetSize(); x ++) { if (!strcmp(username.Get(),g_userlist.Get(x)->name.Get())) { user_valid=1; reqpass=1; char *pass=g_userlist.Get(x)->pass.Get(); WDL_SHA1 shatmp; shatmp.add(username.Get(),strlen(username.Get())); shatmp.add(":",1); shatmp.add(pass,strlen(pass)); shatmp.result(sha1buf_user); privs=g_userlist.Get(x)->priv_flag; max_channels=g_config_maxch_user; break; } } } return 1; }
int SHM_MsgReplyConnection::Send(int type, const void *msg, int msglen, void *replybuf, int maxretbuflen, const int *forceMsgID, const void *secondchunk, int secondchunklen, WDL_HeapBuf *hbreplyout) { if (!m_shm||m_has_had_error) return -1; if (secondchunk && secondchunklen>0) msglen+=secondchunklen; else secondchunklen=0; int msgid; { WDL_MutexLock lock(&m_shmmutex); m_shm->send_queue.AddDataToLE(&type,4,4); if (forceMsgID) msgid = *forceMsgID; else { if (!replybuf&&!hbreplyout) msgid=0; else if (!(msgid = ++m_lastmsgid)) msgid = ++m_lastmsgid; } m_shm->send_queue.AddDataToLE(&msgid,4,4); m_shm->send_queue.AddDataToLE(&msglen,4,4); if (msglen>secondchunklen) m_shm->send_queue.Add(msg,msglen-secondchunklen); if (secondchunklen>0) m_shm->send_queue.Add(secondchunk,secondchunklen); #ifdef VERIFY_MESSAGES WDL_SHA1 t; t.add(&type,4); t.add(&msgid,4); t.add(&msglen,4); if (msglen>secondchunklen) t.add(msg,msglen-secondchunklen); if (secondchunklen>0) t.add(secondchunk,secondchunklen); char tb[WDL_SHA1SIZE]; t.result(tb); m_shm->send_queue.Add(tb,sizeof(tb)); #endif if ((!replybuf && !hbreplyout) || !msgid) m_shm->Run(); // get this reply out ASAP } if ((hbreplyout||replybuf) && msgid) { int wait_cnt=30; // dont run idleproc for first Xms or so while (!m_has_had_error) { if (wait_cnt<=0 && IdleProc && IdleProc(this)) { m_has_had_error=true; break; } WaitingMessage *msg=NULL; bool r = RunInternal(msgid,&msg); if (msg) { int rv = msg->m_msgdata.GetSize(); if (hbreplyout) { memcpy(hbreplyout->Resize(rv,false),msg->m_msgdata.Get(),rv); } if (replybuf) { if (rv > maxretbuflen) rv=maxretbuflen; if (rv>0) memcpy(replybuf,msg->m_msgdata.Get(),rv); } m_shmmutex.Enter(); msg->_next = m_spares; m_spares=msg; m_shmmutex.Leave(); return rv; } else if (r) break; if (wait_cnt>0) wait_cnt--; HANDLE evt=m_shm->GetWaitEvent(); if (evt) WaitForSingleObject(evt,1); else Sleep(1); } } if (hbreplyout) hbreplyout->Resize(0,false); return -1; }
bool SHM_MsgReplyConnection::RunInternal(int checkForReplyID, WaitingMessage **replyPtr) { if (!m_shm||m_has_had_error) return true; if (replyPtr) *replyPtr=0; int s=0; do { m_shmmutex.Enter(); // autocompact on first time through if (!s) m_shm->recv_queue.Compact(); s = m_shm->Run(); if (m_shm->send_queue.Available() > m_maxqueuesize) s=-1; while (m_shm->recv_queue.GetSize()>=12) { int datasz = *(int *)((char *)m_shm->recv_queue.Get()+8); WDL_Queue::WDL_Queue__bswap_buffer(&datasz,4); // convert to LE if needed if (m_shm->recv_queue.GetSize() < 12 + datasz) break; #ifdef VERIFY_MESSAGES if (m_shm->recv_queue.GetSize() < 12 + datasz + WDL_SHA1SIZE) break; #endif int type = *(int *)((char *)m_shm->recv_queue.Get()); WDL_Queue::WDL_Queue__bswap_buffer(&type,4); // convert to LE if needed WaitingMessage *msg = m_spares; if (msg) m_spares = m_spares->_next; else msg = new WaitingMessage; msg->m_msgid = *(int *)((char *)m_shm->recv_queue.Get() + 4); WDL_Queue::WDL_Queue__bswap_buffer(&msg->m_msgid,4); // convert to LE if needed msg->m_msgtype = type; memcpy(msg->m_msgdata.Resize(datasz,false),(char *)m_shm->recv_queue.Get()+12, datasz); m_shm->recv_queue.Advance(12+datasz); #ifdef VERIFY_MESSAGES WDL_SHA1 t; t.add(&type,4); t.add(&msg->m_msgid,4); t.add(&datasz,4); t.add(msg->m_msgdata.Get(),msg->m_msgdata.GetSize()); char tb[WDL_SHA1SIZE]; t.result(tb); if (memcmp(m_shm->recv_queue.Get(),tb,WDL_SHA1SIZE)) MessageBox(NULL,"FAIL","A",0); m_shm->recv_queue.Advance(WDL_SHA1SIZE); #endif if (type==0) { if (checkForReplyID && replyPtr && !*replyPtr && checkForReplyID == msg->m_msgid) { *replyPtr = msg; s=0; break; // we're done! } else { msg->_next = m_waiting_replies; m_waiting_replies = msg; } } else { m_shmmutex.Leave(); WaitingMessage *msgtail=NULL; if (OnRecv) { msg->_next=0; msgtail = msg = OnRecv(this,msg); while (msgtail && msgtail->_next) msgtail=msgtail->_next; } else if (msg->m_msgid) Reply(msg->m_msgid,"",0); // send an empty reply m_shmmutex.Enter(); // get shm again if (msg) { (msgtail?msgtail:msg)->_next = m_spares; m_spares=msg; } } } // while queue has stuff if (checkForReplyID && replyPtr && !*replyPtr) { WaitingMessage *m=m_waiting_replies; WaitingMessage *lp=NULL; while (m) { if (m->m_msgid == checkForReplyID) { if (lp) lp->_next = m->_next; else m_waiting_replies=m->_next; *replyPtr = m; s=0; // make sure we return ASAP break; } lp = m; m=m->_next; } } m_shmmutex.Leave(); } while (s>0); if (s<0) m_has_had_error=true; else if (m_shm && m_shm->WantSendKeepAlive()) { int zer=0; Send(0,NULL,0,NULL,0,&zer); } return s<0; }