cwbe coordinatez:
101
792011
2663954
2663960

ABSOLUT
KYBERIA
permissions
you: r,
system: public
net: yes

neurons

stats|by_visit|by_K
source
tiamat
K|my_K|given_K
last
commanders
polls

total descendants::
total children::19
3 ❤️


show[ 2 | 3] flat


urza0
ondrish0
lbnd0
tux0
mono0
michael czer...0
mx0
::0
-sXero-0
freezy0
Robin0
joseph0
rigor0
fifteen0
||0
bon0
janko_hrasko0
Michael[Lock...2
z13

technologicko | programovaco | geekovsky pseudoblog

mx


technology | code | brainstorm | algorithm



eye|mx personal blog





0000010100792011026639540266396003402036
SYNAPSE CREATOR
 mx      01.10.2007 - 01:09:55 (modif: 01.10.2007 - 01:10:14), level: 1, UP   NEW  HARDLINK !!CONTENT CHANGED!!
podla toho, co potrebujes...
ja napriklad ak potrebujem zrusit vsetko a vypisat len error, by som pouzil exception, ktora by mala barikadu az na nejakom najhlavnejsom skripte a tam by vypisalo potrebny error document... napriklad:

mam code.php, co je hlavny skript, ktory je inkludovany vsetkym ostatnym a je v nom case, ktory hovori, co sa bude diat (inak velmi uzitocna vec)... v pseudokode nieco taketo:

---
core.php
---
try {
ob_start();
switch ($PAGE) {
case 'index':
include_once dirname(__FILE__).'/pages/index.page.php';
break;
}
ob_end_flush();
} catch (Exception $e) {
ob_end_clean();
$tpl_error_msg = $e->message;
include_once dirname(__FILE__).'/templates/error.tpl.php';
}

---
index.page.php
---
if (!$check) {
throw new Exception('Something went wrong.');
}


------
ps: vlastne to takto robim skoro pravidelne ;)

0000010100792011026639540266396002975771
mx
 mx      09.03.2007 - 10:58:53 , level: 1, UP   NEW
pokial potrebujete zistit kolko messages je v queue, nezistil som sposob, ako to spravit cez JMS, je mozne pouzit nativne java classy WsMQ; nejak takto -- v principe velmi jednoduche:

--

package com.exstream.jms;

import com.ibm.mq.MQC;
import com.ibm.mq.MQQueue;
import com.ibm.mq.MQQueueManager;

public class JMSQueuePoller {
public static void main(String[] args) throws Exception {
MQQueueManager manager = new MQQueueManager("QM_prg_harpy");
MQQueue queue = manager.accessQueue("DLGQ_OUT", MQC.MQOO_INQUIRE);
System.out.println("REM> " + queue.getCurrentDepth());
}
}

0000010100792011026639540266396002974306
mx
 mx      08.03.2007 - 17:28:36 , level: 1, UP   NEW
jeden maly postreh, zase raz... ono sa to sice da velmi jednoducho aj vygooglit, ale aj tak...
WebSphereMQ generuje default message vo formate MQRFH2, co je message s pridanym RFH2 headerom, tzn, aplikacie, ktore ocakavaju plain-text message s tym maju problem. Obist sa to da tak, ze sa ako queue (URI) nastavi targetClient na hodnotu 1, tzn. napriklad...

Queue queue = session.createQueue("queue://QueueManagerName/QueueName?targetClient=1");

... to je len vec, ktora ma dnes celkom zaujala a nie je nejak extremne dokumentovana -- resp, vo WSMQ online books som to nenasiel.

0000010100792011026639540266396002745992
SYNAPSE CREATOR
 mx      10.11.2006 - 02:47:33 (modif: 10.11.2006 - 02:48:14), level: 1, UP   NEW  HARDLINK !!CONTENT CHANGED!!
mas 5 krabic
v kazdej moze byt papierik s cislom, alebo cislom krabice, v ktorom sa cislo nachadza
oznacme si krabice cislami 1 az 5
pozrieme sa do krabice 1 a tam je cislo "2"
v krabici 2 je papierik s napisom, hodnotu najdes v krabici 4
v krabici 3 je papierik s napisom hodnotu najdes v krabici 2
v krabici 4 je cislo "3"
krabica 5 je prazdna
--
nech mame premennu typu int
krabica 1 predstavuje "int k1" kde k1 = 2
krabica 2 predstavuje "int* k2" (takze ukazovatel na hodnotu, v nasom pripade krabicu 4), takze int* k2 = &k4 = 4, a hodnotu ziskame dereferencovanim *k2 = 3
krabica 3 je "int** k3" (ukazovate na ukazovatel na hodnotu, v nasom pripade na krabicu 2, ktora ukazuje na krabicu 4), takze int** k3 = &k2 = 4, hodnotu ziskame **k3 = 3
krabica 4 je "int k4", k4 = 3
krabica 5 je NULL, moze to byt napriklad int* k5 = NULL, tzn. ukazovatel, ktory ukazuje na nic, keby sme ho chceli pouzit, dopustime sa chyby

-- povedane v C --
#include <stdio.h>
int main(int argc, char* argv[]) {
int k1 = 2;
int k4 = 3; // krabica k4 je definovana skor kvoli tomu, aby sme na nu mohli odkazovat
int* k2 = &k4; // *k2 = 3
int**k3 = &k2; // **k3 = 3
int* k5 = NULL; // k5 = NULL, *k5 = chyba

printf("k1: %d, k2: %d, k3: %d, k4: %d, k5: (null)\n",
k1, *k2, **k3, k4);

return (0);
}

--
lepsia analogia ma v rychlosti, po troske vina a o tejto nocnej hodine nenapadla :)

0000010100792011026639540266396002740124
mx
 mx      07.11.2006 - 15:17:59 , level: 1, UP   NEW
... potreboval som pozastavit beh programu na 5 sekund ... toto skoncilo v zdrojaku:


DWORD dwTickBegin = GetTickCount();
while (GetTickCount() < dwTickBegin + 5000)
Sleep(100);


... uz sa nekomentujem.

000001010079201102663954026639600274012402740928
ventYl
 ventYl      07.11.2006 - 22:01:19 , level: 2, UP   NEW
o sleepe na windowsoch nechyrovali? resp. o volani alert :)

00000101007920110266395402663960027401240274092802741445
mx
 mx      08.11.2006 - 09:29:36 , level: 3, UP   NEW
je to este horsie
ja som tam ten sleep nakoniec aj pouzil ;) len si vsimni ako :-))
podotykam, bol to ciry blackout
potom som to samozrejme nahradil Sleep(5000);

0000010100792011026639540266396002740124027409280274144502741838
ventYl
 ventYl      08.11.2006 - 12:51:31 , level: 4, UP   NEW
je dobre mat volnost robit jednoduche veci lubovolne zlozitou metodou riesenia :]

000001010079201102663954026639600274012402740140
Thunder Perfect Mind
 Thunder Perfect Mind      07.11.2006 - 15:23:01 (modif: 07.11.2006 - 15:24:02), level: 2, UP   NEW !!CONTENT CHANGED!!
rofl
http://thedailywtf.com/

00000101007920110266395402663960027401240274014002740175
mx
 mx      07.11.2006 - 15:38:30 , level: 3, UP   NEW
:-)))
ok, tak nie som na tom AZ tak zle!

0000010100792011026639540266396002731249
mx
 mx      03.11.2006 - 09:20:08 , level: 1, UP   NEW
kedze vsade sa kazdy vytesuje zo std::string, spravil som si jeden rychly "benchmark", softwareovi teoretici ma mozu spindat, ze to nie je uplne reprezentativne, ale mne to stacilo... tu su vysledky... pre tych, ktorych to zaujima:

release>bm_cstr.exe
100000 additions in 20 msec (26904606, 26904626) -- 0.00020 per add
release>bm_stdstr.exe
100000 additions in 170 msec (26907120, 26907290) -- 0.00170 per add

testovaci program:

#define __STDSTRING

#include <string>
#include <stdio.h>
#include <windows.h>

using namespace std;

int main(int argc, char* argv[]) {
DWORD tick_begin, tick_end;
tick_begin = GetTickCount();

#ifdef __STDSTRING
string dest;
string src("test1");
for (int x = 0; x < 100000; x++) dest = src + "test2";
#else
char* dest = (char*)malloc(1024);
memset(dest, 0, 1024);
char* src = "test1";
for (int x = 0; x < 100000; x++) {
memset(dest, 0, 1024);
strcat(dest, (char*)&src);
strcat(dest, "test2");
}
free(dest);
#endif
tick_end = GetTickCount();

printf("100000 additions in %u msec (%u, %u) -- %.5f per add\n", tick_end - tick_begin,
tick_begin, tick_end, (tick_end - tick_begin) / 100000.0);

return (0);
}

0000010100792011026639540266396002722573
mx
 mx      30.10.2006 - 11:15:53 (modif: 31.10.2006 - 10:31:06), level: 1, UP   NEW !!CONTENT CHANGED!!
sice vytvarat mutexy s NULL DACL je mierne nebezpecne, pouzil som v jednom VB projekte (uprave existujuceho, inak by som sa VB ani len nechytil) presne tento pristup... tu je zdrojak vytvarania (otvarania) takeho mutexu (pointa je, aby fungoval medzi roznymi usermi):


' WinAPI structures
Private Type ACL
AclRevision As Byte
Sbz1 As Byte
AclSize As Integer
AceCount As Integer
Sbz2 As Integer
End Type

Private Type SECURITY_DESCRIPTOR
Revision As Byte
Sbz1 As Byte
Control As Long
Owner As Long
Group As Long
Sacl As ACL
Dacl As ACL
End Type

Private Type SECURITY_ATTRIBUTES
nLength As Long
lpSecurityDescriptor As Long
bInheritHandle As Long
End Type

' WinAPI constants
Private Const MUTEX_ALL_ACCESS = 2031617
Private Const SECURITY_DESCRIPTOR_REVISION = (1)

' Mutex related WinAPI imports
Private Declare Function CreateMutex Lib "kernel32" Alias "CreateMutexA" (lpMutexAttributes As SECURITY_ATTRIBUTES, ByVal bInitialOwner As Long, ByVal lpName As String) As Long
Private Declare Function OpenMutex Lib "kernel32" Alias "OpenMutexA" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal lpName As String) As Long
Private Declare Function InitializeSecurityDescriptor Lib "advapi32.dll" (pSecurityDescriptor As SECURITY_DESCRIPTOR, ByVal dwRevision As Long) As Long
Private Declare Function SetSecurityDescriptorDacl Lib "advapi32.dll" (pSecurityDescriptor As SECURITY_DESCRIPTOR, ByVal bDaclPresent As Long, pDacl As Long, ByVal bDaclDefaulted As Long) As Long
...
Dim MutexHandle As Long
...
' Opening mutex with NULL DACL
MutexHandle = OpenMutex(MUTEX_ALL_ACCESS, 0, "VBMUTEX05")
If MutexHandle = 0 Then
Select Case Err.LastDllError
Case 2&
' Preparation of NULL SECURITY_DESCRIPTOR
Dim MutexAtts As SECURITY_ATTRIBUTES
MutexAtts.bInheritHandle = False
MutexAtts.nLength = Len(MutexAtts)
Dim SecDesc As SECURITY_DESCRIPTOR
Dim SecInitRes As Boolean
SecInitRes = InitializeSecurityDescriptor(SecDesc, _
SECURITY_DESCRIPTOR_REVISION)
If Not SecInitRes Then
' ERROR initializing SD
Exit Sub
End If
Dim SetSDRes As Boolean
SetSDRes = SetSecurityDescriptorDacl(SecDesc, _
True, ByVal 0&, False)
If Not SetSDRes Then
' ERROR creating DACL-SD
Exit Sub
End If
MutexAtts.lpSecurityDescriptor = VarPtr(SecDesc)

' Creating the mutex with NULL DACL
MutexHandle = CreateMutex(ByVal MutexAtts, 0, "VBMUTEX05")
Case Else
' ERROR: Unknown
Exit Sub
End Select
End If
' SUCCESS
...


zaujimave je na tom podla mna hlavne predavanie lp* parametrov WinAPI funkciam cez VarPtr(NazovPremennej).

0000010100792011026639540266396002722474
mx
 mx      30.10.2006 - 10:18:05 , level: 1, UP   NEW
pre vsetkych, ktori su nuteni pouzivat WinAPI vo Visual Basicu, velmi uzitocna vec:

http://www.vbforums.com/attachment.php?s=106444fe2e138055cec766c99042870b&attachmentid=26572
http://www.redheadedlefty.com/vbforums/Win32api_2.zip

prve je viewer a druhe datafile s WinAPI deklaraciami, definiciami konstant a struktur z winapi pre visual basic

0000010100792011026639540266396002718116
mx
 mx      27.10.2006 - 16:05:53 , level: 1, UP   NEW
Kedze som nuteny v praci upravit jednu aplikaciu vo VB6 na multithread synchronizaciu, potreboval som nastudovat pouzitie Mutexov vo VB... kto by take nieco potreboval, tu ma zakladne Declares a Const na bezne pouzitie:

' Mutex related WinAPI imports
Private Declare Function CreateMutex Lib "kernel32" Alias "CreateMutexA" (lpMutexAttributes As Any, ByVal bInitialOwner As Long, ByVal lpName As String) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Declare Function OpenMutex Lib "kernel32" Alias "OpenMutexA" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal lpName As String) As Long
Private Declare Function ReleaseMutex Lib "kernel32" (ByVal hMutex As Long) As Long
Private Declare Function WaitForSingleObject Lib "kernel32" (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long

' WinAPI constants
Const MUTEX_ALL_ACCESS = 2031617
Const WAIT_OBJECT_0 = 0&
Const WAIT_TIMEOUT = 258&


pri volani potom treba Long-y predavat ako:

MutexHandle = CreateMutex(ByVal 0&, 0, "VBMUTEX02")

0000010100792011026639540266396002701960
mx
 mx      19.10.2006 - 22:53:20 [1K] , level: 1, UP   NEW
Prvy helper (pre-build event do MSVC, pripadne inych kompilatorov) je na svete...


** BuildTools::AutoVersion 0.9.5.20 (c)2006 Miroslav Hudak
** Usage: AutoVersion.exe [options] <sources-path>
<sources-path>
Path to source files of your project. All other files
provided in switches are relative to this path.

Options:
-ms Version modify string
In form '1.2.3.4' where each number stands for:
1 - Major; 2 - Minor; 3 - Release; 4 - Build
and can be substituted for:
* No Action, leave as it is
+ Increment version number
- Decrement version number
<num> Set to <num> constant
e.g. '*.*.*.+' will increase build number each run
-vh Version header file name (default 'APP_VERSION.h')
-vr Version resource file name (default 'APP_VERSION.rc')
-vdef Define name for storing version number (default 'APP_VERSION')


Download @ http://www.maniax.sk/AutoVersion.0.9.5.20.zip
Z cisla verzie je zrejme, ze je to len BETA, ale ja to pouzivam pri kompilaciach a funguje to bez problemov. Odporucam nastavit len na RELEASE build konfiguracie. A samozrejme, je potrebne mat v projekte includnuty VERSIONINFO resource.

Moje nastavenie release pre-build event:

del "$(InputDir)\$(IntDir)\$(InputName).res"
c:\Btools\AutoVersion.exe -vr "$(InputName).rc" -ms *.*.*.+ "$(InputDir)"

(ten 'del' maze .res subor, aby ho musel znova prekompilovat, asi sa to da donutit rekompilovat aj inak, ale nedosiel som na to ako :)

Zaroven pracujem na postbuild eventoch pre archivaciu a podobne.
(a mne je jasne, ze take nieco uz existuje, ale chcem mat vlastne -- aspon si to viem upravit v momente, ked potrebujem :))

000001010079201102663954026639600270196002711325
ventYl
 ventYl      24.10.2006 - 17:06:04 , level: 2, UP   NEW
neviem, ako to riesis, ci pouzivas makefile, ale ja si obvykle robim v makefile ciel make clean, make rebuild a make package. make package automaticky zbuilduje balicek... a keby som nebol lenivy, tak si spravim aj automaticke zdvihanie verzie :D co tiez nie je tak zle vediet, kolko buildov som vlastne spravil...

00000101007920110266395402663960027019600271132502712435
mx
 mx      25.10.2006 - 08:14:52 , level: 3, UP   NEW
hlavne to riesim pod windowsom vo visual studiu, takze tam makefiles - pokial viem - prilis neficia
takze to riesim ako prebuild event

0000010100792011026639540266396002700856
mx
 mx      19.10.2006 - 15:02:13 , level: 1, UP   NEW
predpokladam, ze pre kazdeho administratora mssql to bude samozrejme, ale pre tych, ktori nemaju 10 certifikatov a len sem tam sa s mssql stretnu to moze byt usefull...

Moj problem spocival v tom, ze pri zapise do databazy z jednej aplikacie cez ODBC (MSSQL ODBC Driver) mi pri vkladanie datumu v tvare 'YYYY-MM-DD HH:MM:SS' vyhlasilo "Arithmetic overflow", alebo podobnu chybu. Pritom z MSSQL Enterprise Managera mi vsetko vkladalo uplne bez problemov.
Skusal som pridat data cez ODBC konektor PHPcka, ale pisalo to tu istu chybu. Na modifikovanom skripte - ktory vkladal datum v tvare 'DD-MM-YYYY HH:MM:SS' (tzn. viacmenej bezny format pre CE) - vsetko bezalo spravne, takze chyba bola jednoznacne niekde v locale.
Dalsi test bol zmenit collation celej databazy, nepomohlo ani SQL_Latin_1_CI_AS ani Latin_1_General_CI_AS (ci nejake take podobne), taktiez nepomohlo ani zmenenie Regional Settings na English... nakoniec po niekolkych hodinach hladania som prisiel na skvele nastavenie hlboko v nastaveni jednotlivych loginov (kedze MSSQL ma 'logins', potom 'DB users') a dany login mal nastaveny jazyk 'Slovak' a prislo mi jasne, ze tam musi mat 'English'...

Takze, ak mate podobny problem, tak:
Server > Security > Logins > double-click na login name > General > Default language ... a tam staci vybrat tu spravnu...

snad to niekomu pomoze :)

0000010100792011026639540266396002694341
mx
 mx      16.10.2006 - 14:51:40 , level: 1, UP   NEW
len sem musim dat jednu citaciu k specifikacii XMP formatu:
"If a DTD is required, be aware that RDF provides many equivalent ways to express the same model. Thus the safest approach is to use a DTD describing any possible RDF. We don’t know of a standard DTD fragment to do this."

pointa je v tom, ze uz viacero ludi sa stazovalo, ze aplikacie (tie od adobe) zapisuju doslovne ako sa im chce, takze jedina spravna implementacia sa zda byt bruteforce nad vsetkymi moznostami a break pri najdeni spravnej...

0000010100792011026639540266396002678750
SYNAPSE CREATOR
 mx      08.10.2006 - 20:29:34 , level: 1, UP   NEW  HARDLINK
je to programovanie, ale davam to schvalne sem:

Go To Statement Considered Harmful
Edsger W. Dijkstra

http://www.acm.org/classics/oct95/

-- oplati sa precitat uz len pre zaujimavost :)

0000010100792011026639540266396002668154
mx
 mx      03.10.2006 - 13:02:12 (modif: 03.10.2006 - 13:33:59) [2K] , level: 1, UP   NEW !!CONTENT CHANGED!!


.about
prezentacia novej verzie havok 4 physical engine, ktory bude pouzity v hrach pre next-gen PC/konzoly, vyuzivajuc GPU sucasnych high-end grafickych kariet.
odporucam pozriet aj nehernej verejnosti

.video
http://www.youtube.com/watch?v=wWjSJ0PHqf8

.info
Havok's modular suite of tools puts power in the hands of creators, making sure they can reach new standards of realism and interactivity, while mitigating the overall cost and risks associated with creating today's leading video games and movies.

000001010079201102663954026639600266815402668171
joseph
 joseph      03.10.2006 - 13:09:11 , level: 2, UP   NEW
parada 8D

0000010100792011026639540266396002667967
mx
 mx      03.10.2006 - 11:42:22 , level: 1, UP   NEW
este jedna poznamka k lockovaniu... je celkom elegantny sposob, ako zistit ake locky ma dana transakcia (a tym padom to vieme vyuzit aj specificky na queries):


BEGIN TRAN
[SQL_QUERY ktoru chceme zanalyzovat]
EXEC sp_lock
SELECT object_name([ID z vysledku ObjID volania sp_lock]) UNION
[dalsie objectnames]...;
COMMIT


idealne je to vykonavat v Query Analyser-i

0000010100792011026639540266396002667830
mx
 mx      03.10.2006 - 11:02:02 (modif: 03.10.2006 - 11:23:14), level: 1, UP   NEW !!CONTENT CHANGED!!
v praci som narazil na jeden (celkom zaujimavy) problem nad ms sqlserver, s ktorym zase nemam az take prenikave skusenosti, tak mi chvilku trvalo, kym som ho vyriesil. mozno bude niekoho zaujimat a niekomu sa bude hodit (myslim, ze je to jedna z beznejsich chyb). popisem priklad z praxe, kazdy, kto vie o com hovorim, by si tam mal najst potrebnu informaciu:

podmienky:

- majme tabulku J a tabulku V, ktore obsahuju informacie o ulohe. v J su standartne informacie o ulohe a vo V su premenne nabindovane k J cez J.id.
- majme dva druhy procesov:
1) update process - UPDATE queries v transakcii:

BEGIN TRAN
UPDATE J ...
UPDATE V ...
UPDATE V ...
...
UPDATE V ...
COMMIT

2) select process - SELECT query nad J

SELECT COUNT(*) from J ...

- majme takychto procesov pustenych niekolko (produkcna prevadzka bola cca 2 UPDATE + 2 SELECT viacmenej simultanne, ja som to testoval v 4/2 pri intervaloch spustania rand(0, 1000) milisekund)

nastava problem: DEADLOCKu nad SELECT query (process typu #2)

riesenie: skusal som vsetko, do primitivnych zaobalovaciek selectu do transakcie, cez read uncommited transakcie cez isolation level nad query, pomohlo - zda sa - nieco velmi trivialne, zakazanie uzamykania selectu pri count(*), co nam je vlastne aj tak jedno, kedze pri tom mnozstve poziadaviek tie cisla nemusia byt 100% presne a to, ze sa objavi odchylka je aj tak malo pravdepodobne. Takze spravna syntax SELECT query v procese typu #2 je:

SELECT count(*) from J (NOLOCK) where ...


test: 30000 update query v kazdom zo 4 procesov + 1200 select query v kazdom z 2 procesov bez deadlocku (inokedy mi to uz najneskor pri selecte#200 hodilo deadlock... takze dufam, ze je to ok



EDIT

nakoniec som - podla mojho nazoru - vybral este lepsie riesenie z ponukanych.
kedze NOLOCK funguje ako read uncommitted (tzn, berie do uvahy vsetko, aj neCOMMITnute riadky), existuje este jedna lepsia alternativa a to READPAST, ktora neberie do uvahy nic, co je locknute (tzn, riadky, ktore su prave spracovavane ignoruje). v tomto pripade mi to pride rozumnejsie, kazdopadne COUNT(*) je ako taky dost nespolahlivy a nikdy by sa nemal pouzivat ako dolezity udaj.

moja finalna query:

SELECT count(*) from J (READPAST) where ...


000001010079201102663954026639600266783005526565
qiNa
 qiNa      02.09.2010 - 09:07:34 , level: 2, UP   NEW
akurat to riesim v praci. Dva dni sa nemozem pohnut. Idem to skusit ...

00000101007920110266395402663960026678300552656505526570
reason
 reason      02.09.2010 - 09:12:45 , level: 3, UP   NEW
otovor okno , vezmi server vyhod ho von oknom :))))

0000010100792011026639540266396002667830055265650552657005526713
qiNa
 qiNa      02.09.2010 - 10:13:34 , level: 4, UP   NEW
ved chudak, v jednom okne uz je... :D

0000010100792011026639540266396002664128
mx
 mx      01.10.2006 - 16:29:51 (modif: 01.10.2006 - 17:00:15) [7K] , level: 1, UP   NEW !!CONTENT CHANGED!!
este jeden, uz velmi technicky clanok, ako objasnenie autentifikacie, ktora bola pouzita v predchadzajucej demonstracii.
Taktiez je k dispozicii krajsia PDF verzia: http://www.hudak.info/kyb-crammd5.pdf




Implementácia CramMD5 autentifikácie


PHP / JavaScript

mx, 2006-10-01


Úvod


Základný problém prihlasovania sa cez http protokol (pri absencii https), prípadne pri prihlasovaní sa na služby tretích strán, je možnosť odchytenia plaintext hesla, či už na strane poskytovateľa internetového pripojenia (prípadne na trase od klienta na server), alebo priamo na serveri zo strany implementátora služby.


Riešením by bolo, neprenášať heslo v plaintext tvare a tým zamedziť uloženiu a následnému zneužitiu hesla.



Teoretické východiská


CramMD5 autentifikácia je založená na predspracovaní hesla na strane klientskej stanice. Základom je skriptovací jazyk (najčastejšie použitý JavaScript), ktorý vytvorí na základe vstupných dát poskytnutých serverom MD5 hash, ktorý sa použije na porovnanie hesla na strane serveru. Tento hash sa potom prenesie v plaintext forme nezašifrovanou linkou a tým zamedzí odchyteniu plaintext hesla. Takýto hash je potom v závislosti na implementácii platný pre dané spojenie, prípadne obmedzený aj špecificky na IP adresu.



Implementačné detaily


Riešenie CramMD5 autentifikácie sa skladá z klientskej a serverovej časti.



Klientská časť


V prípade, že nie je používateľ autentifikovaný, zobrazuje sa – ako v každej klasickej webovej aplikácii – prihlasovací formulár. V prípade CramMD5 autentifikácie je rozšírený o niekoľko skriptov a skryté polia, obsahujúce kontrolné informácie. (Ako konkrétne príklady implementácie použijem zdrojový kód demonštrácie sociálnych sietí.)




<form action="" method="POST" onSubmit="return (SecOnSubmit())">

    <b>ID: </b><input name="sec_login" />

    <b>PWD:</b><input id="SecPwd" name="sec_password" type="password" />



    <input id="SecCraMD5" name="sec_cramd5" value="0" type="hidden" />

    <input id="SecCraMD5Hash" name="sec_cramd5_hash" value="<?php echo md5(uniqid(rand(), true)); ?>" type="hidden" />


    <input type="submit" value="Submit Credentials" />

    

    <script language="JavaScript"><!--

        // will hide the warning if javascript enabled and sets sec_cramd5 to 1

        document.getElementById('SecCraMD5').value = '1';

    //--></script>

</form>



Okrem vstupných polí sec_login a sec_password môžeme vidiet aj skryté polia sec_cramd5 a sec_cramd5_hash. Ich význam je nasledovný:



  • sec_cramd5 obsahuje informáciu o dostupnosti CramMD5 mechanizmu. Použije sa pritom jednoduchý trik s nastavením hodnoty poľa pomocou JavaScriptu. V momente, ked JavaScript nastaví pole na hodnotu „1“, môžeme si byť istí, že JavaScript je dostupný a CramMD5 autentifikácia bude použitá.

  • sec_cramd5_hash je hash, ktorý generuje server unikátne pre každé zobrazenie login formuláru. V tejto implementácii je použitý jednoduchý model, ktorý dovoľuje potenciálnemu útočníkovi zachytiť aj tento hash a poslať ho spolu s odchyteným MD5 hashom hesla na server, čím ho samozrejme autentifikuje. Pokiaľ by sme mali záujem o vyššiu úroveň bezpečnosti, môžeme do sec_cramd5_hash zaobaliť informácie o session vygenerovanej na serveri a po prihlásení túto session zrušiť, čím sa už ďalší používateľ s týmito informáciami neprihlási. Taktiež do hashu vieme zaobaliť IP adresu počítača, z ktorého klient stránku vyžiadal (čo môže byť problematické pri firemných sieťach s proxy servermi).



Po odoslaní takéhoto formulára sa vykoná onsubmit handler SecOnSubmit(), ktorého zdrojový kód vyzerá nasledovne:



function SecOnSubmit() {

    var pwdObj = document.getElementById('SecPwd');

    var hashObj = document.getElementById('SecCraMD5Hash');

    

    pwdObj.value = hex_md5(hashObj.value + hex_md5(pwdObj.value));

    return (true);

}



Je to multiplatformový JavaScript kód, ktorý zozbiera informácie z formulára, zavolá externý skript, ktorý vygeneruje MD5 hash z vložených údajov a prepíše výsledkom pole password vo formulári. Týmto postupom si zabezpečíme, že v prípade funkčnosti CramMD5 autentifikácie prejde z poľa sec_password len náš hash a v konečnom dôsledku si uľahčíme spracovanie na strane serveru.


V prípade, že CramMD5 nie je podporovaný, handler sa nevykoná a na server je poslané plaintext heslo taktiež cez pole sec_password spolu s informáciou v sec_cramd5, že autentifikácia nie je podporovaná.



Serverová časť



<?php

    
include_once dirname(__FILE__).'/passwordList.class.php';



    class
ESecException extends Exception { /* blank */ }


    

    class
CSec {

        static public function
authenticate

            
($in_PwdFile, $in_ID, $in_Password, $in_CraMD5, $in_CraMD5_Hash) {


        

            
$pwd_Hash = CPasswordList::getPasswordById($in_PwdFile, $in_ID);

            if (!
$pwd_Hash) throw new ESecException('User unknown.');


            

            if (
$in_CraMD5 == '1')

                
$sec_Hash = CSec::generateCraMD5Hash($pwd_Hash, $in_CraMD5_Hash);

            else {


                
$sec_Hash    = $pwd_Hash;

                
$in_Password = md5($in_Password);

            }

            

            return (
$sec_Hash == $in_Password);


        }

        

        static public function
generateCraMD5Hash($in_Pwd_Hash, $in_CraMD5_Hash) {

            return (
md5($in_CraMD5_Hash.$in_Pwd_Hash));

        }


    }

?>




Serverová časť je – ako vidieť na listingu – v tomto prípade veľmi priamočiara, na základe kontrolných údajov vyberie vhodnú metódu autentifikácie a vytvorí požadovaný porovnávací hash. Následne vo výsledku volania funkcie rozhodne o zhode / nezhode hashu a pošle logickú informáciu ako výsledok. Prihlasovací mechanizmus následne rozhodne o ďalšom postupe.


V tejto časti môže byť taktiež implementované bezpečnostné vylepšenie, napríklad kontrola IP adresy, alebo spolupráca s databázou, alebo sessions.



Využitie mechanizmu


CramMD5 nájde uplatnenie všade tam, kde je podstatná bezpečnosť hesiel a istota používateľov aj bez možnosti preskúmať serverovú časť aplikácie. Technológia zabezpečí, že pri splnení všetkých požiadaviek, nie je používateľovo heslo odosielané na server v žiadnom prípade (pokiaľ nie je požiadavka na zmenu hesla, v tom prípade je nutné posielať toto heslo minimálne v tvare MD5 hashu na uloženie do databázy).



000001010079201102663954026639600266412802669177
ventYl
 ventYl      03.10.2006 - 20:24:28 , level: 2, UP   NEW
cosi podobne som implementoval ja v mojej rocnikovej praci cca rok dozadu... oproti tomuto som pouzil len male zmeny (inac nadava sa tomu udajne aj challange-response autentification):

- pre kazdy session som si drzal jeden tzv. certifikat, ktory sa po kazdom pokuse o autentifikaciu v danom sessione okamzite znehodnotil a nahradil novym - nutne z dovodu zabranenia replay utokom
- namiesto obycajneho hex_md5() som pouzil md5_hmac. Rozdiel je asi taky, ze md5() hashuje retazec za pouzitia jeho dlzky ako hashovacieho kluca, zatial co md5_hmac() umoznuje ako hashovaci kluc pouzit cokolvek. Ja som ako hashovaci kluc pouzival certifikat. Preco? Lebo je to jednoducho bezpecnejsie, ako plain md5.

pri zmene hesla je mozne pouzit javascriptove implementacie nejakych asymetrickych sifrovacich algoritmov, ako napriklad gpg, alebo RSA, aby bolo heslo zasifrovane pred prenosom a desifrovane az na serveri.

tento mechanizmus ale neriesi man in the middle attack ani v jednom pripade

00000101007920110266395402663960026641280266917702669200
mx
 mx      03.10.2006 - 20:33:50 , level: 3, UP   NEW
mno, tak postupne:
1) tvoje certifikaty su nieco ako mnou navrhovane jedinecne zaznamy v databaze, teda, ak predpokladam, ze hned po refreshi stranky (teda, po autentifikovani) sa zaznam zmaze (a ked ho naviazes na ip adresu, tak to obmedzis este viac)
2) hex_md5 som pouzil preto, lebo som v danom momente nasiel ako prvu hex_md5 javascript implementaciu (kedze som to cele zbuchal za nejaku hodinu aj s cestou (myslim to demo)), ale uznavam... anyway, kolizii md5ky doteraz bolo najdenych malo, i ked boli ... ak tou nebezpecnostou myslis to
3) man in the middle - zabranis kazdopadne tomu, aby bolo heslo exposnute v plaintexte komukolvek, tzn, ze aj pri MITM dostane utocnik len md5hash hesla + challenge, pri rozumne zvolenom challenge moze skusat myslim, ze do smrti, problemy s odchytenim paketov vsak neriesi, transport layer nie je sifrovany

kazdopadne dobre pripomienky, nesnazil som sa robit mudreho, len mi to pride ako dobra alternativa ku klasickej plaintext autentifikacii a je velmi jednoducha na implementaciu a imho zvysuje bezpecnost systemu dost vyrazne

0000010100792011026639540266396002664128026691770266920002669507
ventYl
 ventYl      03.10.2006 - 23:07:49 , level: 4, UP   NEW
doteraz tych kolizii bolo sice najdenych malo, ale tunely v md5 existuju a masivne znizuju nekolizovatelnost md5 ako takej, pouzitie hmac dava vacsie spektrum moznosti a minimalne zvysuje rozstrel hodnot a ich variabilitu.

ono naozaj v tomto pripade ide hlavne o to, aby nebolo exposnute heslo, nakolko man in the middle attack je v tomto okamihu absolutne zbytocny a je asi tak na urovni obycajneho pasivneho sledovania. v suvislosti s tym ma napadla taka vec, ako by mohli byt napriklad untheftable sessions... je to iba zatial iba v rovine idey, ale principialne by to mohlo fungovat takto (ak nebude zadrhel s cookiesami).

povedzme, ze pomocou javascriptu si zadefinujeme pre nejaku neexistujucu cast nasho webu cookie (tym zabezpecime, ze sa cookie nebude posielat na server nikdy).

nasledne po prihlaseni pouzijeme nejaky algoritmus (napriklad md5_hmac(md5(heslo), sess_key), ktorym si vygenerujeme session vector. sess_key mu bude poslany zo servera. tento vector ulozime do tejto cookie, ktora sa nikdy neposiela (ale dufam, ze sa aspon da pomocou JS vybrakovat z prehliadaca, ak nie, tak smola, vykonat sa to neda).

po prihlaseni by sa rovnaky proces spravil aj na serveri (ten ma uz v DB ulozenu md5 hodnotu hesla, cize mu staci spravit md5_hmac(md5_hesla, sess_key).

a princip neodcudzitelnosti sessionu by spocivalo v tom, ze:
pri kazdom posielani formularu by sa vykonala nejaka operacia so session vectorom tak, aby ju nebolo mozne bez hesla predpovedat (mozno by sa dal pouzit algoritmus RC5) a tato hodnota by sa ulozila do skrytej cookie a vysledna hodnota by sa pribalila k formularu. na serveri by sa po prijati formularu vykonalo to iste, ak by server nedosiel k rovnakemu vysledku manipulacie s vectorom, ako je uvedene vo formulari, request by ignoroval, v opacnom pripade by si zmeny poznamenal a request by spracoval.

zadrhele:
1) nie je zname, ci je mozne takto ulozit cookie a zabranit tomu, aby sa posielala
2) momentalne ma nenapada ziadny algoritmus, ktory by umoznil synchronizaciu klienta a servera bez toho, aby bolo medzi nimi nutne prenasat nejake inicializacne udaje (ale tu RC5 by pouzit slo, u wifi je sice nachylna na prelomenie, ale potrebnych pol miliona requestov sa nedosiahne u tohto typu komunikacie)
3) v pripade veci, ako zrusenych requestov, padnuteho spojenia a podobne, by dochadzalo k desynchronizacii klienta, cize by asi bolo vhodne prenasat spolu so spojenim aj nejake inicializacne vektory, alebo nieco take, popripade implementovat restart poziadavky...

je to len kusa idea a napadla ma len tak mimochodom...

000001010079201102663954026639600266412802669177026692000266950702669571
mx
 mx      03.10.2006 - 23:35:54 , level: 5, UP   NEW
no, spoliehat sa pri autentifikacii na javascript je v principe nebezpecne, donutis tym uzivatela akceptovat tvoje poziadavky ... potom by sa dalo pokojne spravit aj take, ze si spravis jeden skryty frame, ktory nikdy nebudes refreshovat a riesis vsetky veci s modifikaciou nejakeho tokenu tam.
potom by to bolo - ak ma o pol dvanastej moj mozog neklame - celkom jednoduche
na strane klienta nechas bezat generator tokenu, ktory bude mat v pamati plaintext heslo (na klientskej strane, neprenesie sa nikdy po sieti) a stranka si ho z druheho frame vzdy pred submitom vyziada, spracuje do nejakej podoby a odosle naspat serveru ...
-- tuto som zmazal niekolko riadkov a zacal rozoberat inu uvahu, takze ak to bude nekonzistentne s uvodom, tak sorry --
co tak md5() poctu odoslani dat na server?
server vie, kolko ich je, lebo vie session id a klient si ich vie pocitat pri odosielani
samozrejme, problem rozsynchronizovania tam nastava, pokial sa stane nieco s linkou a tym padom by doslo k logoutu, ale to je dan za bezpecnost
toto je take jedno jednoduche riesenie, co ma napada momentalne