Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| Comment: | Special processing on the cases of disabled email confirmations. Additional bot protection on registering and login forms. |
|---|---|
| Downloads: | Tarball | ZIP archive | SQL archive |
| Timelines: | family | ancestors | descendants | both | trunk |
| Files: | files | file ages | folders |
| SHA1: |
9cea86855573c5beb9fdbe6e646fb302 |
| User & Date: | johnfound 2018-11-20 20:28:26 |
Context
|
2018-11-20
| ||
| 20:50:20 | Binary pack updated with the latest version of the bot protection. Notice, that the skins are updated as well. check-in: 943c49adf9 user: johnfound tags: trunk | |
| 20:28:26 | Special processing on the cases of disabled email confirmations. Additional bot protection on registering and login forms. check-in: 9cea868555 user: johnfound tags: trunk | |
|
2018-11-17
| ||
| 08:06:17 | Binary pack updated. check-in: ac0e89748d user: johnfound tags: trunk | |
Changes
Changes to source/accounts.asm.
| ︙ | ︙ | |||
17 18 19 20 21 22 23 |
sqlGetUserInfo text "select id, salt, passHash, status from Users where nick = ?"
sqlInsertSession text "insert into sessions (userID, sid, FromIP, last_seen) values ( ?1, ?2, ?3, strftime('%s','now') )"
sqlUpdateSession text "update Sessions set userID = ?1, FromIP = ?3, last_seen = strftime('%s','now') where sid = ?2"
sqlCheckSession text "select sid from sessions where userID = ? and fromIP = ?"
sqlCleanSessions text "delete from sessions where last_seen < (strftime('%s','now') - 2592000)"
| | > > > > > > > > > > > > > | 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 |
sqlGetUserInfo text "select id, salt, passHash, status from Users where nick = ?"
sqlInsertSession text "insert into sessions (userID, sid, FromIP, last_seen) values ( ?1, ?2, ?3, strftime('%s','now') )"
sqlUpdateSession text "update Sessions set userID = ?1, FromIP = ?3, last_seen = strftime('%s','now') where sid = ?2"
sqlCheckSession text "select sid from sessions where userID = ? and fromIP = ?"
sqlCleanSessions text "delete from sessions where last_seen < (strftime('%s','now') - 2592000)"
sqlLoginTicket text "select ?1 as ticket, ?2 as email_flag"
sqlCheckLoginTicket text "select 1 from userlog where remoteIP=?1 and Client = ?2 and Param = ?3 and Activity = ?4"
sqlClearLoginTicket text "update userlog set Param = NULL where remoteIP=?1 and Activity in (1, 3, 14, 15, 16, 17)"
proc UserLogin, .pSpecial
.stmt dd ?
.user dd ?
.password dd ?
.userID dd ?
.session dd ?
.status dd ?
.ticket dd ?
.email_flag dd ?
begin
pushad
xor eax, eax
mov [.session], eax
mov [.user], eax
mov [.password], eax
mov [.ticket], eax
cinvoke sqliteExec, [hMainDatabase], sqlCleanSessions, sqlCleanSessions.length, eax, eax
xor eax, eax ; default no?
stdcall GetParam, "email_confirm", gpInteger
mov [.email_flag], eax
; check the information
mov esi, [.pSpecial]
mov ebx, [esi+TSpecialParams.post_array]
test ebx, ebx
jnz .do_login_user
stdcall StrCat, [esi+TSpecialParams.page_title], cLoginDialogTitle
stdcall GetRandomString, 32
mov ebx, eax
stdcall LogUserActivity, esi, uaLoggingIn, ebx
lea ecx, [.stmt]
cinvoke sqlitePrepare_v2, [hMainDatabase], sqlLoginTicket, sqlLoginTicket.length, ecx, 0
stdcall StrPtr, ebx
cinvoke sqliteBindText, [.stmt], 1, eax, [eax+string.len], SQLITE_STATIC
cinvoke sqliteBindInt, [.stmt], 2, [.email_flag]
cinvoke sqliteStep, [.stmt]
stdcall RenderTemplate, 0, "form_login.tpl", [.stmt], esi
mov [esp+4*regEAX], eax
cinvoke sqliteFinalize, [.stmt]
stdcall StrDel, ebx
clc
popad
return
.do_login_user:
stdcall ValueByName, [esi+TSpecialParams.post_array], txt "submit.x"
jc .redirect_back_bad_permissions
stdcall ValueByName, [esi+TSpecialParams.post_array], txt "submit.y"
jc .redirect_back_bad_permissions
stdcall GetPostString, ebx, "username", 0
mov [.user], eax
test eax, eax
jz .redirect_back_short
|
| ︙ | ︙ | |||
377 378 379 380 381 382 383 | .user dd ? .password dd ? .password2 dd ? .email dd ? .secret dd ? .ticket dd ? | | > > > > | > > > > > > > > > | > > > > > > > > > > > > > > > > > > > | 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 |
.user dd ?
.password dd ?
.password2 dd ?
.email dd ?
.secret dd ?
.ticket dd ?
.email_flag dd ?
begin
pushad
xor eax, eax
mov [.user], eax
mov [.password], eax
mov [.password2], eax
mov [.email], eax
mov [.secret], eax
mov [.ticket], eax
; check the information
xor eax, eax ; default no?
stdcall GetParam, "email_confirm", gpInteger
mov [.email_flag], eax
mov esi, [.pSpecial]
cmp [esi+TSpecialParams.userID], 0
jne .error_trick
test [esi+TSpecialParams.userStatus], permLogin ; For the guests, permLogin == permRegister
jz .error_closed_registration
mov ebx, [esi+TSpecialParams.post_array]
test ebx, ebx
jnz .do_register_user
stdcall GetRandomString, 32
mov ebx, eax
stdcall LogUserActivity, esi, uaRegistering, ebx
lea ecx, [.stmt]
cinvoke sqlitePrepare_v2, [hMainDatabase], sqlLoginTicket, sqlLoginTicket.length, ecx, 0
stdcall StrPtr, ebx
cinvoke sqliteBindText, [.stmt], 1, eax, [eax+string.len], SQLITE_STATIC
cinvoke sqliteBindInt, [.stmt], 2, [.email_flag]
cinvoke sqliteStep, [.stmt]
stdcall RenderTemplate, 0, "form_register.tpl", [.stmt], esi
mov [esp+4*regEAX], eax
cinvoke sqliteFinalize, [.stmt]
stdcall StrDel, ebx
clc
popad
return
.do_register_user:
stdcall ValueByName, [esi+TSpecialParams.post_array], txt "submit.x"
jc .error_trick
stdcall ValueByName, [esi+TSpecialParams.post_array], txt "submit.y"
jc .error_trick
stdcall GetPostString, ebx, "username", 0
mov [.user], eax
test eax, eax
jz .error_short_name
stdcall ValidateUserName, [.user]
jnc .error_short_name ; the name contains special characters actually!
stdcall StrLen, eax
cmp eax, 3
jbe .error_short_name
cmp eax, 256
ja .error_trick
stdcall GetPostString, ebx, "email", 0
mov [.email], eax
cmp [.email_flag], 0
jne .check_email
; Use the email field as a honeypot, if the activation emails are disabled.
; Some kind of bot protection...
test eax, eax
jz .check_password
stdcall StrLen, eax
test eax, eax
jz .check_password
jmp .error_trick
; Check the email in case the activation email will be sent
.check_email:
test eax, eax
jz .error_bad_email
stdcall CheckEmail, eax
jc .error_bad_email
.check_password:
stdcall GetPostString, ebx, txt "password", 0
mov [.password], eax
test eax, eax
jz .error_short_pass
stdcall GetPostString, ebx, txt "password2", 0
|
| ︙ | ︙ | |||
486 487 488 489 490 491 492 |
stdcall StrLen, eax
test eax, eax
jz .error_trick
; check the ticket
| | | 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 |
stdcall StrLen, eax
test eax, eax
jz .error_trick
; check the ticket
DebugMsg "Check the ticket."
lea eax, [.stmt]
cinvoke sqlitePrepare_v2, [hMainDatabase], sqlCheckLoginTicket, sqlCheckLoginTicket.length, eax, 0
cinvoke sqliteBindInt, [.stmt], 1, [esi+TSpecialParams.remoteIP]
stdcall ValueByName, [esi+TSpecialParams.params], "HTTP_USER_AGENT"
jc .client_ok
|
| ︙ | ︙ | |||
538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 |
; check whether the user exists
lea eax, [.stmt]
cinvoke sqlitePrepare_v2, [hMainDatabase], sqlCheckUserExists, -1, eax, 0
stdcall StrPtr, [.user]
cinvoke sqliteBindText, [.stmt], 1, eax, [eax+string.len], SQLITE_STATIC
stdcall StrPtr, [.email]
cinvoke sqliteBindText, [.stmt], 2, eax, [eax+string.len], SQLITE_STATIC
cinvoke sqliteStep, [.stmt]
mov ebx, eax
cinvoke sqliteFinalize, [.stmt]
cmp ebx, SQLITE_ROW
je .error_exists
lea eax, [.stmt]
cinvoke sqlitePrepare_v2, [hMainDatabase], sqlRegisterUser, sqlRegisterUser.length, eax, 0
stdcall StrPtr, [.user]
cinvoke sqliteBindText, [.stmt], 1, eax, [eax+string.len], SQLITE_STATIC
stdcall StrPtr, [.password]
cinvoke sqliteBindText, [.stmt], 2, eax, [eax+string.len], SQLITE_STATIC
stdcall StrPtr, [.password2]
cinvoke sqliteBindText, [.stmt], 3, eax, [eax+string.len], SQLITE_STATIC
stdcall StrPtr, [.email]
cinvoke sqliteBindText, [.stmt], 4, eax, [eax+string.len], SQLITE_STATIC
cinvoke sqliteBindInt, [.stmt], 5, [esi+TSpecialParams.remoteIP]
stdcall StrPtr, [.secret]
cinvoke sqliteBindText, [.stmt], 6, eax, [eax+string.len], SQLITE_STATIC
cinvoke sqliteBindInt, [.stmt], 7, uopCreateAccount
cinvoke sqliteStep, [.stmt]
mov ebx, eax
cinvoke sqliteFinalize, [.stmt]
cmp ebx, SQLITE_DONE
jne .error_exists
| > > > > > > > > > > > > > > > > < < | < | < | 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 |
; check whether the user exists
lea eax, [.stmt]
cinvoke sqlitePrepare_v2, [hMainDatabase], sqlCheckUserExists, -1, eax, 0
stdcall StrPtr, [.user]
cinvoke sqliteBindText, [.stmt], 1, eax, [eax+string.len], SQLITE_STATIC
cmp [.email], 0
je .email_ok2
stdcall StrPtr, [.email]
cmp [eax+string.len], 0
je .email_ok2
cinvoke sqliteBindText, [.stmt], 2, eax, [eax+string.len], SQLITE_STATIC
.email_ok2:
cinvoke sqliteStep, [.stmt]
mov ebx, eax
cinvoke sqliteFinalize, [.stmt]
cmp ebx, SQLITE_ROW
je .error_exists
lea eax, [.stmt]
cinvoke sqlitePrepare_v2, [hMainDatabase], sqlRegisterUser, sqlRegisterUser.length, eax, 0
stdcall StrPtr, [.user]
cinvoke sqliteBindText, [.stmt], 1, eax, [eax+string.len], SQLITE_STATIC
stdcall StrPtr, [.password]
cinvoke sqliteBindText, [.stmt], 2, eax, [eax+string.len], SQLITE_STATIC
stdcall StrPtr, [.password2]
cinvoke sqliteBindText, [.stmt], 3, eax, [eax+string.len], SQLITE_STATIC
cmp [.email], 0
je .email_ok
stdcall StrPtr, [.email]
cmp [eax+string.len], 0
je .email_ok
cinvoke sqliteBindText, [.stmt], 4, eax, [eax+string.len], SQLITE_STATIC
.email_ok:
cinvoke sqliteBindInt, [.stmt], 5, [esi+TSpecialParams.remoteIP]
stdcall StrPtr, [.secret]
cinvoke sqliteBindText, [.stmt], 6, eax, [eax+string.len], SQLITE_STATIC
cinvoke sqliteBindInt, [.stmt], 7, uopCreateAccount
cinvoke sqliteStep, [.stmt]
mov ebx, eax
cinvoke sqliteFinalize, [.stmt]
cmp ebx, SQLITE_DONE
jne .error_exists
cmp [.email_flag], 0
je .no_confirm
; now send the activation email for all registered user, where the email was not sent.
stdcall ProcessActivationEmails
; the user has been created and now is waiting for email activation.
stdcall TextMakeRedirect, 0, "/!message/user_created/"
jmp .finish
|
| ︙ | ︙ |
Changes to source/commands.asm.
| ︙ | ︙ | |||
1286 1287 1288 1289 1290 1291 1292 | gpString = 0 gpInteger = 1 | | | | 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 |
gpString = 0
gpInteger = 1
sqlGetParam text "select val from params where id = ?"
proc GetParam, .key, .type
.stmt dd ?
begin
pushad
lea eax, [.stmt]
cinvoke sqlitePrepare_v2, [hMainDatabase], sqlGetParam, sqlGetParam.length, eax, 0
stdcall StrPtr, [.key]
cinvoke sqliteBindText, [.stmt], 1, eax, -1, SQLITE_STATIC
cinvoke sqliteStep, [.stmt]
cmp eax, SQLITE_ROW
jne .error
|
| ︙ | ︙ |
Changes to source/engine.asm.
| ︙ | ︙ | |||
22 23 24 25 26 27 28 | options.ShowSizes = 0 options.DebugMode = 0 options.AlignCode = 0 options.ShowImported = 0 options.DebugWeb = 0 | | | 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | options.ShowSizes = 0 options.DebugMode = 0 options.AlignCode = 0 options.ShowImported = 0 options.DebugWeb = 0 options.DebugPost = 0 ; save the latest POST request data in the file "post_data.txt" options.DebugSQLite = 1 options.DebugWebSSE = 0 ; debug server sent events - creates a command "!echo_events" for debugging SSE. options.Benchmark = 0 ;HeapManager equ ASM ;LinuxThreads equ native |
| ︙ | ︙ |
Changes to www/templates/Terminal/form_login.tpl.
1 2 3 4 5 6 7 8 |
[css:navigation.css]
[css:login.css]
<div class="ui_panel">
<a class="ui left" href="/">Threads</a>
</div>
<form class="login-block" method="post" target="_self" action="/!login">
<h1>Login</h1>
| | | | | | | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
[css:navigation.css]
[css:login.css]
<div class="ui_panel">
<a class="ui left" href="/">Threads</a>
</div>
<form class="login-block" method="post" target="_self" action="/!login">
<h1>Login</h1>
<p class="pi_nick"><input type="text" value="" placeholder="Username" name="username" class="username" autofocus maxlength="256"></p>
<p class="pi_pass"><input type="password" value="" placeholder="Password" name="password" class="password" maxlength="1024" autocomplete="off"></p>
<p class="pi_tick"><input type="text" value="[special:referer]" name="backlink" id="backlink"></p>
<p class="pi_nick"><input type="checkbox" name="persistent" id="pr" value="1"><label for="pr">Persistent login</label></p>
<p class="pi_tick"><input type="text" value="[ticket]" name="ticket" id="ticket"></p>
<input type="image" name="submit" id="submit" value="Submit"><label class="submit" for="submit">Submit</label>
</form>
<article>
[case:[email_flag]||<p>If you forgot your password, <b><a href="/!resetpassword">click here</a></b>. You have limited reset attempts.</p>]
[case:[special:canregister]||<p>If you don't have an account, you should <b><a href="/!register">register one</a></b>.</p>]
<p></p>
<p>The login process uses cookies. If the "Persistent login" checkbox is checked, the cookie will be stored persistently in your browser.</p>
<p>If the "Persistent login" checkbox is not checked (default), AsmBB uses so called "session cookies" that are automatically removed when you close your browser.</p>
<p>When you logout from the forum, all cookies are removed as well.</p>
</article>
|
Changes to www/templates/Terminal/login.less.
| ︙ | ︙ | |||
38 39 40 41 42 43 44 |
input[type=checkbox] + label {
display: block;
color: @clFormFG;
margin: 0 0 @LineH 0;
}
| > > > > > > > > > > > > > > > > > > > > > > | 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
input[type=checkbox] + label {
display: block;
color: @clFormFG;
margin: 0 0 @LineH 0;
}
.pi_nick, .pi_pass, .pi_tick, .pi_email {
margin: 0px;
padding: 0px;
}
.pi_tick, .pi_email {
display: none;
}
#submit {
position: absolute;
z-index: -1;
left: -10000px;
&:focus + label {
background: @clButtonActiveBG;
color: @clButtonActiveFG;
outline: 2px dotted @clSeparator;
outline-offset: -2px;
}
}
|
Changes to www/templates/Wasp/form_login.tpl.
1 2 3 4 5 6 7 8 9 |
[css:navigation.css]
[css:login.css]
<div class="login">
<div class="ui">
<a class="ui" href="/">Threads</a>
</div>
<form class="login-block" method="post" target="_self" action="/!login">
<h1>Login</h1>
| | | | | | | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
[css:navigation.css]
[css:login.css]
<div class="login">
<div class="ui">
<a class="ui" href="/">Threads</a>
</div>
<form class="login-block" method="post" target="_self" action="/!login">
<h1>Login</h1>
<p class="pi_nick"><input type="text" value="" placeholder="Username" name="username" class="username" autofocus maxlength="256"></p>
<p class="pi_pass"><input type="password" value="" placeholder="Password" name="password" class="password" maxlength="1024" autocomplete="off"></p>
<p class="pi_tick"><input type="text" value="[special:referer]" name="backlink" id="backlink"></p>
<p class="pi_nick"><input type="checkbox" name="persistent" id="pr" value="1"><label for="pr">Persistent login</label></p>
<p class="pi_tick"><input type="text" value="[ticket]" name="ticket" id="ticket"></p>
<input type="image" name="submit" id="submit" value="Submit"><label class="submit" for="submit">Submit</label>
</form>
<article>
[case:[email_flag]||<p>If you forgot your password, <b><a href="/!resetpassword">click here</a></b>. You have limited reset attempts.</p>]
[case:[special:canregister]||<p>If you don't have an account, you should <b><a href="/!register">register one</a></b>.</p>]
<p></p>
<p>The login process uses cookies. If the "Persistent login" checkbox is checked, the cookie will be stored persistently in your browser.</p>
<p>If the "Persistent login" checkbox is not checked (default), AsmBB uses so called "session cookies" that are automatically removed when you close your browser.</p>
<p>When you logout from the forum, all cookies are removed as well.</p>
</article>
</div>
|
Changes to www/templates/Wasp/form_register.tpl.
1 2 3 4 5 6 7 8 9 |
[css:navigation.css]
[css:login.css]
<div class="login">
<div class="ui">
<a class="ui" href="/">Threads</a>
</div>
<form class="register-block" method="post" action="/!register/">
<h1>Register</h1>
| | | | | | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
[css:navigation.css]
[css:login.css]
<div class="login">
<div class="ui">
<a class="ui" href="/">Threads</a>
</div>
<form class="register-block" method="post" action="/!register/">
<h1>Register</h1>
<p class="pi_nick"><input type="text" value="" placeholder="Username" name="username" class="username" maxlength="256" autofocus></p>
<p class="[case:[email_flag]|pi_email|pi_nick]"><input type="text" value="" placeholder="e-mail" name="email" class="email" maxlength="320"></p>
<p class="pi_pass"><input type="password" value="" placeholder="Password" name="password" class="password" maxlength="1024" autocomplete="off"></p>
<p class="pi_pass"><input type="password" value="" placeholder="Password again" name="password2" class="password" maxlength="1024" autocomplete="off"></p>
<p class="pi_tick"><input type="text" value="[ticket]" name="ticket" id="ticket" class="ticket"></p>
<label class="submit" for="submit">Submit</label><input type="image" name="submit" id="submit" value="Submit">
</form>
<article>
<p>To choose strong password and write it down on a paper is better than to choose easy to remember password.</p>
<p>Because the humans are not very good in remembering random strings, but pretty good in keeping small sheets of paper.</p>
<p>But don't stick it on your monitor. Simply keep it in your wallet...</p>
<p>... or use some password manager program.</p>
</article>
|
| ︙ | ︙ |
Changes to www/templates/Wasp/login.less.
| ︙ | ︙ | |||
61 62 63 64 65 66 67 |
border: @borderEdit;
background: @bgEditor;
color: @clEditorFG;
}
| < > | > | > > > > > > | > > > > > > > > > | 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 |
border: @borderEdit;
background: @bgEditor;
color: @clEditorFG;
}
input.username {
background-image: url('[special:skin]/_images/user.png') !important;
}
input.email {
background-image: url('[special:skin]/_images/email.png') !important;
}
input.password {
background-image: url('[special:skin]/_images/pass.png') !important;
}
input.username:focus, input.email:focus, input.password:focus {
background: @bgEditorFocus;
}
label.submit {
height: 38px;
line-height: 38px;
width: 100%;
background: @clButtonBG;
color: @clButtonFG;
border: none;
font-weight: bold;
font-size: 16px;
font-variant: small-caps;
outline: none;
cursor: pointer;
text-align: center;
padding: 0px;
display: block;
margin: 8px 0px;
&:hover {
background: @clButtonActiveBG;
color: @clButtonActiveFG;
}
}
#submit {
position: absolute;
z-index: -1;
left: -10000px;
&:focus + label {
background: @clButtonActiveBG;
color: @clButtonActiveFG;
outline: 2px dotted @clSeparator;
outline-offset: -2px;
}
}
.pi_nick, .pi_pass, .pi_tick, .pi_email {
margin: 0px;
padding: 0px;
}
.pi_tick, .pi_email {
display: none;
}
|