33
44<?php
55
6- //------------------------------------------------------------------------------
7- // check if authenticated
8- // Be CAREFUL WHEN INCLUDING NEW PHP FILES
9- require_once $ _SERVER ['DOCUMENT_ROOT ' ] . '/php/server/db.php ' ;
10- require_once $ _SERVER ['DOCUMENT_ROOT ' ] . '/php/templates/language/lang.php ' ;
11- require_once $ _SERVER ['DOCUMENT_ROOT ' ] . '/php/templates/security.php ' ;
12-
13- $ CookieSaveLoginName = 'NetAlertX_SaveLogin ' ;
14-
15- if ($ nax_WebProtection != 'true ' )
16- {
17- header ('Location: devices.php ' );
18- $ _SESSION ["login " ] = 1 ;
6+ require_once $ _SERVER ['DOCUMENT_ROOT ' ].'/php/server/db.php ' ;
7+ require_once $ _SERVER ['DOCUMENT_ROOT ' ].'/php/templates/language/lang.php ' ;
8+ require_once $ _SERVER ['DOCUMENT_ROOT ' ].'/php/templates/security.php ' ;
9+
10+ // if (session_status() === PHP_SESSION_NONE) {
11+ // session_start();
12+ // }
13+
14+ session_start ();
15+
16+ const DEFAULT_REDIRECT = '/devices.php ' ;
17+
18+ /* =====================================================
19+ Helper Functions
20+ ===================================================== */
21+
22+ function safe_redirect (string $ path ): void {
23+ header ("Location: {$ path }" , true , 302 );
1924 exit ;
2025}
2126
22- // Logout
23- if (isset ($ _GET ["action " ]) && $ _GET ["action " ] == 'logout ' )
24- {
25- setcookie ($ CookieSaveLoginName , '' , time ()+1 ); // reset cookie
26- $ _SESSION ["login " ] = 0 ;
27- header ('Location: index.php ' );
28- exit ;
27+ function validate_local_path (?string $ encoded ): string {
28+ if (!$ encoded ) return DEFAULT_REDIRECT ;
29+
30+ $ decoded = base64_decode ($ encoded , true );
31+ if ($ decoded === false ) {
32+ return DEFAULT_REDIRECT ;
33+ }
34+
35+ // strict local path check (allow safe query strings + fragments)
36+ // Using ~ as the delimiter instead of #
37+ if (!preg_match ('~^(?!//)(?!.*://)/[a-zA-Z0-9_\-./?=&:%#]*$~ ' , $ decoded )) {
38+ return DEFAULT_REDIRECT ;
39+ }
40+
41+ return $ decoded ;
42+ }
43+
44+ function extract_hash_from_path (string $ path ): array {
45+ /*
46+ Split a path into path and hash components.
47+
48+ For deep links encoded in the 'next' parameter like /devices.php#device-123,
49+ extract the hash fragment so it can be properly included in the redirect.
50+
51+ Args:
52+ path: Full path potentially with hash (e.g., "/devices.php#device-123")
53+
54+ Returns:
55+ Array with keys 'path' (without hash) and 'hash' (with # prefix, or empty string)
56+ */
57+ $ parts = explode ('# ' , $ path , 2 );
58+ return [
59+ 'path ' => $ parts [0 ],
60+ 'hash ' => !empty ($ parts [1 ]) ? '# ' . $ parts [1 ] : ''
61+ ];
62+ }
63+
64+ function append_hash (string $ url ): string {
65+ // First check if the URL already has a hash from the deep link
66+ $ parts = extract_hash_from_path ($ url );
67+ if (!empty ($ parts ['hash ' ])) {
68+ return $ parts ['path ' ] . $ parts ['hash ' ];
69+ }
70+
71+ // Fall back to POST url_hash (for browser-captured hashes)
72+ if (!empty ($ _POST ['url_hash ' ])) {
73+ $ sanitized = preg_replace ('/[^#a-zA-Z0-9_\-]/ ' , '' , $ _POST ['url_hash ' ]);
74+ if (str_starts_with ($ sanitized , '# ' )) {
75+ return $ url . $ sanitized ;
76+ }
77+ }
78+ return $ url ;
2979}
3080
31- // Password without Cookie check -> pass and set initial cookie
32- if (isset ($ _POST ["loginpassword " ]) && $ nax_Password === hash ('sha256 ' ,$ _POST ["loginpassword " ]))
33- {
34- header ('Location: devices.php ' );
35- $ _SESSION ["login " ] = 1 ;
36- if (isset ($ _POST ['PWRemember ' ])) {setcookie ($ CookieSaveLoginName , hash ('sha256 ' ,$ _POST ["loginpassword " ]), time ()+604800 );}
81+ function is_authenticated (): bool {
82+ return isset ($ _SESSION ['login ' ]) && $ _SESSION ['login ' ] === 1 ;
3783}
3884
39- // active Session or valid cookie (cookie not extends)
40- if (( isset ($ _SESSION ["login " ]) && ($ _SESSION ["login " ] == 1 )) || (isset ($ _COOKIE [$ CookieSaveLoginName ]) && $ nax_Password === $ _COOKIE [$ CookieSaveLoginName ]))
41- {
42- header ('Location: devices.php ' );
43- $ _SESSION ["login " ] = 1 ;
44- if (isset ($ _POST ['PWRemember ' ])) {setcookie ($ CookieSaveLoginName , hash ('sha256 ' ,$ _POST ["loginpassword " ]), time ()+604800 );}
85+ function login_user (): void {
86+ $ _SESSION ['login ' ] = 1 ;
87+ session_regenerate_id (true );
4588}
4689
90+
91+ function logout_user (): void {
92+ $ _SESSION = [];
93+ session_destroy ();
94+ }
95+
96+ /* =====================================================
97+ Redirect Handling
98+ ===================================================== */
99+
100+ $ redirectTo = validate_local_path ($ _GET ['next ' ] ?? null );
101+
102+ /* =====================================================
103+ Web Protection Disabled
104+ ===================================================== */
105+
106+ if ($ nax_WebProtection !== 'true ' ) {
107+ if (!is_authenticated ()) {
108+ login_user ();
109+ }
110+ safe_redirect (append_hash ($ redirectTo ));
111+ }
112+
113+ /* =====================================================
114+ Login Attempt
115+ ===================================================== */
116+
117+ if (!empty ($ _POST ['loginpassword ' ])) {
118+
119+ $ incomingHash = hash ('sha256 ' , $ _POST ['loginpassword ' ]);
120+
121+ if (hash_equals ($ nax_Password , $ incomingHash )) {
122+
123+ login_user ();
124+
125+ // Redirect to target page, preserving deep link hash if present
126+ safe_redirect (append_hash ($ redirectTo ));
127+ }
128+ }
129+
130+ /* =====================================================
131+ Already Logged In
132+ ===================================================== */
133+
134+ if (is_authenticated ()) {
135+ safe_redirect (append_hash ($ redirectTo ));
136+ }
137+
138+ /* =====================================================
139+ Login UI Variables
140+ ===================================================== */
141+
47142$ login_headline = lang ('Login_Toggle_Info_headline ' );
48- $ login_info = lang ('Login_Info ' );
49- $ login_mode = 'danger ' ;
50- $ login_display_mode = 'display: block; ' ;
51- $ login_icon = 'fa-info ' ;
52-
53- // no active session, cookie not checked
54- if (isset ($ _SESSION ["login " ]) == FALSE || $ _SESSION ["login " ] != 1 )
55- {
56- if ($ nax_Password === '8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92 ' )
57- {
143+ $ login_info = lang ('Login_Info ' );
144+ $ login_mode = 'info ' ;
145+ $ login_display_mode = 'display:none; ' ;
146+ $ login_icon = 'fa-info ' ;
147+
148+ if ($ nax_Password === '8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92 ' ) {
58149 $ login_info = lang ('Login_Default_PWD ' );
59150 $ login_mode = 'danger ' ;
60- $ login_display_mode = 'display: block; ' ;
151+ $ login_display_mode = 'display:block; ' ;
61152 $ login_headline = lang ('Login_Toggle_Alert_headline ' );
62153 $ login_icon = 'fa-ban ' ;
63- }
64- else
65- {
66- $ login_mode = 'info ' ;
67- $ login_display_mode = 'display: none; ' ;
68- $ login_headline = lang ('Login_Toggle_Info_headline ' );
69- $ login_icon = 'fa-info ' ;
70- }
71154}
72-
73- // ##################################################
74- // ## Login Processing end
75- // ##################################################
76155?>
77156
78157<!DOCTYPE html>
109188 <!-- /.login-logo -->
110189 <div class="login-box-body">
111190 <p class="login-box-msg"><?= lang ('Login_Box ' );?> </p>
112- <form action="index.php" method="post">
191+ <form action="index.php<?php
192+ echo !empty ($ _GET ['next ' ])
193+ ? '?next= ' . htmlspecialchars ($ _GET ['next ' ], ENT_QUOTES , 'UTF-8 ' )
194+ : '' ;
195+ ?> " method="post">
113196 <div class="form-group has-feedback">
197+ <input type="hidden" name="url_hash" id="url_hash">
114198 <input type="password" class="form-control" placeholder="<?= lang ('Login_Psw-box ' );?> " name="loginpassword">
115199 <span class="glyphicon glyphicon-lock form-control-feedback"></span>
116200 </div>
117201 <div class="row">
118- <div class="col-xs-8">
119- <div class="checkbox icheck">
120- <label>
121- <input type="checkbox" name="PWRemember">
122- <div style="margin-left: 10px; display: inline-block; vertical-align: top;">
123- <?= lang ('Login_Remember ' );?> <br><span style="font-size: smaller"><?= lang ('Login_Remember_small ' );?> </span>
124- </div>
125- </label>
126- </div>
127- </div>
128- <!-- /.col -->
129- <div class="col-xs-4" style="padding-top: 10px;">
202+ <div class="col-xs-12">
130203 <button type="submit" class="btn btn-primary btn-block btn-flat"><?= lang ('Login_Submit ' );?> </button>
131204 </div>
132- <!-- /.col -->
205+ <!-- /.col -->
133206 </div>
134207 </form>
135208
159232<!-- iCheck -->
160233<script src="lib/iCheck/icheck.min.js"></script>
161234<script>
235+ if (window.location.hash) {
236+ document.getElementById('url_hash').value = window.location.hash;
237+ }
162238 $(function () {
163239 $('input').iCheck({
164240 checkboxClass: 'icheckbox_square-blue',
@@ -174,7 +250,7 @@ function Passwordhinfo() {
174250 } else {
175251 x.style.display = "none";
176252 }
177- }
253+ }
178254
179255</script>
180256</body>
0 commit comments